feat:国际化多语言适配

This commit is contained in:
2025-10-29 15:48:40 +08:00
parent 985d739324
commit 3d67dc928d
41 changed files with 2636 additions and 2801 deletions
+51 -41
View File
@@ -1,58 +1,59 @@
<template>
<view class="feedback-container">
<!-- <form> -->
<!-- 问题类型选择 -->
<view class="type-section">
<view class="section-title">问题类型</view>
<view class="type-grid">
<view v-for="(type, index) in types" :key="index" class="type-item"
:class="{ active: selectedType === index }" @click="selectType(index)">
{{ type }}
</view>
<!-- 问题类型选择 -->
<view class="type-section">
<view class="section-title">{{ $t('feedback.issueType') }}</view>
<view class="type-grid">
<view v-for="(type, index) in types" :key="index" class="type-item"
:class="{ active: selectedType === index }" @click="selectType(index)">
{{ type }}
</view>
</view>
</view>
<!-- 问题描述 -->
<view class="description-section">
<view class="section-title">问题描述</view>
<textarea class="description-input" v-model="description" placeholder="请详细描述您遇到的问题,以便我们更好地为您解决"
maxlength="500" name="description" />
<view class="word-count">{{ description.length }}/500</view>
</view>
<!-- 问题描述 -->
<view class="description-section">
<view class="section-title">{{ $t('feedback.issueDescription') }}</view>
<textarea class="description-input" v-model="description" :placeholder="$t('feedback.placeholder')"
maxlength="500" name="description" />
<view class="word-count">{{ description.length }}/500</view>
</view>
<!-- 图片上传 -->
<view class="upload-section">
<view class="section-title">图片上传选填</view>
<!-- 图片上传 -->
<view class="upload-section">
<view class="section-title">{{ $t('feedback.imageUpload') }}</view>
<view class="upload-grid">
<view class="upload-item" v-for="(img, index) in images" :key="index">
<image :src="img" mode="aspectFill" />
<view class="delete-btn" @click="deleteImage(index)">×</view>
</view>
<view class="upload-btn" @click="chooseImage" v-if="images.length < 3">
<text class="plus">+</text>
<text class="tip">上传图片</text>
</view>
<view class="upload-btn" @click="chooseImage" v-if="images.length < 3">
<text class="plus">+</text>
<text class="tip">{{ $t('feedback.uploadImage') }}</text>
</view>
</view>
</view>
<!-- 联系方式 -->
<view class="contact-section">
<view class="section-title">联系方式</view>
<input class="contact-input" v-model="contact" placeholder="请留下您的手机号,方便我们联系您" type="number"
maxlength="11" name="contact" />
</view>
<!-- 联系方式 -->
<view class="contact-section">
<view class="section-title">{{ $t('feedback.contactInfo') }}</view>
<input class="contact-input" v-model="contact" :placeholder="$t('feedback.contactPlaceholder')" type="number"
maxlength="11" name="contact" />
</view>
<!-- 提交按钮 -->
<view class="submit-section">
<view class="submit-btn" @click="submitFeedback">提交反馈</view>
</view>
<!-- 提交按钮 -->
<view class="submit-section">
<view class="submit-btn" @click="submitFeedback">{{ $t('feedback.submit') }}</view>
</view>
<!-- </form> -->
</view>
</template>
<script setup>
import {
ref
ref,
onMounted
} from 'vue'
import {
URL,
@@ -64,9 +65,18 @@
import {
addUserFeedback
} from '../../config/api/feedback'
import { useI18n } from '@/utils/i18n.js'
const { t: $t } = useI18n()
onMounted(() => {
uni.setNavigationBarTitle({
title: $t('feedback.title')
})
})
// 响应式数据
const types = ref(['设备故障', '收费问题', '使用建议', '其他'])
const types = ref([$t('feedback.deviceFault'), $t('feedback.chargingIssue'), $t('feedback.usageSuggestion'), $t('feedback.other')])
const selectedType = ref(-1)
const paramsType = ref('')
const description = ref('')
@@ -113,7 +123,7 @@
const submitFeedback = async () => {
if (selectedType.value === -1) {
uni.showToast({
title: '请选择问题类型',
title: $t('feedback.pleaseSelectType'),
icon: 'none'
})
return
@@ -121,7 +131,7 @@
if (!description.value.trim()) {
uni.showToast({
title: '请描述您的问题',
title: $t('feedback.pleaseDescribe'),
icon: 'none'
})
return
@@ -129,13 +139,13 @@
if (!contact.value) {
uni.showToast({
title: '请留下联系方式',
title: $t('feedback.pleaseContact'),
icon: 'none'
})
return
}
if (types.value[selectedType.value] == '设备故障' || types.value[selectedType.value] == '收费问题') {
if (types.value[selectedType.value] == $t('feedback.deviceFault') || types.value[selectedType.value] == $t('feedback.chargingIssue')) {
paramsType.value = 'complain'
} else {
paramsType.value = 'suggestion'
@@ -164,7 +174,7 @@
// 兼容后端返回 { code: 200 } 或 HTTP 200 情况
if ((res.statusCode === 200) && ((res.data && res.data.code === 200) || res.data === true || res.data?.success === true)) {
uni.showToast({
title: '反馈成功',
title: $t('feedback.submitSuccess'),
icon: 'success'
})
setTimeout(() => {
@@ -173,14 +183,14 @@
return
}
uni.showToast({
title: (res.data && (res.data.msg || res.data.message)) || '反馈失败',
title: (res.data && (res.data.msg || res.data.message)) || $t('feedback.submitFailed'),
icon: 'none'
})
},
fail: (err) => {
console.error('feedback request failed:', err)
uni.showToast({
title: '网络错误,请稍后重试',
title: $t('error.networkError'),
icon: 'none'
})
}