完善内容(home)

This commit is contained in:
张文涛 2025-04-13 20:45:22 +08:00
parent eaab5d5c69
commit 148ca25b00
18 changed files with 4153 additions and 462 deletions

5
api/invite.ts Normal file
View File

@ -0,0 +1,5 @@
import { get, post, put, del } from '../utils/request';
export const inviteCode = (data : any = {}) => get('v1/invite.code', data);
export const inviteList = (data : any = {}) => get('v1/invite.list', data);

View File

@ -0,0 +1,292 @@
<template>
<view class="permission-sheet">
<view class="permission-sheet-header">
<text class="permission-sheet-title">权限设置</text>
<view class="permission-sheet-staff">{{ staff ? staff.name : '' }}</view>
</view>
<scroll-view scroll-y class="permission-list">
<!-- 常用权限 -->
<view class="permission-category">
<view class="category-title">常用权限</view>
<view class="permission-items">
<view
v-for="(item, index) in commonPermissions"
:key="index"
class="permission-item"
:class="{ active: hasPermission(item.value) }"
@click="togglePermission(item.value)"
>
<view class="permission-icon" :class="item.colorClass">
<text class="iconfont" :class="item.icon"></text>
</view>
<view class="permission-info">
<view class="permission-name">{{ item.label }}</view>
<view class="permission-desc">{{ item.description }}</view>
</view>
<view class="permission-switch">
<text class="ri-checkbox-circle-fill" v-if="hasPermission(item.value)"></text>
<text class="ri-checkbox-blank-circle-line" v-else></text>
</view>
</view>
</view>
</view>
<!-- 其他权限 -->
<view class="permission-category">
<view class="category-title">其他权限</view>
<view class="permission-items">
<view
v-for="(item, index) in otherPermissions"
:key="index"
class="permission-item"
:class="{ active: hasPermission(item.value) }"
@click="togglePermission(item.value)"
>
<view class="permission-icon" :class="item.colorClass">
<text class="iconfont" :class="item.icon"></text>
</view>
<view class="permission-info">
<view class="permission-name">{{ item.label }}</view>
<view class="permission-desc">{{ item.description }}</view>
</view>
<view class="permission-switch">
<text class="ri-checkbox-circle-fill" v-if="hasPermission(item.value)"></text>
<text class="ri-checkbox-blank-circle-line" v-else></text>
</view>
</view>
</view>
</view>
</scroll-view>
<view class="permission-sheet-footer">
<button class="btn-cancel" @click="handleCancel">取消</button>
<button class="btn-save" @click="handleSave">保存</button>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
const props = defineProps({
staff: {
type: Object,
default: () => null
},
permissions: {
type: Array,
default: () => []
}
});
const emit = defineEmits(['save', 'cancel']);
//
const commonPermissions = computed(() => {
return props.permissions.filter(perm => perm.isCommon);
});
const otherPermissions = computed(() => {
return props.permissions.filter(perm => !perm.isCommon);
});
/**
* 检查权限是否已启用
*/
const hasPermission = (permission) => {
if (!props.staff) return false;
return props.staff.permissions.includes(permission);
};
/**
* 切换权限状态
*/
const togglePermission = (permission) => {
if (!props.staff) return;
emit('toggle', permission);
const index = props.staff.permissions.indexOf(permission);
if (index > -1) {
//
props.staff.permissions.splice(index, 1);
} else {
//
props.staff.permissions.push(permission);
}
};
/**
* 取消操作
*/
const handleCancel = () => {
emit('cancel');
};
/**
* 保存操作
*/
const handleSave = () => {
emit('save', props.staff);
};
</script>
<style lang="scss" scoped>
/* 权限设置面板 */
.permission-sheet {
padding: 20rpx;
border-radius: 20rpx 20rpx 0 0;
max-height: 70vh;
display: flex;
flex-direction: column;
background-color: #fff;
&-header {
padding: 20rpx 0;
text-align: center;
border-bottom: 1px solid #f0f0f0;
}
&-title {
font-size: 32rpx;
font-weight: bold;
}
&-staff {
font-size: 28rpx;
color: #666;
margin-top: 10rpx;
}
}
.permission-list {
flex: 1;
max-height: 50vh;
}
.permission-category {
margin: 20rpx 0;
.category-title {
font-size: 28rpx;
color: #999;
margin-bottom: 15rpx;
}
}
.permission-items {
border-radius: 12rpx;
background-color: #f8f8f8;
overflow: hidden;
}
.permission-item {
display: flex;
align-items: center;
padding: 20rpx;
border-bottom: 1px solid #eee;
&:last-child {
border-bottom: none;
}
&.active {
background-color: rgba(66, 165, 255, 0.05);
}
}
.permission-icon {
width: 70rpx;
height: 70rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20rpx;
.iconfont {
font-size: 36rpx;
color: #fff;
}
/* 权限图标的颜色类 */
&.delivery-color {
background-color: #42a5ff;
}
&.maintenance-color {
background-color: #42a5ff;
}
&.finance-color {
background-color: #42a5ff;
}
&.admin-color {
background-color: #42a5ff;
}
&.general-color {
background-color: #42a5ff;
}
}
.permission-info {
flex: 1;
}
.permission-name {
font-size: 28rpx;
font-weight: 500;
}
.permission-desc {
font-size: 24rpx;
color: #999;
margin-top: 6rpx;
}
.permission-switch {
width: 50rpx;
display: flex;
justify-content: flex-end;
.ri-checkbox-circle-fill {
font-size: 40rpx;
color: #42a5ff;
}
.ri-checkbox-blank-circle-line {
font-size: 40rpx;
color: #ddd;
}
}
.permission-sheet-footer {
display: flex;
padding: 20rpx 0;
border-top: 1px solid #f0f0f0;
button {
flex: 1;
margin: 0 10rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 30rpx;
border-radius: 40rpx;
}
.btn-cancel {
background-color: #f5f5f5;
color: #666;
}
.btn-save {
background-color: #42a5ff;
background-image: linear-gradient(135deg, #42a5ff, #0070F0);
color: #fff;
}
}
</style>

View File

@ -1,51 +1,41 @@
<template>
<view>
<u-popup :safeAreaInsetBottom='false' :show="show" @close="onClose" mode="center" :round="10">
<view style="font-family: YouSheBiaoTiHei;">
<wd-popup custom-class="my-custom-popup" v-model="innerShow" @close="onClose">
<view class="share-poster">
<!-- 海报画布 -->
<canvas class="poster-canvas" canvas-id="posterCanvas"
:style="{width: posterWidth + 'px',height: posterHeight + 'px',}"></canvas>
<!-- 分享操作按钮 -->
<view class="share-actions">
<view class="action-item left" @click="shareToFriend">
微信分享
</view>
<view class="action-item right" @click="savePoster">
保存相册
</view>
</view>
:style="{ width: posterWidth + 'px', height: posterHeight + 'px' }"></canvas>
</view>
</u-popup>
<!-- 分享操作按钮 -->
<view class="share-actions">
<view class="action-item left" @click="shareToFriend"> 微信好友 </view>
<view class="action-item right" @click="savePoster"> 保存相册 </view>
</view>
</wd-popup>
</view>
</template>
<script>
import {
RESOURCES_URL
} from '@/config/app'
/**
* @property {Object} goodsInfo - 商品信息
* @property {string} goodsInfo.title - 商品标题
* @property {number} goodsInfo.price - 商品价格
* @property {string} goodsInfo.image - 商品主图URL
* @property {string} goodsInfo.qrcode - 小程序码URL
* @property {Object} posterInfo - 商品信息
* @property {string} posterInfo.title - 商品标题
* @property {number} posterInfo.price - 商品价格
* @property {string} posterInfo.image - 商品主图URL
* @property {string} posterInfo.qrcode - 小程序码URL
* @property {boolean} show - 控制弹窗显示隐藏
* @event updateShare - 弹窗关闭时触发参数为false
*/
export default {
name: 'SharePoster',
props: {
goodsInfo: {
posterInfo: {
type: Object,
required: true,
default: () => ({
title: '',
price: 0,
image: '',
qrcode: '', // URL
name: '',
qrcode: '',
backImage: ''
}),
},
show: {
@ -55,6 +45,7 @@
},
data() {
return {
innerShow: false, //
generating: false, //
posterWidth: 300, //
posterHeight: 450, //
@ -69,17 +60,30 @@
watch: {
// show
show(newVal) {
if (newVal) {
this.$nextTick(() => {
this.generatePoster()
})
}
this.innerShow = newVal;
// if (newVal) {
this.$nextTick(() => {
console.log('Show changed, generating poster')
let self = this
self.generatePoster()
// uni.loadFontFace({
// family: 'YouSheBiaoTiHei',
// source: 'url("https://hnxix-public.oss-cn-hangzhou.aliyuncs.com/driver/wx/font/YouSheBiaoTiHei.ttf")',
// success() {
// console.log('success')
// self.generatePoster()
// },
// scopes: ["webview", "native"],
// })
})
// }
},
goodsInfo: {
posterInfo: {
immediate: true,
deep: true,
handler(newVal) {
console.log('SharePoster goodsInfo changed:', newVal)
console.log('SharePoster posterInfo changed:', newVal)
},
},
},
@ -113,7 +117,6 @@
async generatePoster() {
if (this.generating) return
this.generating = true
try {
const ctx = uni.createCanvasContext('posterCanvas', this)
//
@ -122,51 +125,61 @@
//
ctx.fillStyle = '#ffffff'
ctx.fillRect(0, 0, this.posterWidth, this.posterHeight)
// -
const imageUrl = this.goodsInfo.image || ''
const imageUrl = this.posterInfo.backImage || ''
if (imageUrl) {
//
await this.drawImage(ctx, imageUrl, 0, 0, this.posterWidth, this.posterHeight)
}
//
// ctx.fillStyle = 'rgba(255, 255, 255, 0.85)'
// ctx.fillRect(20, 80, this.posterWidth - 40, this.posterHeight - 100)
// logo - d
const share_title =
'https://hnxix-public.oss-cn-hangzhou.aliyuncs.com/driver/wx/img/share_title.png'
if (share_title) {
const qrSize = 50
const qrX = 15
const qrY = 20 //
await this.drawImage(ctx, share_title, qrX, qrY, 100, 24)
}
//
const gradient = ctx.createLinearGradient(15, 110, 15, 150)
gradient.addColorStop(0, '#1068FF'); //
gradient.addColorStop(0.48, '#2B497E'); // 48%
gradient.addColorStop(1, '#D51BB6'); //
const gradient = ctx.createLinearGradient(22, 125, 80, 125)
gradient.addColorStop(0, '#1068FF') //
gradient.addColorStop(0.48, '#2B497E') // 48%
gradient.addColorStop(1, '#D51BB6') //
const gradient_sec = ctx.createLinearGradient(22, 160, 130, 160)
gradient_sec.addColorStop(0, '#1068FF') //
gradient_sec.addColorStop(0.48, '#2B497E') // 48%
gradient_sec.addColorStop(1, '#D51BB6') //
ctx.shadowColor = 'rgba(0, 0, 0, 0.15)'
ctx.shadowBlur = 2
ctx.shadowOffsetX = 1
ctx.shadowOffsetY = 1
ctx.font = 'italic bold 20px sans-serif'
ctx.setFontSize(19)
ctx.setFontSize(15)
ctx.setTextAlign('left')
ctx.fillStyle = gradient
ctx.fillText('王师傅', 15, 120)
ctx.setFillStyle('#0060C4')
let title = this.posterInfo.title || ''
ctx.fillText(`${title}`, 18, 35)
ctx.font = 'italic bold 20px sans-serif'
// ctx.font = "20px bold 'YouSheBiaoTiHei'"
ctx.setFontSize(16)
ctx.setTextAlign('left')
ctx.setFillStyle('#21CCF9')
let first = this.posterInfo.name || ''
ctx.fillText(`${first}`, 18, 136)
//
ctx.font = 'italic bold 20px sans-serif'
ctx.setFontSize(19)
// ctx.font = "20px bold 'YouSheBiaoTiHei'"
ctx.setFontSize(16)
ctx.setTextAlign('left')
ctx.fillStyle = gradient
ctx.fillText('邀请您预约行程', 15, 150)
ctx.setFillStyle('#21CCF9')
ctx.fillText('邀请您入驻小区', 18, 170)
//
ctx.shadowColor = 'transparent'
@ -174,8 +187,7 @@
ctx.shadowOffsetX = 0
ctx.shadowOffsetY = 0
// -
const qrcodeUrl = this.goodsInfo.qrcode
const qrcodeUrl = this.posterInfo.qrcode || ''
if (qrcodeUrl) {
const qrSize = 150
const qrX = (this.posterWidth - qrSize) / 2
@ -187,7 +199,7 @@
ctx.setFontSize(11)
ctx.setFillStyle('#666666')
ctx.setTextAlign('center')
ctx.fillText('微信扫码,预约行程', this.posterWidth / 2, 420)
ctx.fillText('微信扫码入驻,获取更多特权', this.posterWidth / 2, 420)
ctx.draw(false, () => {
setTimeout(() => {
@ -236,7 +248,7 @@
x: Math.floor(x),
y: Math.floor(y),
width: Math.floor(finalWidth),
height: Math.floor(finalHeight)
height: Math.floor(finalHeight),
}
},
/**
@ -260,22 +272,11 @@
// 使
const rect = this.calculateImageRect(image.width, image.height, width,
height)
ctx.drawImage(
image.path,
x + rect.x,
y + rect.y,
rect.width,
rect.height
);
ctx.drawImage(image.path, x + rect.x, y + rect.y, rect.width, rect
.height)
} else {
//
ctx.drawImage(
image.path,
x,
y,
width,
height
);
ctx.drawImage(image.path, x, y, width, height)
}
resolve()
},
@ -341,6 +342,31 @@
uni.canvasToTempFilePath({
canvasId: 'posterCanvas',
success: (res) => {
console.log(res, '000')
// APP使uni.share
// #ifdef APP-PLUS
uni.share({
provider: 'weixin',
scene: 'WXSceneSession', // WXSceneSession = WXSceneTimeline =
type: 2,
imageUrl: res.tempFilePath,
success: function() {
console.log('分享图片成功')
},
fail: function(err) {
console.log('分享图片失败:', err)
//
uni.showToast({
title: '分享失败',
icon: 'none',
})
},
})
// #endif
// 使showShareImageMenu
// #ifdef MP-WEIXIN
uni.showShareImageMenu({
path: res.tempFilePath,
success: function() {
@ -350,32 +376,74 @@
console.log('分享图片失败:', err)
},
})
// #endif
},
},
this
)
},
/**
* 分享到朋友圈
*/
// shareToTimeline() {
// uni.canvasToTempFilePath({
// canvasId: 'posterCanvas',
// success: (res) => {
// // APP使uni.share
// // #ifdef APP-PLUS
// uni.share({
// provider: 'weixin',
// scene: 'WXSceneTimeline', //
// type: 'image',
// imageUrl: res.tempFilePath,
// success: function() {
// console.log('')
// },
// fail: function(err) {
// console.log('', err)
// //
// uni.showToast({
// title: '',
// icon: 'none'
// })
// }
// })
// // #endif
// //
// // #ifdef MP-WEIXIN
// uni.showToast({
// title: '',
// icon: 'none'
// })
// // #endif
// },
// },
// this
// )
// },
/**
* 保存到本地
*/
savePoster() {
// #ifdef MP-WEIXIN
//
this.checkAndRequestPermission();
this.checkAndRequestPermission()
// #endif
// #ifdef APP-PLUS || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO
//
this.saveImageToAlbum();
this.saveImageToAlbum()
// #endif
// #ifdef H5
// H5
uni.showToast({
title: 'H5环境不支持保存到相册',
icon: 'none'
});
icon: 'none',
})
// #endif
},
@ -389,29 +457,30 @@
uni.authorize({
scope: 'scope.writePhotosAlbum',
success: () => {
this.saveImageToAlbum();
this.saveImageToAlbum()
},
fail: () => {
this.showAuthModal();
}
});
this.showAuthModal()
},
})
} else {
this.saveImageToAlbum();
this.saveImageToAlbum()
}
},
fail: (err) => {
console.log('获取设置失败:', err);
console.log('获取设置失败:', err)
uni.showToast({
title: '获取权限失败',
icon: 'none'
});
}
});
icon: 'none',
})
},
})
},
/**
* 显示授权引导弹窗
*/
showAuthModal() {
uni.showModal({
title: '提示',
@ -420,51 +489,58 @@
cancelText: '取消',
success: (res) => {
if (res.confirm) {
uni.openSetting();
uni.openSetting()
}
}
});
},
})
},
/**
* 实际保存图片的方法
*/
saveImageToAlbum() {
uni.showLoading({
title: '保存中...',
mask: true,
})
uni.canvasToTempFilePath({
canvasId: 'posterCanvas',
success: (res) => {
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
uni.showToast({
title: '已保存至相册,去朋友圈分享',
icon: 'none',
});
},
fail: (err) => {
console.log('保存失败:', err);
//
if (err.errMsg.indexOf('auth deny') > -1) {
// #ifdef MP-WEIXIN
this.showAuthModal();
// #endif
} else {
canvasId: 'posterCanvas',
success: (res) => {
uni.hideLoading()
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
uni.showToast({
title: '保存失败',
title: '已保存至相册,去朋友圈分享',
icon: 'none',
});
}
},
});
})
},
fail: (err) => {
console.log('保存失败:', err)
//
if (err.errMsg.indexOf('auth deny') > -1) {
// #ifdef MP-WEIXIN
this.showAuthModal()
// #endif
} else {
uni.showToast({
title: '保存失败',
icon: 'none',
})
}
},
})
},
fail: (err) => {
console.log('生成临时文件失败:', err)
uni.showToast({
title: '生成图片失败',
icon: 'none',
})
},
},
fail: (err) => {
console.log('生成临时文件失败:', err);
uni.showToast({
title: '生成图片失败',
icon: 'none',
});
}
}, this);
this
)
},
},
}
@ -473,18 +549,19 @@
<style lang="scss" scoped>
@font-face {
font-family: 'YouSheBiaoTiHei';
src: url('https: //hnxix-public.oss-cn-hangzhou.aliyuncs.com/driver/wx/font/YouSheBiaoTiHei.ttf');
src: url('https://hnxix-public.oss-cn-hangzhou.aliyuncs.com/driver/wx/font/YouSheBiaoTiHei.ttf');
}
.test {
font-family: 'YouSheBiaoTiHei';
}
/* 海报容器 */
.share-poster {
outline: none;
// background-color: #fff;
border-radius: 20rpx;
overflow: hidden;
max-height: 60vh;
// overflow-y: auto;
// padding-bottom: 140rpx; //
/* 画布样式 */
.poster-canvas {
@ -493,35 +570,42 @@
// background: #fff;
}
/* 分享按钮组 */
.share-actions {
position: fixed;
left: 0;
right: 0;
bottom: 140rpx;
}
/* 分享按钮组 */
.share-actions {
position: absolute;
left: 0;
right: 0;
bottom: -200rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 30rpx;
.action-item {
display: flex;
justify-content: space-around;
flex-direction: column;
align-items: center;
padding: 20rpx 40rpx;
padding: 20rpx 30rpx;
border-radius: 40rpx;
min-width: 80rpx;
font-size: 28rpx;
}
.action-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 28rpx 40rpx;
border-radius: 40rpx;
.left {
background-color: #0ed05f;
color: #ffffff;
}
}
.middle {
background-color: #1aad19;
color: #ffffff;
}
.left {
background-color: #0ED05F;
color: #FFFFFF;
}
.right {
background-color: #FFFFFF;
color: #000000;
}
.right {
background-color: #ffffff;
color: #000000;
}
}
@ -532,4 +616,16 @@
// ::v-deep .u-popup__content {
// background-color: rebeccapurple !important;
// }
::v-deep .wd-popup-wrapper .wd-popup {
overflow-y: visible !important;
}
::v-deep(.wd-popup-wrapper .wd-popup) {
overflow-y: visible !important;
}
:deep(.my-custom-popup.wd-popup) {
/* 样式 */
overflow-y: visible !important;
}
</style>

View File

@ -1,6 +1,6 @@
{
"dependencies": {
"pinia-plugin-persistedstate": "^4.2.0",
"crypto-js": "^4.2.0"
"crypto-js": "^4.2.0",
"pinia-plugin-persistedstate": "^4.2.0"
}
}

View File

@ -239,6 +239,60 @@
"navigationStyle": "custom",
"navigationBarTitleText": "房源详情"
}
},
{
"path": "permissions/villageList",
"style": {
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"navigationStyle": "custom",
"navigationBarTitleText": "小区列表"
}
},
{
"path": "permissions/staffList",
"style": {
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"navigationStyle": "custom",
"navigationBarTitleText": "员工列表"
}
},
{
"path": "permissions/addStaff",
"style": {
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"navigationStyle": "custom",
"navigationBarTitleText": "添加员工"
}
},
{
"path": "agreement/index",
"style": {
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"navigationStyle": "custom",
"navigationBarTitleText": "用户协议隐私政策"
}
},
{
"path": "setting/index",
"style": {
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"navigationStyle": "custom",
"navigationBarTitleText": "用户协议隐私政策"
}
},
{
"path": "setting/editInfo",
"style": {
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"navigationStyle": "custom",
"navigationBarTitleText": "用户协议隐私政策"
}
}
]
}],

View File

@ -57,7 +57,8 @@
class="li-w-88% li-h-220 li-mx-auto li-mt-20 li-pt-15">
<text class="li-ml-35 li-text-30 li-text-#010B3E">代处理事项</text>
<view class="li-flex justify-between items-center li-px-50 li-mt-20">
<view class="li-flex li-flex-col items-center" v-for="(item,index) in toDoList" :key="index">
<view class="li-flex li-flex-col items-center" v-for="(item,index) in toDoList" :key="index"
@click="toPages({type:'my_order'})">
<text :class="[index==2?'li-text-#F42429':'li-text-#010B3E']"
class="li-text-43 li-font-bold">{{item.num}}</text>
<text class="li-text-24 li-text-#AFB2B8">{{item.desc}}</text>
@ -85,6 +86,9 @@
</view>
</view>
</view>
<view v-if="problemList?.length === 0" class="empty-state">
<wd-status-tip image="collect" tip="暂无常见问题解答" />
</view>
</view>
<!-- 悬浮按钮 -->
<!-- #ifdef MP-WEIXIN -->
@ -94,7 +98,7 @@
</view>
</view>
<!-- #endif -->
<view>
<view v-if="problemList?.length > 0">
<wd-loadmore loading-text="努力加载中" finished-text="没有更多了" :state="state" @reload="loadmore" />
</view>
</view>
@ -129,8 +133,9 @@
const porcelainList = ref([
{
image: uni.$globalData?.RESOURCE_URL + 'home/back1.png',
title: '新建任务',
desc: '新建工单任务'
title: '我的工单',
desc: '工单一键处理',
type: 'my_order'
},
{
image: uni.$globalData?.RESOURCE_URL + 'home/back2.png',
@ -140,11 +145,11 @@
}
])
const gridList = ref([
{
image: uni.$globalData?.RESOURCE_URL + 'home/grid/xiaoxi.png',
title: '我的工单',
type: 'my_order'
},
// {
// image: uni.$globalData?.RESOURCE_URL + 'home/grid/xiaoxi.png',
// title: '',
// type: 'my_order'
// },
{
image: uni.$globalData?.RESOURCE_URL + 'home/grid/yaoqing.png',
title: '邀请业主',
@ -160,31 +165,36 @@
title: '投诉管理',
type: 'complaint'
},
{
image:uni.$globalData?.RESOURCE_URL + 'home/grid/fangke.png' ,
title: '访客邀请',
type: ''
},
{
image: uni.$globalData?.RESOURCE_URL + 'home/grid/wenjuan.png',
title: '问卷管理',
type: 'questionnaire'
},
{
image: uni.$globalData?.RESOURCE_URL + 'home/grid/fangyuan.png',
title: '房源管理',
type: 'housing'
},
// {
// image: uni.$globalData?.RESOURCE_URL + 'home/grid/fangke.png',
// title: '访',
// type: ''
// },
// {
// image: uni.$globalData?.RESOURCE_URL + 'home/grid/wenjuan.png',
// title: '',
// type: 'questionnaire'
// },
// {
// image: uni.$globalData?.RESOURCE_URL + 'home/grid/fangyuan.png',
// title: '',
// type: 'housing'
// },
// {
// image: uni.$globalData?.RESOURCE_URL + 'home/grid/chewei.png',
// title: '',
// type: ''
// },
{
image:uni.$globalData?.RESOURCE_URL + 'home/grid/gongdan.png' ,
image: uni.$globalData?.RESOURCE_URL + 'home/grid/gongdan.png',
title: '商品核销',
type: 'verification'
}
},
// {
// image: uni.$globalData?.RESOURCE_URL + 'home/grid/gongdan.png',
// title: '',
// type: 'permissions'
// }
])
@ -204,24 +214,24 @@
])
const problemList = ref([
{
image: '/static/swiper/1.png',
title: '如何创建工单任务',
time: '2025-06',
viewCount: '200'
},
{
image: '/static/swiper/1.png',
title: '巡检任务审核说明',
time: '2025-06',
viewCount: '200'
},
{
image: '/static/swiper/1.png',
title: '物业员工催缴流程',
time: '2025-06',
viewCount: '200'
}
// {
// image: '/static/swiper/1.png',
// title: '',
// time: '2025-06',
// viewCount: '200'
// },
// {
// image: '/static/swiper/1.png',
// title: '',
// time: '2025-06',
// viewCount: '200'
// },
// {
// image: '/static/swiper/1.png',
// title: '',
// time: '2025-06',
// viewCount: '200'
// }
])
const handleClick = (e) => {
@ -240,7 +250,7 @@
});
break;
case 'my_order':
//
//
uni.navigateTo({
url: '/pagesA/my_order/list'
});
@ -299,6 +309,12 @@
url: '/pagesB/housing/list'
});
break;
case 'permissions':
//
uni.navigateTo({
url: '/pagesB/permissions/villageList'
});
break;
default:
break;
}

View File

@ -14,13 +14,13 @@
</view>
<image class="li-w-240 li-h-240" :src="mine_back" mode="aspectFill"></image>
</view>
<view class="li-w-70% li-ml-50 li-flex li-justify-between li-items-center">
<!-- <view class="li-w-70% li-ml-50 li-flex li-justify-between li-items-center">
<view class="li-flex li-flex-col li-justify-center li-items-center" v-for="(item,index) in incomeList"
:key="index">
<text class="li-text-#b1bbc7 li-text-24">{{item.title}}</text>
<text class="li-text-#010B3E li-text-34 li-mt-6 li-font-bold">{{item.number}}</text>
</view>
</view>
</view> -->
<!-- card -->
<view
class="li-w-94% li-mx-auto li-flex li-justify-between li-items-center li-py-20 !li-rd-tl-30 !li-rd-tr-30 li-mt-20"
@ -45,7 +45,7 @@
</view>
<view class="li-flex li-justify-between li-items-center li-mx-40 li-mt-30">
<view class="li-flex li-flex-col li-justify-center li-items-center" v-for="(item,index) in workList"
:key="index">
:key="index" @click="toPages({type:item.type})">
<wd-badge :hidden="item.number > 0 ? false:true" :modelValue="item.number" top='5' right="-2"
:max='99'>
<image class="li-w-60 li-h-60" :src="item.icon" mode=""></image>
@ -57,10 +57,11 @@
<view class="li-w-94% li-mx-auto li-mt-26 li-bg-white li-rd-20 li-pb-20">
<view class="li-flex li-justify-between li-items-center li-pt-20 li-mx-20 li-pb-10">
<text class="li-text-#19171B li-text-32">常用功能</text>
<text class="li-text-#19171B li-text-32">其他功能</text>
</view>
<wd-grid class="" :column="4" :clickable="true">
<wd-grid-item use-icon-slot use-text-slot v-for="(item,index) in frequentlyList" :key="index">
<wd-grid-item use-icon-slot use-text-slot v-for="(item,index) in frequentlyList" :key="index"
@click="toPages({type:item.type})">
<template #icon>
<wd-badge :hidden="item.number > 0 ? false:true" :modelValue="item.number" top='5' right="-2"
:max='99'>
@ -109,46 +110,115 @@
{
title: '待入库',
number: 12,
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/chuku.png'
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/chuku.png',
type: 'warehousing',
}, {
title: '待配送',
number: 11,
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/peisong.png'
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/peisong.png',
type: 'my_order_F2',
}, {
title: '待报修',
number: 0,
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/baoxiu.png'
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/baoxiu.png',
type: 'my_order_F6',
}, {
title: '待催缴',
number: 0,
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/cuijiao.png'
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/cuijiao.png',
type: 'call'
}
])
const frequentlyList = ref([
// {
// title: '',
// number: 0,
// icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/tousu.png'
// }, {
// title: '',
// number: 11,
// icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/xunjian.png'
// }, {
// title: '',
// number: 0,
// icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/pandian.png'
// }, {
// title: '',
// number: 0,
// icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/menjin.png'
// },
{
title: '投诉管理',
title: '用户协议',
number: 0,
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/tousu.png'
}, {
title: '巡检任务',
number: 11,
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/xunjian.png'
}, {
title: '资产盘点',
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/pandian.png',
type: 'protocol'
},
{
title: '隐私政策',
number: 0,
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/pandian.png'
}, {
title: '门禁申请',
number: 0,
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/menjin.png'
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/menjin.png',
type: 'privacy'
},
{
title: '设置',
number: 0,
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/shezhi.png'
icon: uni.$globalData?.RESOURCE_URL + 'mine/icon/shezhi.png',
type: 'setting'
}
])
const toPages = (item) => {
console.log('111111111111');
switch (item.type) {
case 'warehousing':
//
uni.navigateTo({
url: '/pagesA/warehousing/index'
});
break;
case 'my_order_F2':
//
uni.navigateTo({
url: '/pagesA/my_order/list?type=1&status=1'
});
break;
case 'my_order_F6':
//
uni.navigateTo({
url: '/pagesA/my_order/list?type=2&status=1'
});
break;
case 'call':
//
uni.navigateTo({
url: '/pagesB/call/index'
});
break;
case 'protocol':
//
uni.navigateTo({
url: '/pagesB/agreement/index?type=1'
});
break;
case 'privacy':
//
uni.navigateTo({
url: '/pagesB/agreement/index?type=2'
});
break;
case 'setting':
//
uni.navigateTo({
url: '/pagesB/setting/index'
});
break;
default:
break;
}
}
onShow(async () => {
const userInfo = await uni.$store.state.userInfos
userInfo.realname && (user_info.value.realname = userInfo.realname)

View File

@ -22,22 +22,27 @@
<view class="invite-card li-w-92% li-mx-auto li-mt-40 li-bg-white li-rd-20 li-shadow-sm li-p-30">
<view class="card-header li-flex li-justify-between li-items-center">
<text class="li-text-36 li-text-#333">邀请福利</text>
<text class="li-text-28 li-text-#0070F0" @click="showRules">活动规则</text>
<!-- <text class="li-text-28 li-text-#0070F0" @click="showRules">活动规则</text> -->
</view>
<view class="card-content li-mt-30">
<!-- 主要返佣说明 -->
<view
:style="{backgroundImage:`url(${card_back})`,backgroundSize:'cover',backgroundPosition:'center'}"
<view :style="{backgroundImage:`url(${card_back})`,backgroundSize:'cover',backgroundPosition:'center'}"
class="commission-card li-bg-gradient-to-r li-from-#4481EB li-to-#0070F0 li-rd-20 li-p-30 li-mb-30">
<view class="li-flex li-items-center li-mb-20">
<text class="ri-shopping-bag-3-line li-text-48 li-text-#0a4696"></text>
<text class="li-text-34 li-text-#0a4696 li-ml-15 li-font-medium">业主消费返佣</text>
<text
class="li-text-34 li-text-#0a4696 li-ml-15 li-font-medium">{{codeInfo?.config?.shop_brokerage_mode==1?'业主消费返佣':'业主关系'}}</text>
</view>
<view class="li-flex li-items-baseline li-mb-15">
<text class="li-text-70 li-text-#0a4696 li-font-bold">5</text>
<view v-if="codeInfo?.config?.shop_brokerage_mode == 1" class="li-flex li-items-baseline li-mb-15">
<text
class="li-text-70 li-text-#0a4696 li-font-bold">{{codeInfo?.config?.employee_shop_brokerage_rate}}</text>
<text class="li-text-34 li-text-#0a4696 li-ml-10">%</text>
</view>
<text class="li-text-26 li-text-#0a4696 li-opacity-100">邀请的业主每笔消费您都可获得返佣</text>
<view v-else class="li-flex li-items-baseline li-mb-15">
<text class="li-text-70 li-text-#0a4696 li-font-bold">建立</text>
</view>
<text
class="li-text-26 li-text-#0a4696 li-opacity-100">{{codeInfo?.config?.shop_brokerage_mode==1?'邀请的业主每笔消费,您都可获得返佣':'邀请业主建立联系'}}</text>
</view>
<!-- 收益说明 -->
@ -51,7 +56,8 @@
<text class="li-text-26 li-text-#666 li-block li-mt-5">邀请业主注册并完成实名认证</text>
</view>
</view>
<view class="benefit-item li-flex li-items-center li-mb-30">
<view v-if="codeInfo?.config?.shop_brokerage_mode!=1"
class="benefit-item li-flex li-items-center li-mb-30">
<view class="icon-box li-bg-#E1F0FF li-rd-12 li-p-15">
<text class="ri-link-m li-text-36 li-text-#0070F0"></text>
</view>
@ -60,7 +66,7 @@
<text class="li-text-26 li-text-#666 li-block li-mt-5">与业主建立永久绑定关系</text>
</view>
</view>
<view class="benefit-item li-flex li-items-center">
<view v-if="codeInfo?.config?.shop_brokerage_mode==1" class="benefit-item li-flex li-items-center">
<view class="icon-box li-bg-#E1F0FF li-rd-12 li-p-15">
<text class="ri-money-cny-box-line li-text-36 li-text-#0070F0"></text>
</view>
@ -72,7 +78,7 @@
</view>
</view>
<view class="invite-button li-mt-40">
<wd-button type="primary" block custom-class="share-btn">
<wd-button type="primary" block custom-class="share-btn" @click="openSharePoster">
<text class="ri-share-forward-line li-mr-10"></text>立即邀请
</wd-button>
</view>
@ -83,15 +89,15 @@
<view class="records-header li-flex li-justify-between li-items-center">
<view class="li-flex li-items-center">
<text class="li-text-34 li-text-#333">邀请记录</text>
<text class="li-text-26 li-text-#666 li-ml-15">({{inviteList.length}})</text>
<text class="li-text-26 li-text-#666 li-ml-15">({{inviteListData?.length}})</text>
</view>
<view class="li-flex li-items-center">
<view v-if="codeInfo?.config?.shop_brokerage_mode==1" class="li-flex li-items-center">
<text class="ri-money-cny-box-line li-text-32 li-text-#0070F0"></text>
<text class="li-text-26 li-text-#666 li-ml-10">累计返佣¥1280.50</text>
<text class="li-text-26 li-text-#666 li-ml-10">累计返佣¥{{codeInfo?.sumMoney}}</text>
</view>
</view>
<scroll-view scroll-y class="records-list li-mt-20" @scrolltolower="loadMore">
<view v-for="(item, index) in inviteList" :key="index"
<view v-for="(item, index) in inviteListData" :key="index"
class="record-item li-bg-white li-rd-20 li-p-30 li-mb-20 li-shadow-sm">
<view class="li-flex li-justify-between li-items-center">
<view class="li-flex li-items-center">
@ -106,13 +112,12 @@
</view>
</view>
</view>
<view v-if="loading" class="loading li-text-center li-py-30 li-text-28 li-text-#999">
加载中...
<view v-if="inviteListData?.length>0">
<wd-loadmore loading-text="努力加载中" finished-text="没有更多了" :state="state" />
</view>
<view v-if="!hasMore && inviteList.length > 0" class="li-text-center li-py-30 li-text-28 li-text-#999">
没有更多了
</view>
<view v-if="inviteList.length === 0" class="empty-state li-py-60">
<view v-if="inviteListData?.length === 0" class="empty-state">
<wd-status-tip image="search" tip="暂无邀请记录" />
</view>
</scroll-view>
@ -142,68 +147,94 @@
</view>
</view>
</wd-popup>
<zero-loading type="wobble" v-if="loading"></zero-loading>
<SharePoster v-model:show="showPoster" :posterInfo="posterInfo" @updateShare="handleUpdateShare"></SharePoster>
</view>
</template>
<script setup lang="ts">
<script setup>
import {
ref,
onMounted,
defineExpose
} from 'vue'
import {
inviteList,
inviteCode
} from '@/api/invite'
import {
useToast
} from '@/uni_modules/wot-design-uni'
import { onLoad } from '@dcloudio/uni-app'
import { useNavigation } from '@/hooks/useNavigation'
declare const uni : Uni
import {
onLoad
} from '@dcloudio/uni-app'
import {
useNavigation
} from '@/hooks/useNavigation'
import SharePoster from '@/components/SharePoster.vue'
const {
hasMultiplePages, //
isTabBarPage, // tabBar
checkRouteStack //
hasMultiplePages, //
isTabBarPage, // tabBar
checkRouteStack //
} = useNavigation()
const Toast = useToast()
const loading = ref(false)
const hasMore = ref(true)
const page = ref(1)
const inviteList = ref([])
const inviteListData = ref([])
const showRulePopup = ref(false)
const showPoster = ref(false)
const posterInfo = ref({})
const state = ref('loading')
const codeInfo = ref({})
const page = ref(1)
const limit = ref(10)
const userInfo = ref(uni.getStorageSync('userInfo'))
const count = ref(0)
const card_back = uni.$globalData?.RESOURCE_URL + 'invite/card-back.png'
onLoad(() => {
checkRouteStack()
getInviteCode()
loadInviteRecords()
})
const getInviteCode = async () => {
var res = await inviteCode()
if (res.code == 200) {
codeInfo.value = res.data
}
posterInfo.value = {
title: userInfo.value.owner.name,
name: userInfo.value.realname,
qrcode: codeInfo.value.code,
backImage: uni.$globalData?.RESOURCE_URL + 'invite/poster_back.png'
}
}
//
const loadInviteRecords = async () => {
if (loading.value || !hasMore.value) return
loading.value = true
try {
//
await new Promise(resolve => setTimeout(resolve, 1000))
const res = await inviteList({
page: page.value,
limit: limit.value,
})
if (res.code == 200) {
inviteListData.value = [...inviteListData.value, ...res.data]
count.value = res.count
}
const mockData = Array(10).fill().map((_, index) => ({
id: page.value * 10 + index,
name: `业主${page.value * 10 + index}`,
avatar: '/static/swiper/1.png',
time: '2024-03-26 12:00:00',
status: Math.random() > 0.5 ? 1 : 0
}))
inviteList.value.push(...mockData)
hasMore.value = page.value < 3 // 3
page.value++
} catch (error) {
Toast.error('加载失败')
} finally {
loading.value = false
}
}
//
const toPages = (item) => {
if (item.type === 'nav') {
@ -218,11 +249,19 @@
//
const loadMore = () => {
if (inviteListData?.value.length >= count.value) {
state.value = 'finished'
return
}
page++
loadInviteRecords()
}
onMounted(() => {
loadInviteRecords()
// loadInviteRecords()
//
})
//
@ -230,8 +269,16 @@
console.log('显示规则弹窗')
showRulePopup.value = true
}
//
const openSharePoster = () => {
showPoster.value = true
}
//
const handleUpdateShare = (val) => {
showPoster.value = val
}
</script>
<style lang="scss">
@ -242,169 +289,159 @@
.invite-page {
min-height: 100vh;
padding-bottom: 40rpx;
//
.nav-bg-layer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: calc(var(--status-bar-height) + 88rpx);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.9) 100%);
z-index: -1;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
}
.invite-card {
.card-content {
.commission-card {
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 30rpx;
/* 导航背景层 */
.nav-bg-layer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: calc(var(--status-bar-height) + 88rpx);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.9) 100%);
z-index: -1;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.ri-shopping-bag-3-line {
font-size: 48rpx;
margin-right: 15rpx;
}
.invite-card .card-content .commission-card {
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 30rpx;
}
.li-text-34 {
font-size: 34rpx;
font-weight: bold;
}
.invite-card .card-content .commission-card .ri-shopping-bag-3-line {
font-size: 48rpx;
margin-right: 15rpx;
}
.li-text-26 {
font-size: 26rpx;
opacity: 0.8;
}
}
.invite-card .card-content .commission-card .li-text-34 {
font-size: 34rpx;
font-weight: bold;
}
.benefit-list {
padding: 30rpx;
border-radius: 16rpx;
background: #f8faff;
.invite-card .card-content .commission-card .li-text-26 {
font-size: 26rpx;
opacity: 0.8;
}
.benefit-item {
.icon-box {
width: 48rpx;
height: 48rpx;
border-radius: 12rpx;
background: #E1F0FF;
margin-right: 20rpx;
padding: 15rpx;
.invite-card .card-content .benefit-list {
padding: 30rpx;
border-radius: 16rpx;
background: #f8faff;
}
.ri-user-add-line,
.ri-link-m,
.ri-money-cny-box-line {
font-size: 36rpx;
color: #0070F0;
}
}
.invite-card .card-content .benefit-list .benefit-item .icon-box {
width: 48rpx;
height: 48rpx;
border-radius: 12rpx;
background: #E1F0FF;
margin-right: 20rpx;
padding: 15rpx;
}
.li-text-30 {
font-size: 30rpx;
color: #333;
}
.invite-card .card-content .benefit-list .benefit-item .icon-box .ri-user-add-line,
.invite-card .card-content .benefit-list .benefit-item .icon-box .ri-link-m,
.invite-card .card-content .benefit-list .benefit-item .icon-box .ri-money-cny-box-line {
font-size: 36rpx;
color: #0070F0;
}
.li-text-26 {
font-size: 26rpx;
color: #666;
display: block;
margin-top: 5rpx;
}
}
}
}
.invite-card .card-content .benefit-list .benefit-item .li-text-30 {
font-size: 30rpx;
color: #333;
}
.share-btn {
background: linear-gradient(135deg, #42a5ff 0%, #0070F0 100%) !important;
border: none !important;
height: 90rpx !important;
font-size: 32rpx !important;
}
}
.invite-card .card-content .benefit-list .benefit-item .li-text-26 {
font-size: 26rpx;
color: #666;
display: block;
margin-top: 5rpx;
}
.invite-records {
.records-list {
height: calc(100vh - 600rpx);
.invite-card .share-btn {
background: linear-gradient(135deg, #42a5ff 0%, #0070F0 100%) !important;
border: none !important;
height: 90rpx !important;
font-size: 32rpx !important;
}
.record-item {
.avatar {
width: 90rpx;
height: 90rpx;
border-radius: 20rpx;
}
.invite-records .records-list {
height: calc(100vh - 600rpx);
}
.status-tag {
padding: 4rpx 20rpx;
border-radius: 30rpx;
font-size: 24rpx;
.invite-records .records-list .record-item .avatar {
width: 90rpx;
height: 90rpx;
border-radius: 20rpx;
}
&.success {
color: #07c160;
background-color: rgba(7, 193, 96, 0.1);
}
.invite-records .records-list .record-item .status-tag {
padding: 4rpx 20rpx;
border-radius: 30rpx;
font-size: 24rpx;
}
&.pending {
color: #f0ad4e;
background-color: rgba(240, 173, 78, 0.1);
}
}
}
}
}
.invite-records .records-list .record-item .status-tag.success {
color: #07c160;
background-color: rgba(7, 193, 96, 0.1);
}
.invite-records .records-list .record-item .status-tag.pending {
color: #f0ad4e;
background-color: rgba(240, 173, 78, 0.1);
}
.rules-popup {
width: 580rpx;
overflow: hidden;
.rules-header {
border-color: rgba(0, 0, 0, 0.05);
position: relative;
&::after {
content: '';
position: absolute;
left: 30rpx;
right: 30rpx;
bottom: 0;
height: 1px;
background: rgba(0, 0, 0, 0.05);
transform: scaleY(0.5);
}
.ri-close-line {
padding: 10rpx;
}
}
.rules-content {
padding:40rpx 30rpx 50rpx;
.rule-item {
display: flex;
align-items: flex-start;
margin-bottom: 20rpx;
.rule-icon {
display: flex;
align-items: center;
justify-content: center;
width: 36rpx;
height: 36rpx;
border-radius: 50%;
background: #0070F0;
color: white;
font-size: 24rpx;
margin-right: 16rpx;
flex-shrink: 0;
}
&:last-child {
margin-bottom: 0;
}
}
}
}
.rules-popup .rules-header {
border-color: rgba(0, 0, 0, 0.05);
position: relative;
}
.rules-popup .rules-header::after {
content: '';
position: absolute;
left: 30rpx;
right: 30rpx;
bottom: 0;
height: 1px;
background: rgba(0, 0, 0, 0.05);
transform: scaleY(0.5);
}
.rules-popup .rules-header .ri-close-line {
padding: 10rpx;
}
.rules-popup .rules-content {
padding: 40rpx 30rpx 50rpx;
}
.rules-popup .rules-content .rule-item {
display: flex;
align-items: flex-start;
margin-bottom: 20rpx;
}
.rules-popup .rules-content .rule-item .rule-icon {
display: flex;
align-items: center;
justify-content: center;
width: 36rpx;
height: 36rpx;
border-radius: 50%;
background: #0070F0;
color: white;
font-size: 24rpx;
margin-right: 16rpx;
flex-shrink: 0;
}
.rules-popup .rules-content .rule-item:last-child {
margin-bottom: 0;
}
</style>

View File

@ -49,7 +49,7 @@
{{getStatusText(item.status)}}
</view>
</view>
<!-- 订单内容 -->
<view class="order-content">
<view class="info-row">
@ -65,12 +65,12 @@
<text v-if="item.type == 'F4'">量房</text>
</view>
</view>
<view class="info-row">
<text class="row-label">小区名称</text>
<text class="row-value">{{item.order.village_name}}</text>
</view>
<view class="contact-info">
<view class="contact-row">
<text class="contact-icon ri-user-3-line"></text>
@ -83,7 +83,7 @@
</view>
</view>
</view>
<!-- 订单底部 -->
<view class="order-footer">
<view class="time-info">
@ -94,7 +94,7 @@
</view>
</view>
</view>
<view v-if="taskList.length==0" class="!li-mt-300">
<wd-status-tip image="search" tip="您还没有待处理的订单哦~" />
</view>
@ -115,14 +115,18 @@
} = useNavigation()
onLoad(() => {
onLoad((options) => {
checkRouteStack()
if (options.type) {
activeTab.value = Number(options.type)
handleStatusChange(Number(options.status))
}
})
onShow(() => {
query.value.page = 1
taskList.value = []
poolList()
// query.value.page = 1
// taskList.value = []
// poolList()
})
onPullDownRefresh(() => {
@ -300,10 +304,8 @@
}
const handleStatusChange = (id) => {
query.value.page = 1
query.value.status = id
taskList.value = []
poolList()
tabChange()
}
</script>
@ -393,12 +395,12 @@
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.04);
position: relative;
overflow: hidden;
&:active {
transform: scale(0.99);
transition: transform 0.2s;
}
/* 工单头部 */
.order-header {
display: flex;
@ -407,30 +409,30 @@
margin-bottom: 20rpx;
padding-bottom: 20rpx;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
.order-id {
display: flex;
align-items: center;
.id-icon {
font-size: 32rpx;
color: #999;
margin-right: 10rpx;
}
.id-text {
font-size: 28rpx;
color: #666;
font-weight: 500;
}
.copy-icon {
font-size: 28rpx;
color: #009aff;
margin-left: 16rpx;
}
}
.order-status {
font-size: 22rpx;
padding: 4rpx 18rpx;
@ -438,22 +440,22 @@
font-weight: 500;
}
}
/* 工单内容 */
.order-content {
padding: 10rpx 0 16rpx;
.info-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
.row-label {
font-size: 26rpx;
color: #999;
}
.row-value {
font-size: 26rpx;
color: #333;
@ -463,7 +465,7 @@
text-overflow: ellipsis;
white-space: nowrap;
}
.type-tag {
display: flex;
align-items: center;
@ -473,60 +475,60 @@
font-weight: 500;
color: #009aff;
background-color: rgba(0, 154, 255, 0.08);
&.type-F2 {
color: #ff9d00;
background-color: rgba(255, 157, 0, 0.08);
}
&.type-F6 {
color: #00b42a;
background-color: rgba(0, 180, 42, 0.08);
}
&.type-F4 {
color: #643bed;
background-color: rgba(100, 59, 237, 0.08);
}
.tag-icon {
margin-right: 6rpx;
}
}
}
.contact-info {
padding: 16rpx 20rpx;
background-color: rgba(0, 154, 255, 0.03);
border-radius: 12rpx;
.contact-row {
display: flex;
align-items: center;
margin-bottom: 12rpx;
&:last-child {
margin-bottom: 0;
}
.contact-icon {
font-size: 28rpx;
color: #009aff;
margin-right: 10rpx;
}
.contact-label {
font-size: 26rpx;
color: #999;
margin-right: 10rpx;
}
.contact-name {
font-size: 26rpx;
color: #333;
font-weight: 500;
}
.contact-phone {
font-size: 26rpx;
color: #009aff;
@ -535,7 +537,7 @@
}
}
}
/* 工单底部 */
.order-footer {
display: flex;
@ -543,23 +545,23 @@
align-items: center;
border-top: 1px dashed rgba(0, 0, 0, 0.05);
padding-top: 16rpx;
.time-info {
display: flex;
align-items: center;
.time-icon {
font-size: 24rpx;
color: #999;
margin-right: 6rpx;
}
.time-text {
font-size: 24rpx;
color: #999;
}
}
.detail-btn {
padding: 8rpx 30rpx;
background: linear-gradient(to right, #7bbfff, #009aff);

162
pagesB/agreement/index.vue Normal file
View File

@ -0,0 +1,162 @@
<template>
<view class="complaint-page">
<!-- 自定义导航栏 -->
<wd-navbar :bordered="false"
custom-style="background: transparent !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(10px) !important;"
safeAreaInsetTop fixed placeholder>
<template #left>
<view class="li-ml-15 li-mt-10 li-flex li-items-center">
<text v-if="hasMultiplePages" class="ri-arrow-left-s-line li-text-70"
@click="toPages({type:'nav'})"></text>
<text v-if="!hasMultiplePages" class="ri-home-5-line li-text-55 li-mb-8 li-mr-10"
@click="toPages({type:'home'})"></text>
<text class="li-text-42">{{paramsType=='1'?'用户协议':'隐私政策'}}</text>
</view>
</template>
</wd-navbar>
<!-- 导航栏背景 -->
<view class="nav-bg-layer"></view>
<view v-html="rawHtml"></view>
</view>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { useNavigation } from '@/hooks/useNavigation';
import { useToast } from '@/uni_modules/wot-design-uni';
const Toast = useToast();
// 使composable
const {
hasMultiplePages,
isTabBarPage,
checkRouteStack
} = useNavigation();
const paramsType = ref('1')
const rawHtml = ref('<div style="text-align:center;background-color: #007AFF;"><div >我是内容</div><img src="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/uni@2x.png"/></div>')
//
const toPages = (item) => {
switch (item.type) {
case 'nav':
uni.navigateBack({
delta: 1
});
break;
case 'home':
uni.switchTab({
url: '/pages/index/index'
});
break;
default:
break;
}
};
//
onLoad((options) => {
checkRouteStack();
paramsType.value = options.type
});
</script>
<style lang="scss">
page {
background-color: #F7F8FA;
}
.complaint-page {
min-height: 100vh;
}
.nav-bg-layer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: calc(var(--status-bar-height) + 88rpx);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.9) 100%);
z-index: -1;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.status-tag {
padding: 8rpx 24rpx;
border-radius: 30rpx;
font-size: 28rpx;
color: #666;
background: #f5f5f5;
margin-right: 16rpx;
transition: all 0.3s;
}
.status-tag.active {
color: #0070F0;
background: rgba(0, 112, 240, 0.1);
font-weight: 500;
}
.complaint-card {
transition: all 0.3s;
&:active {
transform: scale(0.98);
opacity: 0.9;
}
}
.complaint-header {
.status-badge {
padding: 4rpx 20rpx;
border-radius: 20rpx;
font-size: 24rpx;
}
}
.li-bottom-border2 {
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}
.preview-image {
width: 120rpx;
height: 120rpx;
border-radius: 8rpx;
object-fit: cover;
}
.more-image-text {
display: flex;
align-items: center;
justify-content: center;
width: 120rpx;
height: 120rpx;
background-color: #f8f8f8;
border-radius: 8rpx;
}
/* 覆盖组件样式 */
::v-deep .wd-search {
background-color: transparent !important;
padding: 0 !important;
border-radius: 10rpx !important;
}
::v-deep .wd-search__block {
background-color: rgba(255, 255, 255, 0.8) !important;
padding: 8rpx !important;
border-radius: 10rpx !important;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.015);
}
::v-deep .wd-status-tip__text {
margin-top: 30rpx !important;
color: #999 !important;
}
</style>

View File

@ -0,0 +1,408 @@
<template>
<view class="container">
<!-- 自定义导航栏 -->
<wd-navbar :bordered="false"
custom-style="background: transparent !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(20px) !important;"
safeAreaInsetTop fixed placeholder>
<template #left>
<view class="li-ml-15 li-mt-10 li-flex li-items-center">
<text class="ri-arrow-left-s-line li-text-70" @click="goBack"></text>
<text class="li-text-42">添加员工</text>
</view>
</template>
</wd-navbar>
<!-- 导航栏背景 -->
<view class="nav-bg-layer"></view>
<!-- 页面背景 -->
<view class="page-bg"></view>
<view class="content">
<!-- 表单区域 -->
<wd-form ref="form" :model="formData" :rules="rules" class="form-wrapper">
<wd-cell-group border class="form-card">
<wd-input
v-model="formData.name"
label="员工姓名"
placeholder="请输入姓名"
prop="name"
label-width="100px"
clearable
/>
<wd-input
v-model="formData.phone"
label="手机号码"
type="number"
placeholder="请输入手机号"
prop="phone"
label-width="100px"
clearable
/>
<wd-input
v-model="formData.password"
label="初始密码"
placeholder="123456"
prop="password"
label-width="100px"
disabled
/>
<wd-cell
title="所属小区"
:value="villageName"
@click="showVillagePopup = true"
is-link
title-width="100px"
/>
<wd-cell
title="权限设置"
@click="openPermissionPopup"
is-link
title-width="100px"
>
<view class="permission-summary">
<text>{{ getPermissionSummary() }}</text>
</view>
</wd-cell>
</wd-cell-group>
<!-- 提交按钮 -->
<view class="submit-btn-wrapper">
<wd-button type="primary" block @click="submitForm" custom-style="background: linear-gradient(135deg, #42a5ff, #0070F0);">创建员工</wd-button>
</view>
</wd-form>
<!-- 选择小区弹窗 -->
<wd-popup v-model="showVillagePopup" position="bottom" title="选择小区" round>
<view class="village-popup">
<view
v-for="(item, index) in villages"
:key="index"
class="village-item"
:class="{ active: formData.villageId === item.id }"
@click="selectVillage(item)"
>
<view class="village-name">{{ item.name }}</view>
<view class="village-check">
<text class="ri-checkbox-circle-fill" v-if="formData.villageId === item.id"></text>
</view>
</view>
</view>
</wd-popup>
<!-- 权限设置弹窗 -->
<wd-popup v-model="showPermissionPopup" position="bottom" custom-style="border-radius: 20rpx 20rpx 0 0;" :safe-area-inset-bottom="true">
<permission-settings
:staff="staffWithPermissions"
:permissions="allPermissions"
@save="savePermissions"
@cancel="closePermissionPopup"
/>
</wd-popup>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, computed, reactive } from 'vue';
import { useNavigation } from '@/hooks/useNavigation';
import PermissionSettings from '@/components/PermissionSettings.vue';
//
const { toPages } = useNavigation();
//
const form = ref(null);
//
const formData = reactive({
name: '',
phone: '',
password: '123456',
villageId: '',
permissions: []
});
//
const rules = {
name: [
{ required: true, message: '请输入员工姓名' }
],
phone: [
{ required: true, message: '请输入手机号码' },
{ pattern: /^1\d{10}$/, message: '手机号格式不正确' }
],
password: [
{ required: true, message: '默认初始密码' }
]
};
//
const villages = ref([
{ id: '1', name: '阳光花园小区' },
{ id: '2', name: '幸福家园小区' },
{ id: '3', name: '时代广场小区' }
]);
//
const showVillagePopup = ref(false);
//
const villageName = computed(() => {
const village = villages.value.find(v => v.id === formData.villageId);
return village ? village.name : '请选择';
});
//
const selectVillage = (village) => {
formData.villageId = village.id;
showVillagePopup.value = false;
};
//
const showPermissionPopup = ref(false);
//
const staffWithPermissions = computed(() => {
return {
name: formData.name || '新员工',
permissions: formData.permissions
};
});
//
const allPermissions = [
{ value: 'delivery', label: '配送权限', icon: 'ri-truck-line', description: '允许配送相关的订单处理', colorClass: 'delivery-color', isCommon: true },
{ value: 'maintenance', label: '维修权限', icon: 'ri-tools-line', description: '允许接受维修工单和处理', colorClass: 'maintenance-color', isCommon: true },
{ value: 'finance', label: '财务管理', icon: 'ri-money-cny-circle-line', description: '允许处理财务相关事务', colorClass: 'finance-color', isCommon: true },
{ value: 'resident', label: '住户管理', icon: 'ri-user-line', description: '允许管理小区住户信息', colorClass: 'general-color', isCommon: false },
{ value: 'security', label: '安防权限', icon: 'ri-shield-line', description: '允许管理小区安防系统', colorClass: 'general-color', isCommon: false },
{ value: 'admin', label: '管理员权限', icon: 'ri-admin-line', description: '系统管理员权限', colorClass: 'admin-color', isCommon: false },
{ value: 'parking', label: '车位管理', icon: 'ri-parking-line', description: '允许管理小区车位', colorClass: 'general-color', isCommon: false },
{ value: 'visitor', label: '访客管理', icon: 'ri-user-location-line', description: '允许管理小区访客', colorClass: 'general-color', isCommon: false },
{ value: 'complaint', label: '投诉处理', icon: 'ri-customer-service-line', description: '允许处理业主投诉', colorClass: 'general-color', isCommon: true },
{ value: 'facility', label: '设施管理', icon: 'ri-building-4-line', description: '允许管理小区公共设施', colorClass: 'general-color', isCommon: false },
{ value: 'notice', label: '通知发布', icon: 'ri-notification-line', description: '允许发布小区通知', colorClass: 'general-color', isCommon: false },
{ value: 'inspection', label: '巡检权限', icon: 'ri-survey-line', description: '允许进行小区巡检记录', colorClass: 'maintenance-color', isCommon: true },
];
//
const openPermissionPopup = () => {
showPermissionPopup.value = true;
};
//
const closePermissionPopup = () => {
showPermissionPopup.value = false;
};
//
const savePermissions = (staffData) => {
formData.permissions = [...staffData.permissions];
closePermissionPopup();
};
//
const getPermissionSummary = () => {
if (formData.permissions.length === 0) {
return '未设置权限';
}
//
const permNames = formData.permissions.map(code => {
const perm = allPermissions.find(p => p.value === code);
return perm ? perm.label : '';
}).filter(name => name);
if (permNames.length <= 2) {
return permNames.join('、');
} else {
return `${permNames[0]}${permNames[1]}${permNames.length}`;
}
};
//
const goBack = () => {
uni.navigateBack();
};
//
const submitForm = () => {
form.value.validate()
.then(({ valid, errors }) => {
if (valid) {
if (!formData.villageId) {
uni.showToast({ title: '请选择所属小区', icon: 'none' });
return;
}
//
uni.showLoading({ title: '提交中...' });
//
setTimeout(() => {
uni.hideLoading();
uni.showToast({ title: '添加成功', icon: 'success' });
//
setTimeout(() => {
uni.navigateBack();
}, 1500);
}, 1000);
} else {
console.log('表单校验失败', errors);
}
})
.catch(error => {
console.error('表单校验异常', error);
});
};
</script>
<style lang="scss" scoped>
/* 主容器 */
.container {
min-height: 100vh;
background-color: transparent;
position: relative;
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Helvetica, Segoe UI, Arial, Roboto, PingFang SC, sans-serif;
padding-bottom: env(safe-area-inset-bottom);
}
/* 导航栏背景 */
.nav-bg-layer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: calc(var(--status-bar-height) + 88rpx);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.9) 100%);
z-index: -1;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
/* 页面背景 */
.page-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, #f8fafd 0%, #eef2f9 100%);
z-index: -2;
&::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 30%;
background: linear-gradient(135deg, rgba(66, 165, 255, 0.03), rgba(0, 112, 240, 0));
z-index: -1;
}
&::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 40%;
background: linear-gradient(315deg, rgba(66, 165, 255, 0.02), rgba(0, 112, 240, 0));
z-index: -1;
}
}
/* 内容区域 */
.content {
position: relative;
z-index: 2;
padding: 30rpx;
padding-bottom: 50rpx;
/* #ifdef MP-WEIXIN */
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
/* #endif */
}
/* 表单包装器 */
.form-wrapper {
width: 100%;
}
/* 表单卡片 */
.form-card {
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
margin-bottom: 40rpx;
box-shadow: 0 8rpx 16rpx rgba(0, 112, 240, 0.06);
}
/* 提交按钮 */
.submit-btn-wrapper {
margin-top: 60rpx;
padding: 0 20rpx;
}
/* 小区选择弹窗 */
.village-popup {
padding: 30rpx;
max-height: 60vh;
}
.village-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 16rpx;
border-bottom: 1px solid #f5f5f5;
&:last-child {
border-bottom: none;
}
&.active {
background-color: rgba(66, 165, 255, 0.05);
}
.village-name {
font-size: 28rpx;
color: #333;
}
.village-check {
color: #42a5ff;
font-size: 40rpx;
}
}
/* 权限摘要 */
.permission-summary {
display: flex;
align-items: center;
justify-content: flex-end;
font-size: 28rpx;
color: #666;
}
:deep(.wd-input__label) {
font-size: 28rpx !important;
color: #333 !important;
}
:deep(.wd-cell__title) {
font-size: 28rpx !important;
color: #333 !important;
}
:deep(.wd-cell__value) {
color: #666 !important;
}
:deep(.wd-button--primary) {
background: linear-gradient(135deg, #42a5ff, #0070F0) !important;
border: none !important;
}
</style>

View File

@ -0,0 +1,944 @@
<template>
<view class="container">
<!-- 自定义导航栏 -->
<wd-navbar :bordered="false"
custom-style="background: transparent !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(20px) !important;"
safeAreaInsetTop fixed placeholder>
<template #left>
<view class="li-ml-15 li-mt-10 li-flex li-items-center">
<text v-if="hasMultiplePages" class="ri-arrow-left-s-line li-text-70"
@click="toPages({type:'nav'})"></text>
<text v-if="!hasMultiplePages" class="ri-home-5-line li-text-55 li-mb-8 li-mr-10"
@click="toPages({type:'home'})"></text>
<text class="li-text-42">员工权限</text>
</view>
</template>
<!-- #ifdef MP-WEIXIN -->
<template #right>
<view class="li-flex-center li-mr-200 li-pt-6" @click="handleAddStaff">
<text class="ri-add-line li-text-50"></text>
</view>
</template>
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<template #right>
<view class="li-flex-center li-mr-25 li-pt-6" @click="handleAddStaff">
<text class="ri-add-line li-text-55"></text>
</view>
</template>
<!-- #endif -->
</wd-navbar>
<!-- 导航栏背景 -->
<view class="nav-bg-layer"></view>
<!-- 页面背景 -->
<view class="page-bg"></view>
<view class="content">
<!-- 员工列表 -->
<view class="staff-list li-w-92% li-mx-auto li-mt-20" v-if="filteredStaffList.length > 0">
<view
v-for="staff in filteredStaffList"
:key="staff.id"
class="staff-card"
@tap="openPermissionSetting(staff)"
>
<view class="card-header">
<view class="staff-avatar" v-if="staff.avatar">
<image :src="staff.avatar" mode="aspectFill"></image>
</view>
<view class="staff-avatar default-avatar" v-else>
<text>{{staff.name.substring(0,1)}}</text>
</view>
<view class="staff-info">
<view class="staff-name">{{ staff.name }}</view>
<view class="staff-phone">
<text class="ri-phone-line phone-icon"></text>
<text>{{ staff.phone }}</text>
</view>
</view>
<view class="right-area">
<view class="perm-count" :class="{'has-perm': staff.permissions.length > 0}">
{{ staff.permissions.length }}
</view>
<text class="ri-arrow-right-s-line action-icon"></text>
</view>
</view>
<view class="card-content" v-if="staff.permissions.length > 0">
<!-- 权限标签 -->
<view class="perm-tags">
<view
v-for="(perm, index) in staff.permissions.slice(0, 2)"
:key="perm"
class="perm-tag"
:class="getPermissionClass(perm)"
>
<text :class="getPermissionIcon(perm)"></text>
<text>{{ getPermissionName(perm) }}</text>
</view>
<view class="perm-tag more" v-if="staff.permissions.length > 2">
<text>+{{ staff.permissions.length - 2 }}</text>
</view>
</view>
</view>
<view class="card-content" v-else>
<view class="no-perm-tag">
<text class="ri-lock-line"></text>
<text>暂无权限</text>
</view>
</view>
</view>
</view>
<!-- 空状态 -->
<view class="empty-state" v-else>
<wd-empty description="暂无员工数据">
<wd-button type="primary" @click="handleAddStaff">添加员工</wd-button>
</wd-empty>
</view>
<!-- 底部权限设置面板 -->
<wd-popup v-model="showPermissionPopup" position="bottom" custom-style="border-radius: 20rpx 20rpx 0 0;" @close="handlePopupClose" :safe-area-inset-bottom="true">
<permission-settings
:staff="currentStaff"
:permissions="allPermissions"
@save="savePermissions"
@cancel="closePermissionSheet"
/>
</wd-popup>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, reactive, computed, nextTick } from 'vue';
import { useNavigation } from '@/hooks/useNavigation';
import { onLoad, onPullDownRefresh } from '@dcloudio/uni-app';
import PermissionSettings from '@/components/PermissionSettings.vue';
//
const { toPages, hasMultiplePages, checkRouteStack } = useNavigation();
//
const villageId = ref('');
const villageName = ref('阳光花园小区');
const villageAddress = ref('市政府北路123号');
//
const searchKeyword = ref('');
const currentFilter = ref('全部');
const filterOptions = ['全部', '配送权限', '维修权限'];
//
const permissionSearchKeyword = ref('');
//
const showMorePermissionsPopup = ref(false);
const currentStaffPermissions = ref([]);
//
const showPermissionPopup = ref(false);
const currentStaff = ref(null);
const tempPermissions = reactive({});
// - 使
const staffList = ref([
{
id: 1,
name: '张三',
phone: '13800138000',
avatar: '/static/swiper/1.png',
permissions: ['delivery', 'complaint'],
department: '配送部'
},
{
id: 2,
name: '李四',
phone: '13800138001',
avatar: '/static/swiper/1.png',
permissions: ['delivery', 'maintenance', 'inspection', 'facility', 'visitor'],
department: '综合部'
},
{
id: 3,
name: '王五',
phone: '13800138002',
avatar: '/static/swiper/1.png',
permissions: ['maintenance', 'inspection'],
department: '工程部'
},
{
id: 4,
name: '赵六',
phone: '13800138003',
avatar: '/static/swiper/1.png',
permissions: [],
department: '客服部'
}
]);
//
const allPermissions = [
{ value: 'delivery', label: '配送权限', icon: 'ri-truck-line', description: '允许配送相关的订单处理', colorClass: 'delivery-color', isCommon: true },
{ value: 'maintenance', label: '维修权限', icon: 'ri-tools-line', description: '允许接受维修工单和处理', colorClass: 'maintenance-color', isCommon: true },
{ value: 'finance', label: '财务管理', icon: 'ri-money-cny-circle-line', description: '允许处理财务相关事务', colorClass: 'finance-color', isCommon: true },
{ value: 'resident', label: '住户管理', icon: 'ri-user-line', description: '允许管理小区住户信息', colorClass: 'general-color', isCommon: false },
{ value: 'security', label: '安防权限', icon: 'ri-shield-line', description: '允许管理小区安防系统', colorClass: 'general-color', isCommon: false },
{ value: 'admin', label: '管理员权限', icon: 'ri-admin-line', description: '系统管理员权限', colorClass: 'admin-color', isCommon: false },
{ value: 'parking', label: '车位管理', icon: 'ri-parking-line', description: '允许管理小区车位', colorClass: 'general-color', isCommon: false },
{ value: 'visitor', label: '访客管理', icon: 'ri-user-location-line', description: '允许管理小区访客', colorClass: 'general-color', isCommon: false },
{ value: 'complaint', label: '投诉处理', icon: 'ri-customer-service-line', description: '允许处理业主投诉', colorClass: 'general-color', isCommon: true },
{ value: 'facility', label: '设施管理', icon: 'ri-building-4-line', description: '允许管理小区公共设施', colorClass: 'general-color', isCommon: false },
{ value: 'notice', label: '通知发布', icon: 'ri-notification-line', description: '允许发布小区通知', colorClass: 'general-color', isCommon: false },
{ value: 'inspection', label: '巡检权限', icon: 'ri-survey-line', description: '允许进行小区巡检记录', colorClass: 'maintenance-color', isCommon: true },
];
//
const filteredStaffList = computed(() => {
let result = staffList.value;
//
if (searchKeyword.value) {
result = result.filter(staff =>
staff.name.includes(searchKeyword.value) ||
staff.phone.includes(searchKeyword.value)
);
}
//
if (currentFilter.value !== '全部') {
//
const permCode = allPermissions.find(p => p.label === currentFilter.value)?.value;
if (permCode) {
result = result.filter(staff => staff.permissions.includes(permCode));
}
}
return result;
});
//
const commonPermissions = computed(() => {
return allPermissions.filter(perm => perm.isCommon);
});
const otherPermissions = computed(() => {
return allPermissions.filter(perm => !perm.isCommon);
});
/**
* 获取权限图标
* @param {string} permCode 权限代码
* @returns {string} 图标class
*/
const getPermissionIcon = (permCode) => {
const perm = allPermissions.find(p => p.value === permCode);
return perm ? perm.icon : 'ri-lock-line';
};
/**
* 获取权限名称
* @param {string} permCode 权限代码
* @returns {string} 权限名称
*/
const getPermissionName = (permCode) => {
const perm = allPermissions.find(p => p.value === permCode);
return perm ? perm.label : '未知权限';
};
/**
* 获取权限样式类
* @param {string} permCode 权限代码
* @returns {string} 样式类名
*/
const getPermissionClass = (permCode) => {
const perm = allPermissions.find(p => p.value === permCode);
return perm ? perm.colorClass : '';
};
/**
* 获取激活的权限数量
*/
const getActivePermissionsCount = () => {
return Object.values(tempPermissions).filter(v => v === true).length;
};
/**
* 显示更多权限弹窗
* @param {Object} staff 员工信息
*/
const showMorePermissions = (staff) => {
currentStaff.value = staff;
currentStaffPermissions.value = staff.permissions;
showMorePermissionsPopup.value = true;
};
/**
* 获取小区信息
*/
const getVillageInfo = () => {
//
console.log('获取小区ID为', villageId.value, '的信息');
};
/**
* 获取员工列表
*/
const getStaffList = () => {
//
console.log('获取小区ID为', villageId.value, '的员工列表');
};
/**
* 处理搜索
*/
const handleSearch = () => {
console.log('搜索关键词:', searchKeyword.value);
//
};
/**
* 设置筛选条件
* @param {string} filter 筛选条件
*/
const setFilter = (filter) => {
currentFilter.value = filter;
console.log('筛选条件:', filter);
//
};
/**
* 处理添加员工
*/
const handleAddStaff = () => {
uni.navigateTo({
url: '/pagesB/permissions/addStaff'
});
};
/**
* 处理权限设置
* @param {Object} staff 员工信息
*/
const handleSetPermission = (staff) => {
currentStaff.value = staff;
//
allPermissions.forEach(perm => {
tempPermissions[perm.value] = staff.permissions.includes(perm.value);
});
showPermissionPopup.value = true;
};
/**
* 保存权限设置
*/
const savePermissions = () => {
if (!currentStaff.value) return;
//
uni.showLoading({
title: '保存中...',
mask: true
});
// API
// API
const requestData = {
staffId: currentStaff.value.id,
permissions: currentStaff.value.permissions,
villageId: villageId.value
};
// API
setTimeout(() => {
// API:
/*
uni.request({
url: 'https://api.example.com/staff/permissions',
method: 'POST',
data: requestData,
success: (res) => {
if (res.data.code === 0) {
//
updateLocalStaffPermissions();
//
closePermissionSheet();
uni.showToast({
title: '权限设置成功',
icon: 'success'
});
} else {
uni.showToast({
title: res.data.message || '保存失败',
icon: 'none'
});
}
},
fail: (err) => {
uni.showToast({
title: '网络错误,请重试',
icon: 'none'
});
console.error('保存权限失败:', err);
},
complete: () => {
uni.hideLoading();
}
});
*/
//
updateLocalStaffPermissions();
//
uni.hideLoading();
//
closePermissionSheet();
uni.showToast({
title: '权限设置成功',
icon: 'success'
});
}, 800);
};
/**
* 更新本地员工权限数据
*/
const updateLocalStaffPermissions = () => {
const index = staffList.value.findIndex(item => item.id === currentStaff.value.id);
if (index !== -1) {
staffList.value[index] = {
...staffList.value[index],
permissions: [...currentStaff.value.permissions]
};
}
};
//
const permissionActions = [
{ name: '配送权限', value: 'delivery', icon: 'ri-truck-line' },
{ name: '维修权限', value: 'maintenance', icon: 'ri-tools-line' },
{ name: '财务管理', value: 'finance', icon: 'ri-money-cny-circle-line' },
{ name: '住户管理', value: 'resident', icon: 'ri-user-line' },
{ name: '安防权限', value: 'security', icon: 'ri-shield-line' },
{ name: '管理员权限', value: 'admin', icon: 'ri-admin-line' },
{ name: '投诉处理', value: 'complaint', icon: 'ri-customer-service-line' },
{ name: '巡检权限', value: 'inspection', icon: 'ri-survey-line' },
];
//
const handleFilterChange = (filter) => {
currentFilter.value = filter;
};
//
const resetFilter = () => {
currentFilter.value = '全部';
searchKeyword.value = '';
};
//
const clearSearchKeyword = () => {
searchKeyword.value = '';
};
//
const openPermissionSetting = (staff) => {
//
currentStaff.value = {
...staff,
//
permissions: [...staff.permissions]
};
//
showPermissionPopup.value = true;
};
//
const closePermissionSheet = () => {
showPermissionPopup.value = false;
};
//
const togglePermission = (permission) => {
if (!currentStaff.value) return;
const index = currentStaff.value.permissions.indexOf(permission);
if (index > -1) {
//
currentStaff.value.permissions.splice(index, 1);
} else {
//
currentStaff.value.permissions.push(permission);
}
};
//
const hasPermission = (permission) => {
if (!currentStaff.value) return false;
return currentStaff.value.permissions.includes(permission);
};
//
onLoad((options) => {
if (options.villageId) {
villageId.value = options.villageId;
//
getVillageInfo();
getStaffList();
}
checkRouteStack();
});
//
onPullDownRefresh(() => {
getStaffList();
setTimeout(() => {
uni.stopPullDownRefresh();
}, 1000);
});
// wd-popupclose
const handlePopupClose = () => {
//
};
</script>
<style lang="scss" scoped>
/* 主容器 */
.container {
min-height: 100vh;
background-color: transparent;
position: relative;
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Helvetica, Segoe UI, Arial, Roboto, PingFang SC, sans-serif;
padding-bottom: env(safe-area-inset-bottom);
}
/* 导航栏背景 */
.nav-bg-layer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: calc(var(--status-bar-height) + 88rpx);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.9) 100%);
z-index: -1;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
/* 页面背景 */
.page-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, #f8fafd 0%, #eef2f9 100%);
z-index: -2;
&::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 30%;
background: linear-gradient(135deg, rgba(76, 132, 255, 0.03), rgba(76, 132, 255, 0));
z-index: -1;
}
&::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 40%;
background: linear-gradient(315deg, rgba(76, 132, 255, 0.02), rgba(76, 132, 255, 0));
z-index: -1;
}
}
/* 添加按钮 */
.add-btn {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
background-color: #4080FF;
color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
font-size: 40rpx;
box-shadow: 0 4rpx 8rpx rgba(64, 128, 255, 0.3);
}
/* 内容区域 */
.content {
position: relative;
z-index: 2;
padding-bottom: 30rpx;
/* #ifdef MP-WEIXIN */
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
/* #endif */
/* #ifdef APP-PLUS || H5 */
padding-bottom: 50rpx;
/* #endif */
}
/* 小区卡片 */
.village-card {
margin: 0 30rpx 30rpx;
background-color: #fff;
border-radius: 24rpx;
overflow: hidden;
box-shadow: 0 10rpx 30rpx rgba(31, 35, 172, 0.05);
}
.card-header {
padding: 36rpx 40rpx;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1rpx solid rgba(0, 0, 0, 0.03);
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 200rpx;
height: 200rpx;
background: radial-gradient(circle at top right, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0));
z-index: 1;
}
.village-name {
font-size: 36rpx;
font-weight: 600;
color: #333;
position: relative;
z-index: 2;
}
.badge-container {
position: relative;
z-index: 2;
.badge {
display: inline-flex;
align-items: center;
padding: 6rpx 20rpx;
background-color: rgba(76, 132, 255, 0.1);
border-radius: 30rpx;
color: #4C84FF;
.badge-num {
font-size: 28rpx;
font-weight: bold;
margin-right: 6rpx;
}
.badge-text {
font-size: 24rpx;
}
}
}
}
.card-content {
padding: 25rpx 40rpx;
.village-address {
display: flex;
align-items: center;
font-size: 28rpx;
color: #666;
.address-icon {
color: #999;
margin-right: 10rpx;
font-size: 32rpx;
}
.address-text {
color: #666;
}
}
}
/* 搜索容器 */
.search-wrapper {
position: relative;
z-index: 3;
margin-bottom: 30rpx;
&::before {
content: '';
position: absolute;
top: 50%;
left: -15%;
width: 120rpx;
height: 120rpx;
border-radius: 50%;
background: linear-gradient(135deg, rgba(76, 132, 255, 0.1), rgba(76, 132, 255, 0));
z-index: -1;
transform: translateY(-50%);
}
&::after {
content: '';
position: absolute;
top: -20rpx;
right: -5%;
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: linear-gradient(135deg, rgba(66, 211, 170, 0.06), rgba(66, 211, 170, 0));
z-index: -1;
}
}
/* 筛选容器 */
.filter-container {
margin: 0 0 20rpx;
position: relative;
z-index: 2;
}
/* 筛选标签 */
.filter-tabs {
white-space: nowrap;
padding: 0 30rpx 10rpx;
.filter-tab {
display: inline-block;
padding: 15rpx 32rpx;
margin-right: 15rpx;
background-color: #fff;
border-radius: 50rpx;
font-size: 28rpx;
color: #666;
box-shadow: 0 6rpx 12rpx rgba(76, 132, 255, 0.06);
transition: all 0.3s;
position: relative;
overflow: hidden;
&:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0));
z-index: -1;
}
&.active {
background-color: #4080FF;
color: #fff;
font-weight: 500;
box-shadow: 0 8rpx 16rpx rgba(64, 128, 255, 0.3);
&:before {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
}
}
}
}
/* 员工列表 */
.staff-list {
padding: 0 30rpx;
}
/* 员工卡片 */
.staff-card {
padding: 24rpx;
background-color: #fff;
border-radius: 16rpx;
margin-bottom: 16rpx;
position: relative;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
transition: all 0.3s;
// border-left: 3rpx solid #0070F0;
&:active {
transform: translateY(1rpx);
background-color: #fafafa;
}
.card-header {
display: flex;
align-items: center;
position: relative;
.staff-avatar {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
overflow: hidden;
margin-right: 16rpx;
flex-shrink: 0;
background-color: #f2f8ff;
image {
width: 100%;
height: 100%;
}
&.default-avatar {
background-color: #0070F0;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
font-weight: bold;
}
}
.staff-info {
flex: 1;
.staff-name {
font-size: 28rpx;
font-weight: 600;
color: #333;
margin-bottom: 4rpx;
}
.staff-phone {
font-size: 24rpx;
color: #999;
display: flex;
align-items: center;
.phone-icon {
font-size: 22rpx;
color: #999;
margin-right: 4rpx;
}
}
}
.right-area {
display: flex;
align-items: center;
.action-icon {
font-size: 32rpx;
color: #ddd;
margin-left: 10rpx;
}
}
}
.card-content {
margin-top: 12rpx;
}
}
/* 权限标签 */
.perm-tags {
display: flex;
flex-wrap: wrap;
margin-top: 2rpx;
.perm-tag {
height: 38rpx;
line-height: 38rpx;
display: inline-flex;
align-items: center;
padding: 0 10rpx;
background-color: #f0f7ff;
color: #0070F0;
font-size: 24rpx;
border-radius: 4rpx;
margin-right: 10rpx;
margin-bottom: 0;
text {
&:first-child {
margin-right: 4rpx;
font-size: 22rpx;
}
}
&.more {
background-color: #f0f0f0;
color: #999;
}
&.delivery-color {
background-color: #f0f7ff;
color: #0070F0;
}
&.maintenance-color {
background-color: #f0f7ff;
color: #0070F0;
}
&.finance-color {
background-color: #f0f7ff;
color: #0070F0;
}
&.admin-color {
background-color: #f0f7ff;
color: #0070F0;
}
&.general-color {
background-color: #f0f7ff;
color: #0070F0;
}
}
}
.no-perm-tag {
font-size: 24rpx;
color: #999;
display: flex;
align-items: center;
.ri-lock-line {
margin-right: 4rpx;
}
}
/* 空状态 */
.empty-state {
padding: 100rpx 0;
}
.perm-count {
min-width: 32rpx;
height: 32rpx;
padding: 0 6rpx;
border-radius: 16rpx;
background-color: #0070F0;
color: #fff;
font-size: 22rpx;
display: flex;
align-items: center;
justify-content: center;
}
</style>

View File

@ -0,0 +1,596 @@
<template>
<view class="container">
<!-- 自定义导航栏 -->
<wd-navbar :bordered="false"
custom-style="background: transparent !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(20px) !important;"
safeAreaInsetTop fixed placeholder>
<template #left>
<view class="li-ml-15 li-mt-10 li-flex li-items-center">
<text v-if="hasMultiplePages" class="ri-arrow-left-s-line li-text-70"
@click="toPages({type:'nav'})"></text>
<text v-if="!hasMultiplePages" class="ri-home-5-line li-text-55 li-mb-8 li-mr-10"
@click="toPages({type:'home'})"></text>
<text class="li-text-42">小区列表</text>
</view>
</template>
</wd-navbar>
<!-- 导航栏背景 -->
<view class="nav-bg-layer"></view>
<!-- 页面背景 -->
<view class="page-bg"></view>
<view class="content">
<!-- 搜索区域 -->
<view class="search-wrapper li-w-90% li-mx-auto li-mt-30">
<wd-search placeholderStyle="color:#a0aec0" v-model="searchKeyword" placeholder="搜索小区名称或地址" hide-cancel
placeholder-left @search="handleSearch">
<!-- <template #prefix>
<text class="ri-search-line li-text-36 li-text-#4C84FF"></text>
</template> -->
</wd-search>
</view>
<!-- 小区列表 -->
<view class="village-list li-w-92% li-mx-auto li-mt-30">
<view class="village-card" v-for="(item, index) in villageList" :key="index"
@click="handleSelectVillage(item)">
<view class="card-header">
<view class="village-name">{{item.name}}</view>
<view class="badge-container">
<view class="badge li-mr-20">
<text class="badge-num">{{item.staffCount}}</text>
<text class="badge-text">员工</text>
</view>
<view class="badge">
<text class="badge-num">{{item.buildingCount}}</text>
<text class="badge-text">楼栋</text>
</view>
</view>
</view>
<view class="card-content">
<view class="village-address">
<text class="ri-map-pin-line address-icon"></text>
<text class="address-text">{{item.address}}</text>
</view>
<view class="village-action">
<text class="action-text">设置权限</text>
<text class="ri-arrow-right-s-line action-icon"></text>
</view>
</view>
<view class="card-footer">
<view class="footer-tag">
<text class="ri-building-2-line"></text>
<text>物业管理</text>
</view>
</view>
</view>
</view>
<!-- 空状态 -->
<view v-if="villageList.length === 0" class="empty-state li-mt-100">
<wd-status-tip image="search" tip="暂无小区数据" />
<view class="empty-action">
<wd-button type="primary" custom-class="add-village-btn" @click="handleAddVillage">添加小区</wd-button>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import {
ref
} from 'vue';
import {
useNavigation
} from '@/hooks/useNavigation';
import {
onLoad,
onPullDownRefresh,
onReachBottom
} from '@dcloudio/uni-app';
// 使composable
const {
hasMultiplePages,
isTabBarPage,
checkRouteStack
} = useNavigation();
//
const searchKeyword = ref('');
//
const villageList = ref([{
id: 1,
name: '阳光花园小区',
address: '市政府北路123号',
staffCount: 12,
buildingCount: 8
},
{
id: 2,
name: '翠湖庭院',
address: '湖滨路456号',
staffCount: 8,
buildingCount: 5
},
{
id: 3,
name: '金色家园',
address: '市政府东路789号',
staffCount: 15,
buildingCount: 10
},
{
id: 4,
name: '铂金公寓',
address: '南山大道458号',
staffCount: 9,
buildingCount: 6
},
{
id: 5,
name: '滨江华府',
address: '滨河路367号',
staffCount: 18,
buildingCount: 14
}
]);
/**
* 处理搜索
*/
const handleSearch = () => {
console.log('搜索关键词:', searchKeyword.value);
// TODO:
};
/**
* 选择小区前往权限设置页面
* @param {Object} village 小区数据
*/
const handleSelectVillage = (village) => {
//
uni.navigateTo({
url: '/pagesB/permissions/staffList?villageId=' + village.id
});
};
/**
* 添加小区
*/
const handleAddVillage = () => {
// TODO:
uni.showToast({
title: '添加小区功能开发中',
icon: 'none'
});
};
//
const toPages = (item) => {
switch (item.type) {
case 'nav':
uni.navigateBack({
delta: 1
});
break;
case 'home':
uni.switchTab({
url: '/pages/index/index'
});
break;
default:
break;
}
};
//
onLoad(() => {
checkRouteStack();
});
</script>
<style lang="scss" scoped>
.container {
min-height: 100vh;
background-color: transparent;
position: relative;
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Helvetica, Segoe UI, Arial, Roboto, PingFang SC, sans-serif;
}
.page-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, #f8fafd 0%, #eef2f9 100%);
z-index: -2;
&::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 30%;
background: linear-gradient(135deg, rgba(76, 132, 255, 0.03), rgba(76, 132, 255, 0));
z-index: -1;
}
&::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 40%;
background: linear-gradient(315deg, rgba(76, 132, 255, 0.02), rgba(76, 132, 255, 0));
z-index: -1;
}
}
.nav-bg-layer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: calc(var(--status-bar-height) + 88rpx);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.9) 100%);
z-index: -1;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.content {
position: relative;
z-index: 2;
padding-bottom: 30rpx;
/* #ifdef MP-WEIXIN */
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
/* #endif */
/* #ifdef APP-PLUS || H5 */
padding-bottom: 50rpx;
/* #endif */
}
.search-wrapper {
position: relative;
z-index: 3;
margin-bottom: 40rpx;
&::before {
content: '';
position: absolute;
top: 50%;
left: -15%;
width: 120rpx;
height: 120rpx;
border-radius: 50%;
background: linear-gradient(135deg, rgba(76, 132, 255, 0.1), rgba(76, 132, 255, 0));
z-index: -1;
transform: translateY(-50%);
}
&::after {
content: '';
position: absolute;
top: -20rpx;
right: -5%;
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: linear-gradient(135deg, rgba(66, 211, 170, 0.06), rgba(66, 211, 170, 0));
z-index: -1;
}
}
.village-list {
.village-card {
background-color: #fff;
border-radius: 24rpx;
overflow: hidden;
box-shadow: 0 10rpx 30rpx rgba(31, 35, 172, 0.05);
margin-bottom: 30rpx;
transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1);
position: relative;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 6rpx;
height: 100%;
background: linear-gradient(180deg, #4C84FF, #6EAEFE);
opacity: 0;
transition: opacity 0.3s ease;
}
&:active {
transform: translateY(2rpx) scale(0.99);
box-shadow: 0 6rpx 15rpx rgba(31, 35, 172, 0.03);
&::before {
opacity: 1;
}
}
.card-header {
padding: 36rpx 40rpx;
display: flex;
justify-content: space-between;
align-items: center;
background: linear-gradient(135deg, rgba(76, 132, 255, 0.06), rgba(76, 132, 255, 0.12));
border-bottom: 1rpx solid rgba(0, 0, 0, 0.03);
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 200rpx;
height: 200rpx;
background: radial-gradient(circle at top right, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0));
z-index: 1;
}
.village-name {
font-size: 36rpx;
font-weight: 600;
color: #333;
position: relative;
z-index: 2;
background: linear-gradient(90deg, #333, #555);
-webkit-background-clip: text;
color: transparent;
letter-spacing: 1rpx;
}
.badge-container {
display: flex;
position: relative;
z-index: 2;
.badge {
display: flex;
flex-direction: column;
align-items: center;
background-color: rgba(76, 132, 255, 0.1);
padding: 10rpx 24rpx;
border-radius: 12rpx;
box-shadow: 0 4rpx 12rpx rgba(76, 132, 255, 0.1);
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1rpx;
background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0));
}
.badge-num {
font-size: 30rpx;
font-weight: 600;
color: #4C84FF;
text-shadow: 0 1rpx 2rpx rgba(76, 132, 255, 0.1);
}
.badge-text {
font-size: 22rpx;
color: #666;
margin-top: 2rpx;
}
}
}
}
.card-content {
padding: 30rpx 40rpx;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
&::before {
content: '';
position: absolute;
bottom: 0;
left: 40rpx;
right: 40rpx;
height: 1px;
background: linear-gradient(90deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.03), rgba(0, 0, 0, 0));
}
.village-address {
display: flex;
align-items: center;
.address-text {
font-size: 28rpx;
color: #666;
margin-left: 6rpx;
}
}
.village-action {
display: flex;
align-items: center;
background: rgba(76, 132, 255, 0.06);
padding: 10rpx 20rpx;
border-radius: 40rpx;
transition: all 0.3s ease;
&:active {
background: rgba(76, 132, 255, 0.1);
transform: translateX(-4rpx);
}
.action-text {
font-size: 26rpx;
color: #4C84FF;
margin-right: 8rpx;
font-weight: 500;
}
}
}
}
}
/* 覆盖组件样式 */
::v-deep .wd-search {
background-color: transparent !important;
padding: 0 !important;
}
::v-deep .wd-search__block {
background-color: rgba(255, 255, 255, 0.9) !important;
padding: 20rpx 30rpx !important;
border-radius: 20rpx !important;
box-shadow: 0 15rpx 30rpx rgba(31, 35, 172, 0.05);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1rpx solid rgba(255, 255, 255, 0.8);
}
::v-deep .wd-search__input {
font-size: 28rpx !important;
color: #333 !important;
}
::v-deep .wd-search__input-inner {
height: 70rpx !important;
}
::v-deep .wd-search__placeholder {
font-size: 28rpx !important;
}
::v-deep .wd-search__label {
color: #4C84FF !important;
}
::v-deep .wd-status-tip__text {
margin-top: 30rpx !important;
color: #999 !important;
font-size: 30rpx !important;
}
::v-deep .wd-status-tip__image {
opacity: 0.8 !important;
}
.page-title {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 40rpx;
margin-top: 20rpx;
.title-wrapper {
.title-main {
font-size: 44rpx;
font-weight: 600;
color: #333;
margin-right: 15rpx;
background: linear-gradient(90deg, #333, #555);
-webkit-background-clip: text;
color: transparent;
}
.title-sub {
font-size: 28rpx;
color: #999;
margin-left: 15rpx;
}
}
.add-button {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: linear-gradient(135deg, #4C84FF, #6EAEFE);
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 6rpx 20rpx rgba(76, 132, 255, 0.3);
transition: all 0.3s ease;
&:active {
transform: scale(0.92);
box-shadow: 0 3rpx 10rpx rgba(76, 132, 255, 0.2);
}
text {
color: white;
font-size: 44rpx;
}
}
}
.address-icon {
color: #999;
font-size: 32rpx;
margin-right: 2rpx;
}
.action-icon {
color: #4C84FF;
font-size: 36rpx;
}
.card-footer {
padding: 20rpx 40rpx;
border-top: 1rpx solid rgba(0, 0, 0, 0.03);
background: #fafbfc;
.footer-tag {
display: inline-flex;
align-items: center;
background: rgba(76, 132, 255, 0.06);
padding: 6rpx 16rpx;
border-radius: 8rpx;
text:first-child {
color: #4C84FF;
font-size: 28rpx;
margin-right: 6rpx;
}
text:last-child {
font-size: 24rpx;
color: #666;
}
}
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
.empty-action {
margin-top: 40rpx;
}
}
.add-village-btn {
background: linear-gradient(135deg, #4C84FF, #6EAEFE) !important;
border: none !important;
box-shadow: 0 6rpx 20rpx rgba(76, 132, 255, 0.2) !important;
border-radius: 12rpx !important;
font-weight: 500 !important;
letter-spacing: 2rpx !important;
}
</style>

511
pagesB/setting/editInfo.vue Normal file
View File

@ -0,0 +1,511 @@
<template>
<view class="container">
<!-- 自定义导航栏 -->
<wd-navbar :bordered="false"
custom-style="background: transparent !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(20px) !important;"
safeAreaInsetTop fixed placeholder>
<template #left>
<view class="li-ml-15 li-mt-10 li-flex li-items-center">
<text v-if="hasMultiplePages" class="ri-arrow-left-s-line li-text-70"
@click="toPages({type:'nav'})"></text>
<text v-if="!hasMultiplePages" class="ri-home-5-line li-text-55 li-mb-8 li-mr-10"
@click="toPages({type:'home'})"></text>
<text class="li-text-42">个人信息</text>
</view>
</template>
</wd-navbar>
<!-- 导航栏背景 -->
<view class="nav-bg-layer"></view>
<!-- 页面背景 -->
<view class="page-bg"></view>
<view class="content">
<!-- 个人信息表单 -->
<view class="form-container">
<!-- 头像设置 -->
<view class="avatar-section" @click="chooseAvatar">
<view class="section-left">
<text class="form-label">头像</text>
</view>
<view class="section-right">
<view class="user-avatar">
<image v-if="userInfo.avatar" :src="userInfo.avatar" mode="aspectFill"></image>
<view v-else class="default-avatar">{{ userInfo.nickname.substring(0, 1) }}</view>
</view>
<text class="ri-arrow-right-s-line arrow-icon"></text>
</view>
</view>
<!-- 昵称设置 -->
<view class="form-section">
<view class="section-left">
<text class="form-label">昵称</text>
</view>
<view class="section-right">
<view class="input-wrapper">
<input class="form-input" type="text" v-model="userInfo.nickname" placeholder="请输入昵称"
@blur="validateNickname" />
</view>
<text class="ri-arrow-right-s-line arrow-icon"></text>
</view>
</view>
<!-- 手机号展示 -->
<view class="form-section">
<view class="section-left">
<text class="form-label">手机号</text>
</view>
<view class="section-right">
<text class="phone-text">{{ formatPhone(userInfo.phone) }}</text>
</view>
</view>
</view>
<!-- 保存按钮 -->
<view class="save-btn-container">
<button class="save-btn" @click="saveUserInfo">保存</button>
</view>
</view>
<!-- 头像选择弹窗 -->
<wd-popup v-model="showAvatarPopup" position="bottom">
<view class="avatar-popup">
<view class="popup-title">修改头像</view>
<view class="avatar-options">
<view class="option-item" @click="handleSelectAlbum">
<text class="ri-image-2-line option-icon"></text>
<text class="option-text">从相册选择</text>
</view>
<view class="option-item" @click="handleTakePhoto">
<text class="ri-camera-line option-icon"></text>
<text class="option-text">拍照</text>
</view>
</view>
<view class="cancel-btn" @click="showAvatarPopup = false">取消</view>
</view>
</wd-popup>
</view>
</template>
<script setup>
import {
ref,
reactive,
onMounted
} from 'vue';
import {
useNavigation
} from '@/hooks/useNavigation';
import {
onLoad
} from '@dcloudio/uni-app'
// 使 composable
const {
hasMultiplePages, //
isTabBarPage, // tabBar
checkRouteStack //
} = useNavigation()
//
const userInfo = reactive({
nickname: '里派用户',
phone: '13800138000',
avatar: ''
});
//
const showAvatarPopup = ref(false);
/**
* 格式化手机号码为带星号格式
*/
const formatPhone = (phone) => {
if (!phone) return '';
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
};
/**
* 校验昵称
*/
const validateNickname = () => {
if (!userInfo.nickname.trim()) {
uni.showToast({
title: '昵称不能为空',
icon: 'none'
});
userInfo.nickname = '里派用户';
}
};
/**
* 选择头像
*/
const chooseAvatar = () => {
showAvatarPopup.value = true;
};
/**
* 从相册选择照片
*/
const handleSelectAlbum = () => {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album'],
success: (res) => {
//
showAvatarPopup.value = false;
//
const tempFilePath = res.tempFilePaths[0];
// URL
//
uni.showLoading({
title: '上传中...'
});
setTimeout(() => {
uni.hideLoading();
userInfo.avatar = tempFilePath;
uni.showToast({
title: '头像已更新',
icon: 'success'
});
}, 1000);
}
});
};
/**
* 拍照
*/
const handleTakePhoto = () => {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['camera'],
success: (res) => {
//
showAvatarPopup.value = false;
//
const tempFilePath = res.tempFilePaths[0];
// URL
//
uni.showLoading({
title: '上传中...'
});
setTimeout(() => {
uni.hideLoading();
userInfo.avatar = tempFilePath;
uni.showToast({
title: '头像已更新',
icon: 'success'
});
}, 1000);
}
});
};
const toPages = (item) => {
if (item.type === 'nav') {
uni.navigateBack()
} else if (item.type === 'home') {
//
uni.switchTab({
url: '/pages/index/index'
})
}
}
/**
* 保存用户信息
*/
const saveUserInfo = () => {
//
if (!userInfo.nickname.trim()) {
uni.showToast({
title: '昵称不能为空',
icon: 'none'
});
return;
}
//
uni.showLoading({
title: '保存中...'
});
//
setTimeout(() => {
//
uni.hideLoading();
//
uni.setStorageSync('userInfo', JSON.stringify(userInfo));
//
uni.showToast({
title: '保存成功',
icon: 'success'
});
//
setTimeout(() => {
goBack();
}, 1500);
}, 1000);
};
/**
* 返回上一页
*/
const goBack = () => {
uni.navigateBack();
};
onMounted(() => {
checkRouteStack()
//
const userInfoStorage = uni.getStorageSync('userInfo');
if (userInfoStorage) {
Object.assign(userInfo, JSON.parse(userInfoStorage));
}
});
</script>
<style lang="scss" scoped>
/* 主容器 */
.container {
min-height: 100vh;
background-color: transparent;
position: relative;
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Helvetica, Segoe UI, Arial, Roboto, PingFang SC, sans-serif;
padding-bottom: env(safe-area-inset-bottom);
}
/* 导航栏背景 */
.nav-bg-layer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: calc(var(--status-bar-height) + 88rpx);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.9) 100%);
z-index: -1;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
/* 页面背景 */
.page-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, #f8fafd 0%, #eef2f9 100%);
z-index: -2;
}
/* 内容区域 */
.content {
position: relative;
z-index: 2;
padding: 30rpx;
}
/* 表单容器 */
.form-container {
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
margin-bottom: 40rpx;
}
/* 头像设置区域 */
.avatar-section {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #f5f5f5;
.section-left {
.form-label {
font-size: 32rpx;
color: #333;
font-weight: 500;
}
}
.section-right {
display: flex;
align-items: center;
.user-avatar {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
overflow: hidden;
margin-right: 16rpx;
border: 2rpx solid rgba(0, 0, 0, 0.05);
image {
width: 100%;
height: 100%;
}
.default-avatar {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #4080FF, #5E96FF);
color: #fff;
font-size: 48rpx;
font-weight: bold;
}
}
.arrow-icon {
font-size: 44rpx;
color: #ccc;
}
}
}
/* 表单项 */
.form-section {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.section-left {
.form-label {
font-size: 32rpx;
color: #333;
font-weight: 500;
}
}
.section-right {
display: flex;
align-items: center;
.input-wrapper {
text-align: right;
.form-input {
font-size: 30rpx;
color: #333;
text-align: right;
min-width: 200rpx;
}
}
.phone-text {
font-size: 30rpx;
color: #999;
}
.arrow-icon {
font-size: 44rpx;
color: #ccc;
margin-left: 16rpx;
}
}
}
/* 保存按钮 */
.save-btn-container {
padding: 0 20rpx;
margin-top: 60rpx;
.save-btn {
background-color: #4080FF;
color: #fff;
border: none;
height: 96rpx;
line-height: 96rpx;
font-size: 32rpx;
border-radius: 16rpx;
font-weight: 500;
box-shadow: 0 4rpx 16rpx rgba(64, 128, 255, 0.3);
&:active {
background-color: #3a75e6;
}
}
}
/* 头像选择弹窗 */
.avatar-popup {
background-color: #fff;
border-radius: 24rpx 24rpx 0 0;
overflow: hidden;
.popup-title {
text-align: center;
font-size: 32rpx;
font-weight: 600;
color: #333;
padding: 30rpx 0;
border-bottom: 1px solid #f0f0f0;
}
.avatar-options {
padding: 20rpx 0;
.option-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 30rpx 0;
.option-icon {
font-size: 60rpx;
color: #4080FF;
margin-bottom: 16rpx;
}
.option-text {
font-size: 28rpx;
color: #333;
}
}
}
.cancel-btn {
border-top: 12rpx solid #f5f5f5;
text-align: center;
padding: 30rpx 0;
font-size: 32rpx;
color: #999;
&:active {
background-color: #f8f8f8;
}
}
}
</style>

489
pagesB/setting/index.vue Normal file
View File

@ -0,0 +1,489 @@
<template>
<view class="container">
<!-- 自定义导航栏 -->
<wd-navbar :bordered="false"
custom-style="background: transparent !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(20px) !important;"
safeAreaInsetTop fixed placeholder>
<template #left>
<view class="li-ml-15 li-mt-10 li-flex li-items-center">
<text v-if="hasMultiplePages" class="ri-arrow-left-s-line li-text-70"
@click="toPages({type:'nav'})"></text>
<text v-if="!hasMultiplePages" class="ri-home-5-line li-text-55 li-mb-8 li-mr-10"
@click="toPages({type:'home'})"></text>
<text class="li-text-42">设置</text>
</view>
</template>
</wd-navbar>
<!-- 导航栏背景 -->
<view class="nav-bg-layer"></view>
<!-- 页面背景 -->
<view class="page-bg"></view>
<view class="content">
<!-- 用户信息预览 -->
<view class="user-preview" @click="handleEditInfo">
<view class="user-avatar">
<image v-if="userInfo.avatar" :src="userInfo.avatar" mode="aspectFill"></image>
<view v-else class="default-avatar">{{userInfo.nickname.substring(0,1)}}</view>
</view>
<view class="user-detail">
<view class="user-name">{{userInfo.nickname || '未设置昵称'}}</view>
<view class="user-phone">{{formatPhone(userInfo.phone)}}</view>
</view>
<text class="ri-arrow-right-s-line arrow-icon"></text>
</view>
<view class="setting-section">
<view class="setting-list">
<view class="setting-item" @click="clearCache">
<view class="item-left">
<text class="ri-delete-bin-5-line item-icon cache-color"></text>
<text class="item-title">清除缓存</text>
</view>
<view class="item-right">
<text class="cache-size">{{cacheSize}}</text>
</view>
</view>
<view class="setting-item" @click="handlePrivacyPolicy">
<view class="item-left">
<text class="ri-file-text-line item-icon privacy-color"></text>
<text class="item-title">隐私政策</text>
</view>
<view class="item-right">
<text class="ri-arrow-right-s-line arrow-icon"></text>
</view>
</view>
<view class="setting-item" @click="handleUserAgreement">
<view class="item-left">
<text class="ri-file-list-3-line item-icon agreement-color"></text>
<text class="item-title">用户协议</text>
</view>
<view class="item-right">
<text class="ri-arrow-right-s-line arrow-icon"></text>
</view>
</view>
<view class="setting-item" @click="checkUpdate">
<view class="item-left">
<text class="ri-information-line item-icon about-color"></text>
<text class="item-title">关于我们</text>
</view>
<view class="item-right">
<text class="version-text">v{{appVersion}}</text>
<text class="ri-arrow-right-s-line arrow-icon"></text>
</view>
</view>
</view>
</view>
<!-- 退出登录按钮 -->
<view class="logout-container">
<button class="logout-btn" @click="handleLogout">退出登录</button>
</view>
</view>
<!-- 确认弹窗 -->
<wd-dialog v-model="showLogoutDialog" title="退出登录" :show-cancel-button="true" @confirm="confirmLogout">
<view class="dialog-content">
确定要退出登录吗
</view>
</wd-dialog>
</view>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue';
import { useNavigation } from '@/hooks/useNavigation';
import { onLoad } from '@dcloudio/uni-app'
// 使 composable
const {
hasMultiplePages, //
isTabBarPage, // tabBar
checkRouteStack //
} = useNavigation()
//
const userInfo = reactive({
nickname: '里派用户',
phone: '13800138000',
avatar: ''
});
//
const cacheSize = ref('4.8MB');
//
const appVersion = ref('1.0.0');
//
const isDarkMode = ref(false);
//
const showLogoutDialog = ref(false);
/**
* 格式化手机号码为带星号格式
*/
const formatPhone = (phone) => {
if (!phone) return '';
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
};
//
const toPages = (item : any) => {
if (item.type === 'nav') {
uni.navigateBack()
} else if (item.type === 'home') {
//
uni.switchTab({
url: '/pages/index/index'
})
}
}
/**
* 处理修改用户信息
*/
const handleEditInfo = () => {
uni.navigateTo({
url: '/pagesB/setting/editInfo'
});
};
/**
* 清除缓存
*/
const clearCache = () => {
uni.showLoading({
title: '清理中...'
});
//
setTimeout(() => {
uni.hideLoading();
cacheSize.value = '0KB';
uni.showToast({
title: '缓存已清理',
icon: 'success'
});
}, 1000);
};
/**
* 查看隐私政策
*/
const handlePrivacyPolicy = () => {
uni.navigateTo({
url: '/pagesA/other/privacy'
});
};
/**
* 查看用户协议
*/
const handleUserAgreement = () => {
uni.navigateTo({
url: '/pagesA/other/agreement'
});
};
/**
* 检查更新
*/
const checkUpdate = () => {
uni.showToast({
title: '当前已是最新版本',
icon: 'none'
});
};
/**
* 显示退出登录确认框
*/
const handleLogout = () => {
showLogoutDialog.value = true;
};
/**
* 确认退出登录
*/
const confirmLogout = () => {
uni.showLoading({
title: '退出中...'
});
// 退
setTimeout(() => {
uni.hideLoading();
//
uni.removeStorageSync('token');
uni.removeStorageSync('userInfo');
//
uni.reLaunch({
url: '/pages/login/index'
});
}, 1000);
};
onMounted(() => {
checkRouteStack()
//
const userInfoStorage = uni.getStorageSync('userInfo');
if (userInfoStorage) {
Object.assign(userInfo, JSON.parse(userInfoStorage));
}
//
uni.getStorageInfo({
success: (res) => {
const size = res.currentSize;
if (size < 1024) {
cacheSize.value = size + 'KB';
} else {
cacheSize.value = (size / 1024).toFixed(1) + 'MB';
}
}
});
//
// #ifdef APP-PLUS
plus.runtime.getProperty(plus.runtime.appid, (res) => {
appVersion.value = res.version;
});
// #endif
});
</script>
<style lang="scss" scoped>
/* 主容器 */
.container {
min-height: 100vh;
background-color: transparent;
position: relative;
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Helvetica, Segoe UI, Arial, Roboto, PingFang SC, sans-serif;
padding-bottom: env(safe-area-inset-bottom);
}
/* 导航栏背景 */
.nav-bg-layer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: calc(var(--status-bar-height) + 88rpx);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.9) 100%);
z-index: -1;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
/* 页面背景 */
.page-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, #f8fafd 0%, #eef2f9 100%);
z-index: -2;
}
/* 内容区域 */
.content {
position: relative;
z-index: 2;
padding: 30rpx;
}
/* 用户信息预览 */
.user-preview {
background-color: #fff;
border-radius: 16rpx;
padding: 30rpx;
display: flex;
align-items: center;
margin-bottom: 30rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
.user-avatar {
width: 120rpx;
height: 120rpx;
border-radius: 60rpx;
overflow: hidden;
margin-right: 24rpx;
image {
width: 100%;
height: 100%;
border-radius: 60rpx;
}
.default-avatar {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #4080FF, #5E96FF);
color: #fff;
font-size: 60rpx;
font-weight: bold;
}
}
.user-detail {
flex: 1;
.user-name {
font-size: 36rpx;
font-weight: 600;
color: #333;
margin-bottom: 8rpx;
}
.user-phone {
font-size: 28rpx;
color: #999;
}
}
.arrow-icon {
font-size: 44rpx;
color: #ccc;
}
}
/* 设置项区域 */
.setting-section {
margin-bottom: 30rpx;
.section-title {
font-size: 30rpx;
font-weight: 600;
color: #333;
margin-bottom: 16rpx;
padding-left: 16rpx;
}
.setting-list {
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
}
.setting-item {
padding: 28rpx 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.item-left {
display: flex;
align-items: center;
.item-icon {
font-size: 44rpx;
margin-right: 20rpx;
&.account-color {
color: #4080FF;
}
&.security-color {
color: #5AC8FA;
}
&.notice-color {
color: #FF9500;
}
&.theme-color {
color: #5E6687;
}
&.cache-color {
color: #FF3B30;
}
&.privacy-color {
color: #34C759;
}
&.agreement-color {
color: #9013FE;
}
&.about-color {
color: #4080FF;
}
}
.item-title {
font-size: 30rpx;
color: #333;
}
}
.item-right {
display: flex;
align-items: center;
.arrow-icon {
font-size: 44rpx;
color: #ccc;
}
.cache-size,
.version-text {
font-size: 28rpx;
color: #999;
margin-right: 10rpx;
}
}
}
}
/* 退出登录按钮 */
.logout-container {
margin-top: 60rpx;
padding: 0 20rpx;
margin-bottom: 50rpx;
.logout-btn {
background-color: #fff;
color: #FF3B30;
border: none;
height: 96rpx;
line-height: 96rpx;
font-size: 32rpx;
border-radius: 16rpx;
font-weight: 500;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
&:active {
background-color: #f8f8f8;
}
}
}
/* 弹窗内容样式 */
.dialog-content {
padding: 30rpx;
text-align: center;
font-size: 30rpx;
color: #333;
}
</style>

View File

@ -20,7 +20,7 @@
.wd-popup {
position: fixed;
max-height: 100%;
overflow-y: auto;
// overflow-y: auto;
background: #fff;
}
}

View File

@ -1,18 +1,19 @@
.li-mt-25{margin-top:25rpx}
.li-pt-6{padding-top:6rpx}
.li-px-15{padding-left:15rpx;padding-right:15rpx}
.bg-0070F0{background-color:rgb(0,112,240)}
.li-my-10{margin-top:10rpx;margin-bottom:10rpx}
.li-p-20{padding:20rpx}
.li-px-20{padding-left:20rpx;padding-right:20rpx}
.li-py-10{padding-top:10rpx;padding-bottom:10rpx}
.li-py-60{padding-top:60rpx;padding-bottom:60rpx}
.li-rd-8{border-radius:8rpx}
.li-text-dddddd-color{color:rgb(221,221,221)}
.li-text-ff9900-color{color:rgb(255,153,0)}
.li-pt-6{padding-top:6rpx}
.li-px-15{padding-left:15rpx;padding-right:15rpx}
.li-opacity-80{undefined:0.8}
.li-pb-40{padding-bottom:40rpx}
.li-py-100{padding-top:100rpx;padding-bottom:100rpx}
@ -30,3 +31,11 @@

View File

@ -40,7 +40,7 @@ export const request = (endpoint : string, options : RequestOptions = {}) => {
if (response.statusCode >= 200 && response.statusCode < 300) {
if (response.data.code == 500) {
uni.$store.commit("logout")
reject(response.data)
reject(response.data);
return;
}
resolve(response.data);