feat(团队收入页): 搜索框设置本地搜索功能
This commit is contained in:
parent
21e6e017e3
commit
c0a85cbb67
@ -24,7 +24,7 @@
|
|||||||
>
|
>
|
||||||
<div style="display: flex; flex-direction: column; gap: 10px">
|
<div style="display: flex; flex-direction: column; gap: 10px">
|
||||||
<div>{{ t('history_team_income') }}</div>
|
<div>{{ t('history_team_income') }}</div>
|
||||||
<div style="font-weight: 600">$000</div>
|
<div style="font-weight: 600">$0</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style="
|
style="
|
||||||
@ -143,11 +143,7 @@
|
|||||||
|
|
||||||
<!-- 账单详情模态框 (使用 TeamBillMore 组件) -->
|
<!-- 账单详情模态框 (使用 TeamBillMore 组件) -->
|
||||||
<div v-if="showDetailModal" style="position: fixed; bottom: 0; width: 100%" @click.stop>
|
<div v-if="showDetailModal" style="position: fixed; bottom: 0; width: 100%" @click.stop>
|
||||||
<TeamBillMore
|
<TeamBillMore :billData="selectedBill" />
|
||||||
:billData="selectedBill"
|
|
||||||
@close="closeModal"
|
|
||||||
@propsReceived="handlePropsReceived"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -156,9 +152,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import GeneralHeader from '@/components/GeneralHeader.vue'
|
|
||||||
import TeamBillMore from '@/components/team/TeamBillMore.vue'
|
|
||||||
import { getUserIdentity } from '@/api/wallet.js'
|
|
||||||
import {
|
import {
|
||||||
getTeamBill,
|
getTeamBill,
|
||||||
getTeamBillWorkMembers,
|
getTeamBillWorkMembers,
|
||||||
@ -167,6 +160,9 @@ import {
|
|||||||
} from '@/api/teamBill.js'
|
} from '@/api/teamBill.js'
|
||||||
import { getTeamId } from '@/utils/userStore.js'
|
import { getTeamId } from '@/utils/userStore.js'
|
||||||
import { setDocumentDirection } from '@/locales/i18n'
|
import { setDocumentDirection } from '@/locales/i18n'
|
||||||
|
|
||||||
|
import GeneralHeader from '@/components/GeneralHeader.vue'
|
||||||
|
import TeamBillMore from './components/TeamBillMore.vue'
|
||||||
import workReportBox from './components/workReportBox.vue'
|
import workReportBox from './components/workReportBox.vue'
|
||||||
|
|
||||||
const { t, locale } = useI18n()
|
const { t, locale } = useI18n()
|
||||||
|
|||||||
@ -33,11 +33,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 搜索框 -->
|
<!-- 搜索栏 -->
|
||||||
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px">
|
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px">
|
||||||
|
<!-- 搜索框 -->
|
||||||
<div
|
<div
|
||||||
style="
|
style="
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
border-radius: 32px;
|
border-radius: 32px;
|
||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
|
|
||||||
@ -49,11 +51,10 @@
|
|||||||
height: max-content;
|
height: max-content;
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<img src="../../assets/icon/search.png" alt="" width="24px" style="opacity: 0.6" />
|
<img src="../../../assets/icon/search.png" alt="" width="24px" style="opacity: 0.6" />
|
||||||
<input
|
<input
|
||||||
|
v-model="searchQuery"
|
||||||
type="text"
|
type="text"
|
||||||
name=""
|
|
||||||
id=""
|
|
||||||
:placeholder="t('enter_host_id')"
|
:placeholder="t('enter_host_id')"
|
||||||
style="
|
style="
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -63,10 +64,15 @@
|
|||||||
color: black;
|
color: black;
|
||||||
padding: 10px 8px;
|
padding: 10px 8px;
|
||||||
"
|
"
|
||||||
v-model="targetUserId"
|
@keyup.enter="performSearch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style="font-weight: 600" @click="$emit('close')">{{ t('cancel') }}</div>
|
|
||||||
|
<!-- 按钮 -->
|
||||||
|
<div v-if="!hasSearched && searchQuery" style="font-weight: 600" @click="performSearch">
|
||||||
|
{{ t('search') }}
|
||||||
|
</div>
|
||||||
|
<div v-else style="font-weight: 600" @click="clearSearch">{{ t('cancel') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 加载成员 -->
|
<!-- 加载成员 -->
|
||||||
@ -76,9 +82,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 成员列表 -->
|
<!-- 成员列表 -->
|
||||||
<div v-if="members && members.length > 0" class="members-list">
|
<div v-if="searchResults && searchResults.length > 0" class="members-list">
|
||||||
<div
|
<div
|
||||||
v-for="(member, index) in members"
|
v-for="(member, index) in searchResults"
|
||||||
:key="member.memberProfile?.id || index"
|
:key="member.memberProfile?.id || index"
|
||||||
style="
|
style="
|
||||||
background-color: white;
|
background-color: white;
|
||||||
@ -88,34 +94,41 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
gap: 4px;
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<!-- 用户信息 -->
|
<!-- 用户信息 -->
|
||||||
<div style="width: 70%; display: flex; align-items: center; justify-content: space-around">
|
<div
|
||||||
|
style="
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
gap: 4px;
|
||||||
|
"
|
||||||
|
>
|
||||||
<!-- 头像 -->
|
<!-- 头像 -->
|
||||||
<div
|
<div style="width: 20%">
|
||||||
style="
|
|
||||||
position: relative;
|
|
||||||
margin-right: 4px;
|
|
||||||
|
|
||||||
width: 20%;
|
|
||||||
aspect-ratio: 1/1;
|
|
||||||
border-radius: 50%;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<img
|
<img
|
||||||
|
v-smart-img
|
||||||
:src="member.memberProfile?.userAvatar || ''"
|
:src="member.memberProfile?.userAvatar || ''"
|
||||||
:alt="member.memberProfile?.userNickname"
|
:alt="member.memberProfile?.userNickname"
|
||||||
@error="defaultAvatarUrl"
|
@error="defaultAvatarUrl"
|
||||||
style="width: 100%; height: 100%; border-radius: 50%; object-fit: cover"
|
style="
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: 1/1;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- 账号信息 -->
|
<!-- 账号信息 -->
|
||||||
<div style="width: 35%; display: flex; flex-direction: column; gap: 4px">
|
<div style="flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px">
|
||||||
<div
|
<div
|
||||||
style="
|
style="
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@ -163,18 +176,24 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 数据区域 -->
|
<!-- 数据区域 -->
|
||||||
<div style="width: 30%; display: flex; justify-content: flex-end">
|
<div style="min-width: 0; display: flex; justify-content: flex-end">
|
||||||
<div style="width: 100%; display: flex; flex-direction: column">
|
<div style="width: 100%; display: flex; flex-direction: column">
|
||||||
<div style="width: 100%; display: flex; align-items: center">
|
<div style="width: 100%; display: flex; align-items: center">
|
||||||
<img src="../../assets/icon/coin.png" alt="" height="16px" style="display: block" />
|
<img
|
||||||
|
src="../../../assets/icon/coin.png"
|
||||||
|
alt=""
|
||||||
|
height="16px"
|
||||||
|
style="display: block"
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
style="
|
style="
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
color: #ffb627;
|
color: #ffb627;
|
||||||
font-weight: 510;
|
font-weight: 510;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
flex: 1;
|
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
@ -183,12 +202,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style="
|
style="
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
color: rgba(0, 0, 0, 0.4);
|
color: rgba(0, 0, 0, 0.4);
|
||||||
font-weight: 510;
|
font-weight: 510;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
width: 100%;
|
|
||||||
font-size: 0.7em;
|
font-size: 0.7em;
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
@ -208,11 +228,12 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, watch } from 'vue'
|
import { ref, computed, onMounted, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
|
||||||
import { useLangStore } from '@/stores/lang'
|
import { useLangStore } from '@/stores/lang'
|
||||||
import { formatBillStatus, getTeamReleasePolicy } from '../../api/teamBill.js'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { getTeamId } from '../../utils/userStore.js'
|
|
||||||
import { setDocumentDirection } from '@/locales/i18n'
|
import { setDocumentDirection } from '@/locales/i18n'
|
||||||
|
import { getTeamId } from '@/utils/userStore.js'
|
||||||
|
|
||||||
|
import { getTeamReleasePolicy } from '@/api/teamBill.js'
|
||||||
|
|
||||||
const { t, locale } = useI18n()
|
const { t, locale } = useI18n()
|
||||||
|
|
||||||
@ -232,7 +253,10 @@ const loading = ref(false)
|
|||||||
const policyData = ref(null)
|
const policyData = ref(null)
|
||||||
const loadingPolicy = ref(false)
|
const loadingPolicy = ref(false)
|
||||||
|
|
||||||
const targetUserId = ref('') //搜索目标id
|
const searchQuery = ref('') //搜索目标id
|
||||||
|
const searchResults = ref([]) //展示结果
|
||||||
|
const isSearching = ref(false)
|
||||||
|
const hasSearched = ref(false)
|
||||||
|
|
||||||
// 样式
|
// 样式
|
||||||
const color = ref('')
|
const color = ref('')
|
||||||
@ -245,6 +269,39 @@ const members = computed(() => {
|
|||||||
return props.billData?.members || []
|
return props.billData?.members || []
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 执行搜索
|
||||||
|
const performSearch = async () => {
|
||||||
|
console.log('searchQuery.value:', searchQuery.value)
|
||||||
|
|
||||||
|
if (!searchQuery.value.trim()) {
|
||||||
|
searchResults.value = members.value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isSearching.value = true
|
||||||
|
hasSearched.value = false
|
||||||
|
|
||||||
|
let ResultUser = members.value.find(
|
||||||
|
(member) => member.memberProfile.account == searchQuery.value.trim()
|
||||||
|
)
|
||||||
|
|
||||||
|
if (ResultUser) {
|
||||||
|
searchResults.value = [ResultUser]
|
||||||
|
} else {
|
||||||
|
searchResults.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
isSearching.value = false
|
||||||
|
hasSearched.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除搜索
|
||||||
|
const clearSearch = () => {
|
||||||
|
hasSearched.value = false
|
||||||
|
searchQuery.value = ''
|
||||||
|
searchResults.value = members.value
|
||||||
|
}
|
||||||
|
|
||||||
// 获取政策数据
|
// 获取政策数据
|
||||||
const fetchPolicyData = async () => {
|
const fetchPolicyData = async () => {
|
||||||
try {
|
try {
|
||||||
@ -283,9 +340,6 @@ const getTargetLevel = (giftValue) => {
|
|||||||
return parseFloat(b.target) - parseFloat(a.target)
|
return parseFloat(b.target) - parseFloat(a.target)
|
||||||
})
|
})
|
||||||
|
|
||||||
// console.log('sortedPolicy', JSON.stringify(sortedPolicy))
|
|
||||||
// console.log('numValue', JSON.stringify(numValue))
|
|
||||||
|
|
||||||
for (const policy of sortedPolicy) {
|
for (const policy of sortedPolicy) {
|
||||||
if (numValue >= parseFloat(policy.target)) {
|
if (numValue >= parseFloat(policy.target)) {
|
||||||
return policy.level
|
return policy.level
|
||||||
@ -309,7 +363,6 @@ const formatTargetDisplay = (giftValue) => {
|
|||||||
|
|
||||||
// 格式化状态文本
|
// 格式化状态文本
|
||||||
const getStatusText = (status) => {
|
const getStatusText = (status) => {
|
||||||
// const statusInfo = formatBillStatus(status)
|
|
||||||
// 使用翻译键而不是直接文本
|
// 使用翻译键而不是直接文本
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 'Completed':
|
case 'Completed':
|
||||||
@ -325,12 +378,6 @@ const getStatusText = (status) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取状态样式类
|
|
||||||
const getStatusClass = (status) => {
|
|
||||||
const statusInfo = formatBillStatus(status)
|
|
||||||
return statusInfo.class
|
|
||||||
}
|
|
||||||
|
|
||||||
// 格式化钻石数值
|
// 格式化钻石数值
|
||||||
const formatDiamondValue = (value) => {
|
const formatDiamondValue = (value) => {
|
||||||
if (!value || value === '0') return '0'
|
if (!value || value === '0') return '0'
|
||||||
@ -346,25 +393,6 @@ const formatDiamondValue = (value) => {
|
|||||||
return numValue.toLocaleString()
|
return numValue.toLocaleString()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算有效天数
|
|
||||||
const calculateEffectiveDays = (onlineTime) => {
|
|
||||||
if (!onlineTime) return '14'
|
|
||||||
|
|
||||||
// 如果在线时间大于60分钟,则计为1天
|
|
||||||
const minutes = parseInt(onlineTime)
|
|
||||||
if (isNaN(minutes)) return '14'
|
|
||||||
|
|
||||||
// 简单计算:每60分钟算作1天
|
|
||||||
const days = Math.floor(minutes / 60)
|
|
||||||
return days > 0 ? days.toString() : '14'
|
|
||||||
}
|
|
||||||
|
|
||||||
// 头像占位符
|
|
||||||
const getAvatarPlaceholder = (nickname) => {
|
|
||||||
if (!nickname) return 'U'
|
|
||||||
return nickname.charAt(0).toUpperCase()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理图片加载错误
|
// 处理图片加载错误
|
||||||
const defaultAvatarUrl = (e) => {
|
const defaultAvatarUrl = (e) => {
|
||||||
console.log('头像资源出错')
|
console.log('头像资源出错')
|
||||||
@ -397,12 +425,22 @@ watch(
|
|||||||
{ deep: true }
|
{ deep: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => searchQuery.value,
|
||||||
|
(newQuery) => {
|
||||||
|
if (hasSearched.value) {
|
||||||
|
hasSearched.value = false
|
||||||
|
}
|
||||||
|
if (!newQuery.trim()) {
|
||||||
|
searchResults.value = members.value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.billData?.status,
|
() => props.billData?.status,
|
||||||
(newType) => {
|
(newType) => {
|
||||||
console.log('newType:', newType)
|
|
||||||
|
|
||||||
// let newStatus = getStatusText(status)
|
|
||||||
updateTypeShowText()
|
updateTypeShowText()
|
||||||
if (newType == 'In Progress') {
|
if (newType == 'In Progress') {
|
||||||
boxShadow.value = '0 0 1px 0 #6085FF'
|
boxShadow.value = '0 0 1px 0 #6085FF'
|
||||||
Loading…
x
Reference in New Issue
Block a user