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

325 lines
8.2 KiB

2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month 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
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
  1. <template>
  2. <view class="reader-card">
  3. <image class="card-top-bg" src="@/static/images/card-img1.png" mode="widthFix" />
  4. <view class="edit-btn" @click="toggleEditMode">
  5. {{ isEditMode ? '完成' : '解绑' }}
  6. </view>
  7. <view class="card-list">
  8. <view
  9. class="card-list-item"
  10. v-for="(item, index) in cardList"
  11. :key="item.id"
  12. @click="handleSelectItem(item.bindValue)"
  13. :class="{ active: selectedValue === item.bindValue }"
  14. >
  15. <image class="card-left-img" src="@/static/images/card-img2.png" mode="widthFix" />
  16. <view class="card-right-info">
  17. <text class="info-title">读者证号</text>
  18. <text class="info-num">{{ item.bindValue }}</text>
  19. <text class="default-tag" v-if="item.bindDefault">默认证</text>
  20. </view>
  21. <radio v-if="isEditMode" :value="item.bindValue" :checked="selectedValue === item.bindValue"/>
  22. </view>
  23. <view class="add-card-btn" @click="toAddReaderCard" v-if="!isEditMode">
  24. <uni-icons type="plus" size="20" color="#01a4fe"></uni-icons>
  25. <text>新增读者证</text>
  26. </view>
  27. </view>
  28. <!-- 编辑模式显示底部解绑按钮 -->
  29. <button
  30. v-if="isEditMode"
  31. class="unbind-btn"
  32. :disabled="!selectedValue"
  33. :class="{disabled: !selectedValue}"
  34. @click="handleUnbind"
  35. >
  36. 确认解绑
  37. </button>
  38. </view>
  39. </template>
  40. <script>
  41. import {
  42. FetchFindAllReaderBindByOpenId,
  43. FetchSetDefaultReadCard,
  44. FetchUnbindReadCard
  45. } from '@/api/user';
  46. const READLIST = 'reader-card-list';
  47. export default {
  48. data() {
  49. return {
  50. isEditMode: false,
  51. selectedValue: '',
  52. cardList: [],
  53. }
  54. },
  55. onShow() {
  56. this.getBindReaderCardList();
  57. },
  58. methods: {
  59. // 切换编辑模式 + 清空选中
  60. toggleEditMode() {
  61. this.isEditMode = !this.isEditMode;
  62. this.selectedValue = '';
  63. },
  64. // 获取列表
  65. async getBindReaderCardList() {
  66. try {
  67. const openId = uni.getStorageSync('wx_login_code');
  68. if (!openId) return;
  69. const res = await FetchFindAllReaderBindByOpenId({
  70. libcode: '1201',
  71. openId: openId
  72. });
  73. if (res.code === 200 && res.data.length > 0) {
  74. this.cardList = res.data;
  75. uni.setStorageSync(READLIST, res.data);
  76. } else {
  77. this.cardList = [];
  78. this.selectedValue = '';
  79. uni.setStorageSync(READLIST, []);
  80. }
  81. } catch (err) {
  82. this.cardList = uni.getStorageSync(READLIST) || [];
  83. }
  84. },
  85. // 点击卡片
  86. handleSelectItem(value) {
  87. // 编辑模式:只做选择
  88. if (this.isEditMode) {
  89. this.selectedValue = this.selectedValue === value ? '' : value;
  90. return;
  91. }
  92. // 正常模式:切换默认
  93. const currentDefault = this.cardList.find(item => item.bindDefault === true);
  94. if (currentDefault && currentDefault.bindValue === value) {
  95. uni.showToast({
  96. title: '当前已是默认证,请勿重复操作',
  97. icon: 'none'
  98. });
  99. return;
  100. }
  101. const openId = uni.getStorageSync('wx_login_code');
  102. uni.showModal({
  103. title: '提示',
  104. content: '确定切换默认读者证吗?',
  105. success: async (res) => {
  106. if (!res.confirm) return;
  107. try {
  108. const result = await FetchSetDefaultReadCard({
  109. bindType: 'rdid',
  110. bindValue: value,
  111. libcode: '1201',
  112. openid: openId
  113. });
  114. if (result.code === 200) {
  115. uni.setStorageSync('currentReaderCard', value);
  116. await this.getBindReaderCardList();
  117. uni.showToast({ title: '默认证切换成功', icon: 'success' });
  118. }
  119. } catch (err) {
  120. uni.showToast({ title: '切换失败', icon: 'none' });
  121. }
  122. }
  123. });
  124. },
  125. // 解绑(核心逻辑)
  126. async handleUnbind() {
  127. if (!this.selectedValue) {
  128. uni.showToast({ title: '请选择要解绑的读者证', icon: 'none' });
  129. return;
  130. }
  131. const openId = uni.getStorageSync('wx_login_code');
  132. const unbindItem = this.cardList.find(item => item.bindValue === this.selectedValue);
  133. const isUnbindDefault = unbindItem?.bindDefault === true;
  134. uni.showModal({
  135. title: '提示',
  136. content: `确定要解绑读者证【${this.selectedValue}】吗?`,
  137. success: async (res) => {
  138. if (!res.confirm) return;
  139. try {
  140. const result = await FetchUnbindReadCard({
  141. bindType: "rdid",
  142. bindValue: this.selectedValue,
  143. libcode: "1201",
  144. openid: openId
  145. });
  146. if (result.code === 200) {
  147. uni.showToast({ title: '解绑成功', icon: 'success' });
  148. // 清空选中(不解绑模式自动选中第一个)
  149. this.selectedValue = '';
  150. await this.getBindReaderCardList();
  151. // 解绑的是默认 → 自动设置第一个为新默认(接口+缓存)
  152. if (isUnbindDefault && this.cardList.length > 0) {
  153. const newValue = this.cardList[0].bindValue;
  154. await FetchSetDefaultReadCard({
  155. bindType: 'rdid',
  156. bindValue: newValue,
  157. libcode: '1201',
  158. openid: openId
  159. });
  160. uni.setStorageSync('currentReaderCard', newValue);
  161. await this.getBindReaderCardList();
  162. }
  163. // 全部解绑 → 返回
  164. if (this.cardList.length === 0) {
  165. setTimeout(() => uni.navigateBack(), 1500);
  166. }
  167. }
  168. } catch (err) {
  169. uni.showToast({ title: '解绑失败', icon: 'none' });
  170. }
  171. }
  172. });
  173. },
  174. toAddReaderCard() {
  175. uni.navigateTo({ url: "/pages/login/login" });
  176. },
  177. }
  178. }
  179. </script>
  180. <style lang="scss" scoped>
  181. .reader-card{
  182. position: relative;
  183. min-height: 100vh;
  184. background-color: #f5f5f5;
  185. .card-top-bg{
  186. position: absolute;
  187. left: 0;
  188. top: 0;
  189. width: 100%;
  190. }
  191. .edit-btn{
  192. position: absolute;
  193. right: 20px;
  194. top: 20px;
  195. z-index: 100;
  196. font-size: 15px;
  197. }
  198. // 读者证列表
  199. .card-list{
  200. position: absolute;
  201. left: 0;
  202. top: 60px;
  203. width: calc(100% - 24px);
  204. height: calc(100vh - 195px);
  205. overflow-y: auto;
  206. padding: 12px;
  207. z-index: 999;
  208. .card-list-item{
  209. display: flex;
  210. justify-content: space-between;
  211. align-items: center;
  212. padding: 10px;
  213. margin-bottom: 12px;
  214. border: 2px solid #C6C6E2;
  215. border-radius: 8px;
  216. background: rgba(241,241,249,0.4);
  217. cursor: pointer;
  218. transition: all 0.2s;
  219. &.active{
  220. border-color: #01a4fe;
  221. background: rgba(1, 164, 254, 0.1);
  222. }
  223. .card-left-img{
  224. width: 80px;
  225. margin-right: 12px;
  226. display: block;
  227. }
  228. .card-right-info{
  229. flex: 1;
  230. display: flex;
  231. flex-direction: column;
  232. .info-title{
  233. font-size: 16px;
  234. color: #333;
  235. font-weight: bold;
  236. padding-bottom: 4px;
  237. }
  238. .info-num{
  239. font-size: 14px;
  240. color: #999;
  241. }
  242. .default-tag{
  243. width: 46px;
  244. font-size: 12px;
  245. color: #01a4fe;
  246. border: 1px solid #01a4fe;
  247. border-radius: 4px;
  248. padding: 2px 0;
  249. text-align: center;
  250. display: inline-block;
  251. margin-top: 4px;
  252. }
  253. }
  254. }
  255. }
  256. .add-card-btn {
  257. display: flex;
  258. align-items: center;
  259. justify-content: center;
  260. margin-top: 15px;
  261. height: 44px;
  262. border: 1px dashed #01a4fe;
  263. border-radius: 8px;
  264. color: #01a4fe;
  265. font-size: 15px;
  266. uni-icons {
  267. margin-right: 6px;
  268. }
  269. }
  270. .unbind-btn{
  271. position: fixed;
  272. bottom: 40px;
  273. left: 0;
  274. right: 0;
  275. width: calc(100% - 40px);
  276. margin: 0 auto;
  277. padding: 4px 0;
  278. color: #fff;
  279. background-color: #01a4fe;
  280. border-radius: 23px;
  281. font-size: 16px;
  282. &.disabled{
  283. background-color: #ccc;
  284. }
  285. }
  286. }
  287. </style>