109 lines
4.4 KiB
Vue
109 lines
4.4 KiB
Vue
<script setup>
|
||
import { ref, onMounted } from 'vue'
|
||
import { useRouter } from 'vue-router'
|
||
import { showToast } from 'vant'
|
||
import { complaintApi } from '@/api/index'
|
||
|
||
const router = useRouter()
|
||
const list = ref([])
|
||
const loading = ref(true)
|
||
const showForm = ref(false)
|
||
const submitting = ref(false)
|
||
const form = ref({ type: '', content: '' })
|
||
const typeOptions = [
|
||
{ text: '服务质量', value: '服务质量' },
|
||
{ text: '餐饮问题', value: '餐饮问题' },
|
||
{ text: '环境卫生', value: '环境卫生' },
|
||
{ text: '其他', value: '其他' },
|
||
]
|
||
|
||
const statusLabel = { 0: '待处理', 1: '处理中', 2: '已解决', 3: '已关闭' }
|
||
const statusColor = { 0: 'warning', 1: 'primary', 2: 'success', 3: 'default' }
|
||
|
||
const typeLabel = { 1: '服务质量', 2: '餐饮问题', 3: '环境卫生', 4: '其他' }
|
||
|
||
onMounted(fetchList)
|
||
|
||
async function fetchList() {
|
||
loading.value = true
|
||
try {
|
||
const res = await complaintApi.list()
|
||
list.value = res.data?.data?.list || []
|
||
} catch { } finally { loading.value = false }
|
||
}
|
||
|
||
async function submit() {
|
||
if (!form.value.type || !form.value.content) {
|
||
showToast('请填写投诉类型和内容')
|
||
return
|
||
}
|
||
submitting.value = true
|
||
try {
|
||
// 后端 complaints.type 是 tinyInteger,这里把中文选项映射为数字
|
||
const typeMap = { '服务质量': 1, '餐饮问题': 2, '环境卫生': 3, '其他': 4 }
|
||
const payload = {
|
||
...form.value,
|
||
type: typeMap[form.value.type] ?? form.value.type,
|
||
}
|
||
|
||
await complaintApi.create(payload)
|
||
showToast({ type: 'success', message: '提交成功' })
|
||
showForm.value = false
|
||
form.value = { type: '', content: '' }
|
||
fetchList()
|
||
} catch { showToast('提交失败') } finally { submitting.value = false }
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div class="page">
|
||
<van-nav-bar title="投诉反馈" left-arrow @click-left="router.back()">
|
||
<template #right>
|
||
<van-icon name="plus" size="18" color="#e8718d" @click="showForm = true" />
|
||
</template>
|
||
</van-nav-bar>
|
||
|
||
<div class="content">
|
||
<van-loading v-if="loading" vertical color="#e8718d" class="center-load" />
|
||
<van-empty v-else-if="!list.length" description="暂无投诉记录" image="comment-o" />
|
||
<div v-else>
|
||
<div v-for="item in list" :key="item.id" class="item-card">
|
||
<div class="item-header">
|
||
<span class="item-type">{{ typeLabel[item.type] || '其他' }}</span>
|
||
<van-tag :type="statusColor[item.status] || 'default'" size="small">{{ statusLabel[item.status] || '待处理' }}</van-tag>
|
||
</div>
|
||
<p class="item-content">{{ item.content }}</p>
|
||
<p class="item-time">{{ item.created_at?.slice(0, 16) }}</p>
|
||
<div v-if="item.reply" class="item-reply">
|
||
<span class="reply-label">回复:</span>{{ item.reply }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 提交表单 -->
|
||
<van-popup v-model:show="showForm" round position="bottom" :style="{ padding: '24px 16px 40px' }">
|
||
<h3 class="popup-title">提交投诉反馈</h3>
|
||
<van-cell-group inset style="margin-top:8px">
|
||
<van-field label="类型" v-model="form.type" placeholder="如:服务质量 / 餐饮问题" />
|
||
<van-field label="内容" v-model="form.content" type="textarea" placeholder="请详细描述您的问题..." :rows="4" />
|
||
</van-cell-group>
|
||
<van-button block round type="primary" color="linear-gradient(135deg,#f5a0b0,#e8718d)" style="margin-top:16px" :loading="submitting" @click="submit">提交</van-button>
|
||
</van-popup>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.page { background: #f8f0f5; min-height: 100vh; }
|
||
.content { padding: 16px; }
|
||
.center-load { display: flex; justify-content: center; padding: 60px 0; }
|
||
.item-card { background: white; border-radius: 16px; padding: 16px; margin-bottom: 12px; box-shadow: 0 2px 10px rgba(0,0,0,0.04); }
|
||
.item-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
|
||
.item-type { font-size: 14px; font-weight: 600; color: #333; }
|
||
.item-content { font-size: 13px; color: #555; margin: 0 0 6px; line-height: 1.5; }
|
||
.item-time { font-size: 11px; color: #999; margin: 0; }
|
||
.item-reply { margin-top: 8px; padding: 8px; background: #f5f5f5; border-radius: 8px; font-size: 12px; color: #555; }
|
||
.reply-label { color: #e8718d; font-weight: 600; }
|
||
.popup-title { font-size: 16px; font-weight: 600; text-align: center; margin: 0 0 16px; }
|
||
</style>
|