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

353 lines
9.8 KiB

2 months ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
  1. <template>
  2. <view style="background-color: #fff; height: calc(100vh);">
  3. <view class="top-bar">
  4. <image class="top-bar-bg" src="@/static/images/mingqi-beij@2x.png" mode="aspectFill"></image>
  5. <view class="library-info">
  6. <image class="avatar" src="@/static/images/logo.jpg" mode="aspectFill"></image>
  7. <view class="library-name">葛店经济技术开发区图书馆</view>
  8. </view>
  9. </view>
  10. <view class="form-box">
  11. <view class="item">
  12. <uni-icons class="form-icon" custom-prefix="iconfont" type="icon-duzhezheng" size="24"></uni-icons>
  13. <view class="uni-input-wrapper">
  14. <input
  15. class="input"
  16. placeholder="请输入读者证号"
  17. v-model="queryvalue"
  18. @input="handleInput('queryvalue')"
  19. />
  20. <uni-icons
  21. class="clear-icon"
  22. v-if="clearIconStatus.queryvalue"
  23. @click="clearInput('queryvalue')"
  24. type="close"
  25. size="20"
  26. ></uni-icons>
  27. </view>
  28. </view>
  29. <view class="item">
  30. <uni-icons class="form-icon" type="locked" size="24"></uni-icons>
  31. <input class="input" placeholder="请输入密码" :password="!showPwd" v-model="rdpasswd" />
  32. <uni-icons class="form-right-icon" :type="showPwd ? 'eye-slash' : 'eye'" size="20"
  33. @click="togglePwd"></uni-icons>
  34. </view>
  35. <button class="login-btn" type="primary" @click="submit">绑定</button>
  36. </view>
  37. <view class="tips">
  38. 温馨提示<br />
  39. 1密码默认为 <text style="color:#e74c3c">身份证后6位</text>如果身份证号最后一位为XX需要大写;
  40. </view>
  41. </view>
  42. </template>
  43. <script>
  44. // 引入绑定接口
  45. import { FetchInitScreenSetting, FetchReaderList, FetchBindReadCard,FetchFindAllReaderBindByOpenId } from '@/api/user';
  46. import config from '@/utils/config';
  47. import { STORAGE_KEYS } from '@/utils/storage';
  48. export default {
  49. data() {
  50. return {
  51. queryvalue: '',
  52. rdpasswd: '',
  53. showPwd: false,
  54. screenConfig: {},
  55. avatarUrl: '',
  56. nickName: '',
  57. // 清空按钮状态(支持多输入框)
  58. clearIconStatus: {
  59. nickName: false,
  60. queryvalue: false
  61. }
  62. };
  63. },
  64. onLoad() {
  65. this.getScreenSetting();
  66. },
  67. methods: {
  68. // 获取微信头像 + 上传到服务器
  69. onChooseAvatar(e) {
  70. console.log('获取微信头像', e)
  71. // 临时文件路径
  72. const tempFilePath = e.detail.avatarUrl;
  73. // 开始上传
  74. uni.uploadFile({
  75. url: config.baseUrl +'/api/fileRelevant/uploadWxAvatarImg', // 你的后端上传地址
  76. filePath: tempFilePath,
  77. name: 'file', // 后端接收的文件字段名,保持一致!
  78. header: {
  79. "Content-Type": "multipart/form-data"
  80. },
  81. success: (res) => {
  82. console.log("上传成功原始返回:", res);
  83. let realAvatar = '';
  84. try {
  85. const data = JSON.parse(res.data);
  86. console.log('解析成功:', data)
  87. realAvatar = data.data || data.url || ''; // 按你后端字段改
  88. } catch (e) {
  89. realAvatar = res.data; // 如果直接返回字符串URL
  90. }
  91. if (realAvatar) {
  92. console.log("永久头像URL:", realAvatar);
  93. this.avatarUrl = config.baseUrl + '/api/fileRelevant/getImg?imgType=5&imgId=' + realAvatar
  94. } else {
  95. uni.showToast({ title: '头像上传失败', icon: 'none' });
  96. }
  97. },
  98. fail: (err) => {
  99. console.log("上传失败", err);
  100. uni.showToast({ title: '头像上传失败', icon: 'none' });
  101. }
  102. });
  103. },
  104. // 统一监听输入(自动控制清空按钮显示隐藏)
  105. handleInput(field) {
  106. this.clearIconStatus[field] = this[field].trim().length > 0
  107. },
  108. // 统一清空输入框内容
  109. clearInput(field) {
  110. this[field] = ''
  111. this.clearIconStatus[field] = false
  112. },
  113. // 切换密码显隐
  114. togglePwd() {
  115. this.showPwd = !this.showPwd;
  116. },
  117. async getScreenSetting() {
  118. try {
  119. const res = await FetchInitScreenSetting({ libcode: '1201' });
  120. const data = res.data;
  121. this.screenConfig = {
  122. thirdUrl: data.open_lib_http?.context || '',
  123. thirdAppid: data.open_lib_appId?.context || '',
  124. thirdSecret: data.open_lib_secret?.context || '',
  125. sm4Key: data.sm4_key?.context || ''
  126. };
  127. } catch (err) {
  128. console.error('获取配置失败:', err);
  129. }
  130. },
  131. async submit() {
  132. // 去除首尾空格
  133. this.nickName = this.nickName.trim()
  134. this.queryvalue = this.queryvalue.trim()
  135. if (!this.queryvalue || !this.rdpasswd) {
  136. uni.showToast({ title: '请输入读者证号和密码', icon: 'none' });
  137. return;
  138. }
  139. uni.showLoading({ title: '绑定中...' });
  140. try {
  141. const params = {
  142. ...this.screenConfig,
  143. selecttype: 'rdid',
  144. queryvalue: this.queryvalue,
  145. rdpasswd: this.rdpasswd,
  146. };
  147. // {"code":200,"message":"操作成功","data":"{\"messagelist\":[{\"code\":\"R00138\",\"message\":\"未找到符合条件的读者!\"}],\"success\":false}","timestamp":1778154499544}
  148. // {"code":200,"message":"操作成功","data":"{\"success\":true,\"pagedata\":[{\"rdClusterCode\":null,\"rdlib\":\"GD\",\"rdid\":\"420105198509200438\",\"rdcfstate\":1}]}","timestamp":1778154647854}
  149. // {"code":200,"message":"操作成功","data":"{\"messageList\":[{\"R00131\":\"认证失败,系统存在该读者,密码不匹配!\"}],\"success\":true,\"pagedata\":\"\"}","timestamp":1778155520501}
  150. const res = await FetchReaderList(params);
  151. let result = {};
  152. try {
  153. result = JSON.parse(res.data);
  154. } catch (e) {
  155. uni.hideLoading();
  156. uni.showToast({ title: '数据解析失败', icon: 'none' });
  157. return;
  158. }
  159. // 统一提取错误信息
  160. let errMsg = '';
  161. if (result.messagelist?.length) {
  162. const item = result.messagelist[0];
  163. errMsg = item.message || Object.values(item)[0] || '认证失败';
  164. }
  165. if (result.messageList?.length) {
  166. const item = result.messageList[0];
  167. errMsg = item.message || Object.values(item)[0] || '认证失败';
  168. }
  169. // 成功判断
  170. const realSuccess = result.success === true && result.pagedata?.length > 0;
  171. if (realSuccess) {
  172. // 开始绑定
  173. const openId = uni.getStorageSync("wx_login_code");
  174. const bindParams = {
  175. openid: openId,
  176. bindValue: this.queryvalue,
  177. bindType: 'rdid',
  178. libcode: '1201',
  179. }
  180. // 调用绑定接口
  181. const bindRes = await FetchBindReadCard(bindParams);
  182. console.log('绑定结果', bindRes);
  183. if(bindRes.code === 200 ){
  184. uni.hideLoading();
  185. uni.showToast({
  186. title: bindRes.data || '读者证绑定成功',
  187. icon: 'success'
  188. });
  189. const data = {
  190. libcode: '1201',
  191. openId: openId
  192. }
  193. FetchFindAllReaderBindByOpenId(data).then(res => {
  194. console.log('获取读者证列表',res)
  195. if (res.code === 200 && res.data.length > 0) {
  196. uni.setStorageSync(STORAGE_KEYS.READER_CARD_LIST, res.data);
  197. } else {
  198. uni.setStorageSync(STORAGE_KEYS.READER_CARD_LIST, []);
  199. }
  200. })
  201. .catch(err => {
  202. console.error('获取读者证列表失败:', err);
  203. })
  204. // 绑定成功后返回上一页
  205. setTimeout(() => {
  206. uni.navigateBack();
  207. }, 1500);
  208. }else{
  209. // 绑定失败提示
  210. uni.hideLoading()
  211. uni.showToast({
  212. title: bindResult.message || '绑定失败,请重试',
  213. icon: 'none'
  214. })
  215. }
  216. } else {
  217. uni.hideLoading();
  218. uni.showToast({
  219. title: errMsg || '读者证或密码错误',
  220. icon: 'none'
  221. });
  222. }
  223. } catch (err) {
  224. console.error('绑定流程异常:', err)
  225. uni.hideLoading();
  226. uni.showToast({ title: '网络异常或绑定失败', icon: 'none' });
  227. }
  228. }
  229. }
  230. };
  231. </script>
  232. <style lang="scss" scoped>
  233. .user-info-section {
  234. display: flex;
  235. flex-direction: column;
  236. align-items: center;
  237. padding: 30px 0 0 0;
  238. .avatar-btn {
  239. background: transparent;
  240. display: flex;
  241. flex-direction: column;
  242. align-items: center;
  243. &::after{
  244. border: none !important;
  245. }
  246. .avatar-img {
  247. width: 60px;
  248. height: 60px;
  249. border-radius: 50%;
  250. }
  251. .tip-text {
  252. font-size: 12px;
  253. color: #999;
  254. }
  255. }
  256. }
  257. .form-box {
  258. padding: 20px 15px;
  259. .item {
  260. width: 100%;
  261. min-height: 44px;
  262. border-radius: 22px;
  263. background-color: #f7f7f7;
  264. display: flex;
  265. align-items: center;
  266. margin-bottom: 15px;
  267. .input {
  268. flex: 1;
  269. padding: 10px;
  270. font-size: 14px;
  271. }
  272. }
  273. .uni-input-wrapper{
  274. flex: 1;
  275. display: flex;
  276. align-items: center;
  277. .input {
  278. flex: 1;
  279. padding: 10px;
  280. font-size: 14px;
  281. }
  282. .clear-icon{
  283. padding: 0 12px;
  284. color: #ccc;
  285. }
  286. }
  287. }
  288. .login-btn {
  289. margin-top: 10px;
  290. background-color: #01a4fe !important;
  291. border-radius: 22px;
  292. font-size: 16px;
  293. height: 44px;
  294. line-height: 44px;
  295. }
  296. .tips {
  297. margin: 30px 20px;
  298. font-size: 12px;
  299. color: #333;
  300. line-height: 20px;
  301. }
  302. .form-icon {
  303. ::v-deep .uni-icons {
  304. margin-left: 10px;
  305. color: #01a4fe !important;
  306. }
  307. }
  308. .form-right-icon {
  309. ::v-deep .uni-icons {
  310. margin-right: 10px;
  311. }
  312. }
  313. </style>