Files
lucky_shop/pages_tool/member/card_log.vue
ZF sun 783c10fc62 refactor: 统一项目内国际化key的命名空间格式
本次提交对全项目的国际化调用进行了规范化重构:
1. 为中文/英文语言包新增了avatar和gender的别名映射,兼容旧有headImg/sex写法
2. 修正了lang.js中的注释路径错误
3. 将所有页面和组件内的$lang调用从短路径改为带业务模块前缀的完整命名空间路径,例如将$lang('title')改为$lang('article.list.title')
4. 优化了i18n-lazy.js的注释说明,补充了正确的key命名格式示例
5. 统一了分销、订单、会员等模块的国际化key层级,确保所有语言调用路径一致
2026-07-04 09:24:35 +08:00

314 lines
7.1 KiB
Vue

<template>
<view :style="themeColor">
<!-- 顶部统计 -->
<view class="stat-header">
<view class="stat-item">
<view class="stat-value">{{ cardStat.total_consume }}</view>
<view class="stat-label">{{ $lang('member.card_log.totalConsume') }}{{ $lang('member.card_log.statUnit', { unit: $lang('member.card_log.yuanSuffix') }) }}</view>
</view>
<view class="stat-divider"></view>
<view class="stat-item">
<view class="stat-value">{{ cardStat.balance }}</view>
<view class="stat-label">{{ $lang('member.card_log.cardBalance') }}{{ $lang('member.card_log.statUnit', { unit: $lang('member.card_log.yuanSuffix') }) }}</view>
</view>
<view class="stat-divider"></view>
<view class="stat-item">
<view class="stat-value">{{ cardStat.total_recharge }}</view>
<view class="stat-label">{{ $lang('member.card_log.totalRecharge') }}{{ $lang('member.card_log.statUnit', { unit: $lang('member.card_log.yuanSuffix') }) }}</view>
</view>
</view>
<!-- 筛选 tab -->
<scroll-view class="filter-tab" :scroll-x="true" :show-scrollbar="false">
<view v-for="(item, index) in filterList" :key="index"
class="tab-item" :class="{ active: currentFilter === item.value }"
@click="onFilterChange(item.value)">
<text>{{ item.label }}</text>
</view>
</scroll-view>
<!-- 列表 -->
<mescroll-uni @getData="getData" ref="mescroll">
<block slot="list">
<block v-if="logList.length > 0">
<view class="log-list">
<view class="log-item" v-for="(item, index) in logList" :key="index" @click="goDetail(item)">
<view class="log-icon" :class="item.type">
<text class="iconfont" :class="getIconClass(item.type)"></text>
</view>
<view class="log-info">
<view class="log-title">{{ item.title }}</view>
<view class="log-desc">{{ item.desc }}</view>
<view class="log-time">{{ formatTime(item.create_time) }}</view>
</view>
<view class="log-amount">
<text :class="item.amount > 0 ? 'income' : 'expense'">
{{ item.amount > 0 ? '+' : '' }}{{ $lang('member.card_log.amountWithUnit', { amount: item.amount }) }}
</text>
</view>
</view>
</view>
</block>
<block v-else>
<ns-empty :isIndex="false" :text="$lang('member.card_log.emptyTips')"></ns-empty>
</block>
</block>
</mescroll-uni>
<ns-login ref="login"></ns-login>
<loading-cover ref="loadingCover"></loading-cover>
</view>
</template>
<script>
export default {
data() {
return {
cardStat: {
total_consume: '0.00',
balance: '0.00',
total_recharge: '0.00'
},
logList: [],
filterList: [
{ label: this.$lang('member.card_log.filterAll', value: 'all' },
{ label: this.$lang('member.card_log.filterIncome', value: 'income' },
{ label: this.$lang('member.card_log.filterExpense', value: 'expense' },
{ label: this.$lang('member.card_log.filterRecharge', value: 'recharge' },
{ label: this.$lang('member.card_log.filterConsume', value: 'consume' },
{ label: this.$lang('member.card_log.filterGift', value: 'gift' }
],
currentFilter: 'all'
};
},
onLoad() {},
onShow() {
if (!this.storeToken) {
this.redirectTologinOnShowLifecycle('/pages_tool/member/card_log');
return;
}
this.loadStat();
},
methods: {
// 加载统计数据
loadStat() {
this.$api.sendRequest({
url: '/api/membercard/stat',
success: res => {
if (res.code == 0 && res.data) {
this.cardStat = res.data;
}
}
});
},
// 筛选切换
onFilterChange(value) {
this.currentFilter = value;
this.$refs.mescroll.refresh();
},
// 获取图标 class
getIconClass(type) {
const iconMap = {
recharge: 'icon-chongzhi',
consume: 'icon-xiaofei',
gift: 'icon-liwu',
refund: 'icon-tuikuan'
};
return iconMap[type] || 'icon-jifen';
},
// 格式化时间
formatTime(timestamp) {
return this.$util.timeStampTurnTime(timestamp);
},
// 跳转详情
goDetail(item) {
if (item.related_type === 'order') {
this.$util.redirectTo('/pages_order/detail', { order_id: item.related_id });
}
},
// 获取列表数据
getData(mescroll) {
this.$api.sendRequest({
url: '/api/membercard/logPage',
data: {
page_size: mescroll.size,
page: mescroll.num,
type: this.currentFilter
},
success: res => {
let newArr = [];
if (res.code == 0 && res.data) {
newArr = res.data.list;
} else {
this.$util.showToast({
title: res.message
});
}
mescroll.endSuccess(newArr.length);
if (mescroll.num == 1) {
this.logList = [];
}
this.logList = this.logList.concat(newArr);
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
},
fail: res => {
mescroll.endErr();
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
}
});
}
}
};
</script>
<style lang="scss" scoped>
.stat-header {
display: flex;
align-items: center;
padding: 30rpx;
background: linear-gradient(135deg, #e3b66b 0%, #d4a04a 100%);
color: #fff;
.stat-item {
flex: 1;
text-align: center;
.stat-value {
font-size: 36rpx;
font-weight: bold;
margin-bottom: 8rpx;
}
.stat-label {
font-size: 24rpx;
opacity: 0.85;
}
}
.stat-divider {
width: 1rpx;
height: 60rpx;
background: rgba(255, 255, 255, 0.3);
}
}
.filter-tab {
width: 100%;
white-space: nowrap;
background: #fff;
border-bottom: 1rpx solid $color-line;
.tab-item {
display: inline-block;
padding: 24rpx 32rpx;
font-size: $font-size-base;
color: $color-tip;
position: relative;
&.active {
color: $color-base-text;
font-weight: 500;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 4rpx;
background: $color-base-text;
border-radius: 2rpx;
}
}
}
}
.log-list {
padding: 0 32rpx;
background: #fff;
.log-item {
display: flex;
align-items: center;
padding: 28rpx 0;
border-bottom: 1rpx solid $color-line;
&:last-child {
border-bottom: none;
}
.log-icon {
width: 72rpx;
height: 72rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 24rpx;
font-size: 32rpx;
&.recharge {
background: rgba(76, 175, 80, 0.1);
color: #4caf50;
}
&.consume {
background: rgba(244, 67, 54, 0.1);
color: #f44336;
}
&.gift {
background: rgba(255, 152, 0, 0.1);
color: #ff9800;
}
&.refund {
background: rgba(33, 150, 243, 0.1);
color: #2196f3;
}
}
.log-info {
flex: 1;
overflow: hidden;
.log-title {
font-size: $font-size-base;
color: $color-base-text;
font-weight: 500;
margin-bottom: 8rpx;
}
.log-desc {
font-size: $font-size-activity-tag;
color: $color-tip;
margin-bottom: 8rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.log-time {
font-size: $font-size-activity-tag;
color: $color-tip;
}
}
.log-amount {
margin-left: 20rpx;
font-size: $font-size-toolbar;
font-weight: 500;
.income {
color: #4caf50;
}
.expense {
color: $color-base-text;
}
}
}
}
</style>