图书馆小程序
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.

273 lines
5.8 KiB

2 months ago
2 months ago
1 month ago
2 months ago
2 months ago
2 months ago
1 month ago
2 months ago
2 months ago
1 month ago
1 month ago
1 month ago
2 months ago
2 months ago
  1. <template>
  2. <view class="feedback-container">
  3. <view class="form-box">
  4. <view class="item">
  5. <text class="label">姓名</text>
  6. <input
  7. class="input"
  8. placeholder="请输入姓名"
  9. v-model="formData.name"
  10. :disabled="hasNickname"
  11. />
  12. </view>
  13. <view class="item">
  14. <text class="label">读者证</text>
  15. <input
  16. class="input"
  17. placeholder="请输入读者证号"
  18. v-model="formData.readerCard"
  19. disabled
  20. />
  21. </view>
  22. <view class="item">
  23. <text class="label">主题</text>
  24. <input
  25. class="input"
  26. placeholder="请输入主题(最少5个字)"
  27. v-model="formData.subject"
  28. maxlength="50"
  29. />
  30. </view>
  31. <view class="item">
  32. <text class="label">联系方式/手机号码</text>
  33. <input
  34. class="input"
  35. placeholder="请输入手机号码"
  36. v-model="formData.phone"
  37. type="number"
  38. maxlength="11"
  39. />
  40. </view>
  41. <view class="item textarea-item">
  42. <text class="label">您的建议或意见</text>
  43. <textarea
  44. class="textarea"
  45. placeholder="HI,请留下您的留言吧!(最少10个字)"
  46. v-model="formData.content"
  47. :maxlength="500"
  48. />
  49. </view>
  50. <button class="commit" type="primary" @click="onBtnClick">提交</button>
  51. </view>
  52. </view>
  53. </template>
  54. <script>
  55. import { FetchReaderMessage } from '@/api/user';
  56. import config from '@/utils/config';
  57. import { getCurrentReaderCard,getOpenId } from '@/utils/storage';
  58. const USER_KEY = 'user-info';
  59. export default {
  60. data() {
  61. return {
  62. hasNickname: false,
  63. formData: {
  64. name: '',
  65. readerCard: '',
  66. subject: '',
  67. phone: '',
  68. content: ''
  69. }
  70. };
  71. },
  72. onLoad() {
  73. this.loadReaderCardInfo();
  74. this.loadUserInfo();
  75. },
  76. methods: {
  77. async loadReaderCardInfo() {
  78. try {
  79. const readerCard = await getCurrentReaderCard();
  80. if (readerCard) {
  81. this.formData.readerCard = readerCard.bindValue || '';
  82. }
  83. } catch (err) {
  84. console.error('获取读者证信息失败:', err);
  85. }
  86. },
  87. loadUserInfo() {
  88. const userInfo = uni.getStorageSync(USER_KEY) || {};
  89. if (userInfo.nickname) {
  90. this.formData.name = userInfo.nickname;
  91. this.hasNickname = true;
  92. }
  93. },
  94. validatePhone(phone) {
  95. const phoneReg = /^1[3-9]\d{9}$/;
  96. return phoneReg.test(phone);
  97. },
  98. async onBtnClick() {
  99. const { name, readerCard, subject, phone, content } = this.formData;
  100. if (!name || name.trim().length === 0) {
  101. uni.showToast({
  102. title: '请输入姓名',
  103. icon: 'none'
  104. });
  105. return;
  106. }
  107. if (!readerCard || readerCard.trim().length === 0) {
  108. uni.showToast({
  109. title: '请先绑定读者证',
  110. icon: 'none'
  111. });
  112. return;
  113. }
  114. if (!subject || subject.trim().length < 5) {
  115. uni.showToast({
  116. title: '主题至少需要5个字',
  117. icon: 'none'
  118. });
  119. return;
  120. }
  121. if (!phone) {
  122. uni.showToast({
  123. title: '请输入手机号码',
  124. icon: 'none'
  125. });
  126. return;
  127. }
  128. if (!this.validatePhone(phone)) {
  129. uni.showToast({
  130. title: '手机号码格式不正确',
  131. icon: 'none'
  132. });
  133. return;
  134. }
  135. if (!content || content.trim().length < 10) {
  136. uni.showToast({
  137. title: '建议内容至少需要10个字',
  138. icon: 'none'
  139. });
  140. return;
  141. }
  142. uni.showLoading({
  143. title: '提交中'
  144. });
  145. try {
  146. const openId = await getOpenId();
  147. if (!openId) {
  148. uni.showToast({ title: '获取用户信息失败', icon: 'none' });
  149. this.isLoading = false;
  150. return;
  151. }
  152. const res = await FetchReaderMessage({
  153. libcode: config.LIB_CODE,
  154. openid: openId,
  155. phone,
  156. readCardNo: readerCard,
  157. readName: name,
  158. suggestion: content,
  159. title: subject
  160. });
  161. if (res.code !== 200) {
  162. uni.showToast({ title: res.message || '留言提交失败', icon: 'none' });
  163. this.isLoading = false;
  164. return;
  165. }else{
  166. // 设置刷新标记
  167. uni.setStorageSync('needRefreshFeedback', true);
  168. uni.showToast({ title: '留言提交成功', icon: 'success' });
  169. setTimeout(() => {
  170. uni.navigateBack();
  171. }, 1500);
  172. }
  173. } catch (err) {
  174. console.error('留言提交失败', err);
  175. uni.showToast({ title: err.message || '留言提交失败', icon: 'none' });
  176. } finally {
  177. this.isLoading = false;
  178. }
  179. }
  180. }
  181. };
  182. </script>
  183. <style lang="scss" scoped>
  184. .feedback-container {
  185. padding: 15px;
  186. background-color: #f5f5f5;
  187. min-height: 100vh;
  188. }
  189. .form-box {
  190. background-color: #fff;
  191. border-radius: 10px;
  192. padding: 20px;
  193. }
  194. .item {
  195. margin-bottom: 20px;
  196. }
  197. .label {
  198. display: block;
  199. font-size: 15px;
  200. font-weight: bold;
  201. color: #333;
  202. margin-bottom: 10px;
  203. }
  204. .input {
  205. width: 100%;
  206. height: 44px;
  207. background-color: #f5f5f5;
  208. border-radius: 6px;
  209. padding: 0 15px;
  210. font-size: 14px;
  211. color: #333;
  212. box-sizing: border-box;
  213. }
  214. .input[disabled] {
  215. background-color: #e8e8e8;
  216. color: #999;
  217. }
  218. .textarea-item {
  219. margin-bottom: 30px;
  220. }
  221. .textarea {
  222. width: 100%;
  223. min-height: 120px;
  224. background-color: #f5f5f5;
  225. border-radius: 6px;
  226. padding: 12px 15px;
  227. font-size: 14px;
  228. color: #333;
  229. box-sizing: border-box;
  230. line-height: 1.6;
  231. }
  232. .commit {
  233. width: 100%;
  234. height: 44px;
  235. background-color: #01a4fe;
  236. color: #fff;
  237. border-radius: 22px;
  238. font-size: 16px;
  239. border: none;
  240. margin-top: 20px;
  241. }
  242. .commit::after {
  243. border: none;
  244. }
  245. </style>