骑手端app代码仓库创建
This commit is contained in:
26
pages/index/components/first-one.vue
Normal file
26
pages/index/components/first-one.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<!-- 分类展示:first-one 风格 -->
|
||||
<template>
|
||||
<view class="ss-flex-col">
|
||||
<view class="goods-box" v-for="item in pagination.list" :key="item.id">
|
||||
<s-goods-column
|
||||
size="sl"
|
||||
:data="item"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const props = defineProps({
|
||||
pagination: Object,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.goods-box {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
66
pages/index/components/first-two.vue
Normal file
66
pages/index/components/first-two.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<!-- 分类展示:first-two 风格 -->
|
||||
<template>
|
||||
<view>
|
||||
<view class="ss-flex flex-wrap">
|
||||
<view class="goods-box" v-for="item in pagination?.list" :key="item.id">
|
||||
<view @click="sheep.$router.go('/pages/goods/index', { id: item.id })">
|
||||
<view class="goods-img">
|
||||
<image class="goods-img" :src="item.picUrl" mode="aspectFit" />
|
||||
</view>
|
||||
<view class="goods-content">
|
||||
<view class="goods-title ss-line-1 ss-m-b-28">{{ item.name }}</view>
|
||||
<view class="goods-price">¥{{ fen2yuan(item.price) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
|
||||
const props = defineProps({
|
||||
pagination: Object,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.goods-box {
|
||||
width: calc((100% - 20rpx) / 2);
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.goods-img {
|
||||
width: 100%;
|
||||
height: 246rpx;
|
||||
border-radius: 10rpx 10rpx 0px 0px;
|
||||
}
|
||||
|
||||
.goods-content {
|
||||
width: 100%;
|
||||
background: #ffffff;
|
||||
box-shadow: 0px 0px 20rpx 4rpx rgba(199, 199, 199, 0.22);
|
||||
padding: 20rpx 0 32rpx 16rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 10rpx 10rpx;
|
||||
|
||||
.goods-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.goods-price {
|
||||
font-size: 24rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 500;
|
||||
color: #e1212b;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(2n + 1) {
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
97
pages/index/components/second-one.vue
Normal file
97
pages/index/components/second-one.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<!-- 分类展示:second-one 风格 -->
|
||||
<template>
|
||||
<view>
|
||||
<!-- 一级分类的名字 -->
|
||||
<!-- <view class="title-box ss-flex ss-col-center ss-row-center ss-p-b-30">
|
||||
<view class="title-line-left" />
|
||||
<view class="title-text ss-p-x-20">{{ props.data[activeMenu].name }}</view>
|
||||
<view class="title-line-right" />
|
||||
</view> -->
|
||||
<view class="title-box ss-flex ss-p-b-30">
|
||||
<view class="theme-line"></view>
|
||||
<view class="title-text">{{ props.data[activeMenu].name }}</view>
|
||||
</view>
|
||||
<!-- 二级分类的名字 -->
|
||||
<view class="goods-item-box ss-flex ss-flex-wrap ss-p-b-20">
|
||||
<view
|
||||
class="goods-item"
|
||||
v-for="item in props.data[activeMenu].children"
|
||||
:key="item.id"
|
||||
@tap="
|
||||
sheep.$router.go('/pages/goods/list', {
|
||||
categoryId: item.id,
|
||||
})
|
||||
"
|
||||
>
|
||||
<image class="goods-img" :src="item.picUrl" mode="aspectFill" />
|
||||
<view class="ss-p-10">
|
||||
<view class="goods-title ss-line-1">{{ item.name }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
activeMenu: [Number, String],
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title-box {
|
||||
font-weight: 800;
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
|
||||
.title-line-left,
|
||||
.title-line-right {
|
||||
width: 15px;
|
||||
height: 1px;
|
||||
background: #d2d2d2;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-item {
|
||||
width: calc((100% - 20px) / 3);
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:nth-of-type(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.goods-img {
|
||||
width: calc((100vw - 140px) / 3);
|
||||
height: calc((100vw - 140px) / 3);
|
||||
}
|
||||
|
||||
.goods-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
line-height: 40rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.goods-price {
|
||||
color: $red;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-line {
|
||||
margin-right: 15rpx;
|
||||
width: 8rpx;
|
||||
height: 28rpx;
|
||||
background: var(--ui-BG-Main);
|
||||
border-radius: 8rpx 8rpx 8rpx 8rpx;
|
||||
}
|
||||
|
||||
</style>
|
||||
480
pages/index/index.vue
Normal file
480
pages/index/index.vue
Normal file
@@ -0,0 +1,480 @@
|
||||
<!-- 接单页:将原首页替换为接单页面(含订单卡片、顶部 tab、底部批量操作栏) -->
|
||||
<template>
|
||||
<view class="receive-page">
|
||||
<!-- 顶部区域:状态 + tabs -->
|
||||
<view class="top-area" :style="headerStyle">
|
||||
<view class="top-bg"></view>
|
||||
<view class="top-inner">
|
||||
<view class="user-info">
|
||||
<image class="user-avatar" :src="driverInfo.avatar || defaultAvatar" mode="cover" />
|
||||
<view class="user-meta">
|
||||
<!-- <text class="user-name">{{ driverInfo.nickName || '骑手姓名' }}</text> -->
|
||||
<text class="user-status" @click="toggleOnline">{{ driverInfo.isOnline ? '在线中' : '离线' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tabs">
|
||||
<view :class="['tab', activeTab === 'pickup' ? 'active' : '']" @click="switchTab('pickup')">
|
||||
<text>待取货</text>
|
||||
<text class="count">({{ pickupCount }})</text>
|
||||
</view>
|
||||
<view :class="['tab', activeTab === 'delivering' ? 'active' : '']" @click="switchTab('delivering')">
|
||||
<text>配送中</text>
|
||||
<text class="count">({{ deliveringCount }})</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单列表 -->
|
||||
<scroll-view class="order-list" scroll-y="true" :style="{ height: listHeight + 'px' }">
|
||||
<view v-for="order in filteredOrders" :key="order.id" class="order-card">
|
||||
<!-- 头部编号 -->
|
||||
<view class="order-header">
|
||||
<view class="order-badge">{{ order.type === 'pickup' ? '取' : '送' }}</view>
|
||||
<view class="order-title">
|
||||
<text class="shop-name">{{ order.shopName }}</text>
|
||||
<text class="order-id">#{{ order.id }}</text>
|
||||
</view>
|
||||
<view class="order-status">{{ order.statusText }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 地址信息 -->
|
||||
<view class="order-info">
|
||||
<view class="address-row">
|
||||
<view class="icon pickup">取</view>
|
||||
<view class="address-content">
|
||||
<text class="address-title">{{ order.pickupAddress }}</text>
|
||||
<text class="address-sub">商家已出餐 · {{ order.pickupNote || '' }}</text>
|
||||
</view>
|
||||
<view class="nav-icon" @click="openMap(order.pickupLat, order.pickupLng, order.pickupAddress)">导航</view>
|
||||
</view>
|
||||
<view class="address-row">
|
||||
<view class="icon deliver">送</view>
|
||||
<view class="address-content">
|
||||
<text class="address-title">{{ order.deliveryAddress }}</text>
|
||||
<text class="address-sub">收货人:{{ order.receiverName }} {{ order.receiverPhone ? ('尾号' + (order.receiverPhone + '').slice(-4)) : ''}}</text>
|
||||
</view>
|
||||
<view class="nav-icon" @click="openMap(order.deliveryLat, order.deliveryLng, order.deliveryAddress)">导航</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 备注 -->
|
||||
<view class="order-note" v-if="order.note">
|
||||
<text>顾客:{{ order.note }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 操作区 -->
|
||||
<view class="order-actions">
|
||||
<view class="contact" @click="callPhone(order.receiverPhone)">
|
||||
<text>联系</text>
|
||||
</view>
|
||||
<view class="confirm" @click="confirmArrive(order.id)">
|
||||
<text>确认到店</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部批量操作栏 -->
|
||||
<view class="bottom-bar">
|
||||
<view class="batch-item" @click="scanQr">扫一扫取单</view>
|
||||
<view class="batch-item" @click="openManualInput">输入用户单编码</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
|
||||
// 驿站/骑手信息(从 store 获取或 mock)
|
||||
const driverInfo = ref({
|
||||
isOnline: true,
|
||||
nickName: '骑手张三',
|
||||
avatar: ''
|
||||
});
|
||||
|
||||
const defaultAvatar = 'https://huichibao.oss-cn-guangzhou.aliyuncs.com/1/material/348b8223-8d03-46aa-8836-6757e8beebd2.png';
|
||||
|
||||
// 页面状态
|
||||
const activeTab = ref('pickup'); // 'pickup' | 'delivering'
|
||||
const listHeight = ref(600);
|
||||
|
||||
// Mock 订单数据(真实项目应从后端接口拉取 / store)
|
||||
const orders = ref([
|
||||
{
|
||||
id: 1001,
|
||||
type: 'pickup',
|
||||
statusText: '待取货',
|
||||
shopName: '取货点店铺名称',
|
||||
pickupAddress: '广东省广州市天河区学院站荷光路118-121号',
|
||||
pickupLat: 23.1,
|
||||
pickupLng: 113.3,
|
||||
pickupNote: '商家已出餐',
|
||||
deliveryAddress: '广东省广州市天河区华景新城软件园区',
|
||||
deliveryLat: 23.12,
|
||||
deliveryLng: 113.31,
|
||||
receiverName: '张先生',
|
||||
receiverPhone: '13900001234',
|
||||
note: '根据餐量提供餐具'
|
||||
},
|
||||
{
|
||||
id: 1002,
|
||||
type: 'pickup',
|
||||
statusText: '待取货',
|
||||
shopName: '乐易购(学院店)',
|
||||
pickupAddress: '广东省广州市天河区学院站荷光路118--121号',
|
||||
pickupLat: 23.11,
|
||||
pickupLng: 113.32,
|
||||
pickupNote: '',
|
||||
deliveryAddress: '广东省广州市天河区某小区',
|
||||
deliveryLat: 23.13,
|
||||
deliveryLng: 113.33,
|
||||
receiverName: '李女士',
|
||||
receiverPhone: '13900005678',
|
||||
note: ''
|
||||
}
|
||||
]);
|
||||
|
||||
// 计算各 tab 数量与过滤列表
|
||||
const pickupCount = computed(() => orders.value.filter(o => o.type === 'pickup').length);
|
||||
const deliveringCount = computed(() => orders.value.filter(o => o.type === 'delivering').length);
|
||||
const filteredOrders = computed(() => {
|
||||
if (activeTab.value === 'pickup') {
|
||||
return orders.value.filter(o => o.type === 'pickup');
|
||||
}
|
||||
return orders.value.filter(o => o.type === 'delivering');
|
||||
});
|
||||
|
||||
// 切换 tab
|
||||
function switchTab(tab) {
|
||||
activeTab.value = tab;
|
||||
}
|
||||
|
||||
// 切换上线/下线(简单 UI 切换,建议接入后端)
|
||||
function toggleOnline() {
|
||||
driverInfo.value.isOnline = !driverInfo.value.isOnline;
|
||||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast(driverInfo.value.isOnline ? '已上线' : '已下线');
|
||||
}
|
||||
|
||||
// 确认到店(演示:改变订单状态)
|
||||
function confirmArrive(orderId) {
|
||||
const order = orders.value.find(o => o.id === orderId);
|
||||
if (!order) return;
|
||||
// 示例逻辑:到店后将类型改为 delivering
|
||||
if (order.type === 'pickup') {
|
||||
order.type = 'delivering';
|
||||
order.statusText = '配送中';
|
||||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('已确认到店,开始配送');
|
||||
}
|
||||
}
|
||||
|
||||
// 拨打电话
|
||||
function callPhone(phone) {
|
||||
if (!phone) {
|
||||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('未找到联系电话');
|
||||
return;
|
||||
}
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: phone
|
||||
});
|
||||
}
|
||||
|
||||
// 打开地图导航(使用 openLocation 打开经纬度或直接跳转小程序地图)
|
||||
function openMap(lat, lng, name) {
|
||||
if (!lat || !lng) {
|
||||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('无法获取坐标');
|
||||
return;
|
||||
}
|
||||
uni.openLocation({
|
||||
latitude: Number(lat),
|
||||
longitude: Number(lng),
|
||||
name: name || '',
|
||||
scale: 18
|
||||
});
|
||||
}
|
||||
|
||||
// 底部操作(扫码、手动输入)
|
||||
function scanQr() {
|
||||
uni.scanCode({
|
||||
onlyFromCamera: false,
|
||||
success(res) {
|
||||
const code = res.result || res.path || '';
|
||||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('已识别:' + code);
|
||||
},
|
||||
fail() {
|
||||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('扫码失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function openManualInput() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/index/user' // 示例跳转,按需替换为真实手动输入页面
|
||||
});
|
||||
}
|
||||
|
||||
// 入口:计算列表高度适配底部栏
|
||||
onMounted(() => {
|
||||
try {
|
||||
const sys = uni.getSystemInfoSync();
|
||||
const windowHeight = sys.windowHeight || 667;
|
||||
// 留出顶部和底部空间
|
||||
listHeight.value = windowHeight - 200;
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
// 顶部安全区处理:参考 pages/index/user.vue 的实现
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
|
||||
const headerStyle = ref({});
|
||||
|
||||
function setHeaderSafeArea() {
|
||||
try {
|
||||
const sys = uni.getSystemInfoSync();
|
||||
const statusBarHeightPx = sys?.statusBarHeight || 0;
|
||||
const windowWidth = sys?.windowWidth || 375;
|
||||
// 将 px 转为 rpx: rpx = px / windowWidth * 750
|
||||
const statusBarHeightRpx = Math.round((statusBarHeightPx / windowWidth) * 750);
|
||||
headerStyle.value = {
|
||||
paddingTop: statusBarHeightPx + 'px',
|
||||
'--statusbar': statusBarHeightRpx + 'rpx'
|
||||
};
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setHeaderSafeArea();
|
||||
// 计算列表高度适配底部栏
|
||||
try {
|
||||
const sys = uni.getSystemInfoSync();
|
||||
const windowHeight = sys.windowHeight || 667;
|
||||
// 留出顶部和底部空间
|
||||
listHeight.value = windowHeight - 200;
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
// 每次页面显示时重新计算(兼容热更或状态变化)
|
||||
setHeaderSafeArea();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.receive-page {
|
||||
background: #fff;
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.top-area {
|
||||
position: relative;
|
||||
/* 兼容刘海屏安全区处理 */
|
||||
padding-top: constant(safe-area-inset-top);
|
||||
padding-top: env(safe-area-inset-top);
|
||||
height: 220rpx;
|
||||
}
|
||||
.top-bg {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
/* 背景高度需要包含安全区高度 */
|
||||
height: 270rpx;
|
||||
height: calc(270rpx + constant(safe-area-inset-top));
|
||||
height: calc(270rpx + env(safe-area-inset-top));
|
||||
height: calc(270rpx + var(--statusbar, 0rpx));
|
||||
background: #c292ee;
|
||||
border-bottom-left-radius: 12rpx;
|
||||
border-bottom-right-radius: 12rpx;
|
||||
z-index: 0;
|
||||
}
|
||||
.top-inner {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: calc(var(--statusbar, 0rpx) + 30rpx);
|
||||
z-index: 1;
|
||||
padding: 0 30rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.user-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
.user-avatar {
|
||||
width: 110rpx;
|
||||
height: 110rpx;
|
||||
border-radius: 55rpx;
|
||||
border: 4rpx solid rgba(255,255,255,0.6);
|
||||
}
|
||||
.user-meta {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
.user-name {
|
||||
font-size: 32rpx;
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
.user-status {
|
||||
margin-top: 8rpx;
|
||||
color: rgba(255,255,255,0.9);
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.tabs {
|
||||
margin-top: 18rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 20rpx;
|
||||
}
|
||||
.tab {
|
||||
padding: 10rpx 20rpx;
|
||||
background: rgba(255,255,255,0.12);
|
||||
border-radius: 40rpx;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.tab.active {
|
||||
background: #fff;
|
||||
color: #6b3aa6;
|
||||
}
|
||||
.tab .count {
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.order-list {
|
||||
padding: 20rpx;
|
||||
padding-right: 20rpx;
|
||||
box-sizing: border-box;
|
||||
background: #f7f7f7;
|
||||
}
|
||||
.order-card {
|
||||
background: #fff;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 18rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.06);
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
}
|
||||
.order-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
.order-badge {
|
||||
width: 54rpx;
|
||||
height: 54rpx;
|
||||
border-radius: 27rpx;
|
||||
background: #e6f7ff;
|
||||
color: #1890ff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 700;
|
||||
}
|
||||
.order-title {
|
||||
flex: 1;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
.shop-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
.order-id {
|
||||
color: #999;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
.order-status {
|
||||
color: #ff7a45;
|
||||
}
|
||||
.order-info {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
.address-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
.icon {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
border-radius: 19rpx;
|
||||
background: #f2f2f2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 10rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
.icon.pickup { background: #87d6ff; color: #fff; }
|
||||
.icon.deliver { background: #ffd591; color: #fff; }
|
||||
.address-content { flex: 1; min-width: 0; }
|
||||
.address-title {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
/* 支持长地址换行,防止撑开布局 */
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
}
|
||||
.address-sub { display: block; font-size: 22rpx; color: #888; margin-top: 6rpx; }
|
||||
.nav-icon { color: #1e9fff; padding: 6rpx 10rpx; }
|
||||
.order-note { background: #f6f6f6; padding: 12rpx; border-radius: 8rpx; margin-top: 12rpx; color: #666; }
|
||||
.order-actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-top: 12rpx;
|
||||
gap: 12rpx;
|
||||
}
|
||||
.contact {
|
||||
flex: 1;
|
||||
background: #fff;
|
||||
border: 1rpx solid #ddd;
|
||||
padding: 14rpx;
|
||||
text-align: center;
|
||||
border-radius: 8rpx;
|
||||
color: #333;
|
||||
}
|
||||
.confirm {
|
||||
flex: 2;
|
||||
background: #1e9fff;
|
||||
padding: 14rpx;
|
||||
text-align: center;
|
||||
border-radius: 8rpx;
|
||||
color: #fff;
|
||||
}
|
||||
.bottom-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 110rpx;
|
||||
background: rgba(255,255,255,0.98);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
border-top: 1rpx solid #eee;
|
||||
}
|
||||
.batch-item {
|
||||
background: #fff;
|
||||
padding: 14rpx 20rpx;
|
||||
border-radius: 40rpx;
|
||||
border: 1rpx solid #ddd;
|
||||
}
|
||||
</style>
|
||||
39
pages/index/login.vue
Normal file
39
pages/index/login.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<!-- 微信公众号的登录回调页 -->
|
||||
<template>
|
||||
<!-- 空登陆页 -->
|
||||
<view />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
|
||||
onLoad(async (options) => {
|
||||
// #ifdef H5
|
||||
// 将 search 参数赋值到 options 中,方便下面解析
|
||||
new URLSearchParams(location.search).forEach((value, key) => {
|
||||
options[key] = value;
|
||||
});
|
||||
// 执行登录 or 绑定,注意需要 await 绑定
|
||||
const event = options.event;
|
||||
const code = options.code;
|
||||
const state = options.state;
|
||||
if (event === 'login') { // 场景一:登录
|
||||
await sheep.$platform.useProvider().login(code, state);
|
||||
} else if (event === 'bind') { // 场景二:绑定
|
||||
await sheep.$platform.useProvider().bind(code, state);
|
||||
}
|
||||
|
||||
// 检测 H5 登录回调
|
||||
let returnUrl = uni.getStorageSync('returnUrl');
|
||||
if (returnUrl) {
|
||||
uni.removeStorage({key:'returnUrl'});
|
||||
location.replace(returnUrl);
|
||||
} else {
|
||||
uni.switchTab({
|
||||
url: '/',
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
});
|
||||
</script>
|
||||
463
pages/index/user.vue
Normal file
463
pages/index/user.vue
Normal file
@@ -0,0 +1,463 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<!-- header -->
|
||||
<view class="header-wrap" :style="headerStyle">
|
||||
<view class="header-bg"></view>
|
||||
<view class="header-inner">
|
||||
<image class="avatar" :src="user.avatar || defautAvatar"></image>
|
||||
<view class="user-meta">
|
||||
<view class="user-name">{{ user.nickName || '姓名(账号)' }}</view>
|
||||
<view class="user-status" @click="handleStatusToggle">
|
||||
{{ user.isOnline ? '在线' : '离线' }}<uni-icons style="margin-left:10rpx;" type="right" size="13" color="#fff"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- stats card -->
|
||||
<view class="stats-card">
|
||||
<view class="stats-row">
|
||||
<view class="stats-item">
|
||||
<text class="stats-title">今日预计收入(元)</text>
|
||||
<text class="stats-value"> {{ formatMoney(todayIncome) }} </text>
|
||||
<view class="stats-link" @click="openAccount">
|
||||
我的账户 <uni-icons type="right" size="13"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stats-item">
|
||||
<text class="stats-title">今日完成单量(单)</text>
|
||||
<text class="stats-value"> {{ todayOrders }} </text>
|
||||
<view class="stats-link" @click="openOrders">
|
||||
订单统计 <uni-icons type="right" size="13"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- shortcuts -->
|
||||
<view class="shortcuts">
|
||||
<view class="shortcut" @click="openAttendance">
|
||||
<image class="shortcut-icon" src="/static/img/order1.png" mode="aspectFit" />
|
||||
<text class="shortcut-text">考勤排班</text>
|
||||
</view>
|
||||
<view class="shortcut" @click="openSalary">
|
||||
<image class="shortcut-icon" src="/static/img/order2.png" mode="aspectFit" />
|
||||
<text class="shortcut-text">薪资助手</text>
|
||||
</view>
|
||||
<view class="shortcut" @click="openSetting">
|
||||
<!-- <image class="shortcut-icon" src="/static/img/edit.png" mode="aspectFit" /> -->
|
||||
<view class="shortcut-icon">
|
||||
<uni-icons type="gear" size="43"></uni-icons>
|
||||
</view>
|
||||
<text class="shortcut-text">设置</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<s-auth-modal />
|
||||
|
||||
<su-popup type="center" :show="showStatusPopup" round="14" :showClose="false">
|
||||
<view class="modal-box">
|
||||
<view class="modal-body">
|
||||
<text class="modal-title">{{ modalTitle }}</text>
|
||||
<text v-if="modalMsg" class="modal-msg">{{ modalMsg }}</text>
|
||||
</view>
|
||||
<view class="modal-footer">
|
||||
<view class="modal-btn cancel" @click="cancelConfirm">取消</view>
|
||||
<view class="modal-btn confirm" @click="confirmAction">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</su-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
computed,
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
onShow,
|
||||
onPageScroll,
|
||||
onPullDownRefresh
|
||||
} from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
|
||||
// 现有 store / 模板数据
|
||||
const template = computed(() => sheep.$store('app').template.user);
|
||||
const isLogin = computed(() => sheep.$store('user').isLogin);
|
||||
|
||||
const user = ref({});
|
||||
const todayIncome = ref(0);
|
||||
const todayOrders = ref(0);
|
||||
const showBind = ref(false);
|
||||
// 动态 header 内联样式,用于兼容不同平台的状态栏高度
|
||||
const headerStyle = ref({});
|
||||
const defautAvatar =
|
||||
'https://huichibao.oss-cn-guangzhou.aliyuncs.com/1/material/348b8223-8d03-46aa-8836-6757e8beebd2.png';
|
||||
|
||||
// 格式化金额显示
|
||||
function formatMoney(val) {
|
||||
if (val == null) return '0';
|
||||
return (Number(val) || 0).toFixed(1);
|
||||
}
|
||||
|
||||
// 微信小程序的“手机号快速验证”
|
||||
const getPhoneNumber = async (e) => {
|
||||
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
||||
sheep.$helper.toast('快捷登录失败');
|
||||
return;
|
||||
}
|
||||
let result = await sheep.$platform.useProvider().mobileLogin(e.detail);
|
||||
if (result) {
|
||||
showBind.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 页面显示时拉取用户信息并填充统计数据(从 store 获取或使用占位)
|
||||
onShow(async () => {
|
||||
const data = await sheep.$store('user').getInfo();
|
||||
if (data) {
|
||||
user.value = data;
|
||||
// 兼容后端字段名,优先使用 data.todayIncome / data.income / placeholder
|
||||
todayIncome.value = data.todayIncome ?? data.income ?? 137.9;
|
||||
todayOrders.value = data.todayOrders ?? data.orders ?? 39;
|
||||
if (data?.status == 1) {
|
||||
console.log("清空缓存");
|
||||
uni.clearStorageSync();
|
||||
}
|
||||
}
|
||||
// 兼容处理:读取原生状态栏高度并设置 header 的 padding-top(px)与 CSS 变量 --statusbar(rpx)
|
||||
try {
|
||||
const sys = uni.getSystemInfoSync();
|
||||
const statusBarHeightPx = sys?.statusBarHeight || 0;
|
||||
const windowWidth = sys?.windowWidth || 375;
|
||||
// 将 px 转为 rpx: rpx = px / windowWidth * 750
|
||||
const statusBarHeightRpx = Math.round((statusBarHeightPx / windowWidth) * 750);
|
||||
headerStyle.value = {
|
||||
paddingTop: statusBarHeightPx + 'px',
|
||||
'--statusbar': statusBarHeightRpx + 'rpx'
|
||||
};
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
// 确认弹框状态(上线/下线/禁止)
|
||||
const showStatusPopup = ref(false);
|
||||
const confirmType = ref(''); // 'online' | 'offline' | 'forbidden'
|
||||
const modalTitle = ref('');
|
||||
const modalMsg = ref('');
|
||||
|
||||
// 判断用户是否被禁止接单(兼容多种字段)
|
||||
function isUserForbidden() {
|
||||
const u = user.value || {};
|
||||
return !!(u.forbidden || u.isForbidden || u.forbid || u.forbidReceive || u.disableReceive || u.receive === false);
|
||||
}
|
||||
|
||||
// 点击状态:根据当前状态弹不同的确认框
|
||||
function handleStatusToggle() {
|
||||
if (user.value.isOnline) {
|
||||
confirmType.value = 'offline';
|
||||
modalTitle.value = '确认下线?';
|
||||
modalMsg.value = '下线需平台进行核准\n此时正常接单请留意核准信息';
|
||||
showStatusPopup.value = true;
|
||||
return;
|
||||
}
|
||||
// 如果被禁止接单
|
||||
if (isUserForbidden()) {
|
||||
confirmType.value = 'forbidden';
|
||||
modalTitle.value = '您处于禁止接单状态';
|
||||
modalMsg.value = '暂无法上线上线';
|
||||
showStatusPopup.value = true;
|
||||
return;
|
||||
}
|
||||
// 普通从离线 -> 上线
|
||||
confirmType.value = 'online';
|
||||
modalTitle.value = '确认上线?';
|
||||
modalMsg.value = '';
|
||||
showStatusPopup.value = true;
|
||||
}
|
||||
|
||||
function cancelConfirm() {
|
||||
showStatusPopup.value = false;
|
||||
}
|
||||
|
||||
async function confirmAction() {
|
||||
const type = confirmType.value;
|
||||
showStatusPopup.value = false;
|
||||
if (type === 'online') {
|
||||
// TODO: 调用后端接口变更上线状态
|
||||
user.value.isOnline = true;
|
||||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('已上线');
|
||||
} else if (type === 'offline') {
|
||||
user.value.isOnline = false;
|
||||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('已下线');
|
||||
} else if (type === 'forbidden') {
|
||||
// 仅展示信息,无操作
|
||||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('无法上线(禁止接单)');
|
||||
}
|
||||
// 可在此处调用 store 或 API 同步服务端状态,例如:
|
||||
// await sheep.$store('user').setOnline(user.value.isOnline);
|
||||
}
|
||||
|
||||
onPullDownRefresh(() => {
|
||||
sheep.$store('user').updateUserData();
|
||||
setTimeout(function() {
|
||||
uni.stopPullDownRefresh();
|
||||
}, 800);
|
||||
});
|
||||
|
||||
onPageScroll(() => {});
|
||||
|
||||
// 跳转/交互方法(保留路由调用位置,用户可按需实现)
|
||||
function goBack() {
|
||||
uni.navigateBack();
|
||||
}
|
||||
|
||||
function openAccount() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/public/webview?type=account'
|
||||
});
|
||||
}
|
||||
|
||||
function openOrders() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/index/order-list'
|
||||
});
|
||||
}
|
||||
|
||||
function openAttendance() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/public/faq'
|
||||
});
|
||||
}
|
||||
|
||||
function openSalary() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/public/richtext'
|
||||
});
|
||||
}
|
||||
|
||||
function openSetting() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/public/setting'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
background: #ffffff;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* header */
|
||||
.header-wrap {
|
||||
position: relative;
|
||||
/* 适配刘海屏安全区:优先使用 constant/env,兼容小程序与 iOS/Android 安全区 */
|
||||
padding-top: constant(safe-area-inset-top);
|
||||
padding-top: env(safe-area-inset-top);
|
||||
}
|
||||
|
||||
.header-bg {
|
||||
/* 背景放置为绝对定位以覆盖安全区(兼容 env/constant 回退与 JS 动态 --statusbar) */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
/* 背景高度需要包含安全区高度,优先使用 env/constant;最后一行为回退值 */
|
||||
height: 250rpx;
|
||||
height: calc(250rpx + constant(safe-area-inset-top));
|
||||
height: calc(250rpx + env(safe-area-inset-top));
|
||||
/* JS 动态变量回退(当 env/constant 不可用时,使用 --statusbar,单位 rpx) */
|
||||
height: calc(250rpx + var(--statusbar, 0rpx));
|
||||
background: #9ad6f0;
|
||||
/* 浅蓝 */
|
||||
border-bottom-left-radius: 24rpx;
|
||||
border-bottom-right-radius: 24rpx;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.header-inner {
|
||||
position: absolute;
|
||||
left: 32rpx;
|
||||
/* 使用 CSS 变量保证当我们通过 JS 设置 --statusbar 时,内容会相对下移(单位 rpx) */
|
||||
top: calc(var(--statusbar, 0rpx) + 40rpx);
|
||||
z-index: 1;
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 60rpx;
|
||||
border: 4rpx solid rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
.user-meta {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 30rpx;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.user-status {
|
||||
margin-top: 8rpx;
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.back {
|
||||
position: absolute;
|
||||
left: 18rpx;
|
||||
top: calc(var(--statusbar, 0rpx) + 12rpx);
|
||||
z-index: 2;
|
||||
color: #fff;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
/* stats card */
|
||||
.stats-card {
|
||||
padding: 0 24rpx;
|
||||
margin-top: 190rpx;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.stats-row {
|
||||
background: #f6c98b;
|
||||
/* 浅橙色 */
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.stats-item {
|
||||
width: 48%;
|
||||
}
|
||||
|
||||
.stats-title {
|
||||
font-size: 24rpx;
|
||||
color: #5b4a32;
|
||||
}
|
||||
|
||||
.stats-value {
|
||||
display: block;
|
||||
margin-top: 12rpx;
|
||||
font-size: 42rpx;
|
||||
color: #222;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.stats-link {
|
||||
display: block;
|
||||
margin-top: 12rpx;
|
||||
font-size: 24rpx;
|
||||
color: #7a5a3a;
|
||||
}
|
||||
|
||||
/* shortcuts */
|
||||
.shortcuts {
|
||||
margin-top: 30rpx;
|
||||
padding: 30rpx 40rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.shortcut {
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.shortcut-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.shortcut-text {
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* popup 原有样式 */
|
||||
.popup {
|
||||
padding: 80rpx 0 50rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
margin-bottom: 30rpx;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
line-height: 44rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.bind-btn {
|
||||
width: 630rpx;
|
||||
height: 96rpx;
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #FFFFFF;
|
||||
line-height: 96rpx;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
background: #00B85B;
|
||||
border-radius: 64rpx 64rpx 64rpx 64rpx;
|
||||
}
|
||||
|
||||
/* 确认弹框样式(su-popup 内部内容) */
|
||||
.modal-box {
|
||||
width: 640rpx;
|
||||
background: #fff;
|
||||
border-radius: 14rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.modal-body {
|
||||
padding: 40rpx 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.modal-title {
|
||||
display: block;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
.modal-msg {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
line-height: 34rpx;
|
||||
white-space: pre-line;
|
||||
}
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-top: 1rpx solid #eee;
|
||||
}
|
||||
.modal-btn {
|
||||
flex: 1;
|
||||
padding: 26rpx 0;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.modal-btn.cancel {
|
||||
color: #666;
|
||||
border-right: 1rpx solid #eee;
|
||||
}
|
||||
.modal-btn.confirm {
|
||||
color: #1e9fff;
|
||||
}
|
||||
</style>
|
||||
60
pages/public/error.vue
Normal file
60
pages/public/error.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<!-- 错误界面 -->
|
||||
<template>
|
||||
<view class="error-page">
|
||||
<s-empty
|
||||
v-if="errCode === 'NetworkError'"
|
||||
icon="/static/internet-empty.png"
|
||||
text="网络连接失败"
|
||||
showAction
|
||||
actionText="重新连接"
|
||||
@clickAction="onReconnect"
|
||||
buttonColor="#ff3000"
|
||||
/>
|
||||
<s-empty
|
||||
v-else-if="errCode === 'TemplateError'"
|
||||
icon="/static/internet-empty.png"
|
||||
text="未找到模板"
|
||||
showAction
|
||||
actionText="重新加载"
|
||||
@clickAction="onReconnect"
|
||||
buttonColor="#ff3000"
|
||||
/>
|
||||
<s-empty
|
||||
v-else-if="errCode !== ''"
|
||||
icon="/static/internet-empty.png"
|
||||
:text="errMsg"
|
||||
showAction
|
||||
actionText="重新加载"
|
||||
@clickAction="onReconnect"
|
||||
buttonColor="#ff3000"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref } from 'vue';
|
||||
import { ShoproInit } from '@/sheep';
|
||||
|
||||
const errCode = ref('');
|
||||
const errMsg = ref('');
|
||||
|
||||
onLoad((options) => {
|
||||
errCode.value = options.errCode;
|
||||
errMsg.value = options.errMsg;
|
||||
});
|
||||
|
||||
// 重新连接
|
||||
async function onReconnect() {
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/index',
|
||||
});
|
||||
await ShoproInit();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.error-page {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
118
pages/public/faq.vue
Normal file
118
pages/public/faq.vue
Normal file
@@ -0,0 +1,118 @@
|
||||
<!-- FAQ 常见问题 -->
|
||||
<template>
|
||||
<s-layout class="set-wrap" title="常见问题" :bgStyle="{ color: '#FFF' }">
|
||||
<uni-collapse>
|
||||
<uni-collapse-item v-for="(item, index) in state.list" :key="item">
|
||||
<template v-slot:title>
|
||||
<view class="ss-flex ss-col-center header">
|
||||
<view class="ss-m-l-20 ss-m-r-20 icon">
|
||||
<view class="rectangle">
|
||||
<view class="num ss-flex ss-row-center ss-col-center">
|
||||
{{ index + 1 < 10 ? '0' + (index + 1) : index + 1 }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="triangle"> </view>
|
||||
</view>
|
||||
<view class="title ss-m-t-36 ss-m-b-36">
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<view class="content ss-p-l-78 ss-p-r-40 ss-p-b-50 ss-p-t-20">
|
||||
<text class="text">{{ item.content }}</text>
|
||||
</view>
|
||||
</uni-collapse-item>
|
||||
</uni-collapse>
|
||||
<s-empty
|
||||
v-if="state.list.length === 0 && !state.loading"
|
||||
text="暂无常见问题"
|
||||
icon="/static/collect-empty.png"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const state = reactive({
|
||||
list: [],
|
||||
loading: true,
|
||||
});
|
||||
|
||||
async function getFaqList() {
|
||||
const { error, data } = await sheep.$api.data.faq();
|
||||
if (error === 0) {
|
||||
state.list = data;
|
||||
state.loading = false;
|
||||
}
|
||||
}
|
||||
onLoad(() => {
|
||||
// TODO 芋艿:【文章】目前简单做,使用营销文章,作为 faq
|
||||
if (true) {
|
||||
sheep.$router.go('/pages/public/richtext', {
|
||||
title: '常见问题',
|
||||
})
|
||||
return;
|
||||
}
|
||||
getFaqList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: 30rpx;
|
||||
max-width: 688rpx;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: relative;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
|
||||
.rectangle {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 40rpx;
|
||||
height: 36rpx;
|
||||
background: var(--ui-BG-Main);
|
||||
border-radius: 4px;
|
||||
|
||||
.num {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: var(--ui-BG);
|
||||
line-height: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.triangle {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 4rpx solid transparent;
|
||||
border-right: 4rpx solid transparent;
|
||||
border-top: 8rpx solid var(--ui-BG-Main);
|
||||
position: absolute;
|
||||
left: 16rpx;
|
||||
bottom: -4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
border-bottom: 1rpx solid #dfdfdf;
|
||||
|
||||
.text {
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
54
pages/public/richtext.vue
Normal file
54
pages/public/richtext.vue
Normal file
@@ -0,0 +1,54 @@
|
||||
<!-- 文章展示 -->
|
||||
<template>
|
||||
<s-layout class="set-wrap" :title="state.title" :bgStyle="{ color: '#FFF' }">
|
||||
<view class="ss-p-30">
|
||||
<mp-html class="richtext" :content="state.content" />
|
||||
</view>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import ArticleApi from '@/sheep/api/promotion/article';
|
||||
|
||||
const state = reactive({
|
||||
title: '',
|
||||
content: '',
|
||||
});
|
||||
|
||||
async function getRichTextContent(id, title) {
|
||||
const { code, data } = await ArticleApi.getArticle(id, title);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.content = data.content;
|
||||
// 标题不一致时,修改标题
|
||||
if (state.title !== data.title) {
|
||||
state.title = data.title;
|
||||
uni.setNavigationBarTitle({
|
||||
title: state.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.title) {
|
||||
state.title = options.title;
|
||||
uni.setNavigationBarTitle({
|
||||
title: state.title,
|
||||
});
|
||||
}
|
||||
getRichTextContent(options.id, options.title);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.set-title {
|
||||
margin: 0 30rpx;
|
||||
}
|
||||
|
||||
.richtext {
|
||||
}
|
||||
</style>
|
||||
242
pages/public/setting.vue
Normal file
242
pages/public/setting.vue
Normal file
@@ -0,0 +1,242 @@
|
||||
<template>
|
||||
<s-layout class="set-wrap" title="系统设置" :bgStyle="{ color: '#fff' }">
|
||||
<view class="header-box ss-flex-col ss-row-center ss-col-center">
|
||||
<image
|
||||
class="logo-img ss-m-b-46"
|
||||
:src="sheep.$url.cdn(appInfo.logo)"
|
||||
mode="aspectFit"
|
||||
></image>
|
||||
<view class="name ss-m-b-24">{{ appInfo.name }}</view>
|
||||
</view>
|
||||
|
||||
<view class="container-list">
|
||||
<uni-list :border="false">
|
||||
<!-- <uni-list-item
|
||||
title="当前版本"
|
||||
:rightText="appInfo.version"
|
||||
showArrow
|
||||
clickable
|
||||
:border="false"
|
||||
class="list-border"
|
||||
@tap="onCheckUpdate"
|
||||
/>
|
||||
<uni-list-item
|
||||
title="本地缓存"
|
||||
:rightText="storageSize"
|
||||
showArrow
|
||||
:border="false"
|
||||
class="list-border"
|
||||
/>
|
||||
<uni-list-item
|
||||
title="关于我们"
|
||||
showArrow
|
||||
clickable
|
||||
:border="false"
|
||||
class="list-border"
|
||||
@tap="
|
||||
sheep.$router.go('/pages/public/richtext', {
|
||||
title: '关于我们'
|
||||
})
|
||||
"
|
||||
/> -->
|
||||
<!-- 为了过审 只有 iOS-App 有注销账号功能 -->
|
||||
<uni-list-item
|
||||
v-if="isLogin && sheep.$platform.os === 'ios' && sheep.$platform.name === 'App'"
|
||||
title="注销账号"
|
||||
rightText=""
|
||||
showArrow
|
||||
clickable
|
||||
:border="false"
|
||||
class="list-border"
|
||||
@click="onLogoff"
|
||||
/>
|
||||
</uni-list>
|
||||
</view>
|
||||
<view class="set-footer ss-flex-col ss-row-center ss-col-center">
|
||||
<view class="agreement-box ss-flex ss-col-center ss-m-b-40">
|
||||
<view class="ss-flex ss-col-center ss-m-b-10">
|
||||
<!-- <view
|
||||
class="tcp-text"
|
||||
@tap="
|
||||
sheep.$router.go('/pages/public/richtext', {
|
||||
title: '用户协议'
|
||||
})
|
||||
"
|
||||
>
|
||||
《用户协议》
|
||||
</view>
|
||||
<view class="agreement-text">与</view> -->
|
||||
<view
|
||||
class="tcp-text"
|
||||
@tap="
|
||||
sheep.$router.go('/pages/public/richtext', {
|
||||
title: '隐私协议'
|
||||
})
|
||||
"
|
||||
>
|
||||
《隐私协议》
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="copyright-text ss-m-b-10">{{ appInfo.copyright }}</view> -->
|
||||
<!-- <view class="copyright-text">{{ appInfo.copytime }}</view> -->
|
||||
</view>
|
||||
<su-fixed bottom placeholder>
|
||||
<view class="ss-p-x-20 ss-p-b-40">
|
||||
<button
|
||||
class="loginout-btn ss-reset-button ui-BG-Main ui-Shadow-Main"
|
||||
@tap="onLogout"
|
||||
v-if="isLogin"
|
||||
>
|
||||
退出登录
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { computed, reactive } from 'vue';
|
||||
import AuthUtil from '@/sheep/api/member/auth';
|
||||
|
||||
const appInfo = computed(() => sheep.$store('app').info);
|
||||
const isLogin = computed(() => sheep.$store('user').isLogin);
|
||||
const storageSize = uni.getStorageInfoSync().currentSize + 'Kb';
|
||||
const state = reactive({
|
||||
showModal: false,
|
||||
});
|
||||
|
||||
function onCheckUpdate() {
|
||||
sheep.$platform.checkUpdate();
|
||||
// 小程序初始化时已检查更新
|
||||
// H5实时更新无需检查
|
||||
// App 1.跳转应用市场更新 2.手动热更新 3.整包更新
|
||||
}
|
||||
|
||||
// 注销账号
|
||||
function onLogoff() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认注销账号?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await AuthUtil.logout();
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
sheep.$store('user').logout();
|
||||
sheep.$router.go('/pages/index/user');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 退出账号
|
||||
function onLogout() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认退出账号?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await AuthUtil.logout();
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
uni.clearStorageSync();
|
||||
console.log('缓存清空成功');
|
||||
} catch (e) {
|
||||
console.log('缓存清空失败', e);
|
||||
}
|
||||
sheep.$store('user').logout();
|
||||
sheep.$router.go('/pages/index/user');
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container-list {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.set-title {
|
||||
margin: 0 30rpx;
|
||||
}
|
||||
|
||||
.header-box {
|
||||
padding: 100rpx 0;
|
||||
|
||||
.logo-img {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 42rpx;
|
||||
font-weight: 400;
|
||||
color: $dark-3;
|
||||
}
|
||||
|
||||
.version {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
line-height: 32rpx;
|
||||
color: $gray-b;
|
||||
}
|
||||
}
|
||||
|
||||
.set-footer {
|
||||
margin: 100rpx 0 0 0;
|
||||
|
||||
.copyright-text {
|
||||
font-size: 22rpx;
|
||||
font-weight: 500;
|
||||
color: $gray-c;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
|
||||
.agreement-box {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
|
||||
.tcp-text {
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.agreement-text {
|
||||
color: $dark-9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loginout-btn {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.list-border {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
border-bottom: 2rpx solid #eeeeee;
|
||||
}
|
||||
|
||||
:deep(.uni-list-item__content-title) {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
:deep(.uni-list-item__extra-text) {
|
||||
color: #bbbbbb;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
</style>
|
||||
18
pages/public/webview.vue
Normal file
18
pages/public/webview.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<!-- 网页加载 -->
|
||||
<template>
|
||||
<view>
|
||||
<web-view :src="url" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const url = ref('');
|
||||
onLoad((options) => {
|
||||
url.value = decodeURIComponent(options.url);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
470
pages/user/info.vue
Normal file
470
pages/user/info.vue
Normal file
@@ -0,0 +1,470 @@
|
||||
<!-- 用户信息 -->
|
||||
<template>
|
||||
<s-layout title="用户信息" class="set-userinfo-wrap">
|
||||
<uni-forms
|
||||
:model="state.model"
|
||||
:rules="state.rules"
|
||||
labelPosition="left"
|
||||
border
|
||||
class="form-box"
|
||||
>
|
||||
<!-- 头像 -->
|
||||
<view class="ss-flex ss-row-center ss-col-center ss-p-t-60 ss-p-b-0 bg-white">
|
||||
<view class="header-box-content">
|
||||
<su-image
|
||||
class="content-img"
|
||||
isPreview
|
||||
:current="0"
|
||||
:src="state.model?.avatar"
|
||||
:height="160"
|
||||
:width="160"
|
||||
:radius="80"
|
||||
mode="scaleToFill"
|
||||
/>
|
||||
<view class="avatar-action">
|
||||
<!-- #ifdef MP -->
|
||||
<button
|
||||
class="ss-reset-button avatar-action-btn"
|
||||
open-type="chooseAvatar"
|
||||
@chooseavatar="onChooseAvatar"
|
||||
>
|
||||
修改
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP -->
|
||||
<button class="ss-reset-button avatar-action-btn" @tap="onChangeAvatar">修改</button>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bg-white ss-p-x-30">
|
||||
<!-- 昵称 + 性别 -->
|
||||
<uni-forms-item name="nickname" label="昵称">
|
||||
<uni-easyinput
|
||||
v-model="state.model.nickname"
|
||||
type="nickname"
|
||||
placeholder="设置昵称"
|
||||
:inputBorder="false"
|
||||
:placeholderStyle="placeholderStyle"
|
||||
/>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item name="sex" label="性别">
|
||||
<view class="ss-flex ss-col-center ss-h-100">
|
||||
<radio-group @change="onChangeGender" class="ss-flex ss-col-center">
|
||||
<label class="radio" v-for="item in sexRadioMap" :key="item.value">
|
||||
<view class="ss-flex ss-col-center ss-m-r-32">
|
||||
<radio
|
||||
:value="item.value"
|
||||
color="var(--ui-BG-Main)"
|
||||
style="transform: scale(0.8)"
|
||||
:checked="parseInt(item.value) === state.model?.sex"
|
||||
/>
|
||||
<view class="gender-name">{{ item.name }}</view>
|
||||
</view>
|
||||
</label>
|
||||
</radio-group>
|
||||
</view>
|
||||
</uni-forms-item>
|
||||
|
||||
<uni-forms-item name="mobile" label="手机号" @tap="onChangeMobile">
|
||||
<uni-easyinput
|
||||
v-model="userInfo.mobile"
|
||||
placeholder="请绑定手机号"
|
||||
:inputBorder="false"
|
||||
disabled
|
||||
:styles="{ disableColor: '#fff' }"
|
||||
:placeholderStyle="placeholderStyle"
|
||||
:clearable="false"
|
||||
>
|
||||
<template v-slot:right>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<su-radio v-if="userInfo.verification?.mobile" :modelValue="true" />
|
||||
<button v-else class="ss-reset-button ss-flex ss-col-center ss-row-center">
|
||||
<text class="_icon-forward" style="color: #bbbbbb; font-size: 26rpx"></text>
|
||||
</button>
|
||||
</view>
|
||||
</template>
|
||||
</uni-easyinput>
|
||||
</uni-forms-item>
|
||||
|
||||
<!-- <uni-forms-item name="password" label="登录密码" @tap="onSetPassword">
|
||||
<uni-easyinput
|
||||
v-model="userInfo.password"
|
||||
placeholder="点击修改登录密码"
|
||||
:inputBorder="false"
|
||||
:styles="{ disableColor: '#fff' }"
|
||||
disabled
|
||||
placeholderStyle="color:#BBBBBB;font-size:28rpx;line-height:normal"
|
||||
:clearable="false"
|
||||
>
|
||||
<template v-slot:right>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<su-radio
|
||||
class="ss-flex"
|
||||
v-if="userInfo.verification?.password"
|
||||
:modelValue="true"
|
||||
/>
|
||||
<button v-else class="ss-reset-button ss-flex ss-col-center ss-row-center">
|
||||
<text class="_icon-forward" style="color: #bbbbbb; font-size: 26rpx" />
|
||||
</button>
|
||||
</view>
|
||||
</template>
|
||||
</uni-easyinput>
|
||||
</uni-forms-item> -->
|
||||
</view>
|
||||
|
||||
<!-- <view class="bg-white ss-m-t-14">
|
||||
<uni-list>
|
||||
<uni-list-item
|
||||
clickable
|
||||
@tap="sheep.$router.go('/pages/user/address/list')"
|
||||
title="地址管理"
|
||||
showArrow
|
||||
:border="false"
|
||||
class="list-border"
|
||||
/>
|
||||
</uni-list>
|
||||
</view> -->
|
||||
</uni-forms>
|
||||
|
||||
<!-- 当前社交平台的绑定关系,只处理 wechat 微信场景 -->
|
||||
<!-- <view v-if="sheep.$platform.name !== 'H5'">
|
||||
<view class="title-box ss-p-l-30">第三方账号绑定</view>
|
||||
<view class="account-list ss-flex ss-row-between">
|
||||
<view v-if="'WechatOfficialAccount' === sheep.$platform.name" class="ss-flex ss-col-center">
|
||||
<image
|
||||
class="list-img"
|
||||
:src="sheep.$url.static('/static/img/shop/platform/WechatOfficialAccount.png')"
|
||||
/>
|
||||
<text class="list-name">微信公众号</text>
|
||||
</view>
|
||||
<view v-if="'WechatMiniProgram' === sheep.$platform.name" class="ss-flex ss-col-center">
|
||||
<image
|
||||
class="list-img"
|
||||
:src="sheep.$url.static('/static/img/shop/platform/WechatMiniProgram.png')"
|
||||
/>
|
||||
<text class="list-name">微信小程序</text>
|
||||
</view>
|
||||
<view v-if="'App' === sheep.$platform.name" class="ss-flex ss-col-center">
|
||||
<image
|
||||
class="list-img"
|
||||
:src="sheep.$url.static('/static/img/shop/platform/wechat.png')"
|
||||
/>
|
||||
<text class="list-name">微信开放平台</text>
|
||||
</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="info ss-flex ss-col-center" v-if="state.thirdInfo">
|
||||
<image class="avatar ss-m-r-20" :src="sheep.$url.cdn(state.thirdInfo.avatar)" />
|
||||
<text class="name">{{ state.thirdInfo.nickname }}</text>
|
||||
</view>
|
||||
<view class="bind-box ss-m-l-20">
|
||||
<button
|
||||
v-if="state.thirdInfo.openid"
|
||||
class="ss-reset-button relieve-btn"
|
||||
@tap="unBindThirdOauth"
|
||||
>
|
||||
解绑
|
||||
</button>
|
||||
<button v-else class="ss-reset-button bind-btn" @tap="bindThirdOauth">绑定</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<su-fixed bottom placeholder bg="none">
|
||||
<view class="footer-box ss-p-20">
|
||||
<button class="ss-rest-button logout-btn ui-Shadow-Main" @tap="onSubmit">保存</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, reactive, onBeforeMount } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { clone } from 'lodash-es';
|
||||
import { showAuthModal } from '@/sheep/hooks/useModal';
|
||||
import FileApi from '@/sheep/api/infra/file';
|
||||
import UserApi from '@/sheep/api/member/user';
|
||||
|
||||
const state = reactive({
|
||||
model: {}, // 个人信息
|
||||
rules: {},
|
||||
thirdInfo: {}, // 社交用户的信息
|
||||
});
|
||||
|
||||
const placeholderStyle = 'color:#BBBBBB;font-size:28rpx;line-height:normal';
|
||||
|
||||
const sexRadioMap = [
|
||||
{
|
||||
name: '男',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
name: '女',
|
||||
value: '2',
|
||||
},
|
||||
];
|
||||
|
||||
const userInfo = computed(() => sheep.$store('user').userInfo);
|
||||
|
||||
// 选择性别
|
||||
function onChangeGender(e) {
|
||||
state.model.sex = e.detail.value;
|
||||
}
|
||||
|
||||
// 修改手机号
|
||||
const onChangeMobile = () => {
|
||||
showAuthModal('changeMobile');
|
||||
};
|
||||
|
||||
// 选择微信的头像,进行上传
|
||||
function onChooseAvatar(e) {
|
||||
const tempUrl = e.detail.avatarUrl || '';
|
||||
uploadAvatar(tempUrl);
|
||||
}
|
||||
|
||||
// 手动选择头像,进行上传
|
||||
function onChangeAvatar() {
|
||||
uni.chooseImage({
|
||||
success: async (chooseImageRes) => {
|
||||
const tempUrl = chooseImageRes.tempFilePaths[0];
|
||||
await uploadAvatar(tempUrl);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 上传头像文件
|
||||
async function uploadAvatar(tempUrl) {
|
||||
if (!tempUrl) {
|
||||
return;
|
||||
}
|
||||
let { data } = await FileApi.uploadFile(tempUrl);
|
||||
state.model.avatar = data;
|
||||
}
|
||||
|
||||
// 修改密码
|
||||
function onSetPassword() {
|
||||
showAuthModal('changePassword');
|
||||
}
|
||||
|
||||
// 绑定第三方账号
|
||||
async function bindThirdOauth() {
|
||||
let result = await sheep.$platform.useProvider('wechat').bind();
|
||||
if (result) {
|
||||
await getUserInfo();
|
||||
}
|
||||
}
|
||||
|
||||
// 解绑第三方账号
|
||||
function unBindThirdOauth() {
|
||||
uni.showModal({
|
||||
title: '解绑提醒',
|
||||
content: '解绑后您将无法通过微信登录此账号',
|
||||
cancelText: '再想想',
|
||||
confirmText: '确定',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const result = await sheep.$platform.useProvider('wechat').unbind(state.thirdInfo.openid);
|
||||
if (result) {
|
||||
await getUserInfo();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 保存信息
|
||||
async function onSubmit() {
|
||||
const { code } = await UserApi.updateUser({
|
||||
avatar: state.model.avatar,
|
||||
nickname: state.model.nickname,
|
||||
sex: state.model.sex,
|
||||
});
|
||||
if (code === 0) {
|
||||
await getUserInfo();
|
||||
}
|
||||
}
|
||||
|
||||
// 获得用户信息
|
||||
const getUserInfo = async () => {
|
||||
// 个人信息
|
||||
const userInfo = await sheep.$store('user').getInfo();
|
||||
state.model = clone(userInfo);
|
||||
|
||||
// 获得社交用户的信息
|
||||
if (sheep.$platform.name !== 'H5') {
|
||||
const result = await sheep.$platform.useProvider('wechat').getInfo();
|
||||
state.thirdInfo = result || {};
|
||||
}
|
||||
};
|
||||
|
||||
onBeforeMount(() => {
|
||||
getUserInfo();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
.uni-file-picker {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.uni-file-picker__container {
|
||||
margin: -14rpx -12rpx;
|
||||
}
|
||||
|
||||
.file-picker__progress {
|
||||
height: 0 !important;
|
||||
}
|
||||
|
||||
.uni-list-item__content-title {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
|
||||
.uni-icons {
|
||||
font-size: 40rpx !important;
|
||||
}
|
||||
|
||||
.is-disabled {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.disabled) {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.gender-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.title-box {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #666666;
|
||||
line-height: 100rpx;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
width: 710rpx;
|
||||
height: 80rpx;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
border-radius: 40rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.radio-dark {
|
||||
filter: grayscale(100%);
|
||||
filter: gray;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.content-img {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.header-box-content {
|
||||
position: relative;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.avatar-action {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
width: 160rpx;
|
||||
height: 46rpx;
|
||||
background: rgba(#000000, 0.3);
|
||||
|
||||
.avatar-action-btn {
|
||||
width: 160rpx;
|
||||
height: 46rpx;
|
||||
font-weight: 500;
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
// 绑定项
|
||||
.account-list {
|
||||
background-color: $white;
|
||||
height: 100rpx;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.list-img {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.list-name {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.info {
|
||||
.avatar {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: $dark-9;
|
||||
}
|
||||
}
|
||||
|
||||
.bind-box {
|
||||
width: 100rpx;
|
||||
height: 50rpx;
|
||||
line-height: normal;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 24rpx;
|
||||
|
||||
.bind-btn {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 25rpx;
|
||||
background: #f4f4f4;
|
||||
color: #999999;
|
||||
}
|
||||
.relieve-btn {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 25rpx;
|
||||
background: var(--ui-BG-Main-opacity-1);
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-border {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
border-bottom: 2rpx solid #eeeeee;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user