图书馆小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

339 lines
8.5 KiB

<template>
<view class="feedback-container">
<view class="form-box">
<view class="item">
<text class="label">姓名</text>
<input
class="input"
placeholder="请输入姓名"
v-model="formData.name"
:disabled="hasNickname"
/>
</view>
<view class="item">
<text class="label">读者证</text>
<input
class="input"
placeholder="请输入读者证号"
v-model="formData.readerCard"
disabled
/>
</view>
<view class="item">
<text class="label">主题</text>
<input
class="input"
placeholder="请输入主题(最少5个字)"
v-model="formData.subject"
maxlength="50"
/>
</view>
<view class="item">
<text class="label">联系方式/手机号码</text>
<input
class="input"
placeholder="请输入手机号码"
v-model="formData.phone"
type="number"
maxlength="11"
/>
</view>
<view class="item textarea-item">
<text class="label">您的建议或意见</text>
<textarea
class="textarea"
placeholder="HI,请留下您的留言吧!(最少10个字)"
v-model="formData.content"
:maxlength="500"
/>
</view>
<button class="commit" type="primary" @click="onBtnClick">提交</button>
</view>
</view>
</template>
<script>
import { FetchReaderMessage,FetchAccessToken,FetchMsgSecCheck } from '@/api/user';
import config from '@/utils/config';
import { getCurrentReaderCard,getOpenId } from '@/utils/storage';
const USER_KEY = 'user-info';
export default {
data() {
return {
hasNickname: false,
formData: {
name: '',
readerCard: '',
subject: '',
phone: '',
content: ''
}
};
},
onLoad() {
this.loadReaderCardInfo();
this.loadUserInfo();
},
methods: {
async loadReaderCardInfo() {
try {
const readerCard = await getCurrentReaderCard();
if (readerCard) {
this.formData.readerCard = readerCard.bindValue || '';
}
} catch (err) {
console.error('获取读者证信息失败:', err);
}
},
loadUserInfo() {
const userInfo = uni.getStorageSync(USER_KEY) || {};
if (userInfo.nickname) {
this.formData.name = userInfo.nickname;
this.hasNickname = true;
}
},
validatePhone(phone) {
const phoneReg = /^1[3-9]\d{9}$/;
return phoneReg.test(phone);
},
async onBtnClick() {
const { name, readerCard, subject, phone, content } = this.formData;
if (!name || name.trim().length === 0) {
uni.showToast({
title: '请输入姓名',
icon: 'none'
});
return;
}
if (!readerCard || readerCard.trim().length === 0) {
uni.showToast({
title: '请先绑定读者证',
icon: 'none'
});
return;
}
if (!subject || subject.trim().length < 5) {
uni.showToast({
title: '主题至少需要5个字',
icon: 'none'
});
return;
}
if (!phone) {
uni.showToast({
title: '请输入手机号码',
icon: 'none'
});
return;
}
if (!this.validatePhone(phone)) {
uni.showToast({
title: '手机号码格式不正确',
icon: 'none'
});
return;
}
if (!content || content.trim().length < 10) {
uni.showToast({
title: '建议内容至少需要10个字',
icon: 'none'
});
return;
}
uni.showLoading({
title: '提交中'
});
try {
const openId = await getOpenId();
if (!openId) {
uni.showToast({ title: '获取用户信息失败', icon: 'none' });
return;
}
// 1. 获取 access_token
const tokenRes = await FetchAccessToken({ libcode: config.LIB_CODE });
if (!tokenRes || tokenRes.code !== 200 || !tokenRes.data) {
uni.showToast({ title: '获取访问令牌失败', icon: 'none' });
return;
}
const accessToken = tokenRes.data.access_token;
// 2. 敏感信息检测
const secCheckRes = await FetchMsgSecCheck({
libcode: config.LIB_CODE,
content: content,
version: 2,
scene: 2,
openid: openId,
title: subject,
nickname: name,
accessToken: accessToken
});
console.log('敏感信息检测结果:', secCheckRes);
// {"code":200,"message":"操作成功","data":{"errcode":0,"result":{"suggest":"risky","label":20003},"trace_id":"6a13c316-710640ab-04e22c75","errmsg":"ok","detail":[{"errcode":0,"prob":90,"suggest":"risky","label":20003,"strategy":"content_model"},{"errcode":0,"strategy":"keyword"}]},"timestamp":1779680023278}
// 1. 检查接口调用是否成功
if (!secCheckRes || secCheckRes.code !== 200) {
uni.showToast({ title: secCheckRes?.message || '敏感信息检测失败', icon: 'none' });
return;
}
// 2. 检查微信官方 errcode(仅当 errcode 为 0 时,结果有效)
const { errcode, errmsg, result } = secCheckRes.data || {};
if (errcode !== 0) {
uni.showToast({ title: errmsg || `检测失败,错误码: ${errcode}`, icon: 'none' });
return;
}
// 3. 检查是否返回了检测结果
if (!result) {
uni.showToast({ title: '未获取到检测结果', icon: 'none' });
return;
}
console.log('敏感信息检测结果:', result);
// result:{
// label: 20003, // 100 正常;10001 广告;20001 时政;20002 色情;20003 辱骂;20006 违法犯罪;20008 欺诈;20012 低俗;20013 版权;21000 其他
// suggest: "risky" // risky、pass、review
// }
// 4. 根据检测结果判断是否允许提交
const labelMap = {
100: '正常',
10001: '广告',
20001: '时政',
20002: '色情',
20003: '辱骂',
20006: '违法犯罪',
20008: '欺诈',
20012: '低俗',
20013: '版权',
21000: '其他'
};
if (result.suggest !== 'pass') {
const labelText = labelMap[result.label] || '敏感内容';
uni.showToast({ title: `内容包含${labelText},请修改后重试`, icon: 'none' });
return;
}
// 3. 检测通过,提交反馈
const res = await FetchReaderMessage({
libcode: config.LIB_CODE,
openid: openId,
phone,
readCardNo: readerCard,
readName: name,
suggestion: content,
title: subject
});
if (res.code !== 200) {
uni.showToast({ title: res.message || '留言提交失败', icon: 'none' });
return;
}
// 设置刷新标记
uni.setStorageSync('needRefreshFeedback', true);
uni.showToast({ title: '留言提交成功', icon: 'success' });
setTimeout(() => {
uni.navigateBack();
}, 1500);
} catch (err) {
console.error('留言提交失败', err);
uni.showToast({ title: err.message || '留言提交失败', icon: 'none' });
} finally {
uni.hideLoading();
}
}
}
};
</script>
<style lang="scss" scoped>
.feedback-container {
padding: 15px;
background-color: #f5f5f5;
min-height: 100vh;
}
.form-box {
background-color: #fff;
border-radius: 10px;
padding: 20px;
}
.item {
margin-bottom: 20px;
}
.label {
display: block;
font-size: 15px;
font-weight: bold;
color: #333;
margin-bottom: 10px;
}
.input {
width: 100%;
height: 44px;
background-color: #f5f5f5;
border-radius: 6px;
padding: 0 15px;
font-size: 14px;
color: #333;
box-sizing: border-box;
}
.input[disabled] {
background-color: #e8e8e8;
color: #999;
}
.textarea-item {
margin-bottom: 30px;
}
.textarea {
width: 100%;
min-height: 120px;
background-color: #f5f5f5;
border-radius: 6px;
padding: 12px 15px;
font-size: 14px;
color: #333;
box-sizing: border-box;
line-height: 1.6;
}
.commit {
width: 100%;
height: 44px;
background-color: #01a4fe;
color: #fff;
border-radius: 22px;
font-size: 16px;
border: none;
margin-top: 20px;
}
.commit::after {
border: none;
}
</style>