oa_app仓库初始化

This commit is contained in:
2026-09-23 16:52:48 +08:00
commit 65c5e9f66f
82 changed files with 6490 additions and 0 deletions
+129
View File
@@ -0,0 +1,129 @@
<template>
<view class="page">
<fy-header title="同事资料" back />
<view v-if="p" class="body">
<view class="card profile">
<image v-if="p.avatar" class="av img" :src="p.avatar" mode="aspectFill" />
<view v-else class="av">{{ p.name.slice(0, 1) }}</view>
<view class="info">
<view class="nm">
<text class="n">{{ p.name }}</text>
<text class="tag">{{ p.employeeStatus || '在职' }}</text>
</view>
<text class="s">{{ p.title }} · {{ p.department }}</text>
<view class="ph" @click="copyPhone">
<text> {{ masked }}</text>
<text class="copy">复制</text>
</view>
</view>
</view>
<view class="acts">
<view class="act" @click="chat">
<text class="ai">💬</text>
<text>发消息</text>
</view>
<view class="act" @click="call">
<text class="ai"></text>
<text>语音通话</text>
</view>
<view class="act" @click="video">
<text class="ai"></text>
<text>视频通话</text>
</view>
</view>
<view class="card rows">
<view class="row">
<text class="k">所属部门</text>
<text class="v">{{ p.department || '—' }}</text>
</view>
<view class="row">
<text class="k">工号</text>
<text class="v">{{ p.jobId || '—' }}</text>
</view>
</view>
<view class="card rows">
<view class="row" @click="toggle('pinned')" v-if="conv">
<text class="k">置顶聊天</text>
<text class="v brand">{{ conv.pinned ? '已置顶' : '未置顶' }}</text>
</view>
<view class="row" @click="toggle('muted')" v-if="conv">
<text class="k">消息免打扰</text>
<text class="v brand">{{ conv.muted ? '已开启' : '未开启' }}</text>
</view>
</view>
</view>
</view>
</template>
<script>
import FyHeader from '../../components/fy-header.vue'
import { store } from '../../utils/store.js'
import { dmId, maskPhone, toast } from '../../utils/format.js'
export default {
components: { FyHeader },
data() { return { id: '', tick: 0 } },
computed: {
p() { return store.person(this.id) },
masked() { return maskPhone(this.p && this.p.phone) },
conv() {
this.tick
if (!this.p || !store.me) return null
return store.findConv(dmId(store.me.id, this.p.id))
}
},
onLoad(q) { this.id = decodeURIComponent(q.id || '') },
methods: {
chat() {
if (!this.p) return
const conv = store.openDirect(this.p)
uni.navigateTo({ url: '/pages/chat/chat?sid=' + encodeURIComponent(conv.id) })
},
call() {
if (!this.p) return
store.startCall(this.p.id, { video: false }).catch((e) => toast((e && e.message) || '无法发起通话'))
},
async video() {
if (!this.p) return
try {
await store.startCall(this.p.id, { video: true })
} catch (e) {
toast((e && e.message) || '暂无法发起视频通话')
}
},
copyPhone() {
if (!this.p || !this.p.phone) return
uni.setClipboardData({ data: String(this.p.phone) })
},
toggle(field) {
if (!this.conv) return
store.setSession(this.conv, { [field]: !this.conv[field] })
this.tick += 1
}
}
}
</script>
<style scoped>
.body { padding: 24rpx; }
.profile { padding: 28rpx; display: flex; align-items: center; }
.av { width: 128rpx; height: 128rpx; border-radius: 20rpx; background: #004ac6; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 48rpx; font-weight: 700; }
.av.img { border-radius: 20rpx; }
.info { margin-left: 24rpx; flex: 1; min-width: 0; }
.nm { display: flex; align-items: center; gap: 12rpx; }
.n { font-size: 36rpx; font-weight: 700; }
.tag { font-size: 20rpx; background: #e2e7ff; color: #434655; padding: 2rpx 10rpx; border-radius: 8rpx; }
.s, .ph { display: block; font-size: 24rpx; color: #737686; margin-top: 8rpx; }
.copy { color: #2563eb; margin-left: 12rpx; }
.acts { display: flex; gap: 16rpx; margin: 20rpx 0; }
.act { flex: 1; background: #fff; border-radius: 16rpx; padding: 20rpx 8rpx; display: flex; flex-direction: column; align-items: center; font-size: 22rpx; font-weight: 600; box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03); }
.ai { font-size: 36rpx; color: #004ac6; margin-bottom: 8rpx; }
.rows { overflow: hidden; margin-bottom: 20rpx; }
.row { display: flex; justify-content: space-between; padding: 28rpx 24rpx; font-size: 28rpx; border-bottom: 1rpx solid #eaedff; }
.k { color: #434655; }
.v { color: #131b2e; }
.brand { color: #2563eb; }
</style>