Files
oa_app/pages/tabs/me.vue
T
2026-09-23 17:47:57 +08:00

131 lines
4.8 KiB
Vue

<template>
<view class="page">
<fy-header title="我的" />
<view class="body">
<view class="card profile">
<view class="row">
<image v-if="me && me.avatar" class="av" :src="me.avatar" mode="aspectFill" />
<view v-else class="av txt">{{ initial }}</view>
<view class="info">
<view class="nm">
<text class="name">{{ me ? me.name : '' }}</text>
<wd-tag type="success" plain>在职</wd-tag>
</view>
<text class="dept">{{ me ? (me.department + ' · ' + me.title) : '' }}</text>
<text class="ph">{{ phone }}{{ job }}</text>
</view>
</view>
<view class="stats">
<view class="s" @click="switchClock">
<text class="n">{{ attendDays }}</text>
<text class="l">本月出勤()</text>
</view>
<view class="s mid" @click="goTodo">
<text class="n">{{ todoCount }}</text>
<text class="l">待办申请()</text>
</view>
<view class="s">
<text class="n ok">正常</text>
<text class="l">考勤状态</text>
</view>
</view>
</view>
<view class="card menu">
<wd-cell-group border>
<wd-cell v-for="a in menus" :key="a.id" :title="a.title" is-link @click="open(a)" />
</wd-cell-group>
</view>
<view class="card menu">
<wd-cell-group border>
<wd-cell title="修改密码" is-link @click="goPwd" />
<wd-cell is-link @click="logout">
<template #title><text class="danger">退出登录</text></template>
</wd-cell>
</wd-cell-group>
</view>
</view>
</view>
</template>
<script>
import FyHeader from '../../components/fy-header.vue'
import { store } from '../../utils/store.js'
import { maskPhone } from '../../utils/format.js'
const ME_IDS = ['archive', 'salary', 'perf', 'expense', 'report', 'apply']
export default {
components: { FyHeader },
data() {
return { off: null }
},
computed: {
me() { return store.me },
initial() { return this.me ? this.me.name.slice(0, 1) : '我' },
phone() { return maskPhone(this.me && this.me.phone) },
job() { return this.me && this.me.jobId ? ' · 工号: ' + this.me.jobId : '' },
todoCount() { return store.todoCount || 0 },
attendDays() { return (store.attendance || []).length || 0 },
menus() {
return store.personalApps().filter((a) => ME_IDS.includes(a.id))
}
},
onShow() {
if (store.phase !== 'app') uni.reLaunch({ url: '/pages/login/login' })
this.off = store.on(() => this.$forceUpdate())
},
onHide() { if (this.off) this.off() },
methods: {
open(a) {
if (a.url.startsWith('/pages/tabs/')) uni.switchTab({ url: a.url.split('?')[0] })
else uni.navigateTo({ url: a.url })
},
switchClock() { uni.switchTab({ url: '/pages/tabs/clock' }) },
goTodo() {
if (store.can('personal', 'approve')) uni.navigateTo({ url: '/pages/todo/list' })
},
goPwd() { uni.navigateTo({ url: '/pages/password/password' }) },
logout() {
uni.showModal({
title: '退出登录',
content: '确定退出当前账号?',
success: (r) => {
if (r.confirm) {
store.logout()
uni.reLaunch({ url: '/pages/login/login' })
}
}
})
}
}
}
</script>
<style scoped>
.body { padding: 8rpx 28rpx 48rpx; }
.profile { padding: 32rpx 28rpx 24rpx; }
.row { display: flex; align-items: center; }
.av { width: 112rpx; height: 112rpx; border-radius: 50%; }
.av.txt { background: #1677FF; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 40rpx; font-weight: 650; }
.info { margin-left: 24rpx; flex: 1; min-width: 0; }
.nm { display: flex; align-items: center; gap: 12rpx; }
.name { font-size: 36rpx; font-weight: 650; }
.st { font-size: 22rpx; background: #E8F8EF; color: #16A34A; padding: 4rpx 12rpx; border-radius: 8rpx; }
.dept, .ph { display: block; font-size: 24rpx; color: #6B7280; margin-top: 8rpx; }
.stats { display: flex; margin-top: 28rpx; padding-top: 24rpx; border-top: 1rpx solid #F0F2F5; }
.s { flex: 1; text-align: center; }
.mid { border-left: 1rpx solid #F0F2F5; border-right: 1rpx solid #F0F2F5; }
.n { display: block; font-size: 34rpx; font-weight: 650; color: #111827; }
.n.ok { color: #16A34A; font-size: 28rpx; }
.l { font-size: 22rpx; color: #6B7280; margin-top: 4rpx; }
.menu { margin-top: 20rpx; overflow: hidden; }
.mi { display: flex; align-items: center; min-height: 100rpx; padding: 0 28rpx; }
.mi + .mi { border-top: 1rpx solid #F0F2F5; }
.ii { width: 48rpx; color: #1677FF; font-weight: 650; }
.it { flex: 1; font-size: 28rpx; }
.arr { color: #C4C9D4; font-size: 32rpx; }
.danger { color: #DC2626; }
</style>