155 lines
5.6 KiB
Vue
155 lines
5.6 KiB
Vue
<template>
|
||
<view class="page edge">
|
||
<fy-header title="我的" />
|
||
<fy-scroll class="edge-scroll" dock @refresh="reload">
|
||
<view class="body">
|
||
<view class="profile" @click="goArchive">
|
||
<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>
|
||
<text v-if="statusText" class="tag">{{ statusText }}</text>
|
||
</view>
|
||
<text class="sub">{{ deptLine }}</text>
|
||
<text class="sub">{{ phone }}{{ job }}</text>
|
||
</view>
|
||
<wd-icon name="qrcode" size="36rpx" color="#111827" />
|
||
<text class="chev">›</text>
|
||
</view>
|
||
|
||
<view class="group">
|
||
<view class="cell" @click="switchClock">
|
||
<wd-icon name="location" size="40rpx" color="#1677FF" />
|
||
<text class="ct">本月出勤</text>
|
||
<text class="cv">{{ attendDays }} 天</text>
|
||
<text class="chev">›</text>
|
||
</view>
|
||
<view class="cell" @click="goTodo">
|
||
<wd-icon name="check-circle" size="40rpx" color="#16A34A" />
|
||
<text class="ct">待办申请</text>
|
||
<text class="cv">{{ todoCount }}</text>
|
||
<text class="chev">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="menus.length" class="group">
|
||
<view v-for="a in menus" :key="a.id" class="cell" @click="open(a)">
|
||
<wd-icon :name="iconOf(a)" size="40rpx" :color="colorOf(a)" />
|
||
<text class="ct">{{ a.title }}</text>
|
||
<text class="chev">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="group">
|
||
<view class="cell" @click="goPwd">
|
||
<wd-icon name="lock-on" size="40rpx" color="#576B95" />
|
||
<text class="ct">修改密码</text>
|
||
<text class="chev">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="group">
|
||
<view class="cell center" @click="logout">
|
||
<text class="danger">退出登录</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</fy-scroll>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import FyHeader from '../../components/fy-header.vue'
|
||
import FyScroll from '../../components/fy-scroll.vue'
|
||
import { store } from '../../utils/store.js'
|
||
import { maskPhone } from '../../utils/format.js'
|
||
import { tileVisual } from '../../utils/nav.js'
|
||
|
||
const ME_IDS = ['archive', 'salary', 'perf', 'expense', 'report', 'apply']
|
||
|
||
export default {
|
||
components: { FyHeader, FyScroll },
|
||
data() {
|
||
return { off: null }
|
||
},
|
||
computed: {
|
||
me() { return store.me },
|
||
initial() { return this.me ? this.me.name.slice(0, 1) : '我' },
|
||
statusText() {
|
||
return (this.me && this.me.employeeStatus) || '在职'
|
||
},
|
||
deptLine() {
|
||
if (!this.me) return ''
|
||
return [this.me.department, this.me.title].filter(Boolean).join(' · ')
|
||
},
|
||
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: {
|
||
iconOf(a) { return tileVisual(a).name },
|
||
colorOf(a) { return tileVisual(a).color },
|
||
goArchive() {
|
||
const a = store.personalApps().find((x) => x.id === 'archive')
|
||
if (a) this.open(a)
|
||
else uni.navigateTo({ url: '/pages/me/archive' })
|
||
},
|
||
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' })
|
||
},
|
||
reload() { store.refreshPerms() },
|
||
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: 16rpx 0 48rpx; background: #EDEDED; min-height: 100%; }
|
||
.profile {
|
||
display: flex; align-items: center;
|
||
background: #fff; padding: 48rpx 28rpx 40rpx; margin-bottom: 16rpx;
|
||
}
|
||
.av { width: 128rpx; height: 128rpx; border-radius: 12rpx; flex-shrink: 0; }
|
||
.av.txt { background: #1677FF; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 48rpx; font-weight: 650; }
|
||
.info { flex: 1; min-width: 0; margin: 0 20rpx; }
|
||
.nm { display: flex; align-items: center; gap: 12rpx; }
|
||
.name { font-size: 40rpx; font-weight: 650; color: #111827; }
|
||
.tag { font-size: 22rpx; color: #16A34A; background: #E8F8EF; border-radius: 8rpx; padding: 2rpx 10rpx; }
|
||
.sub { display: block; font-size: 26rpx; color: #6B7280; margin-top: 8rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.group { background: #fff; margin-bottom: 16rpx; }
|
||
.cell { display: flex; align-items: center; min-height: 108rpx; padding: 0 28rpx; gap: 24rpx; }
|
||
.cell + .cell { border-top: 1rpx solid #EDEDED; }
|
||
.cell.center { justify-content: center; }
|
||
.ct { flex: 1; font-size: 32rpx; color: #111827; }
|
||
.cv { font-size: 28rpx; color: #9CA3AF; }
|
||
.chev { color: #C8C8C8; font-size: 36rpx; }
|
||
.danger { font-size: 32rpx; color: #111827; }
|
||
</style>
|