2025-09-24 11:37:39 +08:00

268 lines
7.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="group-edit-page">
<uni-nav-bar
left-icon="left"
:title="groupUuid ? '编辑分组' : '新建分组'"
@clickLeft="goBack"
fixed
color="#8B2316"
height="140rpx"
:border="false"
backgroundColor="#eee"
>
<template #right>
<view class="save-text" @click="saveGroup">保存</view>
</template>
</uni-nav-bar>
<!-- 分组名称 -->
<view class="section-header">分组名称</view>
<view class="name-row">
<input class="name-input" v-model.trim="groupName" placeholder="请输入分组名称" maxlength="20" />
<view class="icon-btn" v-if="groupName" @click="clearName">
<up-image :src="delImg" width="48rpx" height="48rpx" />
</view>
</view>
<!-- 分组成员 -->
<view class="section-header">分组成员</view>
<view class="add-member" @click="addMember">
<view class="add-circle">
<up-icon name="plus" size="34" color="#bfbfbf" />
</view>
<text class="add-text">添加组患者</text>
</view>
<!-- 已选中的成员 -->
<view class="selected-members" v-if="members.length > 0">
<view class="selected-item" v-for="(m, idx) in members" :key="m.uuid || idx">
<image class="selected-avatar" :src="docUrl + (m.photo || '')" mode="aspectFill" />
<text class="selected-name">{{ m.realName || '未知' }}</text>
<view class="remove-selected" @click="removeMember(idx)">
<text class="remove-text"></text>
<!-- <up-icon name="minus" size="43rpx" color="#fff" bold /> -->
</view>
</view>
</view>
<!-- 底部删除按钮 -->
<view class="bottom-danger">
<button class="danger-btn" @click="visible=true">删除分组</button>
</view>
<unidialog :visible="visible" :content="'删除分析组?'" @close="visible=false" @confirm="confirmDelete"></unidialog>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app'
import navTo from '@/utils/navTo.js'
import docUrl from '@/utils/docUrl.js'
import delImg from "@/static/iv_delete.png"
import api from '@/api/api.js'
import unidialog from '@/components/dialog/dialog.vue'
const groupUuid = ref('')
const groupName = ref('')
const members = ref([])
const visible = ref(false)
const confirmDelete = () => {
deleteGroup();
}
onLoad((query) => {
console.log(query)
groupUuid.value = query?.uuid || '';
if(groupUuid.value){
patientListByGroup()
}
// TODO: 根据 uuid 拉取分组详情
// 预置示例
})
onShow(() => {
// 兜底读取从选择页写入的缓存
try {
const cached = uni.getStorageSync('patientsSelectedPayload')
if (cached && Array.isArray(cached.list) && cached.list.length) {
mergeSelected(cached.list)
uni.removeStorageSync('patientsSelectedPayload')
}
} catch (e) {}
})
const goBack = () => uni.navigateBack()
const clearName = () => { groupName.value = '' }
const saveGroup = () => {
// TODO: 调用保存接口: { uuid: groupUuid, name: groupName, members }
if(groupUuid.value){
groupUpdate()
}else{
groupAdd()
}
}
const addMember = () => {
// 传递已选中的成员ID到选择页面让选择页面知道哪些已经选中
const selectedIds = members.value.map(m => m.uuid)
uni.setStorageSync('preSelectedIds', selectedIds)
// 跳转选择患者页并监听事件通道返回
uni.navigateTo({
url: '/pages_app/selectPatient/selectPatient',
events: {
onPatientsSelected: ({ ids, list }) => {
if (Array.isArray(list)) mergeSelected(list)
}
}
})
}
const removeMember = (idx) => {
members.value.splice(idx, 1)
}
const deleteGroup = () => {
api.groupDelete({
group_uuid: groupUuid.value
}).then(res => {
if(res.code == 200){
uni.showToast({ title: '删除成功', icon: 'none' })
setTimeout(() => goBack(), 700)
}
})
}
const groupAdd = () => {
if(!groupName.value){
uni.showToast({
title: '请输入分组名称',
icon: 'none'
})
return
}
api.groupAdd({
name: groupName.value,
patient_uuid: members.value.map(m => m.uuid).join(','),
}).then(res => {
if(res.code == 200){
uni.showToast({ title: '保存成功', icon: 'none' })
setTimeout(() => goBack(), 700)
}
})
}
const groupUpdate = () => {
if(!groupName.value){
uni.showToast({
title: '请输入分组名称',
icon: 'none'
})
return
}
api.groupUpdate({
group_uuid: groupUuid.value,
name: groupName.value,
patient_uuid: members.value.map(m => m.uuid).join(','),
}).then(res => {
if(res.code == 200){
uni.showToast({ title: '保存成功', icon: 'none' })
setTimeout(() => goBack(), 700)
}
})
}
// 将选择结果合并到成员列表,按 uuid 去重
const mergeSelected = (selectedList) => {
const existIds = new Set(members.value.map(m => m.uuid))
selectedList.forEach(s => {
if (!existIds.has(s.uuid)) {
existIds.add(s.uuid)
members.value.push({ uuid: s.uuid, realName: s.realName, photo: s.photo || '' })
}
})
}
const patientListByGroup = async () => {
const res = await api.patientListByGroup({
group_uuid: groupUuid.value,
list_sort:0
})
if(res.code == 200){
members.value = res.data.patient_list
groupName.value = res.data.group.name
}
}
</script>
<style lang="scss" scoped>
.group-edit-page{
min-height: 100vh;
background: #f5f5f5;
padding-bottom: 160rpx;
}
.save-text{
background:#8B2316;
font-size: 30rpx;
display: flex;
align-items: center;
justify-content: center;
padding: 15rpx 25rpx;
color:#fff;
border-radius: 12rpx;
}
.section-header{
background:#d9d9d9;
color:#333;
padding: 22rpx 30rpx;
font-size: 30rpx;
}
.name-row{
background:#fff;
display:flex;
align-items:center;
justify-content:space-between;
padding: 24rpx 30rpx;
border-bottom: 1rpx solid #eee;
.name-input{
flex:1;
font-size: 32rpx;
color:#333;
}
.icon-btn{ padding-left: 20rpx; }
}
.selected-members{
background:#fff;
.selected-item{
display:flex; align-items:center; justify-content:space-between;
padding: 20rpx 30rpx; border-bottom: 1rpx solid #eee;
.selected-avatar{ width: 80rpx; height: 80rpx; border-radius: 12rpx; background:#ffe; }
.selected-name{ flex:1; margin-left: 20rpx; font-size: 30rpx; color:#333; }
.remove-selected{ width: 48rpx; height: 48rpx; border-radius: 50%; background:#8B2316; display:flex; align-items:center; justify-content:center; }
}
.remove-text{ font-size: 14rpx; color:#fff;font-weight: bold; }
}
.add-member{
background:#fff;
display:flex;
align-items:center;
gap:20rpx;
padding: 26rpx 30rpx;
border-bottom: 1rpx solid #eee;
.add-circle{
width: 96rpx; height: 96rpx; border-radius: 50%;
border: 4rpx solid #e5e5e5;
display:flex; align-items:center; justify-content:center;
background:#fff;
}
.add-text{ font-size: 32rpx; color:#666; }
}
.bottom-danger{
position: fixed; left:30rpx; right:30rpx; bottom: 30rpx;
background:#fff; border-top: 1rpx solid #eee;
.danger-btn{ width:100%; height: 96rpx; background:#8B2316; color:#fff; border:none; border-radius: 12rpx; font-size: 32rpx;display: flex; align-items: center; justify-content: center; }
}
</style>