index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. <template>
  2. <view class="container">
  3. <!-- 固定在顶部的筛选区域 -->
  4. <view class="filter-header">
  5. <view class="input-group">
  6. <u--input
  7. class="input-item"
  8. v-model="customerName"
  9. placeholder="请输入客户名称"
  10. border="surround"
  11. clearable
  12. ></u--input>
  13. <u--input
  14. class="input-item"
  15. v-model="quantity"
  16. placeholder="请输入订单数量"
  17. type="number"
  18. border="surround"
  19. clearable
  20. ></u--input>
  21. </view>
  22. <view class="filter-controls">
  23. <view class="date-picker">
  24. <picker mode="date" @change="bindStartDateChange">
  25. <view class="date-input">
  26. <text>{{startDate || '请选择'}}</text>
  27. <uni-icons
  28. v-if="startDate"
  29. type="clear"
  30. size="16"
  31. @click="clearStartDate"
  32. style="margin-left: 10rpx">
  33. </uni-icons>
  34. </view>
  35. </picker>
  36. </view>
  37. <view class="date-picker">
  38. <picker mode="date" @change="bindEndDateChange">
  39. <view class="date-input">
  40. <text>{{endDate || '请选择'}}</text>
  41. <uni-icons
  42. v-if="endDate"
  43. type="clear"
  44. size="16"
  45. @click="clearEndDate"
  46. style="margin-left: 10rpx">
  47. </uni-icons>
  48. </view>
  49. </picker>
  50. </view>
  51. </view>
  52. <button class="filter-btn" @click="handleSearch">查询</button>
  53. </view>
  54. <!-- 订单列表 -->
  55. <scroll-view
  56. scroll-y
  57. class="list-container"
  58. @scrolltolower="loadMore"
  59. :scroll-top="scrollTop"
  60. >
  61. <u-swipe-action
  62. ref="swipeAction"
  63. >
  64. <view
  65. v-for="(item, index) in orderList"
  66. :key="item.id"
  67. class="list-item"
  68. >
  69. <u-swipe-action-item
  70. :options="options"
  71. :disabled="item.status === 2"
  72. @click="handleSwipeClick(item, index)"
  73. >
  74. <!-- 原有订单内容 -->
  75. <view class="item-header">
  76. <text class="order-id">订单号:{{ item.customerName }}</text>
  77. <view :class="['status-badge', getStatusClass(item.status)]">
  78. {{ getStatusText(item.status) }}
  79. </view>
  80. </view>
  81. <view class="item-content" @click="checkOrder(item)">
  82. <view class="info-row">
  83. <text class="info-label">创建时间:</text>
  84. <text class="info-value">{{ formatDate(item.createTime) }}</text>
  85. </view>
  86. <view class="info-row">
  87. <text class="info-label">总数量:</text>
  88. <text class="info-value">{{ item.quantity }}条</text>
  89. </view>
  90. <view class="info-row">
  91. <text class="info-label">总金额:</text>
  92. <text class="info-value amount">¥{{ item.amount }}</text>
  93. </view>
  94. </view>
  95. </u-swipe-action-item>
  96. </view>
  97. </u-swipe-action>
  98. <!-- 加载状态提示 -->
  99. <view class="loading-tip">
  100. <text v-if="loading">加载中...</text>
  101. <text v-else-if="noMoreData">没有更多数据了</text>
  102. </view>
  103. </scroll-view>
  104. <!-- 新增按钮 -->
  105. <u-button class="add-btn" @click="goToAddPage" icon="plus"/>
  106. </view>
  107. </template>
  108. <script>
  109. import {
  110. getPageList,
  111. delGreenRecycling
  112. } from '@/api/views/recycling/index.js'
  113. export default {
  114. data() {
  115. return {
  116. options: [{
  117. text: '删除',
  118. style: {
  119. backgroundColor: '#FF7F50',
  120. color: '#fff'
  121. }
  122. }],
  123. moveIndex: -1,
  124. startDate: '',
  125. endDate: '',
  126. customerName: '',
  127. quantity: '',
  128. orderList: [],
  129. pageNum: 1,
  130. pageSize: 10,
  131. loading: false,
  132. noMoreData: false,
  133. scrollTop: 0,
  134. isSearching: false
  135. }
  136. },
  137. created() {
  138. this.fetchOrderList()
  139. },
  140. onShow() {
  141. this.handleSearch()
  142. },
  143. methods: {
  144. handleMove(index) {
  145. console.info('index-----', index)
  146. if (this.moveIndex === index) return;
  147. this.moveIndex = index;
  148. this.closeOtherActions();
  149. },
  150. closeOtherActions() {
  151. if (this.moveIndex !== -1) {
  152. const refName = 'swipeAction' + this.moveIndex;
  153. this.$refs[refName]?.[0]?.closeHandler();
  154. }
  155. },
  156. handleSwipeClick(item, index) {
  157. uni.showModal({
  158. title: '确认删除',
  159. content: `确定删除该回收单 ${item.id} 吗?`,
  160. success: (res) => {
  161. if (res.confirm) {
  162. delGreenRecycling(item.id).then(res => {
  163. console.info('res-----', res)
  164. uni.showToast({ title: res.msg, icon: 'success' });
  165. this.handleSearch()
  166. })
  167. }
  168. }
  169. });
  170. },
  171. clearStartDate() {
  172. this.startDate = '';
  173. this.bindStartDateChange({detail: {value: ''}});
  174. },
  175. clearEndDate() {
  176. this.endDate = '';
  177. this.bindEndDateChange({detail: {value: ''}});
  178. },
  179. bindStartDateChange(e) {
  180. this.startDate = e.detail.value
  181. },
  182. bindEndDateChange(e) {
  183. this.endDate = e.detail.value
  184. },
  185. checkOrder(row){
  186. uni.navigateTo({
  187. url: '/pages/views/recycling/details?id=' + row.id
  188. })
  189. },
  190. handleSearch() {
  191. this.pageNum = 1
  192. this.noMoreData = false
  193. this.isSearching = true
  194. this.scrollTop = 0
  195. this.fetchOrderList()
  196. },
  197. fetchOrderList() {
  198. if (this.loading || this.noMoreData) return
  199. this.loading = true
  200. let params = {
  201. current: this.pageNum,
  202. size: this.pageSize,
  203. customerName: this.customerName,
  204. quantity: this.quantity,
  205. startDate: this.startDate,
  206. endDate: this.endDate
  207. }
  208. getPageList(params).then(res => {
  209. if (this.isSearching) {
  210. this.orderList = res.data.records
  211. this.isSearching = false
  212. } else {
  213. this.orderList = [...this.orderList, ...res.data.records]
  214. }
  215. this.noMoreData = this.pageNum * this.pageSize >= res.data.total;
  216. this.pageNum++
  217. }).finally(() => {
  218. this.loading = false
  219. })
  220. },
  221. loadMore() {
  222. if (!this.loading && !this.noMoreData) {
  223. this.fetchOrderList()
  224. }
  225. },
  226. goToAddPage() {
  227. uni.navigateTo({
  228. url: '/pages/views/recycling/details'
  229. })
  230. },
  231. formatDate(dateStr) {
  232. return dateStr.replace(' ', ' ')
  233. },
  234. getStatusText(status) {
  235. const statusMap = {
  236. 0: '待审批',
  237. 2: '已通过',
  238. 1: '已拒绝'
  239. }
  240. return statusMap[status] || ''
  241. },
  242. getStatusClass(status) {
  243. const classMap = {
  244. 0: 'status-pending',
  245. 2: 'status-approved',
  246. 1: 'status-rejected'
  247. }
  248. return classMap[status] || ''
  249. }
  250. }
  251. }
  252. </script>
  253. <style lang="scss" scoped>
  254. .container {
  255. padding: 0;
  256. background-color: #f8f8f8;
  257. min-height: 100vh;
  258. position: relative;
  259. }
  260. /* 筛选区域优化 */
  261. .filter-header {
  262. position: sticky;
  263. top: 0;
  264. z-index: 100;
  265. background: #fff;
  266. padding: 20rpx;
  267. border-bottom: 1rpx solid #f0f0f0;
  268. box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
  269. }
  270. .filter-controls {
  271. display: flex;
  272. align-items: center;
  273. gap: 15rpx;
  274. padding: 10rpx 0;
  275. }
  276. .date-picker {
  277. flex: 1;
  278. .date-input {
  279. background: #f8f8f8;
  280. border-radius: 8rpx;
  281. padding: 18rpx 20rpx;
  282. font-size: 28rpx;
  283. color: #333;
  284. text-align: center;
  285. }
  286. }
  287. .filter-btn {
  288. background: #2979ff;
  289. color: #fff;
  290. border-radius: 8rpx;
  291. padding: 0 30rpx;
  292. height: 80rpx;
  293. line-height: 80rpx;
  294. font-size: 28rpx;
  295. min-width: 120rpx;
  296. &::after {
  297. border: none;
  298. }
  299. }
  300. /* 列表区域 */
  301. .list-container {
  302. height: calc(100vh - 180rpx);
  303. padding: 10rpx;
  304. transform: translateX(15rpx); /* 强制偏移 */
  305. width: calc(100% - 30rpx);
  306. }
  307. .list-item {
  308. background-color: #fff;
  309. border-radius: 12rpx;
  310. padding: 25rpx;
  311. margin: 0 20rpx 20rpx 20rpx; /* 修改为四边统一间距 */
  312. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
  313. border: 1rpx solid #f0f0f0;
  314. }
  315. .item-header {
  316. display: flex;
  317. justify-content: space-between;
  318. align-items: center;
  319. margin-bottom: 20rpx;
  320. padding-bottom: 15rpx;
  321. border-bottom: 1rpx solid #f5f5f5;
  322. }
  323. .order-id {
  324. font-size: 28rpx;
  325. color: #666;
  326. }
  327. .status-badge {
  328. font-size: 24rpx;
  329. padding: 6rpx 16rpx;
  330. border-radius: 20rpx;
  331. &.status-pending {
  332. background-color: #fff8e6;
  333. color: #ff9900;
  334. }
  335. &.status-approved {
  336. background-color: #e6f7ff;
  337. color: #1890ff;
  338. }
  339. &.status-rejected {
  340. background-color: #fff1f0;
  341. color: #ff4d4f;
  342. }
  343. }
  344. .item-content {
  345. .info-row {
  346. display: flex;
  347. margin-bottom: 16rpx;
  348. font-size: 28rpx;
  349. &:last-child {
  350. margin-bottom: 0;
  351. }
  352. }
  353. .info-label {
  354. color: #999;
  355. width: 160rpx;
  356. }
  357. .info-value {
  358. color: #333;
  359. flex: 1;
  360. &.amount {
  361. color: #f56c6c;
  362. font-weight: 500;
  363. }
  364. }
  365. }
  366. .loading-tip {
  367. text-align: center;
  368. padding: 20rpx;
  369. font-size: 26rpx;
  370. color: #999;
  371. }
  372. /* 新增按钮 */
  373. .add-btn {
  374. position: fixed;
  375. right: 25rpx;
  376. bottom: 25rpx;
  377. width: 90rpx;
  378. height: 90rpx;
  379. background: #07C160;
  380. color: #fff;
  381. border-radius: 50%;
  382. display: flex;
  383. justify-content: center;
  384. align-items: center;
  385. box-shadow: 0 4rpx 12rpx rgba(7, 193, 96, 0.3);
  386. z-index: 99;
  387. font-size: 36rpx;
  388. font-weight: bold;
  389. /* 移除按钮默认样式 */
  390. padding: 0;
  391. border: none;
  392. outline: none;
  393. /* 动画效果 */
  394. transition: all 0.2s ease;
  395. &::after {
  396. border: none;
  397. }
  398. /* 点击反馈 */
  399. &:active {
  400. transform: scale(0.95);
  401. box-shadow: 0 2rpx 6rpx rgba(7, 193, 96, 0.3);
  402. }
  403. /* 图标样式 */
  404. .add-icon {
  405. margin-top: 4rpx; /* 微调+号位置 */
  406. }
  407. }
  408. .u-swipe-action {
  409. border-radius: 12rpx; /* 与列表项圆角一致 */
  410. overflow: hidden; /* 防止按钮溢出 */
  411. }
  412. .input-group {
  413. display: flex;
  414. gap: 20rpx;
  415. margin-bottom: 20rpx;
  416. }
  417. .input-item {
  418. flex: 1;
  419. .u--input {
  420. background: #f8f8f8;
  421. border-radius: 10rpx;
  422. padding: 16rpx 20rpx;
  423. font-size: 28rpx;
  424. color: #333;
  425. border: 1rpx solid #e0e0e0;
  426. transition: all 0.3s ease;
  427. &__content {
  428. height: 80rpx;
  429. line-height: 80rpx;
  430. }
  431. &__field-wrapper {
  432. border: none;
  433. }
  434. &__placeholder {
  435. color: #999;
  436. font-size: 26rpx;
  437. }
  438. &:focus {
  439. border-color: #2979ff;
  440. box-shadow: 0 0 0 2rpx rgba(41, 121, 255, 0.2);
  441. background: #fff;
  442. }
  443. }
  444. }
  445. </style>