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

372 lines
10 KiB

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