index.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <template>
  2. <Water></Water>
  3. <view class="scan-range-page">
  4. <view class="loading-page" v-if="getLoading()">
  5. <image class="loading-icon" src="../../../static/images/loading.png" />
  6. </view>
  7. <scroll-view v-else class="content" scroll-y="true" @scrolltolower="onScrollToLower">
  8. <view class="item" v-for="(item, i) in companyList" :key="i" @click="toggle(i)">
  9. <view class="item-header">
  10. <text class="item-title">{{ i + 1 }}.&nbsp;{{ item.entName || "" }}</text>
  11. <uni-icons type="down" size="22" color="#999" :style="{
  12. transform: expanded[i] ? 'rotate(180deg)' : 'rotate(0deg)',
  13. transition: 'transform 0.3s ease-in-out',
  14. }"></uni-icons>
  15. </view>
  16. <scroll-view class="item-collapse" scroll-y="true" :style="{
  17. height: getCollapseHeight(i),
  18. }" @scrolltolower="getDrugInfoNameList(i)">
  19. <view class="cv-item" v-for="(d, di) in products[i]" :key="'drug-' + di">
  20. <text class="cv-index">{{ di + 1 }}</text>
  21. <text class="cv-label">药品名称:</text>
  22. <text class="cv-value">{{ d.physicName || "" }}</text>
  23. </view>
  24. </scroll-view>
  25. </view>
  26. <view class="loading-row" v-if="companyHasMore">
  27. <view class="loading-wrapper">
  28. <image class="loading-icon" src="../../../static/images/loading.png" />
  29. </view>
  30. </view>
  31. </scroll-view>
  32. </view>
  33. </template>
  34. <script>
  35. import request from "../../../request/index.js";
  36. import { getPaginatedList } from "../../../utils/utils.js";
  37. import Water from "@/components/water/water.vue";
  38. export default {
  39. components: {
  40. Water,
  41. },
  42. data() {
  43. return {
  44. companyList: [],
  45. companyPageNum: 1,
  46. companyPageSize: 20,
  47. companyTotalCount: 0,
  48. companyHasMore: true,
  49. companyLoading: false,
  50. fetchedCount: 0,
  51. allCompanies: [],
  52. loading: true,
  53. expanded: {},
  54. products: {},
  55. productPages: [],
  56. canScanCompanyList: ["华润三九医药股份有限公司", '华润三九(枣庄)药业有限公司', '华润三九(南昌)药业有限公司', '合肥华润神鹿药业有限公司', '杭州华润老桐君药业有限公司', '吉林三九金复康药业有限公司', '华润三九(郴州)制药有限公司']
  57. };
  58. },
  59. onLoad() {
  60. this.fetchInitial();
  61. },
  62. methods: {
  63. getDrugInfoNameList(i) {
  64. const res = getPaginatedList({
  65. page: this.productPages[i] || 0,
  66. initData: this.companyList[i]?.drugInfoNameList || [],
  67. data: this.products[i] || [],
  68. });
  69. if (!res || !Array.isArray(res.data)) return;
  70. this.$set(this.productPages, i, res.page || this.productPages[i] || 0);
  71. this.$set(this.products, i, res.data);
  72. },
  73. getCollapseHeight(i) {
  74. return this.expanded[i]
  75. ? Math.min(7.3 * 70, this.companyList[i].drugInfoNameList.length * 70) +
  76. "rpx"
  77. : "0";
  78. },
  79. getLoading() {
  80. return this.loading;
  81. },
  82. fetchInitial() {
  83. this.fetchCustomers();
  84. },
  85. fetchCustomers() {
  86. if (!this.companyHasMore || this.companyLoading) return;
  87. this.companyLoading = true;
  88. request("/customer/info/getEnterpriseData", {
  89. pageNum: this.companyPageNum,
  90. pageSize: this.companyPageSize,
  91. path: "/traceabilityCodeQuery/pages/scanRange/index.vue",
  92. }).then((res) => {
  93. if (res.code == 200) {
  94. const { total, list } = res.data || {};
  95. this.companyTotalCount = total || 0;
  96. const rawList = Array.isArray(list) ? list : [];
  97. this.fetchedCount = (this.fetchedCount || 0) + rawList.length;
  98. const filtered = rawList.filter((item) =>
  99. this.canScanCompanyList.includes(item.entName)
  100. );
  101. this.companyList = [...this.companyList, ...filtered];
  102. if (
  103. rawList.length > 0 &&
  104. this.fetchedCount < this.companyTotalCount
  105. ) {
  106. this.companyPageNum++;
  107. this.companyHasMore = true;
  108. } else {
  109. this.companyHasMore = false;
  110. }
  111. this.companyList.forEach((item, i) => {
  112. this.getDrugInfoNameList(i);
  113. });
  114. if (
  115. this.companyHasMore &&
  116. (filtered.length === 0 || this.companyList.length < 10)
  117. ) {
  118. this.companyLoading = false;
  119. this.fetchCustomers();
  120. return;
  121. }
  122. }
  123. this.companyLoading = false;
  124. this.loading = false;
  125. });
  126. },
  127. onScrollToLower() {
  128. this.fetchCustomers();
  129. },
  130. toggle(i) {
  131. this.$set(this.expanded, i, !this.expanded[i]);
  132. },
  133. },
  134. };
  135. </script>
  136. <style>
  137. .scan-range-page {
  138. box-sizing: border-box;
  139. padding: 24rpx;
  140. height: 100vh;
  141. background: #f3f6f9;
  142. }
  143. .content {
  144. max-height: calc(100vh - 48rpx - 92rpx - 20rpx - env(safe-area-inset-bottom));
  145. background: #fff;
  146. border-radius: 16rpx;
  147. }
  148. .item {
  149. padding: 10rpx 20rpx;
  150. border-bottom: 1rpx solid #eef0f4;
  151. }
  152. .item-header {
  153. display: flex;
  154. align-items: center;
  155. justify-content: space-between;
  156. line-height: 60rpx;
  157. }
  158. .item-title {
  159. font-size: 30rpx;
  160. color: #333;
  161. }
  162. .item-collapse {
  163. margin-top: 12rpx;
  164. height: 0;
  165. transition: height 0.3s ease-in-out;
  166. }
  167. .cv-item {
  168. padding: 16rpx;
  169. display: flex;
  170. align-items: center;
  171. color: #666;
  172. }
  173. .cv-index {
  174. width: 24rpx;
  175. height: 24rpx;
  176. line-height: 24rpx;
  177. font-size: 18rpx;
  178. text-align: center;
  179. border-radius: 50%;
  180. margin-right: 8rpx;
  181. border: 1rpx solid #666;
  182. }
  183. .cv-label {
  184. width: 140rpx;
  185. font-size: 28rpx;
  186. }
  187. .cv-value {
  188. width: 0;
  189. flex: 1;
  190. font-size: 28rpx;
  191. overflow: hidden;
  192. text-overflow: ellipsis;
  193. white-space: nowrap;
  194. }
  195. .loading-page {
  196. width: 100%;
  197. height: 200rpx;
  198. display: flex;
  199. align-items: center;
  200. justify-content: center;
  201. }
  202. .loading-row {
  203. display: flex;
  204. align-items: center;
  205. justify-content: center;
  206. padding: 20rpx;
  207. }
  208. .loading-wrapper {
  209. width: 100%;
  210. display: flex;
  211. align-items: center;
  212. justify-content: center;
  213. }
  214. .loading-icon {
  215. width: 50rpx;
  216. height: 50rpx;
  217. animation: spin 1s linear infinite;
  218. }
  219. @keyframes spin {
  220. from {
  221. transform: rotate(0deg);
  222. }
  223. to {
  224. transform: rotate(360deg);
  225. }
  226. }
  227. </style>