From 6f12eadd25c8f5335fd9eccf373bf9835bf3e4c6 Mon Sep 17 00:00:00 2001
From: quanwei <419654421@qq.com>
Date: Sat, 15 Nov 2025 18:12:50 +0800
Subject: [PATCH] 添加名片聊天功能(未完成)
---
mobile/pages/plus/business/index.vue | 601 ++++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 468 insertions(+), 133 deletions(-)
diff --git a/mobile/pages/plus/business/index.vue b/mobile/pages/plus/business/index.vue
index fc981c4..6fd9929 100644
--- a/mobile/pages/plus/business/index.vue
+++ b/mobile/pages/plus/business/index.vue
@@ -1,41 +1,19 @@
<template>
<view>
- <header-bar title="我的名片" :isBack="true" @click="back"></header-bar>
<!-- 名片展示区域 -->
<view class="content">
- <view class="business-card" v-if="businessList.length > 0">
- <image class="top-image" :src="businessList[current].background_image" mode="aspectFill"></image>
- <view class="business-info">
- <image class="avatar" :src="businessList[current].avatar" mode="aspectFill"></image>
- <view class="info-text">
- <view class="name">{{businessList[current].real_name}}</view>
- <view class="company">{{businessList[current].company_name}}</view>
- <view class="position">{{businessList[current].position}}</view>
- </view>
- </view>
- <view class="business-contact">
- <view class="contact-item" @click="makePhoneCall(businessList[current].phone)">
- <text class="icon iconfont icon-phone"></text>
- <text class="text">{{businessList[current].phone}}</text>
- </view>
- <view class="contact-item" v-if="businessList[current].mobile"
- @click="makePhoneCall(businessList[current].mobile)">
- <text class="icon iconfont icon-mobile"></text>
- <text class="text">{{businessList[current].mobile}}</text>
- </view>
- <view class="contact-item" v-if="businessList[current].email"
- @click="sendEmail(businessList[current].email)">
- <text class="icon iconfont icon-email"></text>
- <text class="text">{{businessList[current].email}}</text>
- </view>
- </view>
+ <view class="business-card">
+ <image style="width: 100%;" @tap="viewPicture(businessImage)" mode="widthFix" :src="businessImage">
+ </image>
</view>
<!-- 名片操作按钮 -->
<view class="action-buttons">
<view class="btn" @click="editCard()">编辑名片</view>
<view class="btn" @click="switchCard()">切换名片</view>
- <view class="btn" @click="shareCard()">分享名片</view>
+ <button open-type="share" class="btn">分享名片</button>
+ <view class="btn" @click="topUpCard()">置顶名片</view>
+ <view class="btn" @click="gotoChatList()">聊天记录</view>
</view>
<!-- 数据统计区域 -->
@@ -61,109 +39,188 @@
<text class="more" @click="viewAllVisitors()">查看全部</text>
</view>
<view class="visitor-list">
- <view class="visitor-item" v-for="(visitor, index) in visitors" :key="index">
- <image class="visitor-avatar" :src="visitor.avatar || '/static/default.png'" mode="aspectFill">
+ <view class="visitor-item" v-for="(visitor, index) in visitors.data" :key="index">
+ <image class="visitor-avatar" :src="visitor.user.avatarUrl || '/static/default.png'"
+ mode="aspectFill">
</image>
<view class="visitor-info">
- <view class="visitor-name">{{visitor.user_name || '未知访客'}}</view>
- <view class="visitor-time">{{formatTime(visitor.visit_time)}}</view>
+ <view class="visitor-name">{{visitor.user.nickName || '未知访客'}}</view>
+ <view class="visitor-time">{{visitor.update_time}}</view>
</view>
</view>
</view>
</view>
+ </view>
- <!-- 切换名片弹窗 -->
- <uni-popup ref="popup" type="bottom" :mask-click="false">
- <view class="popup-content">
- <view class="popup-header">
- <text class="title">选择名片</text>
- <text class="close" @click="closePopup">×</text>
- </view>
- <scroll-view scroll-y="true" class="card-scroll">
- <view class="card-item" v-for="(card, index) in businessList" :key="index"
- :class="{active: index === current}" @click="selectCard(index)">
- <view class="card-preview">
- <view class="card-name">{{card.real_name}}</view>
- <view class="card-company">{{card.company_name}}</view>
- </view>
- <text v-if="index === current" class="icon iconfont icon-check"></text>
- </view>
- <view class="add-card" @click="addNewCard()">
- <text class="icon iconfont icon-add"></text>
- <text>添加新名片</text>
- </view>
- </scroll-view>
+ <!-- 切换名片弹窗 -->
+ <Popup :show="popupShow" type="bottom" :width="screenWidth" :mask-click="false">
+ <view class="popup-content">
+ <view class="popup-header">
+ <text class="title">选择名片</text>
+ <text class="close" @click="closePopup">×</text>
</view>
- </uni-popup>
+ <scroll-view scroll-y="true" class="card-scroll">
+ <uni-swipe-action>
+ <view v-for="(card, index) in businessList" :key="index">
+ <uni-swipe-action-item :right-options="rightOptions" @click="handleDel(index, card)">
+ <view @click="selectCard(index)" class="card-item">
+ <view :class="{active: card.is_default==1}" class="card-preview">
+ <image style="width: 650rpx;border-radius: 12rpx;" :src="card.mp" mode="widthFix"></image>
+ <image v-show="card.is_default==1" src="@/static/icon/mrmp.png" class="mrmp"></image>
+ </view>
+ </view>
+ </uni-swipe-action-item>
+ </view>
+ </uni-swipe-action>
+ <view class="add-card" @click="addNewCard()">
+ <text class="icon iconfont icon-add"></text>
+ <text>添加新名片</text>
+ </view>
+ </scroll-view>
+ </view>
+ </Popup>
+
+ <!-- 支付弹窗 -->
+ <view class="payment-modal" v-if="showPayment">
+ <view class="modal-content">
+ <view class="modal-header">
+ <text class="title">名片置顶确认</text>
+ <text class="close" @click="closePaymentModal">×</text>
+ </view>
+ <view class="modal-body">
+ <view class="payment-info">
+ <view class="info-item">
+ <text class="label">置顶天数:</text>
+ <text class="value">{{topSetting.top_days}}天</text>
+ </view>
+ <view class="info-item">
+ <text class="label">支付金额:</text>
+ <text class="value price">¥{{topSetting.top_amount}}</text>
+ </view>
+ </view>
+ </view>
+ <view class="modal-footer">
+ <button class="cancel-btn" @click="closePaymentModal">取消</button>
+ <button class="confirm-btn" @click="confirmPayment">确认支付</button>
+ </view>
+ </view>
</view>
</view>
</template>
<script>
+ import Popup from '@/components/uni-popup.vue';
+import uniSwipeAction from '@/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue';
+import uniSwipeActionItem from '@/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue';
export default {
+ components: {
+ Popup,
+ uniSwipeAction,
+ uniSwipeActionItem
+ },
data() {
return {
+ businessImage: '',
+ business_card_id: '',
+ height: 0,
businessList: [],
current: 0,
statistics: {},
- visitors: [],
- loading: false,
- page: 1,
- search: ''
+ visitors: {},
+ popupShow: false,
+ screenWidth: 0,
+ showPayment: false, // 显示支付弹窗
+ paymentMethod: 'balance', // 支付方式
+ topSetting: {}, // 置顶设置
+ userInfo: {}, // 用户信息
+ rightOptions: [{
+ text: '删除',
+ style: {
+ backgroundColor: '#FF3B30'
+ }
+ }]
};
},
onLoad() {
- this.init();
- },
- onShow() {
+ this.screenWidth = uni.getSystemInfoSync().windowWidth * 2 - 70;
this.getbusinessList();
this.getVisitorList();
},
methods: {
- back() {
- uni.navigateBack();
- },
- init() {
- this.getbusinessList();
- this.getStatistics();
- this.getVisitorList();
- },
getbusinessList() {
let _this = this;
- _this._post('plus.business/business/getList', {}, function(res) {
- _this.businessList = res.data;
+ _this._post('plus.business.business/getList', {
+ page: 1,
+ list_rows: 1000,
+ user_id: _this.getUserId()
+ }, function(res) {
+ _this.businessList = res.data.data;
if (_this.businessList.length > 0) {
+ for(let i in _this.businessList){
+ if(_this.businessList[i].is_default==1){
+ _this.current=i;
+ }
+ }
+ _this.getbusiness(_this.businessList[_this.current].user_id)
+ _this.shareCard();
_this.getCardStatistics(_this.businessList[_this.current].business_card_id);
}
});
},
getCardStatistics(business_card_id) {
let _this = this;
- _this._post('plus.business/business/getStatistics', {
+ _this._post('plus.business.business/getStatistics', {
business_card_id: business_card_id
}, function(res) {
_this.statistics = res.data;
});
},
- getStatistics() {
- // 获取统计数据
+
+ getStatistics(business_card_id) {
+ // 默认名片
let _this = this;
- _this._post('plus.business/business/getStatistics', {}, function(res) {
- _this.statistics = res.data;
+ _this._post('plus.business.business/editDefault', {
+ business_card_id: business_card_id
+ }, function(res) {
+ _this.getbusinessList();
+ _this.getVisitorList();
});
+ },
+ getbusiness(user_id) {
+ this._get('plus.business.business/getDetail', {
+ user_id: user_id
+ }, res => {
+ this.businessImage = res.data.mp
+ this.height = res.data.height
+ this.business_card_id = res.data.business_card_id
+ })
},
getVisitorList() {
let _this = this;
- _this._post('plus.business/business/getVisitors', {
+ _this._post('plus.business.saving/getList', {
page: 1,
list_rows: 10
}, function(res) {
- _this.visitors = res.data.list;
+ console.log(res);
+ _this.visitors = res.data;
});
},
makePhoneCall(phone) {
uni.makePhoneCall({
phoneNumber: phone
+ });
+ },
+ viewPicture(url) {
+ this.gotoPage(
+ `/pages/plus/business/detail?business_card_id=${this.businessList[this.current].business_card_id}`
+ );
+ },
+ getbusinessDetail() {
+ let _this = this;
+ _this._post('plus.business.business/detail', {
+ business_card_id: _this.business_card_id
+ }, function(res) {
+ _this.businessDetail = res.data;
});
},
sendEmail(email) {
@@ -178,36 +235,101 @@
if (this.businessList.length > 0) {
this.gotoPage(
`/pages/plus/business/add?business_card_id=${this.businessList[this.current].business_card_id}`
- );
+ );
+ }else{
+ this.gotoPage(
+ `/pages/plus/business/add`
+ );
}
},
switchCard() {
- this.$refs.popup.open();
+ this.popupShow = true;
+ //this.$refs.popup.open();
},
closePopup() {
- this.$refs.popup.close();
+ this.popupShow = false;
+ //this.$refs.popup.close();
},
selectCard(index) {
this.current = index;
- this.getCardStatistics(this.businessList[this.current].business_card_id);
+ this.getStatistics(this.businessList[this.current].business_card_id);
this.closePopup();
},
addNewCard() {
- this.closePopup();
+ //this.closePopup();
this.gotoPage('/pages/plus/business/add');
},
shareCard() {
// 分享名片逻辑
- if (this.businessList.length > 0) {
- uni.showShareMenu({
- withShareTicket: true,
- menus: ['shareAppMessage', 'shareTimeline']
- });
- }
+
},
viewAllVisitors() {
// 查看全部访客
this.gotoPage('/pages/plus/business/visitors');
+ },
+
+ // 跳转到聊天记录页面
+ gotoChatList() {
+ uni.navigateTo({
+ url: '/pages/plus/business/chat/list'
+ });
+ },
+ // 置顶名片
+ topUpCard() {
+ if (this.businessList.length > 0) {
+ // 获取置顶设置
+ this._get('plus.business.setting/getAll', {}, (res) => {
+ if (res.data && res.data.basic && res.data.basic.values) {
+ this.topSetting = res.data.basic.values;
+ // 获取用户信息
+ this._get('user.index/detail', {}, (userRes) => {
+ this.userInfo = userRes.data;
+ this.showPayment = true;
+ });
+ }
+ });
+ }
+ },
+ // 关闭支付弹窗
+ closePaymentModal() {
+ this.showPayment = false;
+ },
+ // 选择支付方式
+ selectPaymentMethod(method) {
+ this.paymentMethod = method;
+ },
+ // 确认支付
+ confirmPayment() {
+ if (this.businessList.length > 0) {
+ let payType = this.paymentMethod === 'balance' ? 10 : 20;
+ let params = {
+ business_card_id: this.businessList[this.current].business_card_id,
+ pay_type: payType
+ };
+
+ this._post('plus.business.top/create', params, (res) => {
+ if (res.code === 1) {
+ // 如果是余额支付,直接处理
+ if (this.paymentMethod === 'balance') {
+ // 直接跳转支付
+ uni.redirectTo({
+ url: '/pages/plus/business/cashier?order_id=' + res.data.order_id +
+ '&order_type=100'
+ });
+ } else {
+ // 跳转到收银台支付
+ uni.redirectTo({
+ url: '/pages/plus/business/cashier?order_id=' + res.data.order_id +
+ '&order_type=100'
+ });
+ }
+ } else {
+ this.showError(res.msg || '创建订单失败');
+ }
+ }, (err) => {
+ this.showError('创建订单失败,请重试');
+ });
+ }
},
formatTime(time) {
if (!time) return '';
@@ -224,12 +346,60 @@
} else {
return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
}
+ },
+ // 删除名片
+ handleDel(index, card) {
+ // 防止删除默认名片
+ if (card.is_default === 1) {
+ this.showToast('默认名片不能删除');
+ return;
+ }
+
+ uni.showModal({
+ title: '提示',
+ content: '确定要删除这个名片吗?',
+ success: (res) => {
+ if (res.confirm) {
+ // 调用删除接口
+ this._post('plus.business.business/delete', {
+ business_card_id: card.business_card_id
+ }, (res) => {
+ if (res.code === 1) {
+ // 删除成功,更新列表
+ this.businessList.splice(index, 1);
+ this.showToast('删除成功');
+
+ // 如果删除的是当前选中的名片,切换到第一个名片
+ if (index === this.current) {
+ if (this.businessList.length > 0) {
+ this.current = 0;
+ this.getStatistics(this.businessList[this.current].business_card_id);
+ }
+ } else if (index < this.current) {
+ // 如果删除的是当前选中名片之前的,current减1
+ this.current--;
+ }
+ } else {
+ this.showToast(res.msg || '删除失败');
+ }
+ });
+ }
+ }
+ });
+ },
+ // 显示提示信息
+ showToast(msg) {
+ uni.showToast({
+ title: msg,
+ icon: 'none',
+ duration: 2000
+ });
}
},
onShareAppMessage() {
if (this.businessList.length > 0) {
return {
- title: `${this.businessList[this.current].real_name}的电子名片`,
+ title: `${this.businessList[this.current].name}的电子名片`,
path: `/pages/plus/business/detail?business_card_id=${this.businessList[this.current].business_card_id}&referee_id=${this.getUserId()}`
};
}
@@ -241,7 +411,7 @@
onShareTimeline() {
if (this.businessList.length > 0) {
return {
- title: `${this.businessList[this.current].real_name}的电子名片`,
+ title: `${this.businessList[this.current].name}的电子名片`,
path: `/pages/plus/business/detail?business_card_id=${this.businessList[this.current].business_card_id}&referee_id=${this.getUserId()}`
};
}
@@ -262,7 +432,6 @@
background: #fff;
border-radius: 20rpx;
overflow: hidden;
- padding-bottom: 30rpx;
.top-image {
width: 100%;
@@ -317,7 +486,7 @@
.icon {
font-size: 32rpx;
- color: #37bde6;
+ color: #D41003;
margin-right: 16rpx;
}
@@ -336,13 +505,14 @@
.btn {
flex: 1;
- background: #37bde6;
+ background: #D41003;
color: #fff;
text-align: center;
padding: 24rpx 0;
border-radius: 10rpx;
font-size: 30rpx;
margin: 0 10rpx;
+ line-height: normal;
}
}
@@ -359,7 +529,7 @@
align-items: center;
.number {
- font-size: 40rpx;
+ font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 8rpx;
@@ -375,20 +545,14 @@
.visitors {
background: #fff;
border-radius: 20rpx;
+ padding: 30rpx;
margin-top: 30rpx;
- padding: 20rpx;
.section-title {
display: flex;
justify-content: space-between;
align-items: center;
- margin-bottom: 20rpx;
-
- .title {
- font-size: 32rpx;
- font-weight: bold;
- color: #333;
- }
+ margin-bottom: 30rpx;
.more {
font-size: 26rpx;
@@ -396,35 +560,36 @@
}
}
- .visitor-item {
- display: flex;
- align-items: center;
- padding: 20rpx 0;
- border-bottom: 1rpx solid #f0f0f0;
+ .visitor-list {
+ .visitor-item {
+ display: flex;
+ align-items: center;
+ padding: 20rpx 0;
- &:last-child {
- border-bottom: none;
- }
-
- .visitor-avatar {
- width: 80rpx;
- height: 80rpx;
- border-radius: 50%;
- }
-
- .visitor-info {
- margin-left: 20rpx;
- flex: 1;
-
- .visitor-name {
- font-size: 28rpx;
- color: #333;
- margin-bottom: 4rpx;
+ &:not(:last-child) {
+ border-bottom: 1rpx solid #f0f0f0;
}
- .visitor-time {
- font-size: 24rpx;
- color: #999;
+ .visitor-avatar {
+ width: 70rpx;
+ height: 70rpx;
+ border-radius: 50%;
+ margin-right: 20rpx;
+ }
+
+ .visitor-info {
+ flex: 1;
+
+ .visitor-name {
+ font-size: 30rpx;
+ color: #333;
+ margin-bottom: 8rpx;
+ }
+
+ .visitor-time {
+ font-size: 24rpx;
+ color: #999;
+ }
}
}
}
@@ -465,16 +630,31 @@
padding: 30rpx;
border-bottom: 1rpx solid #f0f0f0;
- &.active {
- background: #f5f5f5;
- }
.card-preview {
+ border-radius: 12rpx;
+ position: relative;
+
+ .mrmp {
+ height: 50rpx;
+ width: 50rpx;
+ position: absolute;
+ bottom: 0rpx;
+ right: 0rpx;
+ border-top-left-radius: 10rpx;
+ border-bottom-right-radius: 10rpx;
+ }
+
.card-name {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 8rpx;
+ }
+
+ &.active {
+ background: #f5f5f5;
+ border: #D41003 solid 1rpx;
}
.card-company {
@@ -494,7 +674,7 @@
align-items: center;
justify-content: center;
padding: 30rpx;
- color: #37bde6;
+ color: #D41003;
font-size: 30rpx;
.icon {
@@ -504,4 +684,159 @@
}
}
}
+
+ // 支付弹窗样式
+ .payment-modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.6);
+ z-index: 9999;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ .modal-content {
+ background: #fff;
+ border-radius: 20rpx;
+ width: 600rpx;
+ max-width: 90%;
+
+ .modal-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 30rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+
+ .title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+ }
+
+ .close {
+ font-size: 40rpx;
+ color: #999;
+ padding: 0 10rpx;
+ }
+ }
+
+ .modal-body {
+ padding: 30rpx;
+
+ .payment-info {
+ background: #f9f9f9;
+ border-radius: 10rpx;
+ padding: 20rpx;
+ margin-bottom: 30rpx;
+
+ .info-item {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 15rpx;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+
+ .label {
+ font-size: 28rpx;
+ color: #666;
+ }
+
+ .value {
+ font-size: 28rpx;
+ color: #333;
+
+ &.price {
+ color: #ff4444;
+ font-weight: bold;
+ }
+ }
+ }
+ }
+
+ .payment-methods {
+ .method-title {
+ font-size: 28rpx;
+ color: #333;
+ margin-bottom: 20rpx;
+ }
+
+ .method-item {
+ display: flex;
+ align-items: center;
+ padding: 20rpx;
+ border: 1rpx solid #f0f0f0;
+ border-radius: 10rpx;
+ margin-bottom: 20rpx;
+ position: relative;
+
+ &.active {
+ border-color: #D41003;
+ background: #f0f9ff;
+ }
+
+ .icon {
+ font-size: 40rpx;
+ margin-right: 20rpx;
+
+ &.icon-yue {
+ color: #ff9900;
+ }
+
+ &.icon-weixin {
+ color: #09bb07;
+ }
+ }
+
+ .method-name {
+ font-size: 28rpx;
+ color: #333;
+ flex: 1;
+ }
+
+ .balance {
+ font-size: 24rpx;
+ color: #999;
+ margin-right: 20rpx;
+ }
+
+ .checked {
+ color: #D41003;
+ font-size: 36rpx;
+ }
+ }
+ }
+ }
+
+ .modal-footer {
+ display: flex;
+ border-top: 1rpx solid #f0f0f0;
+
+ .cancel-btn,
+ .confirm-btn {
+ flex: 1;
+ padding: 30rpx;
+ text-align: center;
+ font-size: 30rpx;
+ border: none;
+ background: none;
+ }
+
+ .cancel-btn {
+ color: #666;
+ border-right: 1rpx solid #f0f0f0;
+ }
+
+ .confirm-btn {
+ color: #37bde6;
+ font-weight: bold;
+ }
+ }
+ }
+ }
</style>
\ No newline at end of file
--
Gitblit v1.9.2