148 lines
4.7 KiB
Plaintext
148 lines
4.7 KiB
Plaintext
<template>
|
||
<hr-page page-bg="#F3F4F6" status-bg="#FFFFFF" nav-title="通讯录" @right-click="onSearch">
|
||
<template v-slot:right>
|
||
<x-icon name="search-line" color="#6B7280" font-size="34rpx"></x-icon>
|
||
</template>
|
||
|
||
<view class="hr-body">
|
||
|
||
<!-- ============ 分组列表:指挥调度 / 协作医院 / 本队同事 ============ -->
|
||
<view v-for="(g, gi) in groups" :key="gi">
|
||
<hr-sec :title="g.title" :first="gi == 0"></hr-sec>
|
||
|
||
<!-- 卡片内每行:左侧头像/机构图标 + 姓名与号码 + 呼叫按钮 -->
|
||
<hr-card padding="4rpx 26rpx">
|
||
<view v-for="(c, ci) in g.items" :key="ci"
|
||
:class="ci == g.items.length - 1 ? 'hr-lrow hr-lrow-last' : 'hr-lrow'" @click="onCall(c)">
|
||
<view class="ct-blk" :style="blkStyle(c)">
|
||
<!-- 机构(医院 / 协作单位)用图标,个人用姓名首字 -->
|
||
<x-icon v-if="!c.useAvatar" name="hospital-line" color="#2563EB"
|
||
font-size="30rpx"></x-icon>
|
||
<text v-else class="ct-blk-t">{{ blkText(c) }}</text>
|
||
</view>
|
||
<view class="hr-lmain">
|
||
<text class="hr-lmain-b">{{ c.name }}</text>
|
||
<text class="hr-lmain-s">{{ c.phone }}</text>
|
||
</view>
|
||
<x-icon name="phone-fill" color="#2563EB" font-size="32rpx"></x-icon>
|
||
</view>
|
||
</hr-card>
|
||
</view>
|
||
|
||
<view style="height:14px"></view>
|
||
</view>
|
||
</hr-page>
|
||
</template>
|
||
|
||
<script lang="uts" setup>
|
||
import { contactGroups } from '@/mock/index.uts'
|
||
import { HrContact, HrContactGroup } from '@/mock/types.uts'
|
||
|
||
/**
|
||
* s28 通讯录
|
||
* 与设计稿一致:按「指挥调度 / 协作医院 / 本队同事」三段分组,
|
||
* 每组 = 小节标题 + 卡片列表行(头像 + 姓名 + 号码 + 呼叫)。
|
||
* 数据全部来自 mock/index.uts,换接口只改取数处。
|
||
*/
|
||
const groups : HrContactGroup[] = contactGroups
|
||
|
||
/** 头像文字:优先用数据里的字母头,缺省回落到姓名首字 */
|
||
function blkText(c : HrContact) : string {
|
||
if (c.avatar != '') { return c.avatar }
|
||
if (c.name.length > 0) { return c.name.substring(0, 1) }
|
||
return '医'
|
||
}
|
||
|
||
/**
|
||
* 头像底色。uvue 不支持复合类选择器(.ct-blk.ct-blk-gn),
|
||
* 因此主题色用内联样式下发;机构块固定浅蓝底。
|
||
*/
|
||
function blkStyle(c : HrContact) : string {
|
||
if (!c.useAvatar) { return 'background-color:#EFF6FF;' }
|
||
if (c.theme == 'gn') { return 'background-color:#059669;' }
|
||
if (c.theme == 'ag') { return 'background-color:#D97706;' }
|
||
if (c.theme == 'rd') { return 'background-color:#DC2626;' }
|
||
if (c.theme == 'gy') { return 'background-color:#94A3B8;' }
|
||
return 'background-color:#2563EB;'
|
||
}
|
||
|
||
/** 只保留数字字符(0-9) */
|
||
function digitsOnly(s : string) : string {
|
||
const table = '0123456789'
|
||
let out = ''
|
||
for (let i = 0; i < s.length; i++) {
|
||
const ch = s.charAt(i)
|
||
if (table.indexOf(ch) > -1) { out += ch }
|
||
}
|
||
return out
|
||
}
|
||
|
||
/**
|
||
* 从「值班室 8801 · 手机 138****2201」这类文案里取出可拨号码。
|
||
* 规则:按「·」分段,取「标签 号码」中的号码部分,
|
||
* 纯数字(不含 * 掩码)、长度≥4 才算号码;「工号 1248」这类直接跳过。
|
||
*/
|
||
function extractPhone(text : string) : string {
|
||
const parts = text.split('·')
|
||
for (let i = 0; i < parts.length; i++) {
|
||
const seg = parts[i].trim()
|
||
const idx = seg.indexOf(' ')
|
||
const label = idx >= 0 ? seg.substring(0, idx) : ''
|
||
const raw = idx >= 0 ? seg.substring(idx + 1) : seg
|
||
if (label.indexOf('工号') > -1) { continue }
|
||
const digits = digitsOnly(raw)
|
||
const compact = raw.replaceAll(' ', '').replaceAll('-', '')
|
||
if (digits.length >= 4 && digits.length == compact.length) { return digits }
|
||
}
|
||
return ''
|
||
}
|
||
|
||
// ⚠ UTS 不提升函数声明:extractPhone / digitsOnly 必须写在 onCall 之前
|
||
function onCall(c : HrContact) : void {
|
||
const digits = extractPhone(c.phone)
|
||
if (digits == '') {
|
||
uni.showToast({ title: '暂无可用号码', icon: 'none' })
|
||
return
|
||
}
|
||
uni.showModal({
|
||
title: c.name,
|
||
content: `呼叫 ${digits}?`,
|
||
confirmText: '呼叫',
|
||
success: (res) => {
|
||
if (!res.confirm) { return }
|
||
// #ifdef APP
|
||
uni.makePhoneCall({ phoneNumber: digits })
|
||
// #endif
|
||
// #ifndef APP
|
||
uni.showToast({ title: '已复制号码 ' + digits, icon: 'none' })
|
||
uni.setClipboardData({ data: digits })
|
||
// #endif
|
||
}
|
||
})
|
||
}
|
||
|
||
function onSearch() : void {
|
||
uni.showToast({ title: '搜索联系人 / 医院', icon: 'none' })
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
/* 头像 / 机构图标块:设计稿 .avt.sm / .lic(30~32px) */
|
||
.ct-blk {
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
border-radius: 18rpx;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.ct-blk-t {
|
||
font-size: 25rpx;
|
||
font-weight: bold;
|
||
color: #FFFFFF;
|
||
}
|
||
</style>
|