ykt-team-wxapp/pages/home/customer-archive.vue

453 lines
11 KiB
Vue
Raw Normal View History

2026-01-20 19:36:49 +08:00
<template>
2026-02-03 09:59:49 +08:00
<view class="archive-container">
2026-01-20 19:36:49 +08:00
<view class="mb-10 flex items-center justify-between">
2026-02-06 17:36:25 +08:00
<view class="module-title flex-shrink-0 truncate"> 成员档案 </view>
2026-02-09 15:17:45 +08:00
<view class="flex items-center leading-normal rounded-sm" style="padding-right: 0" @click="toManagePage()">
<image class="manage-icon mr-5" src="/static/home/archive-manage.png" mode="aspectFit"></image>
2026-02-06 17:36:25 +08:00
<view style="font-size: 28rpx; color: #065bd6">档案管理</view>
2026-01-20 19:36:49 +08:00
</view>
</view>
2026-02-09 15:17:45 +08:00
<view v-if="customers.length === 0" class="add-archive-card" @click="toManagePage()">
2026-02-05 17:06:00 +08:00
<view class="add-archive-btn">
2026-02-09 15:17:45 +08:00
<image class="add-archive-btn-icon" src="/static/home/add-archive-btn.png" mode="aspectFit"></image>
2026-02-05 17:06:00 +08:00
<text class="add-archive-btn-text">新建档案</text>
</view>
2026-02-09 15:17:45 +08:00
<image class="add-archive-bg" src="/static/home/add-archive-bg.png" mode="aspectFit"></image>
2026-01-20 19:36:49 +08:00
</view>
<scroll-view scroll-x="true">
2026-02-05 09:53:49 +08:00
<view class="flex flex-nowrap pb-5">
2026-02-08 10:41:41 +08:00
<view v-for="i in customers" :key="i._id" class="customer-card flex-shrink-0 mr-15 relative"
:class="current && i._id === current._id ? 'current-customer' : ''" @click="toggle(i)">
2026-02-03 15:42:32 +08:00
<!-- 关系标签 -->
2026-02-08 10:41:41 +08:00
<view v-if="i.relationship" class="relationship-tag"
:class="i.relationship === '本人' ? 'tag-blue' : 'tag-green'">
2026-02-03 15:42:32 +08:00
{{ i.relationship }}
</view>
2026-02-03 09:59:49 +08:00
<view class="flex flex-col items-center">
2026-02-09 15:17:45 +08:00
<view class="customer-name text-lg leading-normal font-semibold whitespace-nowrap mb-8"
:class="current && i._id === current._id ? 'text-primary' : 'text-dark'">
2026-01-20 19:36:49 +08:00
{{ i.name }}
</view>
</view>
2026-02-03 15:42:32 +08:00
<!-- 选中状态底部条和三角 -->
2026-02-08 10:41:41 +08:00
<view v-if="current && i._id === current._id" class="active-indicator">
2026-02-03 15:42:32 +08:00
<view class="active-bar"></view>
<view class="active-triangle"></view>
</view>
2026-01-20 19:36:49 +08:00
</view>
</view>
</scroll-view>
2026-02-08 10:41:41 +08:00
<view v-if="canAuth" class="px-10 py-5 mt-5 flex items-center bg-danger rounded-sm">
2026-01-20 19:36:49 +08:00
<view class="mr-5 w-0 flex-grow text-base text-white">
2026-02-04 15:23:57 +08:00
点击右侧授权按钮, 我们将更精准的为您服务
2026-01-20 19:36:49 +08:00
</view>
2026-02-08 10:41:41 +08:00
<view class="px-12 py-5 text-base rounded-sm text-dark bg-white" @click="auth()">
2026-01-20 19:36:49 +08:00
授权
</view>
</view>
2026-02-03 10:45:54 +08:00
<view v-if="current" class="flex mt-15">
2026-02-04 15:23:57 +08:00
<view class="info-card-new flex-grow" @click="fillBaseInfo()">
2026-02-03 10:45:54 +08:00
<view class="info-bg info-bg-base"></view>
2026-02-03 09:59:49 +08:00
<view class="info-content">
2026-02-03 10:45:54 +08:00
<view class="flex items-center justify-between mb-8">
<view class="info-title">个人基本信息</view>
2026-02-08 10:41:41 +08:00
<image class="arrow-icon-small" src="/static/home/arrow-right-blue.png" mode="aspectFit"></image>
2026-02-03 09:59:49 +08:00
</view>
2026-02-08 10:41:41 +08:00
<view v-if="baseInfoError" class="text-sm text-danger">请完善您的个人信息</view>
2026-02-04 15:23:57 +08:00
<view v-else class="info-subtitle">完善个人信息</view>
2026-01-20 19:36:49 +08:00
</view>
</view>
2026-02-08 10:41:41 +08:00
<view v-if="hasHealthTemp" class="ml-10 info-card-new flex-grow" @click="toHealthList()">
2026-02-03 10:45:54 +08:00
<view class="info-bg info-bg-health"></view>
2026-02-03 09:59:49 +08:00
<view class="info-content">
2026-02-03 10:45:54 +08:00
<view class="flex items-center justify-between mb-8">
<view class="info-title">健康信息</view>
2026-02-08 10:41:41 +08:00
<image class="arrow-icon-small" src="/static/home/arrow-right-blue.png" mode="aspectFit"></image>
2026-02-03 09:59:49 +08:00
</view>
2026-02-03 10:45:54 +08:00
<view class="info-subtitle">上传健康档案</view>
2026-01-20 19:36:49 +08:00
</view>
</view>
</view>
</view>
</template>
<script setup>
2026-02-05 09:53:49 +08:00
import { computed, onMounted, ref, watch } from "vue";
import { storeToRefs } from "pinia";
import useAccount from "@/store/account";
import api from "@/utils/api";
import { toast, confirm } from "@/utils/widget";
2026-01-20 19:36:49 +08:00
const props = defineProps({
corpId: {
type: String,
2026-02-05 09:53:49 +08:00
default: "",
2026-01-20 19:36:49 +08:00
},
customers: {
type: Array,
2026-02-05 09:53:49 +08:00
default: () => [],
2026-01-20 19:36:49 +08:00
},
team: {
type: Object,
2026-02-05 09:53:49 +08:00
default: () => ({}),
},
});
2026-01-20 19:36:49 +08:00
2026-02-05 09:53:49 +08:00
const emit = defineEmits(["update:customers"]);
2026-01-28 13:38:05 +08:00
2026-01-20 19:36:49 +08:00
const { account } = storeToRefs(useAccount());
const current = ref(null);
const customers = ref([]);
const canAuth = computed(() => {
if (current.value && props.team && props.team.teamId) {
2026-02-05 09:53:49 +08:00
const teamIds = Array.isArray(current.value.teamId)
? current.value.teamId
: [];
2026-01-20 19:36:49 +08:00
return !teamIds.includes(props.team.teamId);
}
2026-02-05 09:53:49 +08:00
return false;
});
2026-02-04 15:23:57 +08:00
const qrcode = computed(() => {
2026-02-05 09:53:49 +08:00
const qrcodes =
props.team && Array.isArray(props.team.qrcodes) ? props.team.qrcodes : [];
return qrcodes[0] || "";
});
const hasHealthTemp = computed(
() =>
qrcode.value &&
Array.isArray(qrcode.value.healthTempList) &&
qrcode.value.healthTempList.length > 0
);
const baseInfo = computed(() =>
qrcode.value &&
2026-02-08 10:41:41 +08:00
qrcode.value.teamFileds &&
Array.isArray(qrcode.value.teamFileds.baseInfo)
2026-02-05 09:53:49 +08:00
? qrcode.value.teamFileds.baseInfo
: []
);
2026-02-08 10:41:41 +08:00
const baseInfoError = computed(() => current.value && baseInfo.value.some((i) => i.title && !current.value[i.title]));
2026-01-20 19:36:49 +08:00
function fillBaseInfo() {
if (canAuth.value) {
2026-02-05 09:53:49 +08:00
toast("请先授权本服务团队");
2026-01-20 19:36:49 +08:00
} else {
uni.navigateTo({
2026-02-05 09:53:49 +08:00
url: `/pages/archive/edit-archive?teamId=${props.team.teamId}&corpId=${props.corpId}&id=${current.value._id}`,
});
2026-01-20 19:36:49 +08:00
}
}
function toHealthList() {
if (canAuth.value) {
2026-02-05 09:53:49 +08:00
toast("请先授权本服务团队");
2026-01-20 19:36:49 +08:00
} else {
2026-02-08 10:41:41 +08:00
const name = `${current.value.name} ${current.value.relationship ? `(${current.value.relationship})` : ""
}`;
2026-01-20 19:36:49 +08:00
uni.navigateTo({
2026-02-08 10:41:41 +08:00
url: `/pages/health/list?teamId=${props.team.teamId}&corpId=${props.corpId
}&id=${current.value._id}&name=${encodeURIComponent(name)}`,
2026-02-05 09:53:49 +08:00
});
2026-01-20 19:36:49 +08:00
}
}
function toggle(i) {
current.value = i;
}
function toManagePage() {
2026-02-05 09:53:49 +08:00
uni.navigateTo({
url: `/pages/archive/archive-manage?corpId=${props.corpId}&teamId=${props.team.teamId}`,
});
2026-01-20 19:36:49 +08:00
}
2026-01-21 10:35:08 +08:00
async function auth() {
await confirm(`是否授权${props.team.name}提供服务`);
2026-02-05 09:53:49 +08:00
const res = await api("authCustomerToTeam", {
corpId: props.corpId,
teamId: props.team.teamId,
id: current.value._id,
});
2026-01-21 10:35:08 +08:00
if (res && res.success) {
2026-02-05 09:53:49 +08:00
await toast("授权成功");
getCustomers();
2026-01-21 10:35:08 +08:00
} else {
2026-02-05 09:53:49 +08:00
toast(res?.message || "授权失败");
2026-01-21 10:35:08 +08:00
}
}
2026-01-20 19:36:49 +08:00
async function getCustomers() {
2026-02-05 09:53:49 +08:00
const res = await api("getMiniAppCustomers", {
miniAppId: account.value.openid,
corpId: props.corpId,
});
2026-01-20 19:36:49 +08:00
if (res && res.success) {
customers.value = res && Array.isArray(res.data) ? res.data : [];
2026-02-05 09:53:49 +08:00
const customer = customers.value.find(
(i) => current.value && i._id === current.value._id
);
2026-01-21 10:35:08 +08:00
current.value = customer || customers.value[0] || null;
2026-01-28 13:38:05 +08:00
// 向父组件传递 customers 数据
2026-02-05 09:53:49 +08:00
emit("update:customers", customers.value);
2026-01-20 19:36:49 +08:00
} else {
2026-02-05 09:53:49 +08:00
toast(res.message || "获取档案失败");
2026-01-20 19:36:49 +08:00
}
}
2026-02-04 15:23:57 +08:00
onMounted(() => {
2026-02-05 09:53:49 +08:00
uni.$on("reloadTeamCustomers", getCustomers);
});
watch(
() => props.corpId,
(n) => {
if (n) {
getCustomers();
} else {
customers.value = [];
}
},
{ immediate: true }
);
2026-01-20 19:36:49 +08:00
</script>
<style scoped>
2026-02-03 09:59:49 +08:00
.archive-container {
padding: 24rpx 30rpx;
margin: 0 30rpx;
2026-02-05 09:53:49 +08:00
background: linear-gradient(181deg, #c2dcff 1.01%, #ffffff 43.31%);
2026-02-03 15:42:32 +08:00
border-radius: 16rpx;
2026-02-05 09:53:49 +08:00
box-shadow: inset 0 2rpx 0 0 rgba(255, 255, 255, 0.82),
2026-02-03 15:42:32 +08:00
0 8rpx 10rpx 0 rgba(60, 169, 145, 0.06);
2026-02-03 09:59:49 +08:00
}
.manage-icon {
width: 32rpx;
height: 32rpx;
}
2026-02-03 15:42:32 +08:00
.module-title {
color: #000000;
font-size: 36rpx;
font-weight: 600;
line-height: normal;
}
2026-02-03 09:59:49 +08:00
.customer-card {
2026-02-03 15:42:32 +08:00
width: 160rpx;
height: 110rpx;
2026-02-03 15:42:32 +08:00
display: flex;
align-items: center;
justify-content: center;
2026-02-05 09:53:49 +08:00
background: linear-gradient(180deg, #ffffff 0%, #e6effb 100%);
2026-02-03 15:42:32 +08:00
border-radius: 12rpx;
2026-02-05 09:53:49 +08:00
border: 2rpx solid #aecaf2;
2026-02-03 15:42:32 +08:00
transition: all 0.2s;
2026-02-03 10:45:54 +08:00
position: relative;
2026-02-03 09:59:49 +08:00
}
.current-customer {
2026-02-05 09:53:49 +08:00
background: #ffffff;
border: 2rpx solid #065bd6;
2026-02-03 10:45:54 +08:00
}
2026-02-03 15:42:32 +08:00
.relationship-tag {
2026-02-03 10:45:54 +08:00
position: absolute;
2026-02-03 15:42:32 +08:00
top: -2rpx;
right: -10rpx;
padding: 4rpx 16rpx;
font-size: 20rpx;
line-height: normal;
color: #fff;
border-top-left-radius: 16rpx;
border-bottom-left-radius: 16rpx;
z-index: 10;
2026-02-03 10:45:54 +08:00
}
2026-02-03 15:42:32 +08:00
.relationship-tag::after {
2026-02-05 09:53:49 +08:00
content: "";
2026-02-03 10:45:54 +08:00
position: absolute;
2026-02-03 15:42:32 +08:00
right: 0;
bottom: -8rpx;
2026-02-03 10:45:54 +08:00
width: 0;
height: 0;
2026-02-03 15:42:32 +08:00
border-right: 10rpx solid transparent;
2026-02-03 10:45:54 +08:00
}
2026-02-03 15:42:32 +08:00
.tag-blue {
2026-02-05 09:53:49 +08:00
background: #065bd6;
2026-02-03 15:42:32 +08:00
}
.tag-blue::after {
2026-02-05 09:53:49 +08:00
border-top: 8rpx solid #003f96;
2026-02-03 15:42:32 +08:00
}
.tag-green {
2026-02-05 09:53:49 +08:00
background: #1dbf98;
2026-02-03 15:42:32 +08:00
}
.tag-green::after {
2026-02-05 09:53:49 +08:00
border-top: 8rpx solid #0f8c6d;
2026-02-03 15:42:32 +08:00
}
.active-indicator {
position: absolute;
bottom: -2rpx;
left: -2rpx;
right: -2rpx;
height: 10rpx;
z-index: 5;
}
.active-bar {
width: 100%;
height: 100%;
background: #065bd6;
border-bottom-left-radius: 12rpx;
border-bottom-right-radius: 12rpx;
box-sizing: border-box;
}
.active-triangle {
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%) rotate(45deg);
width: 12rpx;
height: 12rpx;
2026-02-05 09:53:49 +08:00
background: #065bd6;
2026-02-03 15:42:32 +08:00
margin-top: -8rpx;
2026-02-03 10:45:54 +08:00
}
.mr-15 {
margin-right: 20rpx;
}
.mt-15 {
margin-top: 24rpx;
}
.mb-8 {
margin-bottom: 12rpx;
2026-02-03 09:59:49 +08:00
}
2026-02-03 10:45:54 +08:00
.info-card-new {
2026-02-03 09:59:49 +08:00
position: relative;
2026-02-03 10:45:54 +08:00
padding: 24rpx;
2026-02-03 15:42:32 +08:00
border-radius: 16rpx;
2026-02-05 09:53:49 +08:00
background: linear-gradient(115deg, #f4f9ff 14.74%, #dbeaff 66.11%);
2026-02-03 09:59:49 +08:00
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
overflow: hidden;
2026-02-03 15:42:32 +08:00
width: 310rpx;
height: 94rpx;
2026-02-03 10:45:54 +08:00
flex: 1;
2026-02-03 09:59:49 +08:00
}
.info-bg {
position: absolute;
2026-02-03 10:45:54 +08:00
left: 0;
top: 0;
2026-02-03 09:59:49 +08:00
right: 0;
bottom: 0;
2026-02-03 10:45:54 +08:00
background-repeat: no-repeat;
background-position: right bottom;
background-size: cover;
opacity: 0.95;
pointer-events: none;
2026-02-03 09:59:49 +08:00
}
.info-content {
position: relative;
z-index: 1;
}
2026-02-03 10:45:54 +08:00
.info-bg-base {
2026-02-05 09:53:49 +08:00
background-image: url("/static/home/basic-info-bg.svg");
2026-02-03 10:45:54 +08:00
}
.info-bg-health {
2026-02-05 09:53:49 +08:00
background-image: url("/static/home/health-info-bg.svg");
2026-02-03 10:45:54 +08:00
}
.info-title {
2026-02-05 09:53:49 +08:00
color: #213e80;
2026-02-03 10:45:54 +08:00
font-size: 32rpx;
2026-02-05 10:27:20 +08:00
font-weight: 400;
line-height: 56rpx;
2026-02-03 10:45:54 +08:00
}
.info-subtitle {
2026-02-05 09:53:49 +08:00
color: #78808f;
2026-02-03 10:45:54 +08:00
font-size: 24rpx;
}
.arrow-icon-small {
width: 24rpx;
height: 24rpx;
flex-shrink: 0;
}
.font-medium {
font-weight: 500;
2026-02-03 09:59:49 +08:00
}
2026-01-20 19:36:49 +08:00
.h-80 {
height: 160rpx;
}
.h-normal {
height: 1.5em;
}
.min-w-100 {
min-width: 200rpx;
}
2026-02-03 09:59:49 +08:00
.rounded-lg {
border-radius: 16rpx;
2026-01-20 19:36:49 +08:00
}
2026-02-05 17:06:00 +08:00
/* 新建档案卡片样式 */
.add-archive-card {
height: 140rpx;
border-radius: 16rpx;
2026-02-06 17:36:25 +08:00
background: linear-gradient(95deg, #ecfbff -7.38%, #a5cbff 72.72%);
2026-02-05 17:06:00 +08:00
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24rpx;
position: relative;
overflow: hidden;
}
.add-archive-btn {
margin-left: 24rpx;
width: 188rpx;
height: 56rpx;
border-radius: 40rpx;
2026-02-06 17:36:25 +08:00
background: linear-gradient(90deg, #33a0f9 0%, #065bd6 100%);
2026-02-05 17:06:00 +08:00
box-shadow: 0 8rpx 8rpx 0 rgba(6, 91, 214, 0.3);
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
}
.add-archive-btn-icon {
width: 32rpx;
height: 32rpx;
margin-right: 8rpx;
}
.add-archive-btn-text {
font-size: 28rpx;
2026-02-06 17:36:25 +08:00
color: #ffffff;
2026-02-05 17:06:00 +08:00
font-weight: 500;
}
.add-archive-bg {
height: 140rpx;
position: absolute;
right: 0;
top: 0;
}
2026-01-20 19:36:49 +08:00
</style>