quanwei
2025-11-11 0d04d60f456b1902c1e27b9586652649df3963d4
mobile/pages/plus/business/detail.vue
@@ -1,112 +1,85 @@
<template>
   <view>
      <header-bar title="名片详情" :isBack="true" @click="back"></header-bar>
      <scroll-view scroll-y="true" class="scroll-view">
         <view class="card-container" v-if="businessInfo">
            <!-- 名片头部 -->
            <view class="card-header" :style="{backgroundColor: backgroundColor}">
               <image v-if="businessInfo.background_image" class="card-bg" :src="businessInfo.background_image" mode="aspectFill"></image>
               <view class="header-content">
                  <image class="avatar" :src="businessInfo.avatar || '/static/default.png'" mode="aspectFill"></image>
                  <view class="user-info">
                     <view class="name">{{businessInfo.real_name}}</view>
                     <view class="company">{{businessInfo.company_name}}</view>
                     <view class="position">{{businessInfo.position}}</view>
                  </view>
            <!-- 名片主体 -->
            <view class="business-card" @click="viewCard">
               <image class="card-image" :src="businessInfo.mp" mode="widthFix"></image>
            </view>
            <!-- 操作按钮区域 -->
            <view class="action-buttons">
               <view class="action-btn" @click="makePhoneCall(businessInfo.mobile)">
                  <image src="@/static/icon/bddh.png" class="btn-icon"></image>
                  <text class="btn-text">拨打电话</text>
               </view>
               <view class="action-btn" @click="shareToWechat">
                  <image src="@/static/wx.png" class="btn-icon"></image>
                  <text class="btn-text">分享微信</text>
               </view>
               <view class="action-btn" @click="openLocation(businessInfo)">
                  <image src="@/static/icon/address_icon.png" class="btn-icon"></image>
                  <text class="btn-text">导航地址</text>
               </view>
               <button open-type="share" class="action-btn">
                  <image src="@/static/icon/fenx.png" class="btn-icon"></image>
                  <text class="btn-text">分享名片</text>
               </button>
            </view>
            <!-- 名片简介 -->
            <view class="card-intro" v-if="businessInfo.Introduction || businessInfo.business_scope">
               <view v-if="businessInfo.Introduction" class="intro-item">
                  <view class="intro-title">个人简介</view>
                  <view class="intro-content">{{businessInfo.Introduction}}</view>
               </view>
               <view v-if="businessInfo.business_scope" class="intro-item">
                  <view class="intro-title">业务范围</view>
                  <view class="intro-content">{{businessInfo.business_scope}}</view>
               </view>
            </view>
            <!-- 公司Logo -->
            <view class="logo-section" v-if="businessInfo.logo_image">
               <image class="logo" :src="businessInfo.logo_image.file_path" mode="aspectFit"></image>
            </view>
            <!-- 联系信息 -->
            <view class="contact-section">
               <view class="section-title">联系方式</view>
               <view class="contact-item" @click="makePhoneCall(businessInfo.phone)">
                  <view class="item-left">
                     <view class="icon-circle">
                        <text class="icon iconfont icon-phone"></text>
                     </view>
                     <text class="item-label">电话</text>
                  </view>
                  <view class="item-right">
                     <text class="item-value">{{businessInfo.phone}}</text>
                     <text class="icon iconfont icon-jiantou"></text>
                  </view>
            <!-- 数字资产卡片 -->
            <view class="asset-cards">
               <view class="asset-card" @click="goToPlatform">
                  <image class="asset-img" :src="background.digital_asset_1" mode="aspectFill"></image>
               </view>
               <view class="contact-item" v-if="businessInfo.mobile" @click="makePhoneCall(businessInfo.mobile)">
                  <view class="item-left">
                     <view class="icon-circle">
                        <text class="icon iconfont icon-mobile"></text>
                     </view>
                     <text class="item-label">手机</text>
                  </view>
                  <view class="item-right">
                     <text class="item-value">{{businessInfo.mobile}}</text>
                     <text class="icon iconfont icon-jiantou"></text>
                  </view>
               </view>
               <view class="contact-item" v-if="businessInfo.email" @click="copyEmail(businessInfo.email)">
                  <view class="item-left">
                     <view class="icon-circle">
                        <text class="icon iconfont icon-email"></text>
                     </view>
                     <text class="item-label">邮箱</text>
                  </view>
                  <view class="item-right">
                     <text class="item-value">{{businessInfo.email}}</text>
                     <text class="icon iconfont icon-jiantou"></text>
                  </view>
               </view>
               <view class="contact-item" v-if="businessInfo.address" @click="openLocation(businessInfo.address)">
                  <view class="item-left">
                     <view class="icon-circle">
                        <text class="icon iconfont icon-location"></text>
                     </view>
                     <text class="item-label">地址</text>
                  </view>
                  <view class="item-right">
                     <text class="item-value">{{businessInfo.address}}</text>
                     <text class="icon iconfont icon-jiantou"></text>
                  </view>
               <view class="asset-card" @click="goToShop">
                  <image class="asset-img" :src="background.digital_asset_2" mode="aspectFill"></image>
               </view>
            </view>
            <!-- 详细信息 -->
            <view class="detail-section">
               <view class="section-title">详细信息</view>
               <view class="detail-item" v-if="businessInfo.intro">
                  <view class="detail-label">个人简介</view>
                  <view class="detail-content">{{businessInfo.intro}}</view>
               </view>
               <view class="detail-item" v-if="businessInfo.business_scope">
                  <view class="detail-label">业务范围</view>
                  <view class="detail-content">{{businessInfo.business_scope}}</view>
               </view>
            </view>
         </view>
         <!-- 底部操作按钮 -->
         <view class="action-section">
            <view class="action-left">
               <view class="action-btn" @click="saveCard" :class="{active: isSaved}">
                  <text class="icon iconfont" :class="isSaved ? 'icon-success' : 'icon-star'"></text>
                  <text>{{isSaved ? '已保存' : '收藏'}}</text>
               </view>
            </view>
            <view class="action-right">
               <view class="share-btn" @click="shareCard">分享名片</view>
            </view>
            <!-- 底部间距 -->
            <view class="bottom-space"></view>
         </view>
      </scroll-view>
      <!-- 底部固定按钮 -->
      <view class="bottom-btn-section">
         <button class="create-card-btn" @click="createNewCard">新建我的数字名片</button>
         <button class="create-card-btn desensitization" @click="buyCard"
            v-if="businessInfo.posterType === 'desensitization' && !businessInfo.has_purchased">查看联系方式</button>
      </view>
      <!-- 支付弹窗 -->
      <view class="payment-modal" v-if="showPayment">
         <view class="modal-content">
            <view class="modal-header">
               <text class="title">查看联系方式确认</text>
               <text class="close" @tap="closePaymentModal">×</text>
            </view>
            <view class="payment-info">
               <text class="name">{{ businessInfo.name }}</text>
               <text class="position"
                  v-if="businessInfo.duties && businessInfo.duties.length > 0">{{ businessInfo.duties[0] }}</text>
               <text class="price">¥{{ businessInfo.grade.price }}</text>
            </view>
            <view class="modal-footer">
               <view class="cancel-btn" @tap="closePaymentModal">取消</view>
               <view class="confirm-btn" @tap="confirmPayment">确认</view>
            </view>
         </view>
      </view>
   </view>
</template>
@@ -116,91 +89,129 @@
         return {
            businessInfo: null,
            business_card_id: '',
            isSaved: false,
            backgroundColor: '#37bde6',
            loading: true
            loading: true,
            // 支付相关
            showPayment: false,
            selectedGrade: {},
            paymentMethod: 'balance',
            background: {}
         };
      },
      onLoad(options) {
         if (options.business_card_id) {
            this.business_card_id = options.business_card_id;
            this.getBusinessDetail();
            this.checkSavedStatus();
            // 记录访问日志
            this.recordVisit();
         }
         this.getSettingBackground()
      },
      methods: {
         back() {
            uni.navigateBack();
         },
         viewCard() {
            let _this = this
            // 预览图片
            uni.previewImage({
               urls: [_this.businessInfo.mp],
               longPressActions: {
                  itemList: ['转发给朋友', '保存图片', '收藏', '翻译图片中的文字', '提取文字'],
                  success: function(data) {
                     if (data.tapIndex == 1) {
                           _this.recordVisit(20)
                        }
                        console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
                  },
                  fail: function(err) {
                     console.log(err.errMsg);
                  }
               },
               complete: function(res) {
                  console.log(res);
               }
            })
         },
         getSettingBackground() {
            let _this = this;
            _this._post('plus.business.setting/getBackground', {}, function(res) {
               _this.background = res.data
            })
         },
         // 获取名片详情
         getBusinessDetail() {
            let _this = this;
            _this.loading = true;
            _this._post('plus.business/business/detail', { business_card_id: _this.business_card_id }, function(res) {
            _this._post('plus.business.business/detail', {
               business_card_id: _this.business_card_id
            }, function(res) {
               _this.businessInfo = res.data;
               // 设置背景色
               if (_this.businessInfo.template && _this.businessInfo.template.style?.background?.color) {
                  _this.backgroundColor = _this.businessInfo.template.style.background.color;
               }
               _this.loading = false;
            });
         },
         // 检查是否已保存
         checkSavedStatus() {
            let _this = this;
            _this._post('plus.business/saving/check', { business_card_id: _this.business_card_id }, function(res) {
               _this.isSaved = res.data.is_saved;
               // 设置默认选中的等级
               if (_this.businessInfo.grade && _this.businessInfo.grade.length > 0) {
                  _this.selectedGrade = _this.businessInfo.grade;
               }
            });
         },
         // 记录访问
         recordVisit() {
         recordVisit(type=10) {
            let _this = this;
            const params = {
               business_card_id: _this.business_card_id
               business_card_id: _this.business_card_id,
               type: type
            };
            // 如果有推荐人ID,也记录下来
            if (this.$route.query.referee_id) {
               params.referee_id = this.$route.query.referee_id;
            }
            _this._post('plus.business/business/recordVisit', params, function() {
            _this._post('plus.business.saving/add', params, function() {
               // 无需处理返回结果
            });
         },
         // 拨打电话
         makePhoneCall(phone) {
            if (!phone) {
               this.showError('暂无联系电话');
               return;
            }
            uni.makePhoneCall({
               phoneNumber: phone
            });
         },
         // 复制邮箱
         copyEmail(email) {
            uni.setClipboardData({
               data: email,
               success: () => {
                  this.showSuccess('邮箱已复制');
               }
            });
         // 分享到微信
         shareToWechat() {
            // 实现分享到微信的逻辑
            if (this.businessInfo && this.businessInfo.wechat) {
               uni.setClipboardData({
                  data: this.businessInfo.wechat,
                  success: () => {
                     this.showSuccess('微信号已复制');
                  }
               });
            } else {
               this.showError('暂未填写微信');
            }
         },
         // 打开地图
         openLocation(address) {
            // 这里简化处理,实际项目中可能需要调用地图API进行地理编码
         openLocation(businessInfo) {
            let address = businessInfo.region.province + ' ' + businessInfo.region.city + ' ' + businessInfo.region
               .region + ' ' + businessInfo.address
            if (!address) {
               this.showError('暂无地址信息');
               return;
            }
            console.log( businessInfo.latitude);
            console.log( businessInfo.longitude);
            let latitude=Number(businessInfo.latitude)
            let longitude=Number(businessInfo.longitude)
            uni.openLocation({
               latitude: 0,
               longitude: 0,
               name: address,
               latitude: latitude,
               longitude: longitude,
               name: businessInfo.address,
               address: address,
               scale: 18
               scale: 18,
               complete: function(res) {
                  console.log(res);
               }
            });
         },
         // 保存名片
         saveCard() {
            let _this = this;
            _this._post('plus.business/saving/save', { business_card_id: _this.business_card_id }, function(res) {
               _this.isSaved = !_this.isSaved;
               _this.showSuccess(_this.isSaved ? '保存成功' : '取消保存');
            });
         },
         // 分享名片
         shareCard() {
@@ -208,12 +219,78 @@
               withShareTicket: true,
               menus: ['shareAppMessage', 'shareTimeline']
            });
         },
         // 跳转到平台
         goToPlatform() {
            uni.navigateTo({
               url: '/pages/shop/shop?shop_supplier_id=1'
            });
         },
         // 跳转到店铺
         goToShop() {
            let _this = this;
            _this._post('store.store/getUserStore', {
               user_id: _this.businessInfo.user_id
            }, function(res) {
               if (res.data.list) {
                  uni.navigateTo({
                     url: '/pages/shop/shop?shop_supplier_id=' + res.data.list.shop_supplier_id
                  });
               } else {
                  _this.showError('该用户暂无店铺')
               }
               /* uni.navigateTo({
                  url: '/pages/shop/shop?shop_supplier_id=1'
               }); */
            });
         },
         // 新建数字名片
         createNewCard() {
            uni.navigateTo({
               url: '/pages/plus/business/add'
            });
         },
         // 购买名片
         buyCard() {
            // 显示支付弹窗
            this.showPayment = true;
         },
         // 关闭支付弹窗
         closePaymentModal() {
            this.showPayment = false;
         },
         // 选择支付方式
         selectPaymentMethod(method) {
            this.paymentMethod = method;
         },
         // 确认支付
         confirmPayment() {
            let payType = this.paymentMethod === 'balance' ? 10 : 20;
            let params = {
               business_card_id: this.business_card_id,
               grade_id: this.businessInfo.grade.grade_id,
               order_source: 10, // 查看名片
               pay_type: payType
            };
            this._post('plus.business.order/create', params, (res) => {
               if (res.code === 1) {
                  // 跳转到收银台支付
                  uni.redirectTo({
                     url: '/pages/plus/business/cashier?order_id=' + res.data.order_id + '&order_type=100'
                  });
               } else {
                  this.showError(res.msg || '支付失败');
               }
            }, (err) => {
               this.showError('支付失败,请重试');
            });
         }
      },
      onShareAppMessage() {
         if (this.businessInfo) {
            return {
               title: `${this.businessInfo.real_name}的电子名片`,
               title: `${this.businessInfo.name}的电子名片`,
               path: `/pages/plus/business/detail?business_card_id=${this.business_card_id}&referee_id=${this.getUserId()}`
            };
         }
@@ -225,7 +302,7 @@
      onShareTimeline() {
         if (this.businessInfo) {
            return {
               title: `${this.businessInfo.real_name}的电子名片`,
               title: `${this.businessInfo.name}的电子名片`,
               path: `/pages/plus/business/detail?business_card_id=${this.business_card_id}&referee_id=${this.getUserId()}`
            };
         }
@@ -242,206 +319,361 @@
      height: calc(100vh - 80rpx);
   }
   .card-header {
      position: relative;
      color: #fff;
      padding: 40rpx;
   .card-container {
      padding: 0 30rpx;
   }
      .card-bg {
         position: absolute;
         top: 0;
         left: 0;
         width: 100%;
         height: 100%;
         z-index: 1;
   // 名片主体样式
   .card-image {
      width: 100%;
   }
   .card-header {
      display: flex;
      align-items: center;
      .avatar {
         width: 140rpx;
         height: 140rpx;
         border-radius: 50%;
         border: 6rpx solid rgba(255, 255, 255, 0.8);
         background: #fff;
      }
      .user-info {
         margin-left: 30rpx;
         .name {
            font-size: 48rpx;
            font-weight: bold;
            margin-bottom: 8rpx;
         }
         .position {
            font-size: 32rpx;
            opacity: 0.9;
         }
      }
   }
   .company-info {
      margin-top: 30rpx;
      .company-name {
         font-size: 34rpx;
         opacity: 0.9;
      }
      .header-content {
         position: relative;
         z-index: 2;
         display: flex;
         align-items: center;
         .avatar {
            width: 180rpx;
            height: 180rpx;
            border-radius: 50%;
            border: 6rpx solid rgba(255, 255, 255, 0.8);
            background: #fff;
         }
         .user-info {
            margin-left: 30rpx;
            .name {
               font-size: 48rpx;
               font-weight: bold;
               margin-bottom: 12rpx;
            }
            .company {
               font-size: 34rpx;
               margin-bottom: 8rpx;
               opacity: 0.9;
            }
            .position {
               font-size: 30rpx;
               opacity: 0.8;
            }
         }
      }
   }
   .logo-section {
      background: #fff;
      padding: 30rpx 0;
      display: flex;
      justify-content: center;
      .logo {
         width: 150rpx;
         height: 150rpx;
         border-radius: 10rpx;
      }
   }
   .contact-section,
   .detail-section {
      background: #fff;
      margin-top: 20rpx;
      padding: 30rpx;
      .section-title {
         font-size: 32rpx;
         font-weight: bold;
         color: #333;
         margin-bottom: 20rpx;
         padding-bottom: 20rpx;
         border-bottom: 1rpx solid #f0f0f0;
      }
   .contact-info {
      margin-top: 30rpx;
      .contact-item {
         display: flex;
         justify-content: space-between;
         align-items: center;
         padding: 25rpx 0;
         border-bottom: 1rpx solid #f0f0f0;
         margin-bottom: 16rpx;
         &:last-child {
            border-bottom: none;
         .contact-label {
            font-size: 30rpx;
            margin-right: 16rpx;
         }
         .item-left {
            display: flex;
            align-items: center;
            .icon-circle {
               width: 60rpx;
               height: 60rpx;
               border-radius: 50%;
               background: #f5f5f5;
               display: flex;
               align-items: center;
               justify-content: center;
               margin-right: 20rpx;
               .icon {
                  font-size: 36rpx;
                  color: #37bde6;
               }
            }
            .item-label {
               font-size: 30rpx;
               color: #666;
            }
         }
         .item-right {
            display: flex;
            align-items: center;
            .item-value {
               font-size: 30rpx;
               color: #333;
               margin-right: 10rpx;
            }
            .icon {
               font-size: 24rpx;
               color: #999;
            }
         .contact-value {
            font-size: 30rpx;
            opacity: 0.9;
            flex: 1;
            word-break: break-all;
         }
      }
   }
      .detail-item {
         margin-bottom: 30rpx;
   .verification-info {
      margin-top: 30rpx;
      display: flex;
      align-items: center;
         .detail-label {
            font-size: 30rpx;
            font-weight: bold;
            color: #666;
            margin-bottom: 15rpx;
      .verification-text {
         font-size: 28rpx;
         opacity: 0.8;
         margin-right: 20rpx;
      }
      .verification-tags {
         display: flex;
         .verification-tag {
            background: rgba(255, 255, 255, 0.2);
            padding: 6rpx 16rpx;
            border-radius: 16rpx;
            font-size: 24rpx;
            margin-right: 12rpx;
         }
      }
   }
   // 操作按钮区域
   .action-buttons {
      display: flex;
      justify-content: space-between;
      background: #fff;
      border-radius: 20rpx;
      padding: 30rpx;
      margin-top: 30rpx;
      box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
      .action-btn {
         display: flex;
         flex-direction: column;
         align-items: center;
         flex: 1;
         line-height: normal;
         background: #ffffff00;
         .btn-icon {
            font-size: 56rpx;
            width: 56rpx;
            height: 56rpx;
            margin-bottom: 12rpx;
         }
         .detail-content {
         .btn-text {
            font-size: 28rpx;
            color: #666;
         }
      }
   }
   // 名片简介
   .card-intro {
      background: #fff;
      border-radius: 20rpx;
      padding: 30rpx;
      margin-top: 30rpx;
      box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
      .intro-item {
         margin-bottom: 30rpx;
         &:last-child {
            margin-bottom: 0;
         }
         .intro-title {
            font-size: 32rpx;
            font-weight: bold;
            color: #333;
            margin-bottom: 16rpx;
         }
         .intro-content {
            font-size: 28rpx;
            color: #666;
            line-height: 1.6;
         }
      }
   }
   .action-section {
      position: fixed;
      bottom: 0;
      left: 0;
      width: 100%;
      background: #fff;
      box-shadow: 0 -2rpx 20rpx rgba(0, 0, 0, 0.1);
   // 跳转卡片
   .redirect-cards {
      margin-top: 30rpx;
      display: flex;
      padding: 20rpx;
      z-index: 999;
      justify-content: space-between;
      .action-left {
         flex: 1;
      .redirect-card {
         flex: 0 0 calc(50% - 15rpx);
         background: #fff;
         border-radius: 20rpx;
         overflow: hidden;
         box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
         display: flex;
         align-items: center;
         padding: 20rpx;
         .action-btn {
         .redirect-img {
            width: 80rpx;
            height: 80rpx;
            border-radius: 12rpx;
         }
         .redirect-info {
            flex: 1;
            margin-left: 20rpx;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 15rpx 30rpx;
            border-radius: 30rpx;
            border: 2rpx solid #37bde6;
            color: #37bde6;
            &.active {
               background: #37bde6;
               color: #fff;
            .redirect-title {
               font-size: 30rpx;
               color: #333;
            }
            .icon {
               font-size: 28rpx;
               margin-right: 10rpx;
            .redirect-arrow {
               font-size: 40rpx;
               color: #999;
            }
         }
      }
   }
      .action-right {
         flex: 2;
   // 数字资产卡片
   .asset-cards {
      margin-top: 30rpx;
      display: flex;
      justify-content: space-between;
         .share-btn {
      .asset-card {
         flex: 0 0 calc(50% - 15rpx);
         overflow: hidden;
         border-radius: 20rpx;
         .asset-img {
            width: 100%;
            background: linear-gradient(90deg, #44bbff, #2b81ff);
            color: #fff;
            height: 200rpx;
            border-radius: 20rpx;
         }
      }
   }
   // 底部间距
   .bottom-space {
      height: 150rpx;
   }
   // 底部固定按钮
   .bottom-btn-section {
      position: fixed;
      bottom: 0;
      left: 0;
      width: calc(100% - 60rpx);
      background: #fff;
      padding: 20rpx 30rpx 40rpx;
      box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05);
      z-index: 999;
      display: flex;
      gap: 10rpx;
      .create-card-btn {
         background: linear-gradient(90deg, #ff1529, #ff435f);
         color: #fff;
         font-weight: bold;
         padding: 10rpx 0;
         border-radius: 60rpx;
         border: none;
         width: 100%;
      }
      .desensitization {
         background: linear-gradient(-45deg, #fe632a 0%, #ff7a04 100%) !important;
      }
   }
   // 支付弹窗
   .payment-modal {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: rgba(0, 0, 0, 0.5);
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 9999;
      .modal-content {
         background-color: #fff;
         width: 80%;
         border-radius: 20rpx;
         overflow: hidden;
         .modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 24rpx 32rpx;
            border-bottom: 1rpx solid #e0e0e0;
            .title {
               font-size: 32rpx;
               font-weight: bold;
               color: #333;
            }
            .close {
               font-size: 40rpx;
               color: #999;
            }
         }
         .payment-info {
            padding: 32rpx;
            text-align: center;
            padding: 24rpx 0;
            border-radius: 30rpx;
            font-size: 32rpx;
            font-weight: bold;
            .name {
               font-size: 36rpx;
               font-weight: bold;
               color: #333;
               margin-bottom: 8rpx;
            }
            .position {
               font-size: 28rpx;
               color: #666;
               margin-bottom: 24rpx;
            }
            .price {
               font-size: 48rpx;
               font-weight: bold;
               color: #ff4757;
            }
         }
         .payment-methods {
            border-top: 1rpx solid #e0e0e0;
            .method-item {
               display: flex;
               justify-content: space-between;
               align-items: center;
               padding: 28rpx 32rpx;
               border-bottom: 1rpx solid #f0f0f0;
               font-size: 28rpx;
               color: #333;
               &.active {
                  color: #37bde6;
               }
               .icon-check {
                  font-size: 32rpx;
               }
            }
         }
         .modal-footer {
            display: flex;
            padding: 24rpx 32rpx;
            .cancel-btn,
            .confirm-btn {
               flex: 1;
               text-align: center;
               padding: 20rpx 0;
               border-radius: 8rpx;
               font-size: 28rpx;
            }
            .cancel-btn {
               color: #666;
               margin-right: 20rpx;
               background-color: #f5f5f5;
            }
            .confirm-btn {
               color: #fff;
               background-color: #D41003;
            }
         }
      }
   }