|
|
|
|
@ -95,13 +95,14 @@
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
|
|
|
|
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
|
|
|
|
|
import { User, Avatar, Phone } from '@element-plus/icons-vue'
|
|
|
|
|
import PhoneWidget from './PhoneWidget.vue'
|
|
|
|
|
import UserCenterDialog from './UserCenterDialog.vue'
|
|
|
|
|
import OCListDialog from './OCListDialog.vue'
|
|
|
|
|
import OCInfoDialog from './OCInfoDialog.vue'
|
|
|
|
|
import { ocList } from '../stores/ocStore.js'
|
|
|
|
|
import { ocList, loadOCFromStorage } from '../stores/ocStore.js'
|
|
|
|
|
import { currentUser } from '../stores/userStore.js'
|
|
|
|
|
|
|
|
|
|
// 默认头像
|
|
|
|
|
const defaultAvatar = 'https://i.pravatar.cc/100?img=1'
|
|
|
|
|
@ -125,6 +126,8 @@ const locationCoords = {
|
|
|
|
|
const ocPositions = ref([])
|
|
|
|
|
// 每个地点的实时状态(位置、在场人数、对应 oc 列表)
|
|
|
|
|
const locationStatuses = ref([])
|
|
|
|
|
// 是否已经按当前用户加载了专属 ocList
|
|
|
|
|
const ocLoadedForUser = ref(false)
|
|
|
|
|
|
|
|
|
|
const computePositions = () => {
|
|
|
|
|
const now = new Date()
|
|
|
|
|
@ -135,7 +138,14 @@ const computePositions = () => {
|
|
|
|
|
Object.keys(locationCoords).forEach(k => {
|
|
|
|
|
locMap[k] = { name: k, x: locationCoords[k].x, y: locationCoords[k].y, count: 0, ocs: [] }
|
|
|
|
|
})
|
|
|
|
|
ocList.value.forEach(oc => {
|
|
|
|
|
// 选择用于计算位置的 OC 列表:优先使用为当前用户单独加载的列表;否则只使用含 owner 且属当前用户的 OC
|
|
|
|
|
const sourceList = ocLoadedForUser.value
|
|
|
|
|
? ocList.value
|
|
|
|
|
: (currentUser.value && currentUser.value.username)
|
|
|
|
|
? ocList.value.filter(o => o.owner && o.owner === currentUser.value.username)
|
|
|
|
|
: []
|
|
|
|
|
|
|
|
|
|
sourceList.forEach(oc => {
|
|
|
|
|
let loc = ''
|
|
|
|
|
if (oc.schedule && oc.schedule.length) {
|
|
|
|
|
// 找到最近时间点 <= now 的活动
|
|
|
|
|
@ -163,6 +173,19 @@ const computePositions = () => {
|
|
|
|
|
|
|
|
|
|
let posTimer = null
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
// 尝试按当前用户加载其专属 OC 列表(如果用户已登录)
|
|
|
|
|
if (currentUser.value && currentUser.value.username) {
|
|
|
|
|
try {
|
|
|
|
|
loadOCFromStorage(currentUser.value.username)
|
|
|
|
|
ocLoadedForUser.value = true
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('Failed to load user-specific OC list:', e)
|
|
|
|
|
ocLoadedForUser.value = false
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ocLoadedForUser.value = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
computePositions()
|
|
|
|
|
posTimer = setInterval(computePositions, 60 * 1000)
|
|
|
|
|
document.addEventListener('click', closePopoverOnClickOutside)
|
|
|
|
|
@ -172,6 +195,24 @@ onUnmounted(() => {
|
|
|
|
|
document.removeEventListener('click', closePopoverOnClickOutside)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 当登录用户变更时,尝试加载该用户的 OC 列表并刷新位置(确保地图只显示自己的 OC)
|
|
|
|
|
watch(currentUser, (val) => {
|
|
|
|
|
if (val && val.username) {
|
|
|
|
|
try {
|
|
|
|
|
loadOCFromStorage(val.username)
|
|
|
|
|
ocLoadedForUser.value = true
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('Failed to load OC list for user on change:', e)
|
|
|
|
|
ocLoadedForUser.value = false
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ocLoadedForUser.value = false
|
|
|
|
|
// 恢复为全局加载(不展示其他账号的 OC)
|
|
|
|
|
loadOCFromStorage()
|
|
|
|
|
}
|
|
|
|
|
computePositions()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// OC 信息弹窗与控制弹窗显示/隐藏
|
|
|
|
|
const showOCInfo = ref(false)
|
|
|
|
|
const selectedOC = ref(null)
|
|
|
|
|
@ -230,7 +271,7 @@ const closePopoverOnClickOutside = (event) => {
|
|
|
|
|
.community-container {
|
|
|
|
|
display: flex;
|
|
|
|
|
height: 100vh;
|
|
|
|
|
background: linear-gradient(135deg, #ffc6c6 0%, #7486c0 100%);
|
|
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
|
|
position: relative;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|