通过微信开发者工具 商城模板 创建新小程序
This commit is contained in:
		
							
								
								
									
										356
									
								
								mini-program/pages/usercenter/address/edit/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										356
									
								
								mini-program/pages/usercenter/address/edit/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,356 @@
 | 
			
		||||
import Toast from 'tdesign-miniprogram/toast/index';
 | 
			
		||||
import { fetchDeliveryAddress } from '../../../../services/address/fetchAddress';
 | 
			
		||||
import { areaData } from '../../../../config/index';
 | 
			
		||||
import { resolveAddress, rejectAddress } from './util';
 | 
			
		||||
 | 
			
		||||
const innerPhoneReg = '^1(?:3\\d|4[4-9]|5[0-35-9]|6[67]|7[0-8]|8\\d|9\\d)\\d{8}$';
 | 
			
		||||
const innerNameReg = '^[a-zA-Z\\d\\u4e00-\\u9fa5]+$';
 | 
			
		||||
const labelsOptions = [
 | 
			
		||||
  { id: 0, name: '家' },
 | 
			
		||||
  { id: 1, name: '公司' },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
Page({
 | 
			
		||||
  options: {
 | 
			
		||||
    multipleSlots: true,
 | 
			
		||||
  },
 | 
			
		||||
  externalClasses: ['theme-wrapper-class'],
 | 
			
		||||
  data: {
 | 
			
		||||
    locationState: {
 | 
			
		||||
      labelIndex: null,
 | 
			
		||||
      addressId: '',
 | 
			
		||||
      addressTag: '',
 | 
			
		||||
      cityCode: '',
 | 
			
		||||
      cityName: '',
 | 
			
		||||
      countryCode: '',
 | 
			
		||||
      countryName: '',
 | 
			
		||||
      detailAddress: '',
 | 
			
		||||
      districtCode: '',
 | 
			
		||||
      districtName: '',
 | 
			
		||||
      isDefault: false,
 | 
			
		||||
      name: '',
 | 
			
		||||
      phone: '',
 | 
			
		||||
      provinceCode: '',
 | 
			
		||||
      provinceName: '',
 | 
			
		||||
      isEdit: false,
 | 
			
		||||
      isOrderDetail: false,
 | 
			
		||||
      isOrderSure: false,
 | 
			
		||||
    },
 | 
			
		||||
    areaData: areaData,
 | 
			
		||||
    labels: labelsOptions,
 | 
			
		||||
    areaPickerVisible: false,
 | 
			
		||||
    submitActive: false,
 | 
			
		||||
    visible: false,
 | 
			
		||||
    labelValue: '',
 | 
			
		||||
    columns: 3,
 | 
			
		||||
  },
 | 
			
		||||
  privateData: {
 | 
			
		||||
    verifyTips: '',
 | 
			
		||||
  },
 | 
			
		||||
  onLoad(options) {
 | 
			
		||||
    const { id } = options;
 | 
			
		||||
    this.init(id);
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  onUnload() {
 | 
			
		||||
    if (!this.hasSava) {
 | 
			
		||||
      rejectAddress();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  hasSava: false,
 | 
			
		||||
 | 
			
		||||
  init(id) {
 | 
			
		||||
    if (id) {
 | 
			
		||||
      this.getAddressDetail(Number(id));
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  getAddressDetail(id) {
 | 
			
		||||
    fetchDeliveryAddress(id).then((detail) => {
 | 
			
		||||
      this.setData({ locationState: detail }, () => {
 | 
			
		||||
        const { isLegal, tips } = this.onVerifyInputLegal();
 | 
			
		||||
        this.setData({
 | 
			
		||||
          submitActive: isLegal,
 | 
			
		||||
        });
 | 
			
		||||
        this.privateData.verifyTips = tips;
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  onInputValue(e) {
 | 
			
		||||
    const { item } = e.currentTarget.dataset;
 | 
			
		||||
    if (item === 'address') {
 | 
			
		||||
      const { selectedOptions = [] } = e.detail;
 | 
			
		||||
      this.setData(
 | 
			
		||||
        {
 | 
			
		||||
          'locationState.provinceCode': selectedOptions[0].value,
 | 
			
		||||
          'locationState.provinceName': selectedOptions[0].label,
 | 
			
		||||
          'locationState.cityName': selectedOptions[1].label,
 | 
			
		||||
          'locationState.cityCode': selectedOptions[1].value,
 | 
			
		||||
          'locationState.districtCode': selectedOptions[2].value,
 | 
			
		||||
          'locationState.districtName': selectedOptions[2].label,
 | 
			
		||||
          areaPickerVisible: false,
 | 
			
		||||
        },
 | 
			
		||||
        () => {
 | 
			
		||||
          const { isLegal, tips } = this.onVerifyInputLegal();
 | 
			
		||||
          this.setData({
 | 
			
		||||
            submitActive: isLegal,
 | 
			
		||||
          });
 | 
			
		||||
          this.privateData.verifyTips = tips;
 | 
			
		||||
        },
 | 
			
		||||
      );
 | 
			
		||||
    } else {
 | 
			
		||||
      const { value = '' } = e.detail;
 | 
			
		||||
      this.setData(
 | 
			
		||||
        {
 | 
			
		||||
          [`locationState.${item}`]: value,
 | 
			
		||||
        },
 | 
			
		||||
        () => {
 | 
			
		||||
          const { isLegal, tips } = this.onVerifyInputLegal();
 | 
			
		||||
          this.setData({
 | 
			
		||||
            submitActive: isLegal,
 | 
			
		||||
          });
 | 
			
		||||
          this.privateData.verifyTips = tips;
 | 
			
		||||
        },
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  onPickArea() {
 | 
			
		||||
    this.setData({ areaPickerVisible: true });
 | 
			
		||||
  },
 | 
			
		||||
  onPickLabels(e) {
 | 
			
		||||
    const { item } = e.currentTarget.dataset;
 | 
			
		||||
    const {
 | 
			
		||||
      locationState: { labelIndex = undefined },
 | 
			
		||||
      labels = [],
 | 
			
		||||
    } = this.data;
 | 
			
		||||
    let payload = {
 | 
			
		||||
      labelIndex: item,
 | 
			
		||||
      addressTag: labels[item].name,
 | 
			
		||||
    };
 | 
			
		||||
    if (item === labelIndex) {
 | 
			
		||||
      payload = { labelIndex: null, addressTag: '' };
 | 
			
		||||
    }
 | 
			
		||||
    this.setData({
 | 
			
		||||
      'locationState.labelIndex': payload.labelIndex,
 | 
			
		||||
    });
 | 
			
		||||
    this.triggerEvent('triggerUpdateValue', payload);
 | 
			
		||||
  },
 | 
			
		||||
  addLabels() {
 | 
			
		||||
    this.setData({
 | 
			
		||||
      visible: true,
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  confirmHandle() {
 | 
			
		||||
    const { labels, labelValue } = this.data;
 | 
			
		||||
    this.setData({
 | 
			
		||||
      visible: false,
 | 
			
		||||
      labels: [...labels, { id: labels[labels.length - 1].id + 1, name: labelValue }],
 | 
			
		||||
      labelValue: '',
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  cancelHandle() {
 | 
			
		||||
    this.setData({
 | 
			
		||||
      visible: false,
 | 
			
		||||
      labelValue: '',
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  onCheckDefaultAddress({ detail }) {
 | 
			
		||||
    const { value } = detail;
 | 
			
		||||
    this.setData({
 | 
			
		||||
      'locationState.isDefault': value,
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  onVerifyInputLegal() {
 | 
			
		||||
    const { name, phone, detailAddress, districtName } = this.data.locationState;
 | 
			
		||||
    const prefixPhoneReg = String(this.properties.phoneReg || innerPhoneReg);
 | 
			
		||||
    const prefixNameReg = String(this.properties.nameReg || innerNameReg);
 | 
			
		||||
    const nameRegExp = new RegExp(prefixNameReg);
 | 
			
		||||
    const phoneRegExp = new RegExp(prefixPhoneReg);
 | 
			
		||||
 | 
			
		||||
    if (!name || !name.trim()) {
 | 
			
		||||
      return {
 | 
			
		||||
        isLegal: false,
 | 
			
		||||
        tips: '请填写收货人',
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
    if (!nameRegExp.test(name)) {
 | 
			
		||||
      return {
 | 
			
		||||
        isLegal: false,
 | 
			
		||||
        tips: '收货人仅支持输入中文、英文(区分大小写)、数字',
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
    if (!phone || !phone.trim()) {
 | 
			
		||||
      return {
 | 
			
		||||
        isLegal: false,
 | 
			
		||||
        tips: '请填写手机号',
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
    if (!phoneRegExp.test(phone)) {
 | 
			
		||||
      return {
 | 
			
		||||
        isLegal: false,
 | 
			
		||||
        tips: '请填写正确的手机号',
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
    if (!districtName || !districtName.trim()) {
 | 
			
		||||
      return {
 | 
			
		||||
        isLegal: false,
 | 
			
		||||
        tips: '请选择省市区信息',
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
    if (!detailAddress || !detailAddress.trim()) {
 | 
			
		||||
      return {
 | 
			
		||||
        isLegal: false,
 | 
			
		||||
        tips: '请完善详细地址',
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
    if (detailAddress && detailAddress.trim().length > 50) {
 | 
			
		||||
      return {
 | 
			
		||||
        isLegal: false,
 | 
			
		||||
        tips: '详细地址不能超过50个字符',
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
      isLegal: true,
 | 
			
		||||
      tips: '添加成功',
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  builtInSearch({ code, name }) {
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
      wx.getSetting({
 | 
			
		||||
        success: (res) => {
 | 
			
		||||
          if (res.authSetting[code] === false) {
 | 
			
		||||
            wx.showModal({
 | 
			
		||||
              title: `获取${name}失败`,
 | 
			
		||||
              content: `获取${name}失败,请在【右上角】-小程序【设置】项中,将【${name}】开启。`,
 | 
			
		||||
              confirmText: '去设置',
 | 
			
		||||
              confirmColor: '#FA550F',
 | 
			
		||||
              cancelColor: '取消',
 | 
			
		||||
              success(res) {
 | 
			
		||||
                if (res.confirm) {
 | 
			
		||||
                  wx.openSetting({
 | 
			
		||||
                    success(settinRes) {
 | 
			
		||||
                      if (settinRes.authSetting[code] === true) {
 | 
			
		||||
                        resolve();
 | 
			
		||||
                      } else {
 | 
			
		||||
                        console.warn('用户未打开权限', name, code);
 | 
			
		||||
                        reject();
 | 
			
		||||
                      }
 | 
			
		||||
                    },
 | 
			
		||||
                  });
 | 
			
		||||
                } else {
 | 
			
		||||
                  reject();
 | 
			
		||||
                }
 | 
			
		||||
              },
 | 
			
		||||
              fail() {
 | 
			
		||||
                reject();
 | 
			
		||||
              },
 | 
			
		||||
            });
 | 
			
		||||
          } else {
 | 
			
		||||
            resolve();
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        fail() {
 | 
			
		||||
          reject();
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  onSearchAddress() {
 | 
			
		||||
    this.builtInSearch({ code: 'scope.userLocation', name: '地址位置' }).then(() => {
 | 
			
		||||
      wx.chooseLocation({
 | 
			
		||||
        success: (res) => {
 | 
			
		||||
          if (res.name) {
 | 
			
		||||
            this.triggerEvent('addressParse', {
 | 
			
		||||
              address: res.address,
 | 
			
		||||
              name: res.name,
 | 
			
		||||
              latitude: res.latitude,
 | 
			
		||||
              longitude: res.longitude,
 | 
			
		||||
            });
 | 
			
		||||
          } else {
 | 
			
		||||
            Toast({
 | 
			
		||||
              context: this,
 | 
			
		||||
              selector: '#t-toast',
 | 
			
		||||
              message: '地点为空,请重新选择',
 | 
			
		||||
              icon: '',
 | 
			
		||||
              duration: 1000,
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        fail: function (res) {
 | 
			
		||||
          console.warn(`wx.chooseLocation fail: ${JSON.stringify(res)}`);
 | 
			
		||||
          if (res.errMsg !== 'chooseLocation:fail cancel') {
 | 
			
		||||
            Toast({
 | 
			
		||||
              context: this,
 | 
			
		||||
              selector: '#t-toast',
 | 
			
		||||
              message: '地点错误,请重新选择',
 | 
			
		||||
              icon: '',
 | 
			
		||||
              duration: 1000,
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  formSubmit() {
 | 
			
		||||
    const { submitActive } = this.data;
 | 
			
		||||
    if (!submitActive) {
 | 
			
		||||
      Toast({
 | 
			
		||||
        context: this,
 | 
			
		||||
        selector: '#t-toast',
 | 
			
		||||
        message: this.privateData.verifyTips,
 | 
			
		||||
        icon: '',
 | 
			
		||||
        duration: 1000,
 | 
			
		||||
      });
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    const { locationState } = this.data;
 | 
			
		||||
 | 
			
		||||
    this.hasSava = true;
 | 
			
		||||
 | 
			
		||||
    resolveAddress({
 | 
			
		||||
      saasId: '88888888',
 | 
			
		||||
      uid: `88888888205500`,
 | 
			
		||||
      authToken: null,
 | 
			
		||||
      id: locationState.addressId,
 | 
			
		||||
      addressId: locationState.addressId,
 | 
			
		||||
      phone: locationState.phone,
 | 
			
		||||
      name: locationState.name,
 | 
			
		||||
      countryName: locationState.countryName,
 | 
			
		||||
      countryCode: locationState.countryCode,
 | 
			
		||||
      provinceName: locationState.provinceName,
 | 
			
		||||
      provinceCode: locationState.provinceCode,
 | 
			
		||||
      cityName: locationState.cityName,
 | 
			
		||||
      cityCode: locationState.cityCode,
 | 
			
		||||
      districtName: locationState.districtName,
 | 
			
		||||
      districtCode: locationState.districtCode,
 | 
			
		||||
      detailAddress: locationState.detailAddress,
 | 
			
		||||
      isDefault: locationState.isDefault === 1 ? 1 : 0,
 | 
			
		||||
      addressTag: locationState.addressTag,
 | 
			
		||||
      latitude: locationState.latitude,
 | 
			
		||||
      longitude: locationState.longitude,
 | 
			
		||||
      storeId: null,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    wx.navigateBack({ delta: 1 });
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  getWeixinAddress(e) {
 | 
			
		||||
    const { locationState } = this.data;
 | 
			
		||||
    const weixinAddress = e.detail;
 | 
			
		||||
    this.setData(
 | 
			
		||||
      {
 | 
			
		||||
        locationState: { ...locationState, ...weixinAddress },
 | 
			
		||||
      },
 | 
			
		||||
      () => {
 | 
			
		||||
        const { isLegal, tips } = this.onVerifyInputLegal();
 | 
			
		||||
        this.setData({
 | 
			
		||||
          submitActive: isLegal,
 | 
			
		||||
        });
 | 
			
		||||
        this.privateData.verifyTips = tips;
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										16
									
								
								mini-program/pages/usercenter/address/edit/index.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								mini-program/pages/usercenter/address/edit/index.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
{
 | 
			
		||||
  "navigationBarTitleText": "添加新地址",
 | 
			
		||||
  "usingComponents": {
 | 
			
		||||
    "t-textarea": "tdesign-miniprogram/textarea/textarea",
 | 
			
		||||
    "t-icon": "tdesign-miniprogram/icon/icon",
 | 
			
		||||
    "t-input": "tdesign-miniprogram/input/input",
 | 
			
		||||
    "t-button": "tdesign-miniprogram/button/button",
 | 
			
		||||
    "t-cell-group": "tdesign-miniprogram/cell-group/cell-group",
 | 
			
		||||
    "t-cell": "tdesign-miniprogram/cell/cell",
 | 
			
		||||
    "t-toast": "tdesign-miniprogram/toast/toast",
 | 
			
		||||
    "t-dialog": "tdesign-miniprogram/dialog/dialog",
 | 
			
		||||
    "t-switch": "tdesign-miniprogram/switch/switch",
 | 
			
		||||
    "t-location": "/pages/usercenter/components/t-location/index",
 | 
			
		||||
    "t-cascader": "tdesign-miniprogram/cascader/cascader"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										134
									
								
								mini-program/pages/usercenter/address/edit/index.wxml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								mini-program/pages/usercenter/address/edit/index.wxml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,134 @@
 | 
			
		||||
<view class="address-detail">
 | 
			
		||||
  <view class="divider-line" />
 | 
			
		||||
  <t-location
 | 
			
		||||
    title="获取微信收获地址"
 | 
			
		||||
    isCustomStyle
 | 
			
		||||
    t-class="address-detail-wx-location"
 | 
			
		||||
    bind:change="getWeixinAddress"
 | 
			
		||||
  >
 | 
			
		||||
    <t-icon class="address-detail-wx-arrow" name="arrow_forward" prefix="wr" color="#bbb" size="32rpx" />
 | 
			
		||||
  </t-location>
 | 
			
		||||
  <view class="divider-line" />
 | 
			
		||||
  <view class="form-address">
 | 
			
		||||
    <form class="form-content">
 | 
			
		||||
      <t-cell-group>
 | 
			
		||||
        <t-cell class="form-cell" t-class-title="t-cell-title" title="收货人" t-class-note="t-cell-note">
 | 
			
		||||
          <t-input
 | 
			
		||||
            class="t-input"
 | 
			
		||||
            slot="note"
 | 
			
		||||
            t-class="field-text"
 | 
			
		||||
            borderless
 | 
			
		||||
            data-item="name"
 | 
			
		||||
            maxlength="20"
 | 
			
		||||
            type="text"
 | 
			
		||||
            value="{{locationState.name}}"
 | 
			
		||||
            placeholder="您的姓名"
 | 
			
		||||
            bind:change="onInputValue"
 | 
			
		||||
          />
 | 
			
		||||
        </t-cell>
 | 
			
		||||
        <t-cell class="form-cell" t-class-title="t-cell-title" title="手机号">
 | 
			
		||||
          <t-input
 | 
			
		||||
            slot="note"
 | 
			
		||||
            class="t-input"
 | 
			
		||||
            t-class="field-text"
 | 
			
		||||
            borderless
 | 
			
		||||
            type="number"
 | 
			
		||||
            value="{{locationState.phone}}"
 | 
			
		||||
            maxlength="11"
 | 
			
		||||
            placeholder="联系您的手机号"
 | 
			
		||||
            bind:change="onInputValue"
 | 
			
		||||
            data-item="phone"
 | 
			
		||||
          />
 | 
			
		||||
        </t-cell>
 | 
			
		||||
        <t-cell class="form-cell" t-class-title="t-cell-title" title="地区">
 | 
			
		||||
          <t-input
 | 
			
		||||
            slot="note"
 | 
			
		||||
            class="t-input"
 | 
			
		||||
            t-class="field-text"
 | 
			
		||||
            borderless
 | 
			
		||||
            placeholder="省/市/区"
 | 
			
		||||
            data-item="address"
 | 
			
		||||
            value="{{locationState.provinceName ? locationState.provinceName+'/':'' }}{{locationState.cityName ? locationState.cityName+'/':''}}{{locationState.districtName}}"
 | 
			
		||||
            catch:tap="onPickArea"
 | 
			
		||||
            disabled
 | 
			
		||||
          />
 | 
			
		||||
          <t-icon slot="right-icon" t-class="map" prefix="wr" name="location" catch:tap="onSearchAddress" />
 | 
			
		||||
        </t-cell>
 | 
			
		||||
        <t-cell class="form-cell" t-class-title="t-cell-title" title="详细地址" bordered="{{false}}">
 | 
			
		||||
          <view slot="note" class="textarea__wrapper">
 | 
			
		||||
            <t-textarea
 | 
			
		||||
              slot="note"
 | 
			
		||||
              type="text"
 | 
			
		||||
              value="{{locationState.detailAddress}}"
 | 
			
		||||
              placeholder="门牌号等(例如:10栋1001号)"
 | 
			
		||||
              autosize
 | 
			
		||||
              bind:change="onInputValue"
 | 
			
		||||
              data-item="detailAddress"
 | 
			
		||||
            />
 | 
			
		||||
          </view>
 | 
			
		||||
        </t-cell>
 | 
			
		||||
 | 
			
		||||
        <view class="divider-line" />
 | 
			
		||||
        <t-cell
 | 
			
		||||
          class="form-cell"
 | 
			
		||||
          t-class-note="t-cell-note address__tag"
 | 
			
		||||
          t-class-title="t-cell-title"
 | 
			
		||||
          title="标签"
 | 
			
		||||
          bordered="{{false}}"
 | 
			
		||||
        >
 | 
			
		||||
          <view class="t-input address-flex-box" slot="note">
 | 
			
		||||
            <t-button
 | 
			
		||||
              wx:for="{{labels}}"
 | 
			
		||||
              wx:for-item="label"
 | 
			
		||||
              wx:key="index"
 | 
			
		||||
              size="extra-small"
 | 
			
		||||
              t-class="label-list {{locationState.labelIndex === index ? 'active-btn':''}}"
 | 
			
		||||
              bindtap="onPickLabels"
 | 
			
		||||
              data-item="{{index}}"
 | 
			
		||||
            >
 | 
			
		||||
              {{label.name}}
 | 
			
		||||
            </t-button>
 | 
			
		||||
            <t-button size="extra-small" t-class="label-list" bindtap="addLabels">
 | 
			
		||||
              <t-icon name="add" size="40rpx" color="#bbb" />
 | 
			
		||||
            </t-button>
 | 
			
		||||
          </view>
 | 
			
		||||
        </t-cell>
 | 
			
		||||
        <view class="divider-line" />
 | 
			
		||||
        <t-cell title="设置为默认收货地址" bordered="{{false}}">
 | 
			
		||||
          <t-switch
 | 
			
		||||
            value="{{locationState.isDefault}}"
 | 
			
		||||
            slot="note"
 | 
			
		||||
            colors="{{['#0ABF5B', '#c6c6c6']}}"
 | 
			
		||||
            bind:change="onCheckDefaultAddress"
 | 
			
		||||
          />
 | 
			
		||||
        </t-cell>
 | 
			
		||||
      </t-cell-group>
 | 
			
		||||
      <view class="submit">
 | 
			
		||||
        <t-button shape="round" block disabled="{{!submitActive}}" bind:tap="formSubmit"> 保存 </t-button>
 | 
			
		||||
      </view>
 | 
			
		||||
    </form>
 | 
			
		||||
  </view>
 | 
			
		||||
  <t-cascader
 | 
			
		||||
    data-item="address"
 | 
			
		||||
    data-type="1"
 | 
			
		||||
    visible="{{areaPickerVisible}}"
 | 
			
		||||
    theme="tab"
 | 
			
		||||
    options="{{areaData}}"
 | 
			
		||||
    value="{{locationState.districtCode}}"
 | 
			
		||||
    title="选择地区"
 | 
			
		||||
    bind:change="onInputValue"
 | 
			
		||||
  ></t-cascader>
 | 
			
		||||
</view>
 | 
			
		||||
<t-dialog
 | 
			
		||||
  visible="{{visible}}"
 | 
			
		||||
  t-class-confirm="dialog__button-confirm"
 | 
			
		||||
  t-class-cancel="dialog__button-cancel"
 | 
			
		||||
  title="填写标签名称"
 | 
			
		||||
  confirm-btn="确定"
 | 
			
		||||
  cancel-btn="取消"
 | 
			
		||||
  bind:confirm="confirmHandle"
 | 
			
		||||
  bind:cancel="cancelHandle"
 | 
			
		||||
>
 | 
			
		||||
  <t-input slot="content" class="dialog__input" model:value="{{labelValue}}" placeholder="请输入标签名称" borderless />
 | 
			
		||||
</t-dialog>
 | 
			
		||||
<t-toast id="t-toast" />
 | 
			
		||||
							
								
								
									
										95
									
								
								mini-program/pages/usercenter/address/edit/index.wxss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								mini-program/pages/usercenter/address/edit/index.wxss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
			
		||||
page {
 | 
			
		||||
  background-color: #f5f5f5;
 | 
			
		||||
}
 | 
			
		||||
page .divider-line {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 20rpx;
 | 
			
		||||
  background-color: #f5f5f5;
 | 
			
		||||
}
 | 
			
		||||
.address-flex-box {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-wrap: wrap;
 | 
			
		||||
}
 | 
			
		||||
.address-detail {
 | 
			
		||||
  font-size: 30rpx;
 | 
			
		||||
}
 | 
			
		||||
.address-detail-wx-location {
 | 
			
		||||
  background: #fff;
 | 
			
		||||
  padding: 24rpx 32rpx;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
}
 | 
			
		||||
.address-detail-wx-arrow {
 | 
			
		||||
  align-items: flex-end;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-cell .t-cell__title {
 | 
			
		||||
  width: 144rpx;
 | 
			
		||||
  padding-right: 32rpx;
 | 
			
		||||
  flex: none !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.textarea__wrapper {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.textarea__wrapper .t-textarea {
 | 
			
		||||
  padding: 0 !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-address .map {
 | 
			
		||||
  font-size: 48rpx !important;
 | 
			
		||||
  margin-left: 20rpx;
 | 
			
		||||
  color: #9d9d9f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.address__tag {
 | 
			
		||||
  justify-content: flex-start !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-address .label-list {
 | 
			
		||||
  background: #f5f5f5;
 | 
			
		||||
  color: #333;
 | 
			
		||||
  min-width: 100rpx;
 | 
			
		||||
  margin-right: 32rpx;
 | 
			
		||||
  font-size: 26rpx;
 | 
			
		||||
  border: 2rpx solid transparent;
 | 
			
		||||
  width: auto;
 | 
			
		||||
}
 | 
			
		||||
.form-address .label-list::after {
 | 
			
		||||
  content: none;
 | 
			
		||||
}
 | 
			
		||||
.form-address .active-btn {
 | 
			
		||||
  color: #fa4126;
 | 
			
		||||
  border: 2rpx solid #fa4126;
 | 
			
		||||
  background: rgba(255, 95, 21, 0.04);
 | 
			
		||||
}
 | 
			
		||||
.form-address .active-btn::after {
 | 
			
		||||
  border: 4rpx solid #ff5f15;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.submit {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  padding: 64rpx 30rpx 88rpx 30rpx;
 | 
			
		||||
}
 | 
			
		||||
.submit .btn-submit-address {
 | 
			
		||||
  background: #fa4126 !important;
 | 
			
		||||
  color: #fff !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dialog__button-confirm {
 | 
			
		||||
  color: #fa4126 !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-address .form-content {
 | 
			
		||||
  --td-input-vertical-padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dialog__input {
 | 
			
		||||
  margin-top: 32rpx;
 | 
			
		||||
  border-radius: 8rpx;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  --td-input-vertical-padding: 12px;
 | 
			
		||||
  --td-input-bg-color: #f3f3f3;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								mini-program/pages/usercenter/address/edit/util.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								mini-program/pages/usercenter/address/edit/util.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
let addressPromise = [];
 | 
			
		||||
 | 
			
		||||
/** 地址编辑Promise */
 | 
			
		||||
export const getAddressPromise = () => {
 | 
			
		||||
  let resolver;
 | 
			
		||||
  let rejecter;
 | 
			
		||||
  const nextPromise = new Promise((resolve, reject) => {
 | 
			
		||||
    resolver = resolve;
 | 
			
		||||
    rejecter = reject;
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  addressPromise.push({ resolver, rejecter });
 | 
			
		||||
 | 
			
		||||
  return nextPromise;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** 用户保存了一个地址 */
 | 
			
		||||
export const resolveAddress = (address) => {
 | 
			
		||||
  const allAddress = [...addressPromise];
 | 
			
		||||
  addressPromise = [];
 | 
			
		||||
 | 
			
		||||
  console.info('用户保存了一个地址', address);
 | 
			
		||||
 | 
			
		||||
  allAddress.forEach(({ resolver }) => resolver(address));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** 取消编辑 */
 | 
			
		||||
export const rejectAddress = () => {
 | 
			
		||||
  const allAddress = [...addressPromise];
 | 
			
		||||
  addressPromise = [];
 | 
			
		||||
 | 
			
		||||
  allAddress.forEach(({ rejecter }) => rejecter(new Error('cancel')));
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										191
									
								
								mini-program/pages/usercenter/address/list/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								mini-program/pages/usercenter/address/list/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
			
		||||
/* eslint-disable no-param-reassign */
 | 
			
		||||
import { fetchDeliveryAddressList } from '../../../../services/address/fetchAddress';
 | 
			
		||||
import Toast from 'tdesign-miniprogram/toast/index';
 | 
			
		||||
import { resolveAddress, rejectAddress } from './util';
 | 
			
		||||
import { getAddressPromise } from '../edit/util';
 | 
			
		||||
 | 
			
		||||
Page({
 | 
			
		||||
  data: {
 | 
			
		||||
    addressList: [],
 | 
			
		||||
    deleteID: '',
 | 
			
		||||
    showDeleteConfirm: false,
 | 
			
		||||
    isOrderSure: false,
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  /** 选择模式 */
 | 
			
		||||
  selectMode: false,
 | 
			
		||||
  /** 是否已经选择地址,不置为true的话页面离开时会触发取消选择行为 */
 | 
			
		||||
  hasSelect: false,
 | 
			
		||||
 | 
			
		||||
  onLoad(query) {
 | 
			
		||||
    const { selectMode = '', isOrderSure = '', id = '' } = query;
 | 
			
		||||
    this.setData({
 | 
			
		||||
      isOrderSure: !!isOrderSure,
 | 
			
		||||
      id,
 | 
			
		||||
    });
 | 
			
		||||
    this.selectMode = !!selectMode;
 | 
			
		||||
    this.init();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  init() {
 | 
			
		||||
    this.getAddressList();
 | 
			
		||||
  },
 | 
			
		||||
  onUnload() {
 | 
			
		||||
    if (this.selectMode && !this.hasSelect) {
 | 
			
		||||
      rejectAddress();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  getAddressList() {
 | 
			
		||||
    const { id } = this.data;
 | 
			
		||||
    fetchDeliveryAddressList().then((addressList) => {
 | 
			
		||||
      addressList.forEach((address) => {
 | 
			
		||||
        if (address.id === id) {
 | 
			
		||||
          address.checked = true;
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      this.setData({ addressList });
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  getWXAddressHandle() {
 | 
			
		||||
    wx.chooseAddress({
 | 
			
		||||
      success: (res) => {
 | 
			
		||||
        if (res.errMsg.indexOf('ok') === -1) {
 | 
			
		||||
          Toast({
 | 
			
		||||
            context: this,
 | 
			
		||||
            selector: '#t-toast',
 | 
			
		||||
            message: res.errMsg,
 | 
			
		||||
            icon: '',
 | 
			
		||||
            duration: 1000,
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        Toast({
 | 
			
		||||
          context: this,
 | 
			
		||||
          selector: '#t-toast',
 | 
			
		||||
          message: '添加成功',
 | 
			
		||||
          icon: '',
 | 
			
		||||
          duration: 1000,
 | 
			
		||||
        });
 | 
			
		||||
        const { length: len } = this.data.addressList;
 | 
			
		||||
        this.setData({
 | 
			
		||||
          [`addressList[${len}]`]: {
 | 
			
		||||
            name: res.userName,
 | 
			
		||||
            phoneNumber: res.telNumber,
 | 
			
		||||
            address: `${res.provinceName}${res.cityName}${res.countryName}${res.detailInfo}`,
 | 
			
		||||
            isDefault: 0,
 | 
			
		||||
            tag: '微信地址',
 | 
			
		||||
            id: len,
 | 
			
		||||
          },
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  confirmDeleteHandle({ detail }) {
 | 
			
		||||
    const { id } = detail || {};
 | 
			
		||||
    if (id !== undefined) {
 | 
			
		||||
      this.setData({ deleteID: id, showDeleteConfirm: true });
 | 
			
		||||
      Toast({
 | 
			
		||||
        context: this,
 | 
			
		||||
        selector: '#t-toast',
 | 
			
		||||
        message: '地址删除成功',
 | 
			
		||||
        theme: 'success',
 | 
			
		||||
        duration: 1000,
 | 
			
		||||
      });
 | 
			
		||||
    } else {
 | 
			
		||||
      Toast({
 | 
			
		||||
        context: this,
 | 
			
		||||
        selector: '#t-toast',
 | 
			
		||||
        message: '需要组件库发新版才能拿到地址ID',
 | 
			
		||||
        icon: '',
 | 
			
		||||
        duration: 1000,
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  deleteAddressHandle(e) {
 | 
			
		||||
    const { id } = e.currentTarget.dataset;
 | 
			
		||||
    this.setData({
 | 
			
		||||
      addressList: this.data.addressList.filter((address) => address.id !== id),
 | 
			
		||||
      deleteID: '',
 | 
			
		||||
      showDeleteConfirm: false,
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  editAddressHandle({ detail }) {
 | 
			
		||||
    this.waitForNewAddress();
 | 
			
		||||
 | 
			
		||||
    const { id } = detail || {};
 | 
			
		||||
    wx.navigateTo({ url: `/pages/usercenter/address/edit/index?id=${id}` });
 | 
			
		||||
  },
 | 
			
		||||
  selectHandle({ detail }) {
 | 
			
		||||
    if (this.selectMode) {
 | 
			
		||||
      this.hasSelect = true;
 | 
			
		||||
      resolveAddress(detail);
 | 
			
		||||
      wx.navigateBack({ delta: 1 });
 | 
			
		||||
    } else {
 | 
			
		||||
      this.editAddressHandle({ detail });
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  createHandle() {
 | 
			
		||||
    this.waitForNewAddress();
 | 
			
		||||
    wx.navigateTo({ url: '/pages/usercenter/address/edit/index' });
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  waitForNewAddress() {
 | 
			
		||||
    getAddressPromise()
 | 
			
		||||
      .then((newAddress) => {
 | 
			
		||||
        let addressList = [...this.data.addressList];
 | 
			
		||||
 | 
			
		||||
        newAddress.phoneNumber = newAddress.phone;
 | 
			
		||||
        newAddress.address = `${newAddress.provinceName}${newAddress.cityName}${newAddress.districtName}${newAddress.detailAddress}`;
 | 
			
		||||
        newAddress.tag = newAddress.addressTag;
 | 
			
		||||
 | 
			
		||||
        if (!newAddress.addressId) {
 | 
			
		||||
          newAddress.id = `${addressList.length}`;
 | 
			
		||||
          newAddress.addressId = `${addressList.length}`;
 | 
			
		||||
 | 
			
		||||
          if (newAddress.isDefault === 1) {
 | 
			
		||||
            addressList = addressList.map((address) => {
 | 
			
		||||
              address.isDefault = 0;
 | 
			
		||||
 | 
			
		||||
              return address;
 | 
			
		||||
            });
 | 
			
		||||
          } else {
 | 
			
		||||
            newAddress.isDefault = 0;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          addressList.push(newAddress);
 | 
			
		||||
        } else {
 | 
			
		||||
          addressList = addressList.map((address) => {
 | 
			
		||||
            if (address.addressId === newAddress.addressId) {
 | 
			
		||||
              return newAddress;
 | 
			
		||||
            }
 | 
			
		||||
            return address;
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        addressList.sort((prevAddress, nextAddress) => {
 | 
			
		||||
          if (prevAddress.isDefault && !nextAddress.isDefault) {
 | 
			
		||||
            return -1;
 | 
			
		||||
          }
 | 
			
		||||
          if (!prevAddress.isDefault && nextAddress.isDefault) {
 | 
			
		||||
            return 1;
 | 
			
		||||
          }
 | 
			
		||||
          return 0;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.setData({
 | 
			
		||||
          addressList: addressList,
 | 
			
		||||
        });
 | 
			
		||||
      })
 | 
			
		||||
      .catch((e) => {
 | 
			
		||||
        if (e.message !== 'cancel') {
 | 
			
		||||
          Toast({
 | 
			
		||||
            context: this,
 | 
			
		||||
            selector: '#t-toast',
 | 
			
		||||
            message: '地址编辑发生错误',
 | 
			
		||||
            icon: '',
 | 
			
		||||
            duration: 1000,
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										11
									
								
								mini-program/pages/usercenter/address/list/index.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								mini-program/pages/usercenter/address/list/index.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "navigationBarTitleText": "收货地址",
 | 
			
		||||
  "usingComponents": {
 | 
			
		||||
    "t-icon": "tdesign-miniprogram/icon/icon",
 | 
			
		||||
    "t-image": "/components/webp-image/index",
 | 
			
		||||
    "t-toast": "tdesign-miniprogram/toast/toast",
 | 
			
		||||
    "t-address-item": "../../components/ui-address-item/index",
 | 
			
		||||
    "t-location": "../../components/t-location/index",
 | 
			
		||||
    "t-empty": "tdesign-miniprogram/empty/empty"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								mini-program/pages/usercenter/address/list/index.wxml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								mini-program/pages/usercenter/address/list/index.wxml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
<view class="address-container">
 | 
			
		||||
	<view class="address-list" wx:if="{{addressList.length > 0}}">
 | 
			
		||||
		<block
 | 
			
		||||
		  wx:for="{{addressList}}"
 | 
			
		||||
		  wx:for-index="index"
 | 
			
		||||
		  wx:for-item="address"
 | 
			
		||||
		  wx:key="addressId"
 | 
			
		||||
		>
 | 
			
		||||
			<t-address-item
 | 
			
		||||
			  isDrawLine="{{index+1 !== addressList.length}}"
 | 
			
		||||
			  extra-space="{{extraSpace}}"
 | 
			
		||||
			  class-prefix="ym"
 | 
			
		||||
			  address="{{address}}"
 | 
			
		||||
			  data-id="{{address.id}}"
 | 
			
		||||
			  bind:onSelect="selectHandle"
 | 
			
		||||
			  bind:onDelete="deleteAddressHandle"
 | 
			
		||||
			  bind:onEdit="editAddressHandle"
 | 
			
		||||
			/>
 | 
			
		||||
		</block>
 | 
			
		||||
	</view>
 | 
			
		||||
	<view wx:else class="no-address">
 | 
			
		||||
		<t-empty icon="" description="暂无收货地址,赶快添加吧" />
 | 
			
		||||
	</view>
 | 
			
		||||
	<view class="bottom-fixed">
 | 
			
		||||
		<view class="btn-wrap">
 | 
			
		||||
			<t-location
 | 
			
		||||
			  title="微信地址导入"
 | 
			
		||||
			  isOrderSure="{{isOrderSure}}"
 | 
			
		||||
			  isDisabledBtn="{{addressList.length >= 20}}"
 | 
			
		||||
			  navigateUrl="/pages/usercenter/address/edit/index"
 | 
			
		||||
				navigateEvent="onWeixinAddressPassed"	
 | 
			
		||||
			  t-class="location-btn"
 | 
			
		||||
			  isCustomStyle="{{true}}"
 | 
			
		||||
				bind:navigate="waitForNewAddress"
 | 
			
		||||
			/>
 | 
			
		||||
			<view class="address-btn {{addressList.length >= 20 ? 'btn-default':''}}" bind:tap="createHandle">
 | 
			
		||||
				<t-icon
 | 
			
		||||
				  name="add"
 | 
			
		||||
				  size="48rpx"
 | 
			
		||||
				  color="#fff"
 | 
			
		||||
				  t-class="custom-class"
 | 
			
		||||
				/>
 | 
			
		||||
				<text>新建收货地址</text>
 | 
			
		||||
			</view>
 | 
			
		||||
		</view>
 | 
			
		||||
		<view class="footer" wx:if="{{addressList.length >= 20}}">最多支持添加20个收货地址</view>
 | 
			
		||||
	</view>
 | 
			
		||||
</view>
 | 
			
		||||
<t-toast id="t-toast" />
 | 
			
		||||
							
								
								
									
										109
									
								
								mini-program/pages/usercenter/address/list/index.wxss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								mini-program/pages/usercenter/address/list/index.wxss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
			
		||||
page {
 | 
			
		||||
  background: #f5f5f5;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
.address-container {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  align-items: stretch;
 | 
			
		||||
  padding-bottom: calc(env(safe-area-inset-bottom) + 172rpx);
 | 
			
		||||
}
 | 
			
		||||
.address-container .address-list {
 | 
			
		||||
  font-size: 24rpx;
 | 
			
		||||
  background-color: #ffffff;
 | 
			
		||||
  -webkit-overflow-scrolling: touch;
 | 
			
		||||
}
 | 
			
		||||
.address-list .no-address {
 | 
			
		||||
  width: 750rpx;
 | 
			
		||||
  padding-top: 30vh;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  justify-content: flex-start;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
}
 | 
			
		||||
.address-list .no-address__icon {
 | 
			
		||||
  width: 224rpx;
 | 
			
		||||
  height: 224rpx;
 | 
			
		||||
}
 | 
			
		||||
.address-list .no-address__text {
 | 
			
		||||
  font-size: 28rpx;
 | 
			
		||||
  line-height: 40rpx;
 | 
			
		||||
  color: #999999;
 | 
			
		||||
  margin-top: 24rpx;
 | 
			
		||||
}
 | 
			
		||||
.address-container .bottom-fixed {
 | 
			
		||||
  border-top: 1rpx solid #e5e5e5;
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  bottom: 0;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  right: 0;
 | 
			
		||||
  z-index: 1000;
 | 
			
		||||
  background: #fff;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  padding: 12rpx 32rpx calc(env(safe-area-inset-bottom) + 12rpx) 32rpx;
 | 
			
		||||
}
 | 
			
		||||
.address-container .btn-wrap {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  font-size: 32rpx;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
.address-container .btn-wrap .location-btn {
 | 
			
		||||
  width: 332rpx;
 | 
			
		||||
  height: 88rpx;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  background-color: #ffffff;
 | 
			
		||||
  color: #333;
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
.address-container .btn-wrap .location-btn::after {
 | 
			
		||||
  content: '';
 | 
			
		||||
  position: absolute; /* 把父视图设置为relative,方便定位*/
 | 
			
		||||
  top: 0;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  width: 200%;
 | 
			
		||||
  height: 200%;
 | 
			
		||||
  transform: scale(0.5);
 | 
			
		||||
  transform-origin: 0 0;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  border-radius: 88rpx;
 | 
			
		||||
  border: #dddddd 2rpx solid;
 | 
			
		||||
}
 | 
			
		||||
.address-container .btn-wrap .address-btn {
 | 
			
		||||
  width: 332rpx;
 | 
			
		||||
  height: 88rpx;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  background-color: #fa4126;
 | 
			
		||||
  border-radius: 44rpx;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
}
 | 
			
		||||
.address-container .btn-wrap .btn-default {
 | 
			
		||||
  background: #c6c6c6;
 | 
			
		||||
}
 | 
			
		||||
.address-container .bottom-fixed .footer {
 | 
			
		||||
  margin-top: 10rpx;
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  font-size: 24rpx;
 | 
			
		||||
  font-weight: 400;
 | 
			
		||||
  color: #ff2525;
 | 
			
		||||
  line-height: 60rpx;
 | 
			
		||||
  height: 60rpx;
 | 
			
		||||
}
 | 
			
		||||
.address-container .message {
 | 
			
		||||
  margin-top: 48rpx;
 | 
			
		||||
}
 | 
			
		||||
.address-container .custom-class {
 | 
			
		||||
  margin-right: 12rpx;
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								mini-program/pages/usercenter/address/list/util.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								mini-program/pages/usercenter/address/list/util.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
let addressPromise = [];
 | 
			
		||||
 | 
			
		||||
/** 获取一个地址选择Promise */
 | 
			
		||||
export const getAddressPromise = () => {
 | 
			
		||||
  let resolver;
 | 
			
		||||
  let rejecter;
 | 
			
		||||
  const nextPromise = new Promise((resolve, reject) => {
 | 
			
		||||
    resolver = resolve;
 | 
			
		||||
    rejecter = reject;
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  addressPromise.push({ resolver, rejecter });
 | 
			
		||||
 | 
			
		||||
  return nextPromise;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** 用户选择了一个地址 */
 | 
			
		||||
export const resolveAddress = (address) => {
 | 
			
		||||
  const allAddress = [...addressPromise];
 | 
			
		||||
  addressPromise = [];
 | 
			
		||||
 | 
			
		||||
  allAddress.forEach(({ resolver }) => resolver(address));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** 用户没有选择任何地址只是返回上一页了 */
 | 
			
		||||
export const rejectAddress = () => {
 | 
			
		||||
  const allAddress = [...addressPromise];
 | 
			
		||||
  addressPromise = [];
 | 
			
		||||
 | 
			
		||||
  allAddress.forEach(({ rejecter }) => rejecter(new Error('cancel')));
 | 
			
		||||
};
 | 
			
		||||
@@ -0,0 +1,37 @@
 | 
			
		||||
Component({
 | 
			
		||||
  externalClasses: ['title-class', 'icon-class', 'number-class'],
 | 
			
		||||
  options: {
 | 
			
		||||
    multipleSlots: true,
 | 
			
		||||
  },
 | 
			
		||||
  properties: {
 | 
			
		||||
    orderTagInfos: {
 | 
			
		||||
      type: Array,
 | 
			
		||||
      value: [],
 | 
			
		||||
    },
 | 
			
		||||
    title: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      value: '我的订单',
 | 
			
		||||
    },
 | 
			
		||||
    desc: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      value: '全部订单',
 | 
			
		||||
    },
 | 
			
		||||
    isTop: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      value: true,
 | 
			
		||||
    },
 | 
			
		||||
    classPrefix: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      value: 'wr',
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    onClickItem(e) {
 | 
			
		||||
      this.triggerEvent('onClickItem', e.currentTarget.dataset.item);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onClickTop() {
 | 
			
		||||
      this.triggerEvent('onClickTop', {});
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "component": true,
 | 
			
		||||
  "usingComponents": {
 | 
			
		||||
    "t-cell": "tdesign-miniprogram/cell/cell",
 | 
			
		||||
    "t-cell-group": "tdesign-miniprogram/cell-group/cell-group",
 | 
			
		||||
    "t-badge": "tdesign-miniprogram/badge/badge",
 | 
			
		||||
    "t-icon": "tdesign-miniprogram/icon/icon"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,37 @@
 | 
			
		||||
<view class="order-group">
 | 
			
		||||
  <t-cell-group wx:if="{{isTop}}">
 | 
			
		||||
    <t-cell
 | 
			
		||||
      t-class="order-group__top"
 | 
			
		||||
      t-class-left="order-group__left"
 | 
			
		||||
      t-class-title="order-group__top__title"
 | 
			
		||||
      t-class-note="order-group__top__note"
 | 
			
		||||
      title="{{title}}"
 | 
			
		||||
      note="{{desc}}"
 | 
			
		||||
      bordered="{{false}}"
 | 
			
		||||
      arrow
 | 
			
		||||
      bind:tap="onClickTop"
 | 
			
		||||
    />
 | 
			
		||||
  </t-cell-group>
 | 
			
		||||
  <view class="order-group__content">
 | 
			
		||||
    <view
 | 
			
		||||
      class="order-group__item"
 | 
			
		||||
      wx:for="{{orderTagInfos}}"
 | 
			
		||||
      wx:for-item="item"
 | 
			
		||||
      wx:key="index"
 | 
			
		||||
      data-item="{{item}}"
 | 
			
		||||
      bindtap="onClickItem"
 | 
			
		||||
    >
 | 
			
		||||
      <view class="order-group__item__icon icon-class">
 | 
			
		||||
        <t-badge count="{{item.orderNum}}" max-count="{{99}}" color="#FF4646">
 | 
			
		||||
          <t-icon
 | 
			
		||||
            prefix="{{classPrefix}}"
 | 
			
		||||
            name="{{item.iconName}}"
 | 
			
		||||
            size="56rpx"
 | 
			
		||||
            customStyle="background-image: -webkit-linear-gradient(90deg, #6a6a6a 0%,#929292 100%);-webkit-background-clip: text;-webkit-text-fill-color: transparent;"
 | 
			
		||||
          />
 | 
			
		||||
        </t-badge>
 | 
			
		||||
      </view>
 | 
			
		||||
      <view class="order-group__item__title title-class">{{item.title}}</view>
 | 
			
		||||
    </view>
 | 
			
		||||
  </view>
 | 
			
		||||
</view>
 | 
			
		||||
@@ -0,0 +1,56 @@
 | 
			
		||||
.order-group {
 | 
			
		||||
  margin-bottom: 24rpx;
 | 
			
		||||
  background-color: #ffffff;
 | 
			
		||||
  border-radius: 16rpx 16rpx 0 0;
 | 
			
		||||
}
 | 
			
		||||
.order-group .order-group__top {
 | 
			
		||||
  padding: 24rpx 18rpx 24rpx 32rpx;
 | 
			
		||||
  border-radius: 16rpx 16rpx 0 0;
 | 
			
		||||
}
 | 
			
		||||
.order-group__top___title {
 | 
			
		||||
  font-size: 32rpx;
 | 
			
		||||
  line-height: 48rpx;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
.order-group__top__note {
 | 
			
		||||
  font-size: 28rpx;
 | 
			
		||||
}
 | 
			
		||||
.order-group__content {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 164rpx;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  background-color: #fff;
 | 
			
		||||
  border-radius: 0 0 16rpx 16rpx;
 | 
			
		||||
}
 | 
			
		||||
.order-group__item {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  flex: 1;
 | 
			
		||||
}
 | 
			
		||||
.order-group__item:first-child {
 | 
			
		||||
  border-radius: 0 0 0 16rpx;
 | 
			
		||||
}
 | 
			
		||||
.order-group__item:last-child {
 | 
			
		||||
  border-radius: 0 0 16rpx 0;
 | 
			
		||||
}
 | 
			
		||||
.order-group__item__title {
 | 
			
		||||
  font-size: 24rpx;
 | 
			
		||||
  color: #666;
 | 
			
		||||
  line-height: 32rpx;
 | 
			
		||||
}
 | 
			
		||||
.order-group__item__icon {
 | 
			
		||||
  margin-bottom: 20rpx;
 | 
			
		||||
  width: 56rpx;
 | 
			
		||||
  height: 56rpx;
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
.order-group__top__title {
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
.order-group .order-group__left {
 | 
			
		||||
  margin-right: 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										124
									
								
								mini-program/pages/usercenter/components/t-location/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								mini-program/pages/usercenter/components/t-location/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
			
		||||
import { getPermission } from '../../../../utils/getPermission';
 | 
			
		||||
import { phoneRegCheck } from '../../../../utils/util';
 | 
			
		||||
import Toast from 'tdesign-miniprogram/toast/index';
 | 
			
		||||
import { addressParse } from '../../../../utils/addressParse';
 | 
			
		||||
import { resolveAddress, rejectAddress } from '../../address/list/util';
 | 
			
		||||
 | 
			
		||||
Component({
 | 
			
		||||
  externalClasses: ['t-class'],
 | 
			
		||||
  properties: {
 | 
			
		||||
    title: {
 | 
			
		||||
      type: String,
 | 
			
		||||
    },
 | 
			
		||||
    navigateUrl: {
 | 
			
		||||
      type: String,
 | 
			
		||||
    },
 | 
			
		||||
    navigateEvent: {
 | 
			
		||||
      type: String,
 | 
			
		||||
    },
 | 
			
		||||
    isCustomStyle: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      value: false,
 | 
			
		||||
    },
 | 
			
		||||
    isDisabledBtn: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      value: false,
 | 
			
		||||
    },
 | 
			
		||||
    isOrderSure: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      value: false,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    getWxLocation() {
 | 
			
		||||
      if (this.properties.isDisabledBtn) return;
 | 
			
		||||
      getPermission({ code: 'scope.address', name: '通讯地址' }).then(() => {
 | 
			
		||||
        wx.chooseAddress({
 | 
			
		||||
          success: async (options) => {
 | 
			
		||||
            const { provinceName, cityName, countyName, detailInfo, userName, telNumber } = options;
 | 
			
		||||
 | 
			
		||||
            if (!phoneRegCheck(telNumber)) {
 | 
			
		||||
              Toast({
 | 
			
		||||
                context: this,
 | 
			
		||||
                selector: '#t-toast',
 | 
			
		||||
                message: '请填写正确的手机号',
 | 
			
		||||
              });
 | 
			
		||||
              return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const target = {
 | 
			
		||||
              name: userName,
 | 
			
		||||
              phone: telNumber,
 | 
			
		||||
              countryName: '中国',
 | 
			
		||||
              countryCode: 'chn',
 | 
			
		||||
              detailAddress: detailInfo,
 | 
			
		||||
              provinceName: provinceName,
 | 
			
		||||
              cityName: cityName,
 | 
			
		||||
              districtName: countyName,
 | 
			
		||||
              isDefault: false,
 | 
			
		||||
              isOrderSure: this.properties.isOrderSure,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
              const { provinceCode, cityCode, districtCode } = await addressParse(provinceName, cityName, countyName);
 | 
			
		||||
 | 
			
		||||
              const params = Object.assign(target, {
 | 
			
		||||
                provinceCode,
 | 
			
		||||
                cityCode,
 | 
			
		||||
                districtCode,
 | 
			
		||||
              });
 | 
			
		||||
              if (this.properties.isOrderSure) {
 | 
			
		||||
                this.onHandleSubmit(params);
 | 
			
		||||
              } else if (this.properties.navigateUrl != '') {
 | 
			
		||||
                const { navigateEvent } = this.properties;
 | 
			
		||||
                this.triggerEvent('navigate');
 | 
			
		||||
                wx.navigateTo({
 | 
			
		||||
                  url: this.properties.navigateUrl,
 | 
			
		||||
                  success: function (res) {
 | 
			
		||||
                    res.eventChannel.emit(navigateEvent, params);
 | 
			
		||||
                  },
 | 
			
		||||
                });
 | 
			
		||||
              } else {
 | 
			
		||||
                this.triggerEvent('change', params);
 | 
			
		||||
              }
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
              wx.showToast({ title: '地址解析出错,请稍后再试', icon: 'none' });
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          fail(err) {
 | 
			
		||||
            console.warn('未选择微信收货地址', err);
 | 
			
		||||
          },
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    async queryAddress(addressId) {
 | 
			
		||||
      try {
 | 
			
		||||
        const { data } = await apis.userInfo.queryAddress({ addressId });
 | 
			
		||||
        return data.userAddressVO;
 | 
			
		||||
      } catch (err) {
 | 
			
		||||
        console.error('查询地址错误', err);
 | 
			
		||||
        throw err;
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    findPage(pageRouteUrl) {
 | 
			
		||||
      const currentRoutes = getCurrentPages().map((v) => v.route);
 | 
			
		||||
      return currentRoutes.indexOf(pageRouteUrl);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    async onHandleSubmit(params) {
 | 
			
		||||
      try {
 | 
			
		||||
        const orderPageDeltaNum = this.findPage('pages/order/order-confirm/index');
 | 
			
		||||
        if (orderPageDeltaNum > -1) {
 | 
			
		||||
          wx.navigateBack({ delta: 1 });
 | 
			
		||||
          resolveAddress(params);
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
      } catch (err) {
 | 
			
		||||
        rejectAddress(params);
 | 
			
		||||
        console.error(err);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "component": true,
 | 
			
		||||
  "usingComponents": {
 | 
			
		||||
    "t-cell": "tdesign-miniprogram/cell/cell",
 | 
			
		||||
    "t-icon": "tdesign-miniprogram/icon/icon",
 | 
			
		||||
    "t-toast": "tdesign-miniprogram/toast/toast"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
<view class="wx-address t-class" bind:tap="getWxLocation">
 | 
			
		||||
  <block wx:if="{{isCustomStyle}}">
 | 
			
		||||
    <view class="wx-address-custom">
 | 
			
		||||
      <t-icon prefix="wr" t-class="weixin" color="#0ABF5B" name="wechat" size="48rpx" />
 | 
			
		||||
      <text>{{title}}</text>
 | 
			
		||||
    </view>
 | 
			
		||||
    <slot />
 | 
			
		||||
  </block>
 | 
			
		||||
  <block wx:else>
 | 
			
		||||
    <t-cell title="{{title}}" title-class="cell__title" wr-class="cell" border="{{false}}">
 | 
			
		||||
      <t-icon t-class="weixin" slot="icon" color="#0ABF5B" name="logo-windows" size="48rpx" />
 | 
			
		||||
      <t-icon slot="right-icon" name="chevron-right" class="custom-icon" color="#bbb" />
 | 
			
		||||
    </t-cell>
 | 
			
		||||
  </block>
 | 
			
		||||
</view>
 | 
			
		||||
<t-toast id="t-toast" />
 | 
			
		||||
@@ -0,0 +1,19 @@
 | 
			
		||||
.wx-address .weixin {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  font-size: 48rpx !important;
 | 
			
		||||
  margin-right: 20rpx;
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
}
 | 
			
		||||
.wx-address .cell {
 | 
			
		||||
  padding: 32rpx 30rpx;
 | 
			
		||||
  border-radius: 8rpx;
 | 
			
		||||
}
 | 
			
		||||
.wx-address .cell__title {
 | 
			
		||||
  font-size: 30rpx;
 | 
			
		||||
  color: #333333;
 | 
			
		||||
}
 | 
			
		||||
.wx-address-custom {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  font-size: 32rpx;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,46 @@
 | 
			
		||||
Component({
 | 
			
		||||
  options: {
 | 
			
		||||
    addGlobalClass: true,
 | 
			
		||||
    multipleSlots: true,
 | 
			
		||||
  },
 | 
			
		||||
  properties: {
 | 
			
		||||
    address: {
 | 
			
		||||
      type: Object,
 | 
			
		||||
      value: {},
 | 
			
		||||
    },
 | 
			
		||||
    customIcon: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      value: 'edit-1',
 | 
			
		||||
    },
 | 
			
		||||
    extraSpace: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      value: true,
 | 
			
		||||
    },
 | 
			
		||||
    isDrawLine: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      value: true,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  externalClasses: [
 | 
			
		||||
    'item-wrapper-class',
 | 
			
		||||
    'title-class',
 | 
			
		||||
    'default-tag-class',
 | 
			
		||||
    'normal-tag-class',
 | 
			
		||||
    'address-info-class',
 | 
			
		||||
    'delete-class',
 | 
			
		||||
  ],
 | 
			
		||||
  methods: {
 | 
			
		||||
    onDelete(e) {
 | 
			
		||||
      const { item } = e.currentTarget.dataset;
 | 
			
		||||
      this.triggerEvent('onDelete', item);
 | 
			
		||||
    },
 | 
			
		||||
    onSelect(e) {
 | 
			
		||||
      const { item } = e.currentTarget.dataset;
 | 
			
		||||
      this.triggerEvent('onSelect', item);
 | 
			
		||||
    },
 | 
			
		||||
    onEdit(e) {
 | 
			
		||||
      const { item } = e.currentTarget.dataset;
 | 
			
		||||
      this.triggerEvent('onEdit', item);
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "component": true,
 | 
			
		||||
  "usingComponents": {
 | 
			
		||||
    "t-icon": "tdesign-miniprogram/icon/icon",
 | 
			
		||||
    "t-tag": "tdesign-miniprogram/tag/tag",
 | 
			
		||||
    "t-swipe-cell": "tdesign-miniprogram/swipe-cell/swipe-cell"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,30 @@
 | 
			
		||||
<wxs module="phoneReg">
 | 
			
		||||
  var toHide = function(array) { var mphone = array.substring(0, 3) + '****' + array.substring(7); return mphone; }
 | 
			
		||||
  module.exports.toHide = toHide;
 | 
			
		||||
</wxs>
 | 
			
		||||
<view class="address-item-wrapper item-wrapper-class">
 | 
			
		||||
  <t-swipe-cell class="swipe-out">
 | 
			
		||||
    <view class="address {{isDrawLine ? 'draw-line' : ''}}" bindtap="onSelect" data-item="{{address}}">
 | 
			
		||||
      <view class="address-left" wx:if="{{extraSpace}}">
 | 
			
		||||
        <t-icon wx:if="{{address.checked}}" name="check" color="#FA4126" class-prefix="{{classPrefix}}" size="46rpx" />
 | 
			
		||||
      </view>
 | 
			
		||||
      <view class="address-content">
 | 
			
		||||
        <view class="title title-class">
 | 
			
		||||
          <text class="text-style">{{address.name}}</text>
 | 
			
		||||
          <text>{{phoneReg.toHide(address.phoneNumber || '')}}</text>
 | 
			
		||||
        </view>
 | 
			
		||||
        <view class="label-adds">
 | 
			
		||||
          <text class="adds address-info-class">
 | 
			
		||||
            <text wx:if="{{address.isDefault === 1}}" class="tag tag-default default-tag-class">默认</text>
 | 
			
		||||
            <text wx:if="{{address.tag}}" class="tag tag-primary normal-tag-class">{{address.tag}}</text>
 | 
			
		||||
            <text class="address-text">{{address.address}}</text>
 | 
			
		||||
          </text>
 | 
			
		||||
        </view>
 | 
			
		||||
      </view>
 | 
			
		||||
      <view catch:tap="onEdit" data-item="{{address}}" class="address-edit">
 | 
			
		||||
        <t-icon name="{{customIcon}}" class-prefix="{{classPrefix}}" size="46rpx" color="#BBBBBB" />
 | 
			
		||||
      </view>
 | 
			
		||||
    </view>
 | 
			
		||||
    <view slot="right" class="swipe-right-del delete-class" bindtap="onDelete" data-item="{{address}}"> 删除 </view>
 | 
			
		||||
  </t-swipe-cell>
 | 
			
		||||
</view>
 | 
			
		||||
@@ -0,0 +1,103 @@
 | 
			
		||||
.address-item-wrapper {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .swipe-out .wr-swiper-cell {
 | 
			
		||||
  margin-top: 20rpx;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .swipe-out .swipe-right-del {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  width: 144rpx;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  background-color: #fa4126;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  font-size: 28rpx;
 | 
			
		||||
  line-height: 40rpx;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .draw-line {
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .draw-line::after {
 | 
			
		||||
  content: '';
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  bottom: 0;
 | 
			
		||||
  left: 32rpx;
 | 
			
		||||
  width: 200%;
 | 
			
		||||
  height: 2rpx;
 | 
			
		||||
  transform: scale(0.5);
 | 
			
		||||
  transform-origin: 0 0;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  border-bottom: #e5e5e5 2rpx solid;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .address {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  padding: 32rpx;
 | 
			
		||||
  background-color: #fff;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .address .address-edit {
 | 
			
		||||
  padding: 20rpx 0 20rpx 46rpx;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .address .address-left {
 | 
			
		||||
  width: 80rpx;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .address .address-content {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  flex: 1;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .address .address-content .title {
 | 
			
		||||
  font-size: 32rpx;
 | 
			
		||||
  line-height: 48rpx;
 | 
			
		||||
  margin-bottom: 16rpx;
 | 
			
		||||
  color: #333333;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
  display: flex;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .address .address-content .title .text-style {
 | 
			
		||||
  margin-right: 8rpx;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  max-width: 280rpx;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .address .address-content .label-adds {
 | 
			
		||||
  display: flex;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .address .address-content .label-adds .adds {
 | 
			
		||||
  display: -webkit-box;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
  -webkit-box-orient: vertical;
 | 
			
		||||
  -webkit-line-clamp: 2;
 | 
			
		||||
  color: #999999;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .address .address-content .label-adds .tag {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  padding: 0rpx 8rpx;
 | 
			
		||||
  min-width: 40rpx;
 | 
			
		||||
  height: 32rpx;
 | 
			
		||||
  border-radius: 18rpx;
 | 
			
		||||
  font-size: 20rpx;
 | 
			
		||||
  line-height: 32rpx;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  margin-right: 8rpx;
 | 
			
		||||
  vertical-align: text-top;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .address .address-content .label-adds .tag-default {
 | 
			
		||||
  background: #ffece9;
 | 
			
		||||
  color: #fa4126;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .address .address-content .label-adds .tag-primary {
 | 
			
		||||
  background: #f0f1ff;
 | 
			
		||||
  color: #5a66ff;
 | 
			
		||||
}
 | 
			
		||||
.address-item-wrapper .address .address-content .label-adds .address-text {
 | 
			
		||||
  font-size: 28rpx;
 | 
			
		||||
  line-height: 40rpx;
 | 
			
		||||
  color: #999999;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,73 @@
 | 
			
		||||
Component({
 | 
			
		||||
  properties: {
 | 
			
		||||
    show: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      observer(show) {
 | 
			
		||||
        if (!show) return;
 | 
			
		||||
        this.updateDivisions();
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    title: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      value: '',
 | 
			
		||||
    },
 | 
			
		||||
    value: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      value: '',
 | 
			
		||||
      observer() {
 | 
			
		||||
        if (!this.data.show) return;
 | 
			
		||||
        this.updateDivisions();
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    pickerOptions: {
 | 
			
		||||
      type: Array,
 | 
			
		||||
      value: [],
 | 
			
		||||
      observer() {
 | 
			
		||||
        if (!this.data.show) return;
 | 
			
		||||
        this.updateDivisions();
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    headerVisible: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      value: true,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  data: {
 | 
			
		||||
    pickerValue: [],
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    updateDivisions() {
 | 
			
		||||
      const { pickerOptions, value } = this.data;
 | 
			
		||||
      const index = (pickerOptions || []).findIndex(
 | 
			
		||||
        (item) => item.code === value,
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      setTimeout(() => {
 | 
			
		||||
        this.setData({ pickerValue: index >= 0 ? [index] : [0] });
 | 
			
		||||
      }, 0);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getAreaByIndex(indexes) {
 | 
			
		||||
      const { pickerOptions } = this.data;
 | 
			
		||||
      return pickerOptions[indexes.toString()];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onChange(e) {
 | 
			
		||||
      const currentValue = e.detail.value;
 | 
			
		||||
      const target = this.getAreaByIndex(currentValue);
 | 
			
		||||
      if (target === null) return;
 | 
			
		||||
 | 
			
		||||
      this.setData({ pickerValue: currentValue });
 | 
			
		||||
      this.triggerEvent('change', { value: target.code, target: target });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onConfirm() {
 | 
			
		||||
      const target = this.getAreaByIndex(this.data.pickerValue);
 | 
			
		||||
      this.triggerEvent('confirm', { value: target?.code, target });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onClose() {
 | 
			
		||||
      this.triggerEvent('close');
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "component": true,
 | 
			
		||||
  "usingComponents": {
 | 
			
		||||
    "t-popup": "tdesign-miniprogram/popup/popup"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,21 @@
 | 
			
		||||
<t-popup visible="{{show}}" placement="bottom">
 | 
			
		||||
  <view class="city-picker-box" slot="content">
 | 
			
		||||
    <view wx:if="{{headerVisible}}" class="city-picker-header city-picker-more">
 | 
			
		||||
      <view class="btn" hover-class="btn__active" catch:tap="onClose">取消</view>
 | 
			
		||||
      <view wx:if="{{title}}" class="title">{{title}}</view>
 | 
			
		||||
      <view class="btn primary" hover-class="btn__active" catch:tap="onConfirm">确定</view>
 | 
			
		||||
    </view>
 | 
			
		||||
    <view wx:else class="city-picker-header">
 | 
			
		||||
      <view wx:if="{{title}}" class="title">{{title}}</view>
 | 
			
		||||
    </view>
 | 
			
		||||
    <picker-view class="picker" indicator-class="picker-center-row" value="{{pickerValue}}" bind:change="onChange">
 | 
			
		||||
      <picker-view-column class="picker-column">
 | 
			
		||||
        <view wx:for="{{ pickerOptions }}" wx:key="code">{{ item.name }}</view>
 | 
			
		||||
      </picker-view-column>
 | 
			
		||||
    </picker-view>
 | 
			
		||||
    <view class="city-picker-footer" wx:if="{{!headerVisible}}">
 | 
			
		||||
      <view class="btn" hover-class="btn__active" catch:tap="onClose">取消</view>
 | 
			
		||||
      <view class="btn primary" hover-class="btn__active" catch:tap="onConfirm">确定</view>
 | 
			
		||||
    </view>
 | 
			
		||||
  </view>
 | 
			
		||||
</t-popup>
 | 
			
		||||
@@ -0,0 +1,102 @@
 | 
			
		||||
.city-picker-container {
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  top: 100vh;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  right: 0;
 | 
			
		||||
  height: 100vh;
 | 
			
		||||
  z-index: 100;
 | 
			
		||||
}
 | 
			
		||||
.city-picker-container.show {
 | 
			
		||||
  top: 0;
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
}
 | 
			
		||||
.city-picker-container.show .city-picker-box {
 | 
			
		||||
  bottom: 0;
 | 
			
		||||
}
 | 
			
		||||
.city-picker-shadow {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  right: 0;
 | 
			
		||||
  bottom: 0;
 | 
			
		||||
  background-color: rgba(0, 0, 0, 0.65);
 | 
			
		||||
}
 | 
			
		||||
.city-picker-header {
 | 
			
		||||
  height: 100rpx;
 | 
			
		||||
  line-height: 100rpx;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  font-size: 32rpx;
 | 
			
		||||
  color: #333333;
 | 
			
		||||
}
 | 
			
		||||
.city-picker-more {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
}
 | 
			
		||||
.city-picker-footer {
 | 
			
		||||
  height: 100rpx;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
}
 | 
			
		||||
.city-picker-footer .btn {
 | 
			
		||||
  width: 330rpx;
 | 
			
		||||
  height: 80rpx;
 | 
			
		||||
  line-height: 80rpx;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  color: #666666;
 | 
			
		||||
  font-size: 32rpx;
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
.city-picker-footer .btn__active {
 | 
			
		||||
  opacity: 0.5;
 | 
			
		||||
}
 | 
			
		||||
.city-picker-footer .btn::after {
 | 
			
		||||
  display: block;
 | 
			
		||||
  content: ' ';
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  left: -50%;
 | 
			
		||||
  right: -50%;
 | 
			
		||||
  top: -50%;
 | 
			
		||||
  bottom: -50%;
 | 
			
		||||
  transform: scale(0.5);
 | 
			
		||||
  border: 1rpx solid #999999;
 | 
			
		||||
  border-radius: 16rpx;
 | 
			
		||||
}
 | 
			
		||||
.city-picker-footer .btn.primary {
 | 
			
		||||
  color: #fa550f;
 | 
			
		||||
}
 | 
			
		||||
.city-picker-footer .btn.primary::after {
 | 
			
		||||
  border-color: #fa550f;
 | 
			
		||||
}
 | 
			
		||||
.picker-column:not(:first-child) {
 | 
			
		||||
  margin-left: 40rpx;
 | 
			
		||||
}
 | 
			
		||||
.city-picker-box {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  bottom: -100%;
 | 
			
		||||
  transition: 0.3s bottom ease-in-out;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  right: 0;
 | 
			
		||||
  z-index: 100;
 | 
			
		||||
  background-color: #fff;
 | 
			
		||||
  padding: 0 30rpx;
 | 
			
		||||
  color: #333333;
 | 
			
		||||
  font-size: 34rpx;
 | 
			
		||||
  border-radius: 20rpx 20rpx 0 0;
 | 
			
		||||
  padding-bottom: env(safe-area-inset-bottom);
 | 
			
		||||
}
 | 
			
		||||
.show .city-picker-shadow {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
.picker {
 | 
			
		||||
  height: 300rpx;
 | 
			
		||||
  margin: 50rpx 0;
 | 
			
		||||
  line-height: 88rpx;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
/* 似乎小程序picker-view的bug,indicator-class仅height生效,其他诸如line-height、text-align等放到父class中设置 */
 | 
			
		||||
.picker-center-row {
 | 
			
		||||
  height: 88rpx;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,35 @@
 | 
			
		||||
const AuthStepType = {
 | 
			
		||||
  ONE: 1,
 | 
			
		||||
  TWO: 2,
 | 
			
		||||
  THREE: 3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Component({
 | 
			
		||||
  options: {
 | 
			
		||||
    multipleSlots: true,
 | 
			
		||||
  },
 | 
			
		||||
  properties: {
 | 
			
		||||
    currAuthStep: {
 | 
			
		||||
      type: Number,
 | 
			
		||||
      value: AuthStepType.ONE,
 | 
			
		||||
    },
 | 
			
		||||
    userInfo: {
 | 
			
		||||
      type: Object,
 | 
			
		||||
      value: {},
 | 
			
		||||
    },
 | 
			
		||||
    isNeedGetUserInfo: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      value: false,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  data: {
 | 
			
		||||
    defaultAvatarUrl:
 | 
			
		||||
      'https://cdn-we-retail.ym.tencent.com/miniapp/usercenter/icon-user-center-avatar@2x.png',
 | 
			
		||||
    AuthStepType,
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    gotoUserEditPage() {
 | 
			
		||||
      this.triggerEvent('gotoUserEditPage');
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
  "component": true,
 | 
			
		||||
  "usingComponents": {
 | 
			
		||||
    "t-icon": "tdesign-miniprogram/icon/icon",
 | 
			
		||||
    "t-avatar": "tdesign-miniprogram/avatar/avatar"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,34 @@
 | 
			
		||||
<view class="user-center-card">
 | 
			
		||||
  <!-- 未登录的情况 -->
 | 
			
		||||
  <block wx:if="{{currAuthStep === AuthStepType.ONE}}">
 | 
			
		||||
    <view class="user-center-card__header" bind:tap="gotoUserEditPage">
 | 
			
		||||
      <t-avatar image="{{userInfo.avatarUrl || defaultAvatarUrl}}" class="user-center-card__header__avatar" />
 | 
			
		||||
      <view class="user-center-card__header__name">{{'请登录'}}</view>
 | 
			
		||||
    </view>
 | 
			
		||||
  </block>
 | 
			
		||||
  <!-- 已登录但未授权用户信息情况 -->
 | 
			
		||||
  <block wx:if="{{currAuthStep === AuthStepType.TWO}}">
 | 
			
		||||
    <view class="user-center-card__header">
 | 
			
		||||
      <t-avatar image="{{userInfo.avatarUrl || defaultAvatarUrl}}" class="user-center-card__header__avatar" />
 | 
			
		||||
      <view class="user-center-card__header__name">{{userInfo.nickName || '微信用户'}}</view>
 | 
			
		||||
      <!-- 需要授权用户信息,通过slot添加弹窗 -->
 | 
			
		||||
      <view class="user-center-card__header__transparent" wx:if="{{isNeedGetUserInfo}}">
 | 
			
		||||
        <slot name="getUserInfo" />
 | 
			
		||||
      </view>
 | 
			
		||||
      <!-- 不需要授权用户信息,仍然触发gotoUserEditPage事件 -->
 | 
			
		||||
      <view class="user-center-card__header__transparent" bind:tap="gotoUserEditPage" wx:else></view>
 | 
			
		||||
    </view>
 | 
			
		||||
  </block>
 | 
			
		||||
  <!-- 已登录且已经授权用户信息的情况 -->
 | 
			
		||||
  <block wx:if="{{currAuthStep === AuthStepType.THREE}}">
 | 
			
		||||
    <view class="user-center-card__header" bind:tap="gotoUserEditPage">
 | 
			
		||||
      <t-avatar
 | 
			
		||||
        t-class="avatar"
 | 
			
		||||
        mode="aspectFill"
 | 
			
		||||
        class="user-center-card__header__avatar"
 | 
			
		||||
        image="{{userInfo.avatarUrl || defaultAvatarUrl}}"
 | 
			
		||||
      />
 | 
			
		||||
      <view class="user-center-card__header__name">{{userInfo.nickName || '微信用户'}}</view>
 | 
			
		||||
    </view>
 | 
			
		||||
  </block>
 | 
			
		||||
</view>
 | 
			
		||||
@@ -0,0 +1,48 @@
 | 
			
		||||
.user-center-card {
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 480rpx;
 | 
			
		||||
  background-image: url('https://cdn-we-retail.ym.tencent.com/miniapp/template/user-center-bg-v1.png');
 | 
			
		||||
  background-size: cover;
 | 
			
		||||
  background-repeat: no-repeat;
 | 
			
		||||
  padding: 0 24rpx;
 | 
			
		||||
}
 | 
			
		||||
.user-center-card__header {
 | 
			
		||||
  margin-top: 192rpx;
 | 
			
		||||
  margin-bottom: 48rpx;
 | 
			
		||||
  height: 96rpx;
 | 
			
		||||
  line-height: 48rpx;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: flex-start;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  color: #333;
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
.user-center-card__header__avatar {
 | 
			
		||||
  width: 96rpx;
 | 
			
		||||
  height: 96rpx;
 | 
			
		||||
  border-radius: 48rpx;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.user-center-card__header__name {
 | 
			
		||||
  font-size: 36rpx;
 | 
			
		||||
  line-height: 48rpx;
 | 
			
		||||
  color: #333;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
  margin-left: 24rpx;
 | 
			
		||||
  margin-right: 16rpx;
 | 
			
		||||
}
 | 
			
		||||
.user-center-card__header__transparent {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
}
 | 
			
		||||
.user-center-card__icon {
 | 
			
		||||
  line-height: 96rpx;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										240
									
								
								mini-program/pages/usercenter/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								mini-program/pages/usercenter/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,240 @@
 | 
			
		||||
import { fetchUserCenter } from '../../services/usercenter/fetchUsercenter';
 | 
			
		||||
import Toast from 'tdesign-miniprogram/toast/index';
 | 
			
		||||
 | 
			
		||||
const menuData = [
 | 
			
		||||
  [
 | 
			
		||||
    {
 | 
			
		||||
      title: '收货地址',
 | 
			
		||||
      tit: '',
 | 
			
		||||
      url: '',
 | 
			
		||||
      type: 'address',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '优惠券',
 | 
			
		||||
      tit: '',
 | 
			
		||||
      url: '',
 | 
			
		||||
      type: 'coupon',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '积分',
 | 
			
		||||
      tit: '',
 | 
			
		||||
      url: '',
 | 
			
		||||
      type: 'point',
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    {
 | 
			
		||||
      title: '帮助中心',
 | 
			
		||||
      tit: '',
 | 
			
		||||
      url: '',
 | 
			
		||||
      type: 'help-center',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '客服热线',
 | 
			
		||||
      tit: '',
 | 
			
		||||
      url: '',
 | 
			
		||||
      type: 'service',
 | 
			
		||||
      icon: 'service',
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const orderTagInfos = [
 | 
			
		||||
  {
 | 
			
		||||
    title: '待付款',
 | 
			
		||||
    iconName: 'wallet',
 | 
			
		||||
    orderNum: 0,
 | 
			
		||||
    tabType: 5,
 | 
			
		||||
    status: 1,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    title: '待发货',
 | 
			
		||||
    iconName: 'deliver',
 | 
			
		||||
    orderNum: 0,
 | 
			
		||||
    tabType: 10,
 | 
			
		||||
    status: 1,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    title: '待收货',
 | 
			
		||||
    iconName: 'package',
 | 
			
		||||
    orderNum: 0,
 | 
			
		||||
    tabType: 40,
 | 
			
		||||
    status: 1,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    title: '待评价',
 | 
			
		||||
    iconName: 'comment',
 | 
			
		||||
    orderNum: 0,
 | 
			
		||||
    tabType: 60,
 | 
			
		||||
    status: 1,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    title: '退款/售后',
 | 
			
		||||
    iconName: 'exchang',
 | 
			
		||||
    orderNum: 0,
 | 
			
		||||
    tabType: 0,
 | 
			
		||||
    status: 1,
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const getDefaultData = () => ({
 | 
			
		||||
  showMakePhone: false,
 | 
			
		||||
  userInfo: {
 | 
			
		||||
    avatarUrl: '',
 | 
			
		||||
    nickName: '正在登录...',
 | 
			
		||||
    phoneNumber: '',
 | 
			
		||||
  },
 | 
			
		||||
  menuData,
 | 
			
		||||
  orderTagInfos,
 | 
			
		||||
  customerServiceInfo: {},
 | 
			
		||||
  currAuthStep: 1,
 | 
			
		||||
  showKefu: true,
 | 
			
		||||
  versionNo: '',
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Page({
 | 
			
		||||
  data: getDefaultData(),
 | 
			
		||||
 | 
			
		||||
  onLoad() {
 | 
			
		||||
    this.getVersionInfo();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  onShow() {
 | 
			
		||||
    this.getTabBar().init();
 | 
			
		||||
    this.init();
 | 
			
		||||
  },
 | 
			
		||||
  onPullDownRefresh() {
 | 
			
		||||
    this.init();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  init() {
 | 
			
		||||
    this.fetUseriInfoHandle();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  fetUseriInfoHandle() {
 | 
			
		||||
    fetchUserCenter().then(
 | 
			
		||||
      ({
 | 
			
		||||
        userInfo,
 | 
			
		||||
        countsData,
 | 
			
		||||
        orderTagInfos: orderInfo,
 | 
			
		||||
        customerServiceInfo,
 | 
			
		||||
      }) => {
 | 
			
		||||
        // eslint-disable-next-line no-unused-expressions
 | 
			
		||||
        menuData?.[0].forEach((v) => {
 | 
			
		||||
          countsData.forEach((counts) => {
 | 
			
		||||
            if (counts.type === v.type) {
 | 
			
		||||
              // eslint-disable-next-line no-param-reassign
 | 
			
		||||
              v.tit = counts.num;
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        });
 | 
			
		||||
        const info = orderTagInfos.map((v, index) => ({
 | 
			
		||||
          ...v,
 | 
			
		||||
          ...orderInfo[index],
 | 
			
		||||
        }));
 | 
			
		||||
        this.setData({
 | 
			
		||||
          userInfo,
 | 
			
		||||
          menuData,
 | 
			
		||||
          orderTagInfos: info,
 | 
			
		||||
          customerServiceInfo,
 | 
			
		||||
          currAuthStep: 2,
 | 
			
		||||
        });
 | 
			
		||||
        wx.stopPullDownRefresh();
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  onClickCell({ currentTarget }) {
 | 
			
		||||
    const { type } = currentTarget.dataset;
 | 
			
		||||
 | 
			
		||||
    switch (type) {
 | 
			
		||||
      case 'address': {
 | 
			
		||||
        wx.navigateTo({ url: '/pages/usercenter/address/list/index' });
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'service': {
 | 
			
		||||
        this.openMakePhone();
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'help-center': {
 | 
			
		||||
        Toast({
 | 
			
		||||
          context: this,
 | 
			
		||||
          selector: '#t-toast',
 | 
			
		||||
          message: '你点击了帮助中心',
 | 
			
		||||
          icon: '',
 | 
			
		||||
          duration: 1000,
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'point': {
 | 
			
		||||
        Toast({
 | 
			
		||||
          context: this,
 | 
			
		||||
          selector: '#t-toast',
 | 
			
		||||
          message: '你点击了积分菜单',
 | 
			
		||||
          icon: '',
 | 
			
		||||
          duration: 1000,
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'coupon': {
 | 
			
		||||
        wx.navigateTo({ url: '/pages/coupon/coupon-list/index' });
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      default: {
 | 
			
		||||
        Toast({
 | 
			
		||||
          context: this,
 | 
			
		||||
          selector: '#t-toast',
 | 
			
		||||
          message: '未知跳转',
 | 
			
		||||
          icon: '',
 | 
			
		||||
          duration: 1000,
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  jumpNav(e) {
 | 
			
		||||
    const status = e.detail.tabType;
 | 
			
		||||
 | 
			
		||||
    if (status === 0) {
 | 
			
		||||
      wx.navigateTo({ url: '/pages/order/after-service-list/index' });
 | 
			
		||||
    } else {
 | 
			
		||||
      wx.navigateTo({ url: `/pages/order/order-list/index?status=${status}` });
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  jumpAllOrder() {
 | 
			
		||||
    wx.navigateTo({ url: '/pages/order/order-list/index' });
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  openMakePhone() {
 | 
			
		||||
    this.setData({ showMakePhone: true });
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  closeMakePhone() {
 | 
			
		||||
    this.setData({ showMakePhone: false });
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  call() {
 | 
			
		||||
    wx.makePhoneCall({
 | 
			
		||||
      phoneNumber: this.data.customerServiceInfo.servicePhone,
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  gotoUserEditPage() {
 | 
			
		||||
    const { currAuthStep } = this.data;
 | 
			
		||||
    if (currAuthStep === 2) {
 | 
			
		||||
      wx.navigateTo({ url: '/pages/usercenter/person-info/index' });
 | 
			
		||||
    } else {
 | 
			
		||||
      this.fetUseriInfoHandle();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  getVersionInfo() {
 | 
			
		||||
    const versionInfo = wx.getAccountInfoSync();
 | 
			
		||||
    const { version, envVersion = __wxConfig } = versionInfo.miniProgram;
 | 
			
		||||
    this.setData({
 | 
			
		||||
      versionNo: envVersion === 'release' ? version : envVersion,
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										14
									
								
								mini-program/pages/usercenter/index.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								mini-program/pages/usercenter/index.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
{
 | 
			
		||||
  "navigationBarTitleText": "个人中心",
 | 
			
		||||
  "navigationStyle": "custom",
 | 
			
		||||
  "usingComponents": {
 | 
			
		||||
    "t-popup": "tdesign-miniprogram/popup/popup",
 | 
			
		||||
    "t-icon": "tdesign-miniprogram/icon/icon",
 | 
			
		||||
    "t-cell-group": "tdesign-miniprogram/cell-group/cell-group",
 | 
			
		||||
    "t-cell": "tdesign-miniprogram/cell/cell",
 | 
			
		||||
    "t-user-center-card": "./components/user-center-card/index",
 | 
			
		||||
    "t-order-group": "./components/order-group/index",
 | 
			
		||||
    "t-toast": "tdesign-miniprogram/toast/toast"
 | 
			
		||||
  },
 | 
			
		||||
  "enablePullDownRefresh": true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								mini-program/pages/usercenter/index.wxml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								mini-program/pages/usercenter/index.wxml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
<t-user-center-card
 | 
			
		||||
  userInfo="{{userInfo}}"
 | 
			
		||||
  isPhoneHide="{{true}}"
 | 
			
		||||
  name-class="custom-name-class"
 | 
			
		||||
  phone-class="custom-phone-class"
 | 
			
		||||
  avatar-class="customer-avatar-class"
 | 
			
		||||
  currAuthStep="{{currAuthStep}}"
 | 
			
		||||
  bind:gotoUserEditPage="gotoUserEditPage"
 | 
			
		||||
/>
 | 
			
		||||
<view class="content-wrapper">
 | 
			
		||||
  <view class="order-group-wrapper">
 | 
			
		||||
    <t-order-group orderTagInfos="{{orderTagInfos}}" bind:onClickTop="jumpAllOrder" bind:onClickItem="jumpNav" />
 | 
			
		||||
  </view>
 | 
			
		||||
  <view wx:for="{{menuData}}" wx:key="item" class="cell-box">
 | 
			
		||||
    <t-cell-group>
 | 
			
		||||
      <t-cell
 | 
			
		||||
        wx:for="{{item}}"
 | 
			
		||||
        wx:for-item="xitem"
 | 
			
		||||
        wx:for-index="xindex"
 | 
			
		||||
        wx:key="xindex"
 | 
			
		||||
        title="{{xitem.title}}"
 | 
			
		||||
        arrow="{{!xitem.icon}}"
 | 
			
		||||
        note="{{xitem.tit}}"
 | 
			
		||||
        data-type="{{xitem.type}}"
 | 
			
		||||
        bordered="{{false}}"
 | 
			
		||||
        bind:click="onClickCell"
 | 
			
		||||
        t-class="t-cell-padding"
 | 
			
		||||
        t-class-note="order-group-note"
 | 
			
		||||
        t-class-left="order-group__left"
 | 
			
		||||
      >
 | 
			
		||||
        <t-icon name="{{xitem.icon}}" size="48rpx" slot="note" />
 | 
			
		||||
      </t-cell>
 | 
			
		||||
    </t-cell-group>
 | 
			
		||||
  </view>
 | 
			
		||||
</view>
 | 
			
		||||
<view class="footer__version" wx:if="{{versionNo !== ''}}">当前版本 {{versionNo}}</view>
 | 
			
		||||
<t-popup visible="{{showMakePhone}}" placement="bottom" bind:visible-change="closeMakePhone" data-index="2">
 | 
			
		||||
  <view class="popup-content">
 | 
			
		||||
    <view class="popup-title border-bottom-1px" wx:if="{{customerServiceInfo.serviceTimeDuration}}">
 | 
			
		||||
      服务时间: {{customerServiceInfo.serviceTimeDuration}}
 | 
			
		||||
    </view>
 | 
			
		||||
    <view class="popup-phone {{showKefu ? 'border-bottom-1px' : ''}}" bind:tap="call">电话客服</view>
 | 
			
		||||
    <button class="popup-phone border-bottom-1px online" open-type="contact" wx:if="{{showKefu}}">在线客服</button>
 | 
			
		||||
    <view class="popup-close" bind:tap="closeMakePhone">取消</view>
 | 
			
		||||
  </view>
 | 
			
		||||
</t-popup>
 | 
			
		||||
<t-toast id="t-toast" />
 | 
			
		||||
							
								
								
									
										146
									
								
								mini-program/pages/usercenter/index.wxss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								mini-program/pages/usercenter/index.wxss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,146 @@
 | 
			
		||||
page {
 | 
			
		||||
  background-color: #f5f5f5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.content-wrapper {
 | 
			
		||||
  margin-top: 340rpx;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  padding: 0 30rpx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.main-content {
 | 
			
		||||
  height: 500rpx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.order-group-wrapper {
 | 
			
		||||
  margin-bottom: 16rpx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.order-group-note {
 | 
			
		||||
  font-size: 28rpx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.cell-box {
 | 
			
		||||
  border-radius: 10rpx;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  margin-bottom: 20rpx;
 | 
			
		||||
}
 | 
			
		||||
.icon-color {
 | 
			
		||||
  color: #aaa;
 | 
			
		||||
}
 | 
			
		||||
.cell-class {
 | 
			
		||||
  height: 100rpx;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.order-content {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  background-color: #fff;
 | 
			
		||||
  border-radius: 16rpx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.order-item {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  height: 180rpx;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.order-content-box {
 | 
			
		||||
  margin: auto;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  top: 50%;
 | 
			
		||||
  left: 50%;
 | 
			
		||||
  -webkit-transform: translate(-50%, -50%);
 | 
			
		||||
  -ms-transform: translate(-50%, -50%);
 | 
			
		||||
  transform: translate(-50%, -50%);
 | 
			
		||||
}
 | 
			
		||||
.order-content-t {
 | 
			
		||||
  margin-top: 10rpx;
 | 
			
		||||
  font-size: 24rpx;
 | 
			
		||||
  color: #333;
 | 
			
		||||
  letter-spacing: 0;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popup-content {
 | 
			
		||||
  background: #f5f5f5;
 | 
			
		||||
  margin-bottom: env(safe-area-inset-bottom);
 | 
			
		||||
  border-radius: 16rpx 16rpx 0 0;
 | 
			
		||||
}
 | 
			
		||||
.popup-content .popup-title {
 | 
			
		||||
  background: #fff;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  font-size: 24rpx;
 | 
			
		||||
  color: #999;
 | 
			
		||||
  height: 112rpx;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  line-height: 112rpx;
 | 
			
		||||
  border-radius: 16rpx 16rpx 0 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.border-bottom-1px {
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.border-bottom-1px::after {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  display: block;
 | 
			
		||||
  content: '';
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  width: 200%;
 | 
			
		||||
  height: 200%;
 | 
			
		||||
  transform: scale(0.5);
 | 
			
		||||
  transform-origin: left top;
 | 
			
		||||
  border-bottom: 2rpx solid #e5e5e5;
 | 
			
		||||
}
 | 
			
		||||
.popup-content .popup-phone,
 | 
			
		||||
.popup-content .popup-close {
 | 
			
		||||
  background: #fff;
 | 
			
		||||
  height: 100rpx;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  font-size: 30rpx;
 | 
			
		||||
  font-family: PingFangSC-Regular, PingFang SC;
 | 
			
		||||
  font-weight: 400;
 | 
			
		||||
  color: #333;
 | 
			
		||||
}
 | 
			
		||||
.popup-content .popup-phone.online {
 | 
			
		||||
  margin-bottom: 20rpx;
 | 
			
		||||
}
 | 
			
		||||
.popup-content .popup-phone.online::after {
 | 
			
		||||
  content: none;
 | 
			
		||||
}
 | 
			
		||||
.popup-content .popup-close {
 | 
			
		||||
  color: #333;
 | 
			
		||||
  border: 0;
 | 
			
		||||
  margin-top: 16rpx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.my-order {
 | 
			
		||||
  border-radius: 10rpx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.footer__version {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  margin-top: 50rpx;
 | 
			
		||||
  color: #999;
 | 
			
		||||
  margin-bottom: 4rpx;
 | 
			
		||||
  font-size: 24rpx;
 | 
			
		||||
  line-height: 32rpx;
 | 
			
		||||
}
 | 
			
		||||
.cell-box .order-group__left {
 | 
			
		||||
  margin-right: 0;
 | 
			
		||||
}
 | 
			
		||||
.cell-box .t-cell-padding {
 | 
			
		||||
  padding: 24rpx 18rpx 24rpx 32rpx;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								mini-program/pages/usercenter/name-edit/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								mini-program/pages/usercenter/name-edit/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
Page({
 | 
			
		||||
  data: {
 | 
			
		||||
    nameValue: '',
 | 
			
		||||
  },
 | 
			
		||||
  onLoad(options) {
 | 
			
		||||
    const { name } = options;
 | 
			
		||||
    this.setData({
 | 
			
		||||
      nameValue: name,
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  onSubmit() {
 | 
			
		||||
    wx.navigateBack({ backRefresh: true });
 | 
			
		||||
  },
 | 
			
		||||
  clearContent() {
 | 
			
		||||
    this.setData({
 | 
			
		||||
      nameValue: '',
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										8
									
								
								mini-program/pages/usercenter/name-edit/index.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								mini-program/pages/usercenter/name-edit/index.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "navigationBarTitleText": "昵称",
 | 
			
		||||
  "usingComponents": {
 | 
			
		||||
    "t-input": "tdesign-miniprogram/input/input",
 | 
			
		||||
    "t-icon": "tdesign-miniprogram/icon/icon",
 | 
			
		||||
    "t-button": "tdesign-miniprogram/button/button"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								mini-program/pages/usercenter/name-edit/index.wxml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								mini-program/pages/usercenter/name-edit/index.wxml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
<view class="name-edit">
 | 
			
		||||
  <t-input
 | 
			
		||||
    borderless
 | 
			
		||||
    model:value="{{nameValue}}"
 | 
			
		||||
    placeholder="请输入文字"
 | 
			
		||||
    label="昵称"
 | 
			
		||||
    clearable
 | 
			
		||||
    bind:clear="clearContent"
 | 
			
		||||
  />
 | 
			
		||||
  <view class="name-edit__input--desc"> 最多可输入15个字 </view>
 | 
			
		||||
  <view class="name-edit__wrapper">
 | 
			
		||||
    <t-button block shape="round" disabled="{{!nameValue}}" bind:tap="onSubmit">保存</t-button>
 | 
			
		||||
  </view>
 | 
			
		||||
</view>
 | 
			
		||||
							
								
								
									
										18
									
								
								mini-program/pages/usercenter/name-edit/index.wxss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								mini-program/pages/usercenter/name-edit/index.wxss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
page {
 | 
			
		||||
  background-color: #f5f5f5;
 | 
			
		||||
}
 | 
			
		||||
page view {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
.name-edit {
 | 
			
		||||
  padding-top: 20rpx;
 | 
			
		||||
}
 | 
			
		||||
.name-edit .name-edit__input--desc {
 | 
			
		||||
  font-size: 26rpx;
 | 
			
		||||
  padding: 16rpx 32rpx;
 | 
			
		||||
  color: #999;
 | 
			
		||||
  margin-bottom: 200rpx;
 | 
			
		||||
}
 | 
			
		||||
.name-edit .name-edit__wrapper {
 | 
			
		||||
  margin: 0 32rpx;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										122
									
								
								mini-program/pages/usercenter/person-info/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								mini-program/pages/usercenter/person-info/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
			
		||||
import { fetchPerson } from '../../../services/usercenter/fetchPerson';
 | 
			
		||||
import { phoneEncryption } from '../../../utils/util';
 | 
			
		||||
import Toast from 'tdesign-miniprogram/toast/index';
 | 
			
		||||
 | 
			
		||||
Page({
 | 
			
		||||
  data: {
 | 
			
		||||
    personInfo: {
 | 
			
		||||
      avatarUrl: '',
 | 
			
		||||
      nickName: '',
 | 
			
		||||
      gender: 0,
 | 
			
		||||
      phoneNumber: '',
 | 
			
		||||
    },
 | 
			
		||||
    showUnbindConfirm: false,
 | 
			
		||||
    pickerOptions: [
 | 
			
		||||
      {
 | 
			
		||||
        name: '男',
 | 
			
		||||
        code: '1',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        name: '女',
 | 
			
		||||
        code: '2',
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
    typeVisible: false,
 | 
			
		||||
    genderMap: ['', '男', '女'],
 | 
			
		||||
  },
 | 
			
		||||
  onLoad() {
 | 
			
		||||
    this.init();
 | 
			
		||||
  },
 | 
			
		||||
  init() {
 | 
			
		||||
    this.fetchData();
 | 
			
		||||
  },
 | 
			
		||||
  fetchData() {
 | 
			
		||||
    fetchPerson().then((personInfo) => {
 | 
			
		||||
      this.setData({
 | 
			
		||||
        personInfo,
 | 
			
		||||
        'personInfo.phoneNumber': phoneEncryption(personInfo.phoneNumber),
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  onClickCell({ currentTarget }) {
 | 
			
		||||
    const { dataset } = currentTarget;
 | 
			
		||||
    const { nickName } = this.data.personInfo;
 | 
			
		||||
 | 
			
		||||
    switch (dataset.type) {
 | 
			
		||||
      case 'gender':
 | 
			
		||||
        this.setData({
 | 
			
		||||
          typeVisible: true,
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      case 'name':
 | 
			
		||||
        wx.navigateTo({
 | 
			
		||||
          url: `/pages/usercenter/name-edit/index?name=${nickName}`,
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      case 'avatarUrl':
 | 
			
		||||
        this.toModifyAvatar();
 | 
			
		||||
        break;
 | 
			
		||||
      default: {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  onClose() {
 | 
			
		||||
    this.setData({
 | 
			
		||||
      typeVisible: false,
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  onConfirm(e) {
 | 
			
		||||
    const { value } = e.detail;
 | 
			
		||||
    this.setData(
 | 
			
		||||
      {
 | 
			
		||||
        typeVisible: false,
 | 
			
		||||
        'personInfo.gender': value,
 | 
			
		||||
      },
 | 
			
		||||
      () => {
 | 
			
		||||
        Toast({
 | 
			
		||||
          context: this,
 | 
			
		||||
          selector: '#t-toast',
 | 
			
		||||
          message: '设置成功',
 | 
			
		||||
          theme: 'success',
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
  async toModifyAvatar() {
 | 
			
		||||
    try {
 | 
			
		||||
      const tempFilePath = await new Promise((resolve, reject) => {
 | 
			
		||||
        wx.chooseImage({
 | 
			
		||||
          count: 1,
 | 
			
		||||
          sizeType: ['compressed'],
 | 
			
		||||
          sourceType: ['album', 'camera'],
 | 
			
		||||
          success: (res) => {
 | 
			
		||||
            const { path, size } = res.tempFiles[0];
 | 
			
		||||
            if (size <= 10485760) {
 | 
			
		||||
              resolve(path);
 | 
			
		||||
            } else {
 | 
			
		||||
              reject({ errMsg: '图片大小超出限制,请重新上传' });
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          fail: (err) => reject(err),
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      const tempUrlArr = tempFilePath.split('/');
 | 
			
		||||
      const tempFileName = tempUrlArr[tempUrlArr.length - 1];
 | 
			
		||||
      Toast({
 | 
			
		||||
        context: this,
 | 
			
		||||
        selector: '#t-toast',
 | 
			
		||||
        message: `已选择图片-${tempFileName}`,
 | 
			
		||||
        theme: 'success',
 | 
			
		||||
      });
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      if (error.errMsg === 'chooseImage:fail cancel') return;
 | 
			
		||||
      Toast({
 | 
			
		||||
        context: this,
 | 
			
		||||
        selector: '#t-toast',
 | 
			
		||||
        message: error.errMsg || error.msg || '修改头像出错了',
 | 
			
		||||
        theme: 'error',
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										12
									
								
								mini-program/pages/usercenter/person-info/index.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								mini-program/pages/usercenter/person-info/index.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
{
 | 
			
		||||
  "navigationBarTitleText": "个人资料",
 | 
			
		||||
  "usingComponents": {
 | 
			
		||||
    "t-cell-group": "tdesign-miniprogram/cell-group/cell-group",
 | 
			
		||||
    "t-cell": "tdesign-miniprogram/cell/cell",
 | 
			
		||||
    "t-button": "tdesign-miniprogram/button/button",
 | 
			
		||||
    "t-image": "/components/webp-image/index",
 | 
			
		||||
    "t-dialog": "tdesign-miniprogram/dialog/dialog",
 | 
			
		||||
    "t-toast": "tdesign-miniprogram/toast/toast",
 | 
			
		||||
    "t-select-picker": "../components/ui-select-picker/index"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								mini-program/pages/usercenter/person-info/index.wxml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								mini-program/pages/usercenter/person-info/index.wxml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
<view class="person-info">
 | 
			
		||||
  <t-cell-group>
 | 
			
		||||
    <t-cell
 | 
			
		||||
      title="头像"
 | 
			
		||||
      center="{{true}}"
 | 
			
		||||
      data-type="avatarUrl"
 | 
			
		||||
      bind:click="onClickCell"
 | 
			
		||||
      arrow
 | 
			
		||||
      t-class-left="order-group__left"
 | 
			
		||||
    >
 | 
			
		||||
      <t-image slot="note" src="{{personInfo.avatarUrl}}" t-class="avatarUrl" mode="aspectFill" />
 | 
			
		||||
    </t-cell>
 | 
			
		||||
    <t-cell
 | 
			
		||||
      title="昵称"
 | 
			
		||||
      arrow
 | 
			
		||||
      note="{{personInfo.nickName}}"
 | 
			
		||||
      data-type="name"
 | 
			
		||||
      bind:click="onClickCell"
 | 
			
		||||
      t-class="t-cell-class"
 | 
			
		||||
      t-class-left="order-group__left"
 | 
			
		||||
    />
 | 
			
		||||
    <t-cell
 | 
			
		||||
      title="性别"
 | 
			
		||||
      arrow
 | 
			
		||||
      note="{{genderMap[personInfo.gender]}}"
 | 
			
		||||
      data-type="gender"
 | 
			
		||||
      bind:click="onClickCell"
 | 
			
		||||
      t-class="t-cell-class"
 | 
			
		||||
      t-class-left="order-group__left"
 | 
			
		||||
    />
 | 
			
		||||
    <t-cell
 | 
			
		||||
      bordered="{{false}}"
 | 
			
		||||
      title="手机号"
 | 
			
		||||
      arrow
 | 
			
		||||
      note="{{personInfo.phoneNumber ? personInfo.phoneNumber : '去绑定手机号'}}"
 | 
			
		||||
      data-type="phoneNumber"
 | 
			
		||||
      bind:click="onClickCell"
 | 
			
		||||
      t-class="t-cell-class"
 | 
			
		||||
      t-class-left="order-group__left"
 | 
			
		||||
    />
 | 
			
		||||
  </t-cell-group>
 | 
			
		||||
</view>
 | 
			
		||||
<view class="person-info__wrapper">
 | 
			
		||||
  <view class="person-info__btn" bind:tap="openUnbindConfirm"> 切换账号登录 </view>
 | 
			
		||||
</view>
 | 
			
		||||
<t-select-picker
 | 
			
		||||
  show="{{typeVisible}}"
 | 
			
		||||
  picker-options="{{pickerOptions}}"
 | 
			
		||||
  title="选择性别"
 | 
			
		||||
  value="{{personInfo.gender}}"
 | 
			
		||||
  bind:confirm="onConfirm"
 | 
			
		||||
  bind:close="onClose"
 | 
			
		||||
/>
 | 
			
		||||
<t-toast id="t-toast" />
 | 
			
		||||
							
								
								
									
										45
									
								
								mini-program/pages/usercenter/person-info/index.wxss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								mini-program/pages/usercenter/person-info/index.wxss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
:host {
 | 
			
		||||
  background-color: #f5f5f5;
 | 
			
		||||
}
 | 
			
		||||
page view {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
.person-info {
 | 
			
		||||
  padding-top: 20rpx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.person-info__btn {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  border: 2rpx solid #ddd;
 | 
			
		||||
  border-radius: 48rpx;
 | 
			
		||||
  padding: 18rpx 0;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-self: center;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
}
 | 
			
		||||
.person-info__wrapper {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  padding: 0 32rpx;
 | 
			
		||||
  padding-bottom: calc(env(safe-area-inset-bottom) + 20rpx);
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  bottom: 0;
 | 
			
		||||
  left: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.avatarUrl {
 | 
			
		||||
  width: 80rpx;
 | 
			
		||||
  height: 80rpx;
 | 
			
		||||
  border-radius: 50% !important;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.t-class-confirm {
 | 
			
		||||
  color: #fa550f !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.person-info .order-group__left {
 | 
			
		||||
  margin-right: 0;
 | 
			
		||||
}
 | 
			
		||||
.person-info .t-cell-class {
 | 
			
		||||
  height: 112rpx;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user