Codex/merge feature nxdev #70

Merged
nanxun merged 16 commits from codex/merge-feature-nxdev into main 2026-09-11 18:38:41 +08:00
4 changed files with 77 additions and 47 deletions
Showing only changes of commit feed24f378 - Show all commits
+4 -4
View File
@@ -1,8 +1,8 @@
VITE_API_BASE_URL = http://localhost:5202/api # VITE_API_BASE_URL = http://localhost:5202/api
VITE_SIGNALR_BASE_URL = http://localhost:5202/chat/ # VITE_SIGNALR_BASE_URL = http://localhost:5202/chat/
# VITE_API_BASE_URL = https://im.test.nxsir.cn/api # VITE_API_BASE_URL = https://im.test.nxsir.cn/api
# VITE_SIGNALR_BASE_URL = https://im.test.nxsir.cn/chat/ # VITE_SIGNALR_BASE_URL = https://im.test.nxsir.cn/chat/
# VITE_API_BASE_URL = http://192.168.5.116:7070/api VITE_API_BASE_URL = http://192.168.5.116:7070/api
# VITE_SIGNALR_BASE_URL = http://192.168.5.116:7070/chat/ VITE_SIGNALR_BASE_URL = http://192.168.5.116:7070/chat/
@@ -8,7 +8,7 @@
<script setup> <script setup>
import { onMounted, ref } from 'vue'; import { onMounted, ref, watch } from 'vue';
import { useCacheStore } from '../stores/cache'; import { useCacheStore } from '../stores/cache';
import { FILE_TYPE } from '../constants/fileTypeDefine'; import { FILE_TYPE } from '../constants/fileTypeDefine';
import default_avatar from '@/assets/default_avatar.png' import default_avatar from '@/assets/default_avatar.png'
@@ -33,8 +33,14 @@ const imgLoadErrHandler = (e) => {
e.target.src = loading_img e.target.src = loading_img
} }
onMounted(async () => { watch(() => props.rawUrl,
if (!props.rawUrl || props.rawUrl == '') return (newVal) => {
finalUrl.value = await cacheStore.getCache(props.rawUrl, FILE_TYPE.Image) if (!props.rawUrl || props.rawUrl == '') return
}) cacheStore.getCache(props.rawUrl, FILE_TYPE.Image).then(res => {
finalUrl.value = res
})
},
{ immediate: true }
)
</script> </script>
@@ -1,65 +1,74 @@
<template> <template>
<div v-for="c in props.contacts" <div v-for="c in props.contacts" :key="c.id" class="list-item" :class="{ active: activeContactId === c.id }"
:key="c.id" @click="routeUserInfo(c.id)">
class="list-item" <AsyncImage :raw-url="c.avatar" class="avatar-std" />
:class="{active: activeContactId === c.id}" <div class="info">
@click="routeUserInfo(c.id)"> <div class="name">{{ c.remarkName }}</div>
<img :src="c.userInfo.avatar" class="avatar-std" /> </div>
<div class="info"> </div>
<div class="name">{{ c.remarkName }}</div>
</div>
</div>
</template> </template>
<script setup> <script setup>
import { defineProps, ref } from 'vue'; import { defineProps, computed } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter, useRoute } from 'vue-router';
import AsyncImage from '../AsyncImage.vue';
const router = useRouter() const router = useRouter()
const route = useRoute()
const activeContactId = ref(null) const activeContactId = computed(() => route.params.id)
const props = defineProps({ const props = defineProps({
contacts: { contacts: {
type:String, type: String,
required: true required: true
} }
}) })
const routeUserInfo = (id) => { const routeUserInfo = (id) => {
router.push(`/contacts/info/${id}`); router.push(`/contacts/info/${id}`);
activeContactId.value = id;
} }
</script> </script>
<style scoped> <style scoped>
.list-item { .list-item {
display: flex; display: flex;
padding: 10px 12px; padding: 10px 12px;
gap: 12px; gap: 12px;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
transition: background 0.2s; transition: background 0.2s;
text-decoration: none; /* 去除下划线 */ text-decoration: none;
color: inherit; /* 继承父元素的文本颜色 */ /* 去除下划线 */
outline: none; /* 去除点击时的蓝框 */ color: inherit;
-webkit-tap-highlight-color: transparent; /* 移动端点击高亮 */ /* 继承父元素的文本颜色 */
outline: none;
/* 去除点击时的蓝框 */
-webkit-tap-highlight-color: transparent;
/* 移动端点击高亮 */
} }
/* 去除 hover、active 等状态的效果 */ /* 去除 hover、active 等状态的效果 */
a:hover, a:hover,
a:active, a:active,
a:focus { a:focus {
text-decoration: none; text-decoration: none;
color: inherit; /* 保持颜色不变 */ color: inherit;
/* 保持颜色不变 */
cursor: pointer; cursor: pointer;
} }
.list-item:hover { background: #e2e2e2; } .list-item:hover {
.list-item.active { background: #c6c6c6; } background: #e2e2e2;
}
.avatar-std { .list-item.active {
background: #c6c6c6;
}
:deep(.avatar-std) {
width: 36px; width: 36px;
height: 36px; height: 36px;
border-radius: 4px; border-radius: 4px;
@@ -76,7 +85,16 @@ a:focus {
color: #fff; color: #fff;
font-size: 16px; font-size: 16px;
} }
.icon-box.orange { background: #faad14; }
.icon-box.green { background: #52c41a; } .icon-box.orange {
.icon-box.blue { background: #1890ff; } background: #faad14;
</style> }
.icon-box.green {
background: #52c41a;
}
.icon-box.blue {
background: #1890ff;
}
</style>
@@ -15,7 +15,7 @@
<p class="sub-text">账号{{ currentContact.userInfo.username }}</p> <p class="sub-text">账号{{ currentContact.userInfo.username }}</p>
<p class="sub-text">地区{{ '未知' }}</p> <p class="sub-text">地区{{ '未知' }}</p>
</div> </div>
<img :src="currentContact.userInfo.avatar" class="big-avatar" /> <AsyncImage :raw-url="currentContact.userInfo.avatar" class="big-avatar" />
</header> </header>
<div class="profile-body"> <div class="profile-body">
@@ -47,9 +47,10 @@
<script setup> <script setup>
import { defineProps, onMounted, ref } from 'vue'; import { defineProps, onMounted, ref } from 'vue';
import { useContactStore } from '@/stores/contact'; import { useContactStore } from '@/stores/contact';
import { useRouter } from 'vue-router'; import { onBeforeRouteUpdate, useRouter } from 'vue-router';
import { useConversationStore } from '@/stores/conversation'; import { useConversationStore } from '@/stores/conversation';
import WindowControls from '../../components/WindowControls.vue'; import WindowControls from '../../components/WindowControls.vue';
import AsyncImage from '../../components/AsyncImage.vue';
const contactStore = useContactStore(); const contactStore = useContactStore();
const router = useRouter(); const router = useRouter();
@@ -71,9 +72,14 @@ function handleGoToChat() {
router.push(`/messages/chat/${cid}`); router.push(`/messages/chat/${cid}`);
} }
} }
onMounted(() => {
currentContact.value = contactStore.contacts.find(x => x.id == props.id); onBeforeRouteUpdate(() => {
currentContact.value = contactStore.contacts.find(x => x.id == props.id);
}) })
onMounted(() => {
currentContact.value = contactStore.contacts.find(x => x.id == props.id);
})
</script> </script>
@@ -122,7 +128,7 @@ onMounted(() => {
margin: 3px 0; margin: 3px 0;
} }
.big-avatar { :deep(.big-avatar) {
width: 70px; width: 70px;
height: 70px; height: 70px;
border-radius: 6px; border-radius: 6px;