<template>
  <view class="page">
    <view class="card">
      <view class="header">
        <view class="avatar">
          <image v-if="archive.avatar" class="avatar-img" :src="archive.avatar" mode="aspectFill" />
        </view>

        <view class="header-main">
          <view class="name-row">
            <text class="name">{{ archive.name || '-' }}</text>
            <text v-if="sexOrAge" class="meta">{{ sexOrAge }}</text>
          </view>

          <view v-if="archive.mobile" class="sub-line">{{ archive.mobile }}</view>

          <view v-if="idRows.length" class="id-rows">
            <view v-for="row in idRows" :key="row.label" class="id-row">
              <text class="id-label">{{ row.label }}：</text>
              <text class="id-value">{{ row.value }}</text>
            </view>
          </view>

          <view v-if="createText" class="create-row">
            <text class="create-text">{{ createText }}</text>
          </view>
        </view>

        <view class="header-right" @click="goEdit">
          <uni-icons type="right" size="18" color="#bbb" />
        </view>
      </view>

      <view class="cells">
        <!-- 联系电话 -->
        <view class="info-row border-bottom">
          <text class="input-label">联系电话</text>
          <view class="info-right">
            <template v-if="archive.mobile">
              <view class="phone-area" @click="makeCall">
                <uni-icons type="phone-filled" size="18" color="#4f6ef7" class="mr-4" />
                <text class="phone-text">{{ archive.mobile }}</text>
              </view>
              <view class="edit-icon" @click.stop="openContact">
                <uni-icons type="compose" size="20" color="#4f6ef7" />
              </view>
            </template>
            <view v-else class="empty-click" @click="openContact">
              <text class="placeholder">添加联系电话</text>
            </view>
          </view>
        </view>

        <!-- 备注 -->
        <view class="info-block border-bottom">
          <view class="block-header">
            <text class="input-label">备注</text>
            <view class="edit-icon" @click.stop="openNotes">
              <uni-icons type="compose" size="20" color="#4f6ef7" />
            </view>
          </view>
          <view class="block-content">
            <text v-if="archive.notes" class="note-content">{{ archive.notes }}</text>
            <view v-else class="empty-click" @click="openNotes">
              <text class="placeholder">添加备注</text>
            </view>
          </view>
        </view>

        <!-- 分组 -->
        <view class="info-block">
          <view class="block-header">
            <text class="input-label">分组</text>
            <view class="edit-icon" @click.stop="openGroups">
              <uni-icons type="compose" size="20" color="#4f6ef7" />
            </view>
          </view>
          <view class="block-content">
            <view v-if="archiveGroupNames.length" class="tags-wrap">
              <view v-for="tag in archiveGroupNames" :key="tag" class="tag-item">
                {{ tag }}
              </view>
            </view>
            <view v-else class="empty-click" @click="openGroups">
              <text class="placeholder">添加分组</text>
            </view>
          </view>
        </view>
      </view>
    </view>

    <view class="tabs">
      <view
        v-for="t in tabs"
        :key="t.key"
        class="tab"
        :class="{ active: currentTab === t.key }"
        @click="switchTab(t.key)"
      >
        {{ t.title }}
      </view>
    </view>

    <view class="content">
      <HealthProfileTab
        v-if="currentTab === 'visitRecord'"
        :data="archive"
        :archiveId="archiveId"
        :floatingBottom="floatingBottom"
      />
      <ServiceInfoTab
        v-else-if="currentTab === 'serviceRecord'"
        :data="archive"
        :archiveId="archiveId"
        :reachBottomTime="reachBottomTime"
        :floatingBottom="floatingBottom"
      />
      <FollowUpManageTab
        v-else
        :data="archive"
        :archiveId="archiveId"
        :reachBottomTime="reachBottomTime"
        :floatingBottom="floatingBottom"
      />
    </view>

    <view v-if="showBindWechat" class="footer">
      <button class="bind-btn" @click="bindWechat">
        <uni-icons type="email" size="18" color="#fff" />
        <text class="bind-text">关联患者微信</text>
      </button>
    </view>

    <!-- 修改联系电话（居中弹窗） -->
    <uni-popup ref="contactPopup" type="center">
      <view class="modal">
        <view class="modal-title">修改联系电话</view>
        <view class="modal-body">
          <input class="modal-input" v-model="contactInput" type="number" placeholder="请输入联系电话" />
        </view>
        <view class="modal-actions">
          <view class="modal-btn cancel" @click="closeContact">取消</view>
          <view class="modal-btn save" @click="saveContact">保存</view>
        </view>
      </view>
    </uni-popup>

    <!-- 修改备注（底部弹层） -->
    <uni-popup ref="notesPopup" type="bottom">
      <view class="sheet">
        <view class="sheet-header">
          <view class="sheet-header-left" />
          <view class="sheet-title">修改备注</view>
          <view class="sheet-close" @click="closeNotes">
            <uni-icons type="closeempty" size="18" color="#333" />
          </view>
        </view>

        <view class="sheet-body">
          <textarea
            v-model="notesInput"
            class="notes-textarea"
            placeholder="请输入备注"
            :maxlength="100"
          />
          <view class="counter">{{ notesInput.length }}/100</view>
        </view>

        <view class="sheet-footer">
          <button class="primary-btn" @click="saveNotes">保存</button>
        </view>
      </view>
    </uni-popup>

    <!-- 选择分组（底部弹层） -->
    <uni-popup ref="groupPopup" type="bottom">
      <view class="sheet">
        <view class="sheet-header">
          <view class="sheet-close" @click="closeGroups">
            <uni-icons type="closeempty" size="18" color="#333" />
          </view>
          <view class="sheet-title">选择分组</view>
          <view class="sheet-link" @click="openAddGroup">添加分组</view>
        </view>

        <view class="group-list">
          <view v-for="g in teamGroups" :key="g._id" class="group-item" @click="toggleGroup(String(g._id))">
            <uni-icons
              :type="selectedGroupMap[String(g._id)] ? 'checkbox-filled' : 'checkbox'"
              size="20"
              :color="selectedGroupMap[String(g._id)] ? '#4f6ef7' : '#c7c7c7'"
            />
            <text class="group-name">{{ g.groupName }}</text>
          </view>
        </view>

        <view class="sheet-footer">
          <button class="primary-btn" @click="saveGroups">保存</button>
        </view>
      </view>
    </uni-popup>

    <!-- 添加新分组（居中弹窗） -->
    <uni-popup ref="addGroupPopup" type="center">
      <view class="modal">
        <view class="modal-title">添加新分组</view>
        <view class="modal-body">
          <input class="modal-input" v-model="newGroupName" placeholder="请输入分组名称" />
        </view>
        <view class="modal-actions">
          <view class="modal-btn cancel" @click="closeAddGroup">取消</view>
          <view class="modal-btn save" @click="saveAddGroup">保存</view>
        </view>
      </view>
    </uni-popup>
  </view>
</template>

<script setup>
import { computed, getCurrentInstance, ref } from 'vue';
import { onLoad, onPullDownRefresh, onReachBottom, onReady, onShow } from '@dcloudio/uni-app';
import { storeToRefs } from 'pinia';

import HealthProfileTab from '@/components/archive-detail/health-profile-tab.vue';
import ServiceInfoTab from '@/components/archive-detail/service-info-tab.vue';
import FollowUpManageTab from '@/components/archive-detail/follow-up-manage-tab.vue';
import api from '@/utils/api';
import useAccountStore from '@/store/account';
import { hideLoading, loading, toast } from '@/utils/widget';

const STORAGE_KEY = 'ykt_case_archive_detail';
const CURRENT_TEAM_STORAGE_KEY = 'ykt_case_current_team';
const NEED_RELOAD_STORAGE_KEY = 'ykt_case_need_reload';

const tabs = [
  { key: 'visitRecord', title: '病历记录' },
  { key: 'followUp', title: '回访任务' },
  { key: 'serviceRecord', title: '服务记录' }
];

const currentTab = ref('visitRecord');
const reachBottomTime = ref(0);
const archiveId = ref('');
const tabsScrollTop = ref(0);
const instanceProxy = getCurrentInstance()?.proxy;

function switchTab(key) {
  currentTab.value = key;
  // 切换 tab 后，将页面滚动到顶部，确保 tab 吸顶可见
  uni.pageScrollTo({ scrollTop: 0, duration: 0 });
}

const archive = ref({
  name: '',
  sex: '',
  age: '',
  avatar: '',
  mobile: '',
  outpatientNo: '',
  inpatientNo: '',
  medicalRecordNo: '',
  createTime: '',
  creator: '',
  createdByDoctor: true,
  hasBindWechat: false,
  notes: '',
  groupIds: []
});

const accountStore = useAccountStore();
const { account, doctorInfo } = storeToRefs(accountStore);
const { getDoctorInfo } = accountStore;

function getUserId() {
  const d = doctorInfo.value || {};
  const a = account.value || {};
  return String(d.userid || d.userId || d.corpUserId || a.userid || a.userId || '') || '';
}

function getCorpId() {
  const d = doctorInfo.value || {};
  const a = account.value || {};
  const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
  return String(d.corpId || a.corpId || team.corpId || '') || '';
}

function normalizeArchiveFromApi(raw) {
  const r = raw && typeof raw === 'object' ? raw : {};
  const next = {
    _id: r._id || archiveId.value,
    name: r.name || '',
    sex: r.sex || r.gender || '',
    age: r.age ?? '',
    avatar: r.avatar || '',
    mobile: r.mobile || r.phone1 || r.phone || '',
    outpatientNo: r.outpatientNo || '',
    inpatientNo: r.inpatientNo || '',
    medicalRecordNo: r.medicalRecordNo || '',
    createTime: r.createTime || '',
    creator: r.creator || '',
    notes: r.notes || r.remark || '',
    groupIds: Array.isArray(r.groupIds) ? r.groupIds : [],
  };
  return next;
}

async function ensureDoctor() {
  if (doctorInfo.value) return;
  if (!account.value?.openid) return;
  try {
    await getDoctorInfo();
  } catch (e) {
    // ignore
  }
}

async function fetchArchive() {
  if (!archiveId.value) return;
  await ensureDoctor();
  loading('加载中...');
  try {
    const res = await api('getCustomerByCustomerId', { customerId: archiveId.value });
    if (!res?.success) {
      toast(res?.message || '获取档案失败');
      return;
    }
    archive.value = { ...archive.value, ...normalizeArchiveFromApi(res.data) };
    saveToStorage();
    await fetchTeamGroups(true);
  } catch (e) {
    toast('获取档案失败');
  } finally {
    hideLoading();
  }
}

const teamGroups = ref([]);
const groupNameMap = computed(() => {
  const map = new Map();
  (Array.isArray(teamGroups.value) ? teamGroups.value : []).forEach((g) => {
    if (g && g._id && g.groupName) map.set(String(g._id), String(g.groupName));
  });
  return map;
});

const archiveGroupNames = computed(() => {
  const ids = Array.isArray(archive.value.groupIds) ? archive.value.groupIds : [];
  const map = groupNameMap.value;
  return ids.map((id) => map.get(String(id))).filter(Boolean);
});

function sortGroupList(list) {
  const { orderList, corpList, restList } = (Array.isArray(list) ? list : []).reduce(
    (p, c) => {
      if (typeof c?.sortOrder === 'number') p.orderList.push(c);
      else if (c?.parentGroupId) p.corpList.push(c);
      else p.restList.push(c);
      return p;
    },
    { orderList: [], corpList: [], restList: [] }
  );
  orderList.sort((a, b) => a.sortOrder - b.sortOrder);
  return [...orderList, ...corpList, ...restList];
}

async function fetchTeamGroups(silent = false) {
  const corpId = getCorpId();
  const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
  const teamId = team?.teamId ? String(team.teamId) : '';
  if (!corpId || !teamId) return;
  try {
    const projection = { _id: 1, groupName: 1, parentGroupId: 1, sortOrder: 1 };
    const res = await api('getGroups', { corpId, teamId, page: 1, pageSize: 1000, projection, countGroupMember: false });
    if (!res?.success) {
      if (!silent) toast(res?.message || '获取分组失败');
      teamGroups.value = [];
      return;
    }
    const list = Array.isArray(res.data) ? res.data : Array.isArray(res.data?.data) ? res.data.data : [];
    teamGroups.value = sortGroupList(list);
  } catch (e) {
    if (!silent) toast('获取分组失败');
    teamGroups.value = [];
  }
}

async function updateArchive(patch) {
  const id = String(archiveId.value || '');
  if (!id) return false;
  await ensureDoctor();
  const userId = getUserId();
  const corpId = getCorpId();
  const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
  const createTeamId = team?.teamId ? String(team.teamId) : '';
  const createTeamName = team?.name ? String(team.name) : '';
  if (!userId || !corpId) {
    toast('缺少登录信息，请先完成登录');
    return false;
  }

  loading('保存中...');
  try {
    const res = await api('updateCustomer', {
      id,
      params: patch,
      userId,
      corpId,
      createTeamId,
      createTeamName,
    });
    if (!res?.success) {
      toast(res?.message || '保存失败');
      return false;
    }
    uni.setStorageSync(NEED_RELOAD_STORAGE_KEY, 1);
    await fetchArchive();
    return true;
  } catch (e) {
    toast('保存失败');
    return false;
  } finally {
    hideLoading();
  }
}

onLoad((options) => {
  archiveId.value = options?.id ? String(options.id) : String(archive.value.medicalRecordNo || archive.value.outpatientNo || archive.value.inpatientNo || '');

  const cached = uni.getStorageSync(STORAGE_KEY);
  if (cached && typeof cached === 'object') {
    archive.value = {
      ...archive.value,
      ...cached,
      groupIds: Array.isArray(cached.groupIds) ? cached.groupIds : archive.value.groupIds
    };
  }

  if (!archive.value.mobile) {
    const mobiles = cached && Array.isArray(cached.mobiles) ? cached.mobiles : [];
    if (mobiles.length) archive.value.mobile = String(mobiles[0]);
  }

  if (!archiveId.value) {
    archiveId.value = String(archive.value.medicalRecordNo || archive.value.outpatientNo || archive.value.inpatientNo || `mock_${Date.now()}`);
  }

  // 接口兜底：优先用接口刷新档案详情
  fetchArchive();
});

function measureTabsTop() {
  const q = instanceProxy ? uni.createSelectorQuery().in(instanceProxy) : uni.createSelectorQuery();
  q.select('.tabs').boundingClientRect();
  q.selectViewport().scrollOffset();
  q.exec((res) => {
    const rect = res && res[0];
    const viewport = res && res[1];
    if (!rect || !viewport) return;
    tabsScrollTop.value = (rect.top || 0) + (viewport.scrollTop || 0);
  });
}

onReady(() => {
  setTimeout(measureTabsTop, 30);
});

onShow(() => {
  const cached = uni.getStorageSync(STORAGE_KEY);
  if (cached && typeof cached === 'object') {
    archive.value = {
      ...archive.value,
      ...cached,
      groupIds: Array.isArray(cached.groupIds) ? cached.groupIds : archive.value.groupIds,
    };
  }
  setTimeout(measureTabsTop, 30);
  fetchArchive();
});

onPullDownRefresh(() => {
  uni.pageScrollTo({
    scrollTop: tabsScrollTop.value || 0,
    duration: 0,
  });
  setTimeout(() => uni.stopPullDownRefresh(), 150);
});

onReachBottom(() => {
  reachBottomTime.value = Date.now();
});

const sexOrAge = computed(() => {
  const sex = archive.value.sex ? String(archive.value.sex) : '';
  const age = archive.value.age || archive.value.age === 0 ? `${archive.value.age}岁` : '';
  if (sex && age) return `${sex} ${age}`;
  return sex || age;
});

const idRows = computed(() => {
  const rows = [];
  if (archive.value.outpatientNo) rows.push({ label: '门诊号', value: String(archive.value.outpatientNo) });
  if (archive.value.inpatientNo) rows.push({ label: '住院号', value: String(archive.value.inpatientNo) });
  if (archive.value.medicalRecordNo) rows.push({ label: '病案号', value: String(archive.value.medicalRecordNo) });
  return rows;
});

const createText = computed(() => {
  const time = archive.value.createTime ? String(archive.value.createTime) : '';
  const rawCreator = archive.value.creator ? String(archive.value.creator) : '';
  const creator = ['-', '—', '--'].includes(rawCreator.trim()) ? '' : rawCreator.trim();
  if (time && creator) return `${time}  ${creator}创建`;
  if (time) return `${time} 创建`;
  return '';
});

const showBindWechat = computed(() => Boolean(archive.value.createdByDoctor && !archive.value.hasBindWechat));
const floatingBottom = computed(() => (showBindWechat.value ? 90 : 16));

// const contactTitle = computed(() => (archive.value.mobile ? '联系方式' : '添加联系电话'));
// const notesTitle = computed(() => (archive.value.notes ? '备注' : '添加备注'));
// const groupTitle = computed(() => (Array.isArray(archive.value.groups) && archive.value.groups.length ? '分组' : '添加分组'));

const saveToStorage = () => {
  uni.setStorageSync(STORAGE_KEY, { ...archive.value });
};

const goEdit = () => {
  uni.navigateTo({ url: `/pages/case/archive-edit?archiveId=${encodeURIComponent(archiveId.value || '')}` });
};

const bindWechat = () => {
  uni.showToast({ title: '关联患者微信功能待接入', icon: 'none' });
};

const makeCall = () => {
  if (archive.value.mobile) {
    uni.makePhoneCall({ phoneNumber: archive.value.mobile });
  }
};

// ===== 联系电话 =====
const contactPopup = ref(null);
const contactInput = ref('');

const openContact = () => {
  contactInput.value = archive.value.mobile ? String(archive.value.mobile) : '';
  contactPopup.value?.open();
};

const closeContact = () => {
  contactPopup.value?.close();
};

const saveContact = () => {
  const v = String(contactInput.value || '').trim();
  if (!v) {
    uni.showToast({ title: '请输入联系电话', icon: 'none' });
    return;
  }
  updateArchive({ mobile: v }).then((ok) => ok && closeContact());
};

// ===== 备注 =====
const notesPopup = ref(null);
const notesInput = ref('');

const openNotes = () => {
  notesInput.value = archive.value.notes ? String(archive.value.notes) : '';
  notesPopup.value?.open();
};

const closeNotes = () => {
  notesPopup.value?.close();
};

const saveNotes = () => {
  const v = String(notesInput.value || '').trim();
  updateArchive({ notes: v }).then((ok) => ok && closeNotes());
};

// ===== 分组 =====
const groupPopup = ref(null);
const addGroupPopup = ref(null);

const selectedGroupMap = ref({});

const syncSelectedMapFromArchive = () => {
  const current = Array.isArray(archive.value.groupIds) ? archive.value.groupIds.map(String) : [];
  selectedGroupMap.value = current.reduce((acc, id) => {
    acc[String(id)] = true;
    return acc;
  }, {});
};

const openGroups = async () => {
  await fetchTeamGroups(false);
  syncSelectedMapFromArchive();
  groupPopup.value?.open();
};

const closeGroups = () => {
  groupPopup.value?.close();
};

const toggleGroup = (groupId) => {
  const key = String(groupId || '');
  if (!key) return;
  selectedGroupMap.value[key] = !selectedGroupMap.value[key];
};

async function applyGroupChange(nextIds) {
  const memberId = String(archiveId.value || '');
  if (!memberId) return false;
  const prevIds = Array.isArray(archive.value.groupIds) ? archive.value.groupIds.map(String) : [];
  const next = Array.isArray(nextIds) ? nextIds.map(String).filter(Boolean) : [];

  const toAdd = next.filter((id) => !prevIds.includes(id));
  const toRemove = prevIds.filter((id) => !next.includes(id));

  if (toAdd.length === 0 && toRemove.length === 0) return true;

  loading('保存中...');
  try {
    for (const id of toAdd) {
      const res = await api('addGroupIdForMember', { memberId, toGroupId: id });
      if (!res?.success) {
        toast(res?.message || '分组保存失败');
        return false;
      }
    }
    for (const id of toRemove) {
      const res = await api('addGroupIdForMember', { memberId, fromGroupId: id });
      if (!res?.success) {
        toast(res?.message || '分组保存失败');
        return false;
      }
    }
    uni.setStorageSync(NEED_RELOAD_STORAGE_KEY, 1);
    await fetchArchive();
    return true;
  } catch (e) {
    toast('分组保存失败');
    return false;
  } finally {
    hideLoading();
  }
}

const saveGroups = async () => {
  const nextIds = Object.keys(selectedGroupMap.value).filter((k) => selectedGroupMap.value[k]);
  const ok = await applyGroupChange(nextIds);
  if (ok) closeGroups();
};

// 添加新分组
const newGroupName = ref('');

const openAddGroup = () => {
  newGroupName.value = '';
  addGroupPopup.value?.open();
};

const closeAddGroup = () => {
  addGroupPopup.value?.close();
};

const saveAddGroup = async () => {
  const name = String(newGroupName.value || '').trim();
  if (!name) {
    uni.showToast({ title: '请输入分组名称', icon: 'none' });
    return;
  }
  const exists = (Array.isArray(teamGroups.value) ? teamGroups.value : []).some((g) => String(g?.groupName || '').trim() === name);
  if (exists) {
    uni.showToast({ title: '该分组已存在', icon: 'none' });
    return;
  }

  const corpId = getCorpId();
  const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
  const teamId = team?.teamId ? String(team.teamId) : '';
  const creator = getUserId();
  if (!corpId || !teamId || !creator) {
    toast('缺少用户/团队信息');
    return;
  }

  loading('保存中...');
  try {
    const params = { groupName: name, teamId, groupType: 'team', creator };
    const res = await api('createGroup', { corpId, teamId, params });
    if (!res?.success) {
      toast(res?.message || '新增分组失败');
      return;
    }
    await fetchTeamGroups(true);
    // 自动选中新建分组（后续在“保存”时调用 addGroupIdForMember）
    const newId = res.data ? String(res.data) : '';
    if (newId) selectedGroupMap.value[newId] = true;
    uni.setStorageSync('ykt_case_groups_need_reload', 1);
    closeAddGroup();
  } catch (e) {
    toast('新增分组失败');
  } finally {
    hideLoading();
  }
};
</script>

<style lang="scss" scoped>
.page {
  min-height: 100vh;
  background: #f5f6f8;
  padding-bottom: calc(80px + env(safe-area-inset-bottom));
}

.card {
  background: #fff;
}

.header {
  display: flex;
  align-items: flex-start;
  padding: 14px 14px 10px;
  border-bottom: 1px solid #f2f2f2;
}

.avatar {
  width: 56px;
  height: 56px;
  border-radius: 6px;
  border: 1px solid #e8e8e8;
  background: #fafafa;
  overflow: hidden;
  flex-shrink: 0;
}

.avatar-img {
  width: 56px;
  height: 56px;
}

.header-main {
  flex: 1;
  min-width: 0;
  padding: 0 10px;
}

.name-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 2px;
}

.name {
  font-size: 18px;
  font-weight: 600;
  color: #1f1f1f;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.meta {
  font-size: 13px;
  color: #666;
}

.sub-line {
  margin-top: 6px;
  font-size: 12px;
  color: #666;
}

.id-rows {
  margin-top: 6px;
}

.id-row {
  display: flex;
  align-items: center;
  font-size: 12px;
  color: #666;
  line-height: 18px;
}

.id-label {
  flex-shrink: 0;
}

.id-value {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.create-row {
  margin-top: 6px;
}

.create-text {
  font-size: 12px;
  color: #999;
}

.header-right {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: 6px;
}

.cells {
  background: #fff;
  padding: 0 14px;
}

.border-bottom {
  border-bottom: 1px solid #f2f2f2;
}

.info-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 0;
  min-height: 24px;
}

.info-block {
  padding: 16px 0;
}

.block-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.block-content {
  min-height: 20px;
}

.input-label {
  font-size: 15px;
  color: #666;
}

.info-right {
  display: flex;
  align-items: center;
}

.phone-area {
  display: flex;
  align-items: center;
  margin-right: 12px;
}

.mr-4 {
  margin-right: 4px;
}

.phone-text {
  font-size: 16px;
  color: #4f6ef7;
  font-weight: 500;
}

.edit-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
}

.placeholder {
  font-size: 14px;
  color: #999;
}

.note-content {
  font-size: 14px;
  color: #333;
  line-height: 1.5;
  word-break: break-all;
}

.tags-wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tag-item {
  height: 24px;
  line-height: 22px;
  padding: 0 10px;
  border: 1px solid #4f6ef7;
  border-radius: 12px;
  font-size: 12px;
  color: #4f6ef7;
  box-sizing: border-box;
}

.empty-click {
  /* To ensure empty area is clickable */
  display: inline-block;
}

.tabs {
  margin-top: 10px;
  background: #fff;
  display: flex;
  border-top: 1px solid #f2f2f2;
  border-bottom: 1px solid #f2f2f2;
  position: sticky;
  top: 0;
  z-index: 30;
}

.tab {
  flex: 1;
  text-align: center;
  height: 44px;
  line-height: 44px;
  font-size: 14px;
  color: #333;
  position: relative;
}

.tab.active {
  color: #4f6ef7;
  font-weight: 600;
}

.tab.active::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 32px;
  height: 3px;
  background: #4f6ef7;
  transform: translateX(-50%);
  border-radius: 2px;
}

.content {
  padding: 0;
}

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.empty-img {
  width: 160px;
  height: 160px;
  opacity: 0.9;
}

.empty-text {
  margin-top: 10px;
  font-size: 13px;
  color: #9aa0a6;
}

.footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  background: #fff;
  padding: 12px 14px calc(12px + env(safe-area-inset-bottom));
  box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.06);
}

.bind-btn {
  width: 100%;
  height: 44px;
  background: #4f6ef7;
  color: #fff;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 15px;
}

.bind-text {
  color: #fff;
}

/* ===== 弹窗样式（居中） ===== */
.modal {
  width: 320px;
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
}

.modal-title {
  font-size: 16px;
  font-weight: 600;
  text-align: center;
  padding: 14px 12px;
  color: #333;
  border-bottom: 1px solid #f0f0f0;
}

.modal-body {
  padding: 14px 14px 8px;
}

.modal-input {
  width: 100%;
  height: 40px;
  border: 1px solid #e6e6e6;
  border-radius: 4px;
  padding: 0 10px;
  font-size: 14px;
  box-sizing: border-box;
}

.modal-actions {
  display: flex;
  gap: 12px;
  padding: 12px 14px 14px;
}

.modal-btn {
  flex: 1;
  height: 40px;
  line-height: 40px;
  text-align: center;
  border-radius: 4px;
  font-size: 14px;
}

.modal-btn.cancel {
  border: 1px solid #4f6ef7;
  color: #4f6ef7;
  background: #fff;
}

.modal-btn.save {
  background: #4f6ef7;
  color: #fff;
}

/* ===== 底部弹层样式 ===== */
.sheet {
  background: #fff;
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
  overflow: hidden;
}

.sheet-header {
  height: 48px;
  display: flex;
  align-items: center;
  padding: 0 14px;
  border-bottom: 1px solid #f0f0f0;
}

.sheet-title {
  flex: 1;
  text-align: center;
  font-size: 16px;
  font-weight: 600;
  color: #333;
}

.sheet-close {
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.sheet-header-left {
  width: 24px;
}

.sheet-link {
  min-width: 60px;
  text-align: right;
  font-size: 14px;
  color: #4f6ef7;
}

.sheet-body {
  padding: 14px;
}

.notes-textarea {
  width: 100%;
  height: 140px;
  border: 1px solid #e6e6e6;
  border-radius: 4px;
  padding: 10px;
  font-size: 14px;
  box-sizing: border-box;
}

.counter {
  text-align: right;
  margin-top: 8px;
  font-size: 12px;
  color: #999;
}

.group-list {
  padding: 8px 14px 14px;
  max-height: 55vh;
  overflow: auto;
}

.group-item {
  display: flex;
  align-items: center;
  padding: 12px 0;
}

.group-name {
  margin-left: 10px;
  font-size: 14px;
  color: #333;
}

.sheet-footer {
  padding: 12px 14px calc(12px + env(safe-area-inset-bottom));
}

.primary-btn {
  width: 100%;
  height: 44px;
  background: #4f6ef7;
  color: #fff;
  border-radius: 4px;
  font-size: 15px;
  line-height: 44px;
}
</style>
