预发布版本
This commit is contained in:
parent
11c24e9d0c
commit
8a546e1b18
@ -22,7 +22,7 @@ export const getTeamMembers = async (teamId) => {
|
|||||||
*/
|
*/
|
||||||
export const deleteMember = async (memberId) => {
|
export const deleteMember = async (memberId) => {
|
||||||
try {
|
try {
|
||||||
const response = await post('/team/member/remove', {
|
const response = await post('/team-member/client/removeMemberTeam', {
|
||||||
memberId: memberId
|
memberId: memberId
|
||||||
})
|
})
|
||||||
return response
|
return response
|
||||||
|
|||||||
@ -55,10 +55,64 @@ export function userBankSearchUserProfile(type, account) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户身份信息
|
* 获取用户身份信息
|
||||||
|
* @param {string} userId - 用户ID
|
||||||
* @returns {Promise} 返回用户身份权限信息
|
* @returns {Promise} 返回用户身份权限信息
|
||||||
*/
|
*/
|
||||||
export function getUserIdentity() {
|
export function getUserIdentity(userId) {
|
||||||
return get('/app/h5/1911661502909562881/identity')
|
return get(`/app/h5/${userId}/identity`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取团队入口信息
|
||||||
|
* @returns {Promise} 返回团队和用户信息
|
||||||
|
*/
|
||||||
|
export function getTeamEntry() {
|
||||||
|
return get('/team/entry')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验金币销售商权限
|
||||||
|
* @returns {Promise} 返回是否具有销售商权限
|
||||||
|
*/
|
||||||
|
export function checkFreightDealer() {
|
||||||
|
return get('/wallet/freight/seller/check/dealer')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取金币销售商余额
|
||||||
|
* @returns {Promise} 返回销售商金币余额
|
||||||
|
*/
|
||||||
|
export function getFreightBalance() {
|
||||||
|
return get('/wallet/freight/balance')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索用户
|
||||||
|
* @param {string} account - 用户账号
|
||||||
|
* @returns {Promise} 返回用户信息
|
||||||
|
*/
|
||||||
|
export function searchFreightUser(account) {
|
||||||
|
return get(`/wallet/freight/search-user?account=${account}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 金币充值
|
||||||
|
* @param {Object} data - 充值数据
|
||||||
|
* @param {number} data.acceptUserId - 接收用户ID
|
||||||
|
* @param {number} data.quantity - 充值数量
|
||||||
|
* @returns {Promise} 返回剩余可用余额
|
||||||
|
*/
|
||||||
|
export function freightRecharge(data) {
|
||||||
|
return post('/wallet/freight/ship', data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取金币交易流水
|
||||||
|
* @param {string} userId - 用户ID
|
||||||
|
* @returns {Promise} 返回交易流水记录
|
||||||
|
*/
|
||||||
|
export function getFreightWaterFlow(userId) {
|
||||||
|
return get(`/wallet/freight/balance/running/water/client/flowByUserId?userId=${userId}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -35,7 +35,7 @@ export function connectApplication(renderFun) {
|
|||||||
window.renderData = renderFun
|
window.renderData = renderFun
|
||||||
// 兼容历史版本
|
// 兼容历史版本
|
||||||
window.getIosAccessOriginParam = renderFun
|
window.getIosAccessOriginParam = renderFun
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (ios()) {
|
if (ios()) {
|
||||||
// iOS可能需要特殊处理,这里先使用通用方法
|
// iOS可能需要特殊处理,这里先使用通用方法
|
||||||
@ -55,10 +55,10 @@ export function connectApplication(renderFun) {
|
|||||||
// 开发环境可以提供模拟数据
|
// 开发环境可以提供模拟数据
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
const mockAccess = JSON.stringify({
|
const mockAccess = JSON.stringify({
|
||||||
'Authorization': 'Bearer mock-token-for-development',
|
'Authorization': 'Bearer F77126B08E13987C3AD88B6015C5B777.djIlM0ExOTU0MDU5NzkzOTYzMzkzMDI1JTNBTElLRUklM0ExNzU3NzYzODU5NzE1JTNBMTc1NTE3MTg1OTcxNQ==',
|
||||||
'Req-Lang': 'en',
|
'Req-Lang': 'en',
|
||||||
'Req-App-Intel': 'build=1.0;version=2.1;channel=official;Req-Imei=mock-imei',
|
'Req-App-Intel': 'build=1.0;version=2.1;channel=official;Req-Imei=mock-imei',
|
||||||
'Req-Sys-Origin': 'origin=web;child=browser'
|
'Req-Sys-Origin': 'origin=LIKEI;originChild=LIKEI'
|
||||||
})
|
})
|
||||||
setTimeout(() => renderFun(mockAccess), 100)
|
setTimeout(() => renderFun(mockAccess), 100)
|
||||||
}
|
}
|
||||||
@ -102,13 +102,13 @@ export function parseHeader(head) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析键值对字符串 (如: "key1=value1;key2=value2")
|
* 解析键值对字符串 (如: "key1=value1;key2=value2")
|
||||||
* @param {string} values
|
* @param {string} values
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
function getKeyValObj(values) {
|
function getKeyValObj(values) {
|
||||||
const keyValBody = {}
|
const keyValBody = {}
|
||||||
if (!values) return keyValBody
|
if (!values) return keyValBody
|
||||||
|
|
||||||
const valueArray = values.split(';')
|
const valueArray = values.split(';')
|
||||||
for (let index = 0; index < valueArray.length; index++) {
|
for (let index = 0; index < valueArray.length; index++) {
|
||||||
const keyVal = valueArray[index]
|
const keyVal = valueArray[index]
|
||||||
@ -150,7 +150,7 @@ export function setHttpHeaders(headerInfo) {
|
|||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error('Failed to update HTTP headers:', error)
|
console.error('Failed to update HTTP headers:', error)
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('🔑 Authorization token set:', headerInfo.authorization)
|
console.log('🔑 Authorization token set:', headerInfo.authorization)
|
||||||
console.log('🌍 Language set:', headerInfo.reqLang)
|
console.log('🌍 Language set:', headerInfo.reqLang)
|
||||||
console.log('📱 App info:', {
|
console.log('📱 App info:', {
|
||||||
|
|||||||
@ -21,7 +21,6 @@
|
|||||||
<!-- 账户状态标签 -->
|
<!-- 账户状态标签 -->
|
||||||
<div class="account-tags">
|
<div class="account-tags">
|
||||||
<span class="tag agency-tag">🏢 Agency</span>
|
<span class="tag agency-tag">🏢 Agency</span>
|
||||||
<span class="tag salary-tag">💰 Salary</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -636,9 +635,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
.team-bill-card .card-content {
|
.team-bill-card .card-content {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
display: flex;
|
position: relative;
|
||||||
flex-direction: column;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 通用卡片内容样式 */
|
/* 通用卡片内容样式 */
|
||||||
@ -650,20 +647,37 @@ onMounted(() => {
|
|||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #1F2937;
|
color: #1F2937;
|
||||||
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-link {
|
.card-link {
|
||||||
|
position: absolute;
|
||||||
|
top: 16px;
|
||||||
|
right: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: #6B7280;
|
gap: 4px;
|
||||||
|
color: #8B5CF6;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-link:hover {
|
||||||
|
color: #7C3AED;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-link .arrow {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-details {
|
.card-details {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-row {
|
.detail-row {
|
||||||
|
|||||||
@ -40,7 +40,14 @@
|
|||||||
>
|
>
|
||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<div class="user-avatar">
|
<div class="user-avatar">
|
||||||
<span>{{ user.name.charAt(0) }}</span>
|
<img
|
||||||
|
v-if="user.userAvatar"
|
||||||
|
:src="user.userAvatar"
|
||||||
|
:alt="user.name"
|
||||||
|
class="avatar-image"
|
||||||
|
@error="(e) => e.target.style.display = 'none'"
|
||||||
|
/>
|
||||||
|
<span v-if="!user.userAvatar" class="avatar-text">{{ user.name.charAt(0) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-details">
|
<div class="user-details">
|
||||||
<h4>{{ user.name }}</h4>
|
<h4>{{ user.name }}</h4>
|
||||||
@ -81,6 +88,7 @@ import { ref } from 'vue'
|
|||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import MobileHeader from '../components/MobileHeader.vue'
|
import MobileHeader from '../components/MobileHeader.vue'
|
||||||
import { setSelectedUser } from '../utils/coinSellerStore.js'
|
import { setSelectedUser } from '../utils/coinSellerStore.js'
|
||||||
|
import { searchFreightUser } from '../api/wallet.js'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const searchQuery = ref('')
|
const searchQuery = ref('')
|
||||||
@ -104,7 +112,7 @@ const mockUsers = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
// 执行搜索
|
// 执行搜索
|
||||||
const performSearch = () => {
|
const performSearch = async () => {
|
||||||
if (!searchQuery.value.trim()) {
|
if (!searchQuery.value.trim()) {
|
||||||
searchResults.value = []
|
searchResults.value = []
|
||||||
return
|
return
|
||||||
@ -112,15 +120,28 @@ const performSearch = () => {
|
|||||||
|
|
||||||
isSearching.value = true
|
isSearching.value = true
|
||||||
|
|
||||||
// 模拟搜索延迟
|
try {
|
||||||
setTimeout(() => {
|
const response = await searchFreightUser(searchQuery.value.trim())
|
||||||
const query = searchQuery.value.toLowerCase()
|
|
||||||
searchResults.value = mockUsers.filter(user =>
|
if (response && response.status && response.body && response.body.userProfile) {
|
||||||
user.name.toLowerCase().includes(query) ||
|
const profile = response.body.userProfile
|
||||||
user.id.includes(query)
|
searchResults.value = [{
|
||||||
)
|
id: profile.account || profile.id,
|
||||||
|
userId: profile.id, // 保存数值型ID用于接口调用
|
||||||
|
name: profile.userNickname || 'User',
|
||||||
|
userNickname: profile.userNickname,
|
||||||
|
account: profile.account,
|
||||||
|
userAvatar: profile.userAvatar
|
||||||
|
}]
|
||||||
|
} else {
|
||||||
|
searchResults.value = []
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('搜索用户失败:', error)
|
||||||
|
searchResults.value = []
|
||||||
|
} finally {
|
||||||
isSearching.value = false
|
isSearching.value = false
|
||||||
}, 500)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清除搜索
|
// 清除搜索
|
||||||
@ -148,7 +169,11 @@ const selectUser = (user) => {
|
|||||||
// 将选中的用户信息保存到全局状态
|
// 将选中的用户信息保存到全局状态
|
||||||
setSelectedUser({
|
setSelectedUser({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
name: user.name
|
userId: user.userId, // 数值型ID
|
||||||
|
name: user.name,
|
||||||
|
userNickname: user.userNickname,
|
||||||
|
account: user.account,
|
||||||
|
userAvatar: user.userAvatar
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('Selected user:', user)
|
console.log('Selected user:', user)
|
||||||
@ -267,6 +292,21 @@ const selectUser = (user) => {
|
|||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-text {
|
||||||
|
color: white;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-details h4 {
|
.user-details h4 {
|
||||||
|
|||||||
@ -2,25 +2,39 @@
|
|||||||
<div class="coin-seller gradient-background-circles">
|
<div class="coin-seller gradient-background-circles">
|
||||||
<MobileHeader title="Coin Seller" />
|
<MobileHeader title="Coin Seller" />
|
||||||
|
|
||||||
<div class="content">
|
<!-- 权限校验加载状态 -->
|
||||||
|
<div v-if="checkingAccess" class="loading-container">
|
||||||
|
<div class="loading-spinner"></div>
|
||||||
|
<p>正在校验权限...</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 主要内容 -->
|
||||||
|
<div v-else-if="dealerAccess" class="content">
|
||||||
<!-- 用户信息卡片 -->
|
<!-- 用户信息卡片 -->
|
||||||
<div class="user-card">
|
<div class="user-card">
|
||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
<span>{{ userInfo.name.charAt(0) }}</span>
|
<img
|
||||||
|
v-if="userInfo.userAvatar"
|
||||||
|
:src="userInfo.userAvatar"
|
||||||
|
:alt="userInfo.userNickname || userInfo.name"
|
||||||
|
class="avatar-image"
|
||||||
|
@error="handleAvatarError"
|
||||||
|
/>
|
||||||
|
<span v-else class="avatar-text">{{ (userInfo.userNickname || userInfo.name).charAt(0) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-details">
|
<div class="user-details">
|
||||||
<h3>{{ userInfo.name }}</h3>
|
<h3>{{ userInfo.userNickname || userInfo.name }}</h3>
|
||||||
<p>ID: {{ userInfo.id }}</p>
|
<p>ID: {{ userInfo.account || userInfo.id }}</p>
|
||||||
</div>
|
</div>
|
||||||
<button class="settings-btn" @click="goToSettings">
|
<button class="settings-btn" @click="goToSettings">
|
||||||
<span>⚙️</span>
|
<span>📈</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 账户状态标签 -->
|
<!-- 账户状态标签 -->
|
||||||
<div class="account-tags">
|
<div class="account-tags">
|
||||||
<span class="tag seller-tag">🪙 Seller</span>
|
<span class="tag seller-tag">🪙 Salary</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -29,7 +43,8 @@
|
|||||||
<h3>My coins:</h3>
|
<h3>My coins:</h3>
|
||||||
<div class="coins-display">
|
<div class="coins-display">
|
||||||
<span class="coin-icon">🪙</span>
|
<span class="coin-icon">🪙</span>
|
||||||
<span class="coins-amount">{{ coinsAmount }}</span>
|
<span v-if="loadingBalance" class="coins-loading">Loading...</span>
|
||||||
|
<span v-else class="coins-amount">{{ coinsAmount }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -67,10 +82,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
class="recharge-btn"
|
class="recharge-btn"
|
||||||
:disabled="!canRecharge"
|
:disabled="!canRecharge || isRecharging"
|
||||||
@click="rechargeNow"
|
@click="rechargeNow"
|
||||||
>
|
>
|
||||||
Recharge now
|
{{ isRecharging ? 'Processing...' : 'Recharge now' }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -82,17 +97,26 @@ import { ref, computed, onMounted } from 'vue'
|
|||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import MobileHeader from '../components/MobileHeader.vue'
|
import MobileHeader from '../components/MobileHeader.vue'
|
||||||
import { getSelectedUser, clearSelectedUser } from '../utils/coinSellerStore.js'
|
import { getSelectedUser, clearSelectedUser } from '../utils/coinSellerStore.js'
|
||||||
|
import { checkFreightDealer, getTeamEntry, getFreightBalance, searchFreightUser, freightRecharge } from '../api/wallet.js'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
// 用户信息
|
// 用户信息
|
||||||
const userInfo = ref({
|
const userInfo = ref({
|
||||||
name: 'User1',
|
name: 'User1',
|
||||||
id: '1234567890'
|
id: '1234567890',
|
||||||
|
userNickname: 'User1',
|
||||||
|
account: '1234567890',
|
||||||
|
userAvatar: null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 权限校验状态
|
||||||
|
const dealerAccess = ref(false)
|
||||||
|
const checkingAccess = ref(true)
|
||||||
|
|
||||||
// 金币数量
|
// 金币数量
|
||||||
const coinsAmount = ref('123456478')
|
const coinsAmount = ref('0')
|
||||||
|
const loadingBalance = ref(false)
|
||||||
|
|
||||||
// 选中的用户
|
// 选中的用户
|
||||||
const selectedUser = ref({
|
const selectedUser = ref({
|
||||||
@ -100,6 +124,73 @@ const selectedUser = ref({
|
|||||||
name: ''
|
name: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 校验销售商权限
|
||||||
|
const checkDealerAccess = async () => {
|
||||||
|
try {
|
||||||
|
checkingAccess.value = true
|
||||||
|
const response = await checkFreightDealer()
|
||||||
|
|
||||||
|
if (response && response.status !== undefined) {
|
||||||
|
dealerAccess.value = response.body === true
|
||||||
|
|
||||||
|
if (!dealerAccess.value) {
|
||||||
|
// 没有权限,跳转回上一页或首页
|
||||||
|
alert('您没有金币销售商权限')
|
||||||
|
router.go(-1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('权限校验失败:', error)
|
||||||
|
dealerAccess.value = false
|
||||||
|
router.go(-1)
|
||||||
|
} finally {
|
||||||
|
checkingAccess.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户信息
|
||||||
|
const fetchUserInfo = async () => {
|
||||||
|
try {
|
||||||
|
const response = await getTeamEntry()
|
||||||
|
|
||||||
|
if (response && response.status && response.body && response.body.memberProfile) {
|
||||||
|
const profile = response.body.memberProfile
|
||||||
|
userInfo.value = {
|
||||||
|
name: profile.userNickname || 'User',
|
||||||
|
id: profile.account || profile.id,
|
||||||
|
userNickname: profile.userNickname,
|
||||||
|
account: profile.account,
|
||||||
|
userAvatar: profile.userAvatar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取用户信息失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取金币余额
|
||||||
|
const fetchFreightBalance = async () => {
|
||||||
|
try {
|
||||||
|
loadingBalance.value = true
|
||||||
|
const response = await getFreightBalance()
|
||||||
|
|
||||||
|
if (response && response.status && response.body !== undefined) {
|
||||||
|
coinsAmount.value = response.body.toString()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取金币余额失败:', error)
|
||||||
|
} finally {
|
||||||
|
loadingBalance.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理头像加载错误
|
||||||
|
const handleAvatarError = () => {
|
||||||
|
console.log('头像加载失败,使用默认显示')
|
||||||
|
userInfo.value.userAvatar = null
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化用户信息
|
// 初始化用户信息
|
||||||
const initializeUser = () => {
|
const initializeUser = () => {
|
||||||
const savedUser = getSelectedUser()
|
const savedUser = getSelectedUser()
|
||||||
@ -110,10 +201,11 @@ const initializeUser = () => {
|
|||||||
|
|
||||||
// 充值金额
|
// 充值金额
|
||||||
const rechargeAmount = ref('')
|
const rechargeAmount = ref('')
|
||||||
|
const isRecharging = ref(false)
|
||||||
|
|
||||||
// 是否可以充值
|
// 是否可以充值
|
||||||
const canRecharge = computed(() => {
|
const canRecharge = computed(() => {
|
||||||
return selectedUser.value.id && rechargeAmount.value && parseFloat(rechargeAmount.value) > 0
|
return selectedUser.value.id && rechargeAmount.value && parseFloat(rechargeAmount.value) > 0 && !isRecharging.value
|
||||||
})
|
})
|
||||||
|
|
||||||
// 跳转到设置
|
// 跳转到设置
|
||||||
@ -127,19 +219,64 @@ const searchUser = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 立即充值
|
// 立即充值
|
||||||
const rechargeNow = () => {
|
const rechargeNow = async () => {
|
||||||
if (!canRecharge.value) return
|
if (!canRecharge.value || isRecharging.value) return
|
||||||
|
|
||||||
alert(`Recharge ${rechargeAmount.value} coins to ${selectedUser.value.name}`)
|
const amount = parseFloat(rechargeAmount.value)
|
||||||
|
if (amount <= 0) {
|
||||||
|
alert('请输入正确的充值金额')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 重置表单
|
// 需要获取接收用户的ID(从用户搜索结果中获取)
|
||||||
rechargeAmount.value = ''
|
const acceptUserId = selectedUser.value.userId || selectedUser.value.id
|
||||||
// 可以选择是否清除用户选择
|
if (!acceptUserId) {
|
||||||
|
alert('无法获取用户ID,请重新选择用户')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
isRecharging.value = true
|
||||||
|
|
||||||
|
const rechargeData = {
|
||||||
|
acceptUserId: parseInt(acceptUserId),
|
||||||
|
quantity: amount
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await freightRecharge(rechargeData)
|
||||||
|
|
||||||
|
if (response && response.status) {
|
||||||
|
// 充值成功,更新余额
|
||||||
|
if (response.body !== undefined) {
|
||||||
|
coinsAmount.value = response.body.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
alert(`成功向 ${selectedUser.value.name} 充值 ${amount} 金币`)
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
rechargeAmount.value = ''
|
||||||
|
} else {
|
||||||
|
alert('充值失败,请重试')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('充值失败:', error)
|
||||||
|
alert('充值失败,请检查网络后重试')
|
||||||
|
} finally {
|
||||||
|
isRecharging.value = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 页面加载时初始化用户信息
|
// 页面加载时校验权限和初始化用户信息
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
initializeUser()
|
// 先校验权限
|
||||||
|
await checkDealerAccess()
|
||||||
|
|
||||||
|
// 权限校验通过后获取用户信息和金币余额
|
||||||
|
if (dealerAccess.value) {
|
||||||
|
await fetchUserInfo()
|
||||||
|
await fetchFreightBalance()
|
||||||
|
initializeUser()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -148,6 +285,30 @@ onMounted(() => {
|
|||||||
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 加载状态 */
|
||||||
|
.loading-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 40px 20px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-spinner {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border: 3px solid #f3f3f3;
|
||||||
|
border-top: 3px solid #F59E0B;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -181,6 +342,21 @@ onMounted(() => {
|
|||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-text {
|
||||||
|
color: white;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-details {
|
.user-details {
|
||||||
@ -258,6 +434,12 @@ onMounted(() => {
|
|||||||
color: #F59E0B;
|
color: #F59E0B;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.coins-loading {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #9ca3af;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
/* 用户搜索部分 */
|
/* 用户搜索部分 */
|
||||||
.user-section {
|
.user-section {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
|||||||
@ -19,11 +19,11 @@
|
|||||||
|
|
||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
<span>{{ userInfo.name.charAt(0) }}</span>
|
<span>{{ (userInfo.userNickname || userInfo.name).charAt(0) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-details">
|
<div class="user-details">
|
||||||
<h3>{{ userInfo.name }}</h3>
|
<h3>{{ userInfo.userNickname || userInfo.name }}</h3>
|
||||||
<p>ID: {{ userInfo.id }}</p>
|
<p>ID: {{ userInfo.account || userInfo.id }}</p>
|
||||||
<!-- 显示系统信息 -->
|
<!-- 显示系统信息 -->
|
||||||
<p v-if="headerInfo.sysOrigin" class="system-info">
|
<p v-if="headerInfo.sysOrigin" class="system-info">
|
||||||
{{ headerInfo.sysOrigin }}
|
{{ headerInfo.sysOrigin }}
|
||||||
@ -132,7 +132,7 @@
|
|||||||
import { ref, reactive, onMounted } from 'vue'
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import MobileHeader from '../components/MobileHeader.vue'
|
import MobileHeader from '../components/MobileHeader.vue'
|
||||||
import { getBankBalance, getUserIdentity } from '../api/wallet.js'
|
import { getBankBalance, getUserIdentity, getTeamEntry } from '../api/wallet.js'
|
||||||
import { connectApplication, parseAccessOrigin, parseHeader, setHttpHeaders, isInApp } from '../utils/appBridge.js'
|
import { connectApplication, parseAccessOrigin, parseHeader, setHttpHeaders, isInApp } from '../utils/appBridge.js'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@ -142,6 +142,8 @@ const currentIdentity = ref('host')
|
|||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const appConnected = ref(false)
|
const appConnected = ref(false)
|
||||||
const headerInfo = ref({})
|
const headerInfo = ref({})
|
||||||
|
const userProfile = ref(null)
|
||||||
|
const identityChecked = ref(false)
|
||||||
|
|
||||||
// 身份选项(保留显示用,但不再用于切换)
|
// 身份选项(保留显示用,但不再用于切换)
|
||||||
const identities = [
|
const identities = [
|
||||||
@ -151,16 +153,16 @@ const identities = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
// 连接APP并获取认证信息
|
// 连接APP并获取认证信息
|
||||||
const connectToApp = () => {
|
const connectToApp = async () => {
|
||||||
if (!isInApp()) {
|
if (!isInApp()) {
|
||||||
console.warn('Not running in APP environment')
|
console.warn('Not running in APP environment')
|
||||||
// 非APP环境,直接执行后续逻辑
|
// 非APP环境,直接执行后续逻辑
|
||||||
appConnected.value = true
|
appConnected.value = true
|
||||||
checkUserIdentity()
|
await fetchTeamEntry()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
connectApplication(access => {
|
connectApplication(async (access) => {
|
||||||
console.log('Received access from APP:', access)
|
console.log('Received access from APP:', access)
|
||||||
|
|
||||||
const result = parseAccessOrigin(access)
|
const result = parseAccessOrigin(access)
|
||||||
@ -176,8 +178,8 @@ const connectToApp = () => {
|
|||||||
|
|
||||||
console.log('APP connection established:', headerInfo.value)
|
console.log('APP connection established:', headerInfo.value)
|
||||||
|
|
||||||
// 连接成功后获取用户身份和银行余额
|
// 连接成功后获取团队信息和银行余额
|
||||||
checkUserIdentity()
|
await fetchTeamEntry()
|
||||||
fetchBankBalance()
|
fetchBankBalance()
|
||||||
} else {
|
} else {
|
||||||
console.error('Failed to parse access origin:', result.error)
|
console.error('Failed to parse access origin:', result.error)
|
||||||
@ -213,7 +215,9 @@ const fetchBankBalance = async () => {
|
|||||||
// 用户信息
|
// 用户信息
|
||||||
const userInfo = reactive({
|
const userInfo = reactive({
|
||||||
name: 'User1',
|
name: 'User1',
|
||||||
id: '1234567890'
|
id: '1234567890',
|
||||||
|
userNickname: 'User1',
|
||||||
|
account: '1234567890'
|
||||||
})
|
})
|
||||||
|
|
||||||
// 收入信息
|
// 收入信息
|
||||||
@ -250,24 +254,70 @@ const goToNotification = () => {
|
|||||||
router.push('/host-setting')
|
router.push('/host-setting')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取用户身份并自动跳转
|
// 获取团队入口信息
|
||||||
const checkUserIdentity = async () => {
|
const fetchTeamEntry = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await getUserIdentity()
|
const response = await getTeamEntry()
|
||||||
|
|
||||||
|
if (response && response.status && response.body) {
|
||||||
|
userProfile.value = response.body
|
||||||
|
|
||||||
|
// 更新用户信息显示
|
||||||
|
if (response.body.memberProfile) {
|
||||||
|
userInfo.userNickname = response.body.memberProfile.userNickname
|
||||||
|
userInfo.account = response.body.memberProfile.account
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户ID后检查身份
|
||||||
|
const userId = response.body.memberProfile?.id
|
||||||
|
if (userId) {
|
||||||
|
await checkUserIdentity(userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
return userId
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取团队信息失败:', error)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户身份并自动跳转
|
||||||
|
const checkUserIdentity = async (userId) => {
|
||||||
|
if (!userId) {
|
||||||
|
console.error('用户ID不存在')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 防止重复检查
|
||||||
|
if (identityChecked.value) {
|
||||||
|
console.log('身份已检查,跳过')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
identityChecked.value = true
|
||||||
|
const response = await getUserIdentity(userId)
|
||||||
|
|
||||||
if (response && response.status && response.body) {
|
if (response && response.status && response.body) {
|
||||||
const { freightAgent, anchor, agent } = response.body
|
const { freightAgent, anchor, agent } = response.body
|
||||||
|
|
||||||
|
console.log('用户身份权限:', { freightAgent, anchor, agent })
|
||||||
|
|
||||||
// 根据优先级判断:freightAgent > anchor > agent
|
// 根据优先级判断:freightAgent > anchor > agent
|
||||||
if (freightAgent) {
|
if (freightAgent) {
|
||||||
router.push('/coin-seller')
|
console.log('跳转到 coin-seller')
|
||||||
|
router.replace('/coin-seller')
|
||||||
} else if (anchor) {
|
} else if (anchor) {
|
||||||
router.push('/agency-center')
|
console.log('跳转到 agency-center')
|
||||||
|
router.replace('/agency-center')
|
||||||
} else if (agent) {
|
} else if (agent) {
|
||||||
// 保持在当前Host页面
|
// 保持在当前Host页面
|
||||||
|
console.log('保持在 host-center')
|
||||||
currentIdentity.value = 'host'
|
currentIdentity.value = 'host'
|
||||||
} else {
|
} else {
|
||||||
// 如果没有任何权限,默认保持在Host页面
|
// 如果没有任何权限,默认保持在Host页面
|
||||||
|
console.log('无特殊权限,保持在 host-center')
|
||||||
currentIdentity.value = 'host'
|
currentIdentity.value = 'host'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -288,9 +338,9 @@ const transfer = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 页面加载时先连接APP,然后获取数据
|
// 页面加载时先连接APP,然后获取数据
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
// 先连接APP获取认证信息
|
// 先连接APP获取认证信息
|
||||||
connectToApp()
|
await connectToApp()
|
||||||
|
|
||||||
// 如果不是APP环境,直接获取银行余额
|
// 如果不是APP环境,直接获取银行余额
|
||||||
if (!isInApp()) {
|
if (!isInApp()) {
|
||||||
|
|||||||
@ -25,7 +25,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="record-amount">
|
<div class="record-amount">
|
||||||
<span class="coins-amount">{{ record.amount }} coins</span>
|
<span :class="['coins-amount', record.type === 0 ? 'positive' : 'negative']">{{ record.amount }} coins</span>
|
||||||
|
<span class="transaction-type">{{ getTransactionType(record.type, record.origin) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -43,10 +44,12 @@
|
|||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import MobileHeader from '../components/MobileHeader.vue'
|
import MobileHeader from '../components/MobileHeader.vue'
|
||||||
|
import { getFreightWaterFlow, getTeamEntry } from '../api/wallet.js'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const records = ref([])
|
const records = ref([])
|
||||||
|
const currentUserId = ref(null)
|
||||||
|
|
||||||
// 模拟记录数据
|
// 模拟记录数据
|
||||||
const mockRecords = [
|
const mockRecords = [
|
||||||
@ -73,24 +76,93 @@ const mockRecords = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
// 获取当前用户ID
|
||||||
|
const fetchCurrentUserId = async () => {
|
||||||
|
try {
|
||||||
|
const response = await getTeamEntry()
|
||||||
|
if (response && response.status && response.body && response.body.memberProfile) {
|
||||||
|
currentUserId.value = response.body.memberProfile.id
|
||||||
|
return response.body.memberProfile.id
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取用户ID失败:', error)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化时间
|
||||||
|
const formatTime = (timestamp) => {
|
||||||
|
const date = new Date(timestamp)
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(date.getDate()).padStart(2, '0')
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0')
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||||
|
|
||||||
|
return `${year}.${month}.${day} ${hours}:${minutes}:${seconds}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取交易类型显示
|
||||||
|
const getTransactionType = (type, origin) => {
|
||||||
|
if (type === 0) {
|
||||||
|
return '进货' // 入账
|
||||||
|
} else if (type === 1) {
|
||||||
|
return '出货' // 出账
|
||||||
|
}
|
||||||
|
return origin || '未知'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取金额显示
|
||||||
|
const getAmountDisplay = (type, quantity) => {
|
||||||
|
const prefix = type === 0 ? '+' : '-'
|
||||||
|
return `${prefix}${quantity}`
|
||||||
|
}
|
||||||
|
|
||||||
// 获取记录
|
// 获取记录
|
||||||
const fetchRecords = async () => {
|
const fetchRecords = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 模拟API调用
|
// 先获取用户ID
|
||||||
setTimeout(() => {
|
const userId = currentUserId.value || await fetchCurrentUserId()
|
||||||
records.value = mockRecords
|
|
||||||
loading.value = false
|
if (!userId) {
|
||||||
}, 800)
|
console.error('无法获取用户ID')
|
||||||
|
records.value = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await getFreightWaterFlow(userId)
|
||||||
|
|
||||||
|
if (response && response.status && response.body) {
|
||||||
|
// 处理返回的数据
|
||||||
|
records.value = response.body.map(item => ({
|
||||||
|
id: item.id,
|
||||||
|
userId: item.acceptUserId,
|
||||||
|
userName: `User${item.acceptUserId.toString().slice(-6)}...`, // 显示最后6位
|
||||||
|
amount: getAmountDisplay(item.type, item.quantity),
|
||||||
|
time: formatTime(item.createTime),
|
||||||
|
type: item.type,
|
||||||
|
quantity: item.quantity,
|
||||||
|
balance: item.balance,
|
||||||
|
origin: item.origin,
|
||||||
|
remark: item.remark,
|
||||||
|
rechargeType: item.rechargeType
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
records.value = []
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to fetch records:', error)
|
console.error('获取记录失败:', error)
|
||||||
|
records.value = []
|
||||||
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
fetchRecords()
|
await fetchRecords()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -203,7 +275,20 @@ onMounted(() => {
|
|||||||
.coins-amount {
|
.coins-amount {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #EF4444;
|
}
|
||||||
|
|
||||||
|
.coins-amount.positive {
|
||||||
|
color: #10B981; /* 绿色表示进货/入账 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.coins-amount.negative {
|
||||||
|
color: #EF4444; /* 红色表示出货/出账 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-type {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #9ca3af;
|
||||||
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 空状态 */
|
/* 空状态 */
|
||||||
|
|||||||
@ -4,19 +4,6 @@
|
|||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<!-- 成员资料信息 -->
|
<!-- 成员资料信息 -->
|
||||||
<div v-if="memberProfile" class="member-profile-card">
|
|
||||||
<div class="member-info">
|
|
||||||
<div class="avatar-wrapper">
|
|
||||||
<img :src="memberProfile.userAvatar" class="member-avatar" alt="Avatar" />
|
|
||||||
<span class="country-flag">{{ memberProfile.countryCode }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="member-details">
|
|
||||||
<div class="member-name">{{ memberProfile.userNickname }}</div>
|
|
||||||
<div class="member-id">ID: {{ memberProfile.account }}</div>
|
|
||||||
<div class="member-status">{{ memberProfile.accountStatusName }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 工作报告标题 -->
|
<!-- 工作报告标题 -->
|
||||||
<div class="work-report-title">
|
<div class="work-report-title">
|
||||||
@ -32,8 +19,8 @@
|
|||||||
|
|
||||||
<!-- 账单列表 -->
|
<!-- 账单列表 -->
|
||||||
<div v-else-if="billList.length > 0" class="bill-list">
|
<div v-else-if="billList.length > 0" class="bill-list">
|
||||||
<div
|
<div
|
||||||
v-for="bill in billList"
|
v-for="bill in billList"
|
||||||
:key="bill.id"
|
:key="bill.id"
|
||||||
class="bill-item"
|
class="bill-item"
|
||||||
@click="showBillDetail(bill)"
|
@click="showBillDetail(bill)"
|
||||||
@ -44,13 +31,13 @@
|
|||||||
{{ getStatusText(bill.status) }}
|
{{ getStatusText(bill.status) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bill-details">
|
<div class="bill-details">
|
||||||
<div class="bill-row">
|
<div class="bill-row">
|
||||||
<span class="bill-label">Host Salary:</span>
|
<span class="bill-label">Host Salary:</span>
|
||||||
<span class="bill-value">${{ formatSalaryValue(bill.target?.ownSalary) }}</span>
|
<span class="bill-value">${{ formatSalaryValue(bill.target?.ownSalary) }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bill-row">
|
<div class="bill-row">
|
||||||
<span class="bill-label">Agent Salary:</span>
|
<span class="bill-label">Agent Salary:</span>
|
||||||
<span class="bill-value">${{ formatSalaryValue(bill.target?.memberSalary) }}</span>
|
<span class="bill-value">${{ formatSalaryValue(bill.target?.memberSalary) }}</span>
|
||||||
@ -61,7 +48,7 @@
|
|||||||
<span class="bill-value total-salary-value">${{ formatSalaryValue(bill.target?.totalSalry) }}</span>
|
<span class="bill-value total-salary-value">${{ formatSalaryValue(bill.target?.totalSalry) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="more-btn">
|
<div class="more-btn">
|
||||||
<span>More</span>
|
<span>More</span>
|
||||||
<span class="arrow">></span>
|
<span class="arrow">></span>
|
||||||
@ -83,14 +70,14 @@
|
|||||||
<h3>Work Report Help</h3>
|
<h3>Work Report Help</h3>
|
||||||
<button class="close-btn" @click="closeHelpModal">×</button>
|
<button class="close-btn" @click="closeHelpModal">×</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="help-modal-body">
|
<div class="help-modal-body">
|
||||||
<div class="help-section">
|
<div class="help-section">
|
||||||
<p class="help-description">
|
<p class="help-description">
|
||||||
Below is the work report of the team members. Click "More" to view detailed daily work records.
|
Below is the work report of the team members. Click "More" to view detailed daily work records.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="help-section">
|
<div class="help-section">
|
||||||
<h4>Status Description:</h4>
|
<h4>Status Description:</h4>
|
||||||
<div class="status-list">
|
<div class="status-list">
|
||||||
@ -118,8 +105,8 @@
|
|||||||
<!-- 账单详情模态框 (使用 TeamBillMore 组件) -->
|
<!-- 账单详情模态框 (使用 TeamBillMore 组件) -->
|
||||||
<div v-if="showDetailModal" class="modal-overlay">
|
<div v-if="showDetailModal" class="modal-overlay">
|
||||||
<div class="detail-modal-wrapper">
|
<div class="detail-modal-wrapper">
|
||||||
<TeamBillMore
|
<TeamBillMore
|
||||||
:billData="selectedBill"
|
:billData="selectedBill"
|
||||||
@close="closeDetailModal"
|
@close="closeDetailModal"
|
||||||
@propsReceived="handlePropsReceived"
|
@propsReceived="handlePropsReceived"
|
||||||
/>
|
/>
|
||||||
@ -150,7 +137,7 @@ const fetchTeamMemberWork = async (userId) => {
|
|||||||
try {
|
try {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const response = await getTeamMemberWork(userId)
|
const response = await getTeamMemberWork(userId)
|
||||||
|
|
||||||
if (response.status && response.body) {
|
if (response.status && response.body) {
|
||||||
memberProfile.value = response.body.memberProfile
|
memberProfile.value = response.body.memberProfile
|
||||||
billList.value = response.body.targets || []
|
billList.value = response.body.targets || []
|
||||||
@ -173,7 +160,7 @@ const formatSalaryValue = (value) => {
|
|||||||
const getStatusText = (status) => {
|
const getStatusText = (status) => {
|
||||||
const statusMap = {
|
const statusMap = {
|
||||||
'UNPAID': 'In Progress',
|
'UNPAID': 'In Progress',
|
||||||
'HANG_UP': 'Pending',
|
'HANG_UP': 'Pending',
|
||||||
'PAID': 'Completed'
|
'PAID': 'Completed'
|
||||||
}
|
}
|
||||||
return statusMap[status] || status
|
return statusMap[status] || status
|
||||||
@ -632,4 +619,4 @@ onMounted(() => {
|
|||||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user