468 lines
15 KiB
Vue
468 lines
15 KiB
Vue
<template>
|
||
<view class="conatiner">
|
||
<!-- 顶部固定:头像行吸顶,避让胶囊的 paddingTop 移到 header 内 -->
|
||
<view class="header" :style="{ paddingTop: top + 15 + 'px' }" @click="toLogin">
|
||
<view class="avatar-container">
|
||
<image class="avatar" :src="userInfo.userPic || 'https://static.hshuishang.com/person/Group_309.png'"
|
||
mode="" />
|
||
</view>
|
||
<view class="avatar_right">
|
||
<view class="avatar_title">
|
||
<view class="login-btn">{{ userInfo.nick_name ? userInfo.nick_name : '登录/注册' }}</view>
|
||
<view class="avatar_setting">
|
||
<view class="avatar_setting_box">
|
||
<image src="https://static.hshuishang.com/property-img-file/page_user_Vector13.png" mode=""
|
||
@click.stop="headerRefreshClick" />
|
||
</view>
|
||
<!-- <button class="login-btn" open-type="getPhoneNumber" style="display: none;"
|
||
@click="headerLoginClick" @getphonenumber="getPhoneNumber" id="hiddenLoginBtn"></button> -->
|
||
<view class="avatar_setting_box">
|
||
<image src="https://static.hshuishang.com/property-img-file/page_user_Vector14.png" mode=""
|
||
@click.stop="headerSettingsClick" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="avater_mobile">{{ userInfo.mobile }}</view>
|
||
</view>
|
||
</view>
|
||
<!-- 我的钱包:白卡 + 标题/眼睛(金额显隐)+ 资产横排(样式对齐原型个人中心) -->
|
||
<view class="wallet-card">
|
||
<view class="wallet-head">
|
||
<text class="wallet-title">我的钱包</text>
|
||
<u-icon :name="walletVisible ? 'eye' : 'eye-off'" color="#888888" size="32"
|
||
@click="walletVisible = !walletVisible"></u-icon>
|
||
</view>
|
||
<view class="wallet-assets">
|
||
<view class="asset-item" @click="goWallet(1, userInfo)">
|
||
<view class="asset-value">{{ walletVisible ? (userInfo.points || 0) : '****' }}</view>
|
||
<view class="asset-label">积分</view>
|
||
</view>
|
||
<view class="asset-item">
|
||
<view class="asset-value">{{ walletVisible ? '0.00' : '****' }}</view>
|
||
<view class="asset-label">通宝</view>
|
||
</view>
|
||
<view class="asset-item" @click="goWallet(2, userInfo)">
|
||
<view class="asset-value">{{ walletVisible ? (userInfo.property_housing_fund || 0) + '元' : '****' }}</view>
|
||
<view class="asset-label">岁银</view>
|
||
</view>
|
||
<view class="asset-item" @click="goRedPacket()">
|
||
<view class="asset-value">{{ walletVisible ? redPacketMoney + '元' : '****' }}</view>
|
||
<view class="asset-label">红包中心</view>
|
||
</view>
|
||
<view class="asset-item" @click="headerGoldClick">
|
||
<view class="asset-value">{{ walletVisible ? '0' : '****' }}</view>
|
||
<view class="asset-label">商票</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 物业快捷入口:三格横排卡(样式对齐原型个人中心 quick-card) -->
|
||
<view class="quick-card">
|
||
<view class="quick-item" @click="handleCommunityClick">
|
||
<view class="quick-text">
|
||
<text class="quick-title">我的房产</text>
|
||
<text class="quick-sub">查看房产 ›</text>
|
||
</view>
|
||
<image class="quick-icon"
|
||
src="https://static.hshuishang.com/property-img-file/page_user_Group_1382.png" />
|
||
</view>
|
||
<view class="quick-item" @click="handleApplyOwnerClick">
|
||
<view class="quick-text">
|
||
<text class="quick-title">物业账单</text>
|
||
<text class="quick-sub">去缴费 ›</text>
|
||
</view>
|
||
<image class="quick-icon"
|
||
src="https://static.hshuishang.com/property-img-file/page_user_Group_1559.png" />
|
||
</view>
|
||
<view class="quick-item" @click="handleFacilityClick">
|
||
<view class="quick-text">
|
||
<text class="quick-title">我的工单</text>
|
||
<text class="quick-sub">报修进度 ›</text>
|
||
</view>
|
||
<image class="quick-icon"
|
||
src="https://static.hshuishang.com/property-img-file/page_user_Group_1557.png" />
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 我的订单:标题 + 全部入口 + 五状态格(点击进订单页对应状态 tab) -->
|
||
<view class="module-card">
|
||
<view class="module-head">
|
||
<text class="module-title">我的订单</text>
|
||
<view class="module-link" @click="goOrderTab(0)">
|
||
全部<u-icon name="arrow-right" color="#999999" size="22"></u-icon>
|
||
</view>
|
||
</view>
|
||
<view class="order-status-row">
|
||
<view class="status-item" v-for="t in orderTabs" :key="t.label" @click="goOrderTab(t.tab)">
|
||
<image class="status-icon" :src="t.icon" />
|
||
<text class="status-label">{{ t.label }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 服务目录:行点击弹出全部功能抽屉并定位到对应分组 -->
|
||
<view class="module-card service-card">
|
||
<view class="service-row" v-for="g in visibleGroups" :key="g.key" @click="openDrawer(g.key)">
|
||
<image class="service-icon" :src="g.icon" />
|
||
<text class="service-label">{{ g.title }}</text>
|
||
<u-icon name="arrow-right" color="#c0c4cc" size="26"></u-icon>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 全部功能抽屉:底部弹出 + 滚动定位到目标分组 -->
|
||
<u-popup :show="drawerShow" mode="bottom" round="24rpx" :safe-area-inset-bottom="true"
|
||
@close="drawerShow = false" @open="onDrawerOpened">
|
||
<view class="fd-wrap">
|
||
<view class="fd-head">
|
||
<text class="fd-title">全部功能</text>
|
||
<u-icon class="fd-close" name="close" color="#999999" size="32"
|
||
@click="drawerShow = false"></u-icon>
|
||
</view>
|
||
<!-- 微信小程序下 scroll-into-view 对插槽内容 id 无效,改用 scroll-top 定位 -->
|
||
<scroll-view scroll-y class="fd-body" :scroll-top="drawerScrollTop" scroll-with-animation>
|
||
<view v-for="g in visibleGroups" :key="g.key" :id="'grp-' + g.key" class="fd-group">
|
||
<view class="fd-group-title">{{ g.title }}</view>
|
||
<view class="fd-grid">
|
||
<view class="fd-item" v-for="it in g.items" :key="it.name" @click="drawerItemClick(it)">
|
||
<image class="fd-item-icon" :src="it.icon" />
|
||
<text class="fd-item-name">{{ it.name }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</u-popup>
|
||
<!-- <view class="customer" @click="headerCustomerClick">
|
||
<image src="https://static.hshuishang.com/property-img-file/page_user_Vector16.png"
|
||
mode="" />
|
||
<view>客服</view>
|
||
</view> -->
|
||
<view style="padding-top: 174rpx;"></view>
|
||
<nav-footer :current="4" />
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { apiArr } from '../../api/login';
|
||
import { apiArr as apiArr2 } from '../../api/v2User';
|
||
import { apiArr as apiArr3 } from '../../api/user';
|
||
import { menuButtonInfo, NavgateTo, picUrl, request } from '../../utils/index';
|
||
import { ORDER_TABS, MENU_GROUPS, FUNC_GROUP_META, FUNC_ICONS } from './profile-menu.js';
|
||
export default {
|
||
data() {
|
||
return {
|
||
top: 0,
|
||
redPacketMoney: '0.00',
|
||
// 我的订单五状态格 + 服务目录分组(数据见 profile-menu.js)
|
||
orderTabs: ORDER_TABS,
|
||
menuGroups: MENU_GROUPS,
|
||
// 功能服务(登录态控制显隐,图标按端从 FUNC_ICONS 映射)
|
||
shopManagementList: [
|
||
{
|
||
name: "商家端",
|
||
url: "/packages/storeManagement/index/index",
|
||
isShow: uni.getStorageSync('is_merchant'),
|
||
},
|
||
{
|
||
name: "物业端",
|
||
url: "/packages/workOrderDashboard/guide/index",
|
||
isShow: uni.getStorageSync("is_worker"),
|
||
},
|
||
{
|
||
name: "师傅端",
|
||
url: "/packages/homeService/worker/index",
|
||
isShow: uni.getStorageSync("is_merchant"),
|
||
}
|
||
],
|
||
userInfo: {},
|
||
isShop: uni.getStorageSync('is_shop'),
|
||
// 钱包金额显隐(眼睛开关,隐藏时显示 ****)
|
||
walletVisible: true,
|
||
// 全部功能抽屉:显隐 + 目标分组 key + 滚动定位(scroll-top 像素值)
|
||
drawerShow: false,
|
||
drawerTargetKey: '',
|
||
drawerScrollTop: 0,
|
||
}
|
||
},
|
||
|
||
computed: {
|
||
// 服务目录:5 个固定分组 + 功能服务(有可见项时置于最后)
|
||
visibleGroups() {
|
||
const groups = [...this.menuGroups];
|
||
const funcItems = this.shopManagementList
|
||
.filter(item => item.isShow)
|
||
.map(item => ({ name: item.name, url: item.url, icon: FUNC_ICONS[item.name] }));
|
||
if (funcItems.length) {
|
||
groups.push({ ...FUNC_GROUP_META, items: funcItems });
|
||
}
|
||
return groups;
|
||
},
|
||
},
|
||
|
||
methods: {
|
||
goWallet(type, item) {
|
||
NavgateTo('/packages/user/wallet/index?type=' + type + '&item=' + JSON.stringify(item));
|
||
},
|
||
goRedPacket() {
|
||
NavgateTo('/packages/user/redPacket/index');
|
||
},
|
||
// 头像点击
|
||
toLogin() {
|
||
NavgateTo('/packages/user/replenishInfo/index');
|
||
},
|
||
|
||
// 刷新
|
||
headerRefreshClick() {
|
||
uni.showLoading({
|
||
title: '刷新中',
|
||
mask: true
|
||
})
|
||
// 清楚缓存信息
|
||
uni.removeStorageSync('ctoken');
|
||
uni.removeStorageSync('userId');
|
||
uni.removeStorageSync('openId');
|
||
uni.removeStorageSync('phone');
|
||
uni.removeStorageSync('is_deal');
|
||
uni.removeStorageSync('is_dev');
|
||
uni.removeStorageSync('is_shop');
|
||
uni.removeStorageSync('is_merchant');
|
||
uni.removeStorageSync('is_worker');
|
||
uni.removeStorageSync('shopId');
|
||
uni.removeStorageSync('order_dispatch_permission');
|
||
uni.removeStorageSync('work_order_permission');
|
||
|
||
const button = uni.createSelectorQuery().select('#hiddenLoginBtn');
|
||
button.boundingClientRect().exec();
|
||
|
||
// 执行原headerLoginClick逻辑
|
||
this.headerLoginClick();
|
||
},
|
||
|
||
headerLoginClick() {
|
||
let that = this;
|
||
uni.login({
|
||
onlyAuthorize: true,
|
||
success: (res) => {
|
||
request(apiArr.login, 'POST', {
|
||
code: res.code,
|
||
phone: '',
|
||
password: '',
|
||
}, { silent: false }).then((loginRes) => {
|
||
// 存储用户信息
|
||
uni.setStorageSync('ctoken', loginRes.token);
|
||
uni.setStorageSync('is_deal', loginRes.is_deal);
|
||
uni.setStorageSync('is_dev', loginRes.is_dev);
|
||
uni.setStorageSync('is_shop', loginRes.is_shop);
|
||
uni.setStorageSync('is_merchant', loginRes.is_merchant);
|
||
uni.setStorageSync('is_worker', loginRes.is_worker);
|
||
|
||
// 重置用户信息状态
|
||
this.userInfo = {};
|
||
// 更新功能服务显隐(商家端/师傅端看 is_merchant,物业端看 is_worker)
|
||
this.shopManagementList = this.shopManagementList.map(item => ({
|
||
...item,
|
||
isShow: item.name === '物业端' ? loginRes.is_worker : loginRes.is_merchant,
|
||
}));
|
||
|
||
|
||
// 获取用户信息
|
||
request(apiArr.loginInfo, 'POST', {
|
||
token: loginRes.token
|
||
}, { silent: false }).then((res2) => {
|
||
if (res2.error) return;
|
||
// 保存userId 后续接口使用
|
||
uni.setStorageSync('userId', res2.user_id);
|
||
uni.setStorageSync('openId', res2.open_id);
|
||
uni.setStorageSync('shopId', res2.wshop_id);
|
||
that.getUserInfo(true)
|
||
|
||
})
|
||
}, (err) => {
|
||
uni.hideLoading();
|
||
console.warn('登录接口错误', err);
|
||
})
|
||
}
|
||
})
|
||
},
|
||
|
||
// 小程序登录获取手机号接口(隐藏登录按钮回调占位,暂无逻辑)
|
||
getPhoneNumber() {},
|
||
|
||
|
||
// 设置
|
||
headerSettingsClick() {
|
||
NavgateTo('/packages/user/index/index');
|
||
},
|
||
|
||
// 客服(入口已注释,占位保留)
|
||
headerCustomerClick() {},
|
||
|
||
// 我的社区跳转
|
||
handleCommunityClick() {
|
||
NavgateTo('/packages/community/myCommunity/index')
|
||
},
|
||
|
||
// 物业账单跳转
|
||
handleApplyOwnerClick() {
|
||
NavgateTo(`/packages/community/propertyPayment/index`)
|
||
},
|
||
|
||
// 我的工单跳转
|
||
handleFacilityClick() {
|
||
const communityId = uni.getStorageSync('changeCommData').id;
|
||
NavgateTo(`/packages/workOrderDashboard/index/index?communityId=${communityId}`)
|
||
},
|
||
|
||
headerGoldClick() {
|
||
this.NotOpen();
|
||
// NavgateTo(`/packages/community/ownerList/index`)
|
||
},
|
||
|
||
// 我的订单:跳订单列表并定位到指定状态 tab(0全部/1待付款/2待发货/3已取消/4待评价/6售后)
|
||
goOrderTab(tab) {
|
||
NavgateTo('/packages/myOrders/index/index?tab=' + tab);
|
||
},
|
||
|
||
// 打开全部功能抽屉,目标分组在弹窗动画结束(@open)后测量定位
|
||
openDrawer(key) {
|
||
this.drawerTargetKey = key;
|
||
this.drawerShow = true;
|
||
},
|
||
|
||
// 弹窗打开动画完成:测量目标分组位置并滚动定位
|
||
onDrawerOpened() {
|
||
this.measureDrawerTarget(2);
|
||
},
|
||
|
||
// 测量并滚动到目标分组;首次打开时渲染层可能未就绪(v-if 懒渲染),查不到节点则短暂重试
|
||
measureDrawerTarget(retry) {
|
||
const key = this.drawerTargetKey;
|
||
if (!key) return;
|
||
const query = uni.createSelectorQuery().in(this);
|
||
query.select('.fd-body').boundingClientRect();
|
||
query.select('.fd-body').scrollOffset();
|
||
query.select('#grp-' + key).boundingClientRect();
|
||
query.exec((res) => {
|
||
const [body, offset, target] = res || [];
|
||
if (!body || !offset || !target) {
|
||
if (retry > 0) {
|
||
setTimeout(() => this.measureDrawerTarget(retry - 1), 50);
|
||
}
|
||
return;
|
||
}
|
||
const top = Math.max(0, target.top - body.top + offset.scrollTop);
|
||
// scroll-top 相同值不触发滚动:先同步为当前实际位置再赋目标值
|
||
this.drawerScrollTop = offset.scrollTop;
|
||
this.$nextTick(() => {
|
||
this.drawerScrollTop = top;
|
||
});
|
||
});
|
||
},
|
||
|
||
// 抽屉内功能项点击:关抽屉后按原跳转逻辑处理
|
||
drawerItemClick(item) {
|
||
this.drawerShow = false;
|
||
this.headerOrderClick(item);
|
||
},
|
||
|
||
// 我的订单跳转
|
||
headerOrderClick(event) {
|
||
if (!event.url) {
|
||
this.NotOpen();
|
||
return
|
||
} else {
|
||
// if (!uni.getStorageSync('city')) {
|
||
// wx.showModal({
|
||
// title: '提示',
|
||
// content: '请先选择您的城市',
|
||
// confirmText:"去选择",
|
||
// complete: (res) => {
|
||
// if (res.cancel) {}
|
||
// if (res.confirm) {
|
||
// NavgateTo( '/pages/index/shopcity')
|
||
// }
|
||
// }
|
||
// })
|
||
// return
|
||
// }
|
||
NavgateTo(`${event.url}`)
|
||
}
|
||
},
|
||
|
||
// 暂未开通服务弹窗
|
||
NotOpen() {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '此功能暂未开通!',
|
||
showCancel: false,
|
||
complete: (res) => {
|
||
if (res.cancel) {
|
||
|
||
}
|
||
}
|
||
})
|
||
return
|
||
},
|
||
|
||
|
||
async getUserInfo(item = false) {
|
||
const isCtoken = uni.getStorageSync('ctoken');
|
||
if (!isCtoken) return;
|
||
const res = await request(apiArr2.getUserInfo, 'POST', {}, { silent: item === true ? false : true });
|
||
const newUserInfo = {
|
||
...res,
|
||
userPic: res.avatar ? `${picUrl}${res.avatar}` : 'https://static.hshuishang.com/person/Group_309.png'
|
||
};
|
||
this.userInfo = newUserInfo;
|
||
if (item) {
|
||
const { community_worker } = res;
|
||
uni.setStorageSync('order_dispatch_permission', community_worker && community_worker[0].order_dispatch_permission == 1 || false);
|
||
uni.setStorageSync('work_order_permission', community_worker && community_worker[0].work_order_permission == 1 || false);
|
||
uni.setStorageSync('phone', res.account);
|
||
uni.hideLoading();
|
||
// uni.showToast({
|
||
// title: '刷新成功',
|
||
// icon: 'success',
|
||
// mask: true,
|
||
// duration: 2000,
|
||
// })
|
||
}
|
||
},
|
||
async getMyRedPacket() {
|
||
const params = {
|
||
user_id: uni.getStorageSync('userId'),
|
||
}
|
||
const res = await request(apiArr3.redPackageMyred, 'POST', params);
|
||
|
||
let processedList = res.rows
|
||
.filter(item => item.status !== 3)
|
||
.map(item => {
|
||
const newItem = { ...item };
|
||
|
||
if (newItem?.agent_info?.ad?.ad_name) {
|
||
newItem.agent_info.ad.ad_name = newItem.agent_info.ad.ad_name.split(',').join('');
|
||
}
|
||
|
||
return newItem;
|
||
});
|
||
this.redPacketMoney = processedList.reduce((total, item) =>
|
||
item.red_package_config ? total + item.red_package_config.money : total, 0.00
|
||
).toFixed(2);
|
||
},
|
||
},
|
||
onLoad() {
|
||
const meun = menuButtonInfo();
|
||
this.top = meun.height + meun.top;
|
||
},
|
||
|
||
onShow() {
|
||
this.getUserInfo();
|
||
this.getMyRedPacket();
|
||
// this.headerLoginClick();
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
@import url("./index.css");
|
||
</style> |