index.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <template>
  2. <view class="pet-list-page">
  3. <!-- 顶部操作栏 -->
  4. <view class="action-bar">
  5. <view class="search-box">
  6. <uni-icons type="search" size="14" color="#999"></uni-icons>
  7. <input type="text" placeholder="搜索宠物名/主人" class="search-input" />
  8. </view>
  9. <button size="mini" class="add-btn" @click="goToAdd">+ 新增档案</button>
  10. </view>
  11. <!-- 宠物档案卡片列表 -->
  12. <view class="list-container">
  13. <view class="pet-card" v-for="pet in pets" :key="pet.id" @click="handleCardClick(pet)">
  14. <image :src="pet.avatar" class="pet-photo" mode="aspectFill"></image>
  15. <view class="card-info">
  16. <view class="info-top">
  17. <text class="pet-name">{{ pet.name }}</text>
  18. <text class="owner-name">{{ pet.ownerName }}</text>
  19. </view>
  20. <text class="pet-meta">{{ pet.breed }} · {{ pet.age }}</text>
  21. <view class="health-overview">
  22. <text class="health-badge">{{ pet.health }}</text>
  23. <text class="vaccine-info">疫苗: {{ pet.vaccine }}</text>
  24. </view>
  25. <view class="card-footer">
  26. <view class="action-btn-group">
  27. <text class="btn-item detail" @click.stop="goToDetail(pet)">详情</text>
  28. <text class="btn-item edit" @click.stop="goToEdit(pet)">编辑</text>
  29. <text class="btn-item delete" @click.stop="onDelete(pet)">删除</text>
  30. </view>
  31. </view>
  32. </view>
  33. </view>
  34. </view>
  35. </view>
  36. </template>
  37. <script setup>
  38. import { ref } from 'vue'
  39. import petMockData from '@/mock/pet.json'
  40. const goToAdd = () => uni.navigateTo({ url: '/pages/my/pet/add/index' })
  41. const goToDetail = (pet) => uni.navigateTo({ url: '/pages/my/pet/detail/index' })
  42. const goToEdit = (pet) => uni.navigateTo({ url: '/pages/my/pet/edit/index' })
  43. const handleCardClick = (pet) => {
  44. goToEdit(pet)
  45. }
  46. const onDelete = (pet) => {
  47. uni.showModal({
  48. title: '确认删除',
  49. content: `确定要删除宠物档案 [${pet.name}] 吗?`,
  50. success: (res) => {
  51. if (res.confirm) {
  52. pets.value = pets.value.filter(item => item.id !== pet.id)
  53. uni.showToast({ title: '删除成功', icon: 'success' })
  54. }
  55. }
  56. })
  57. }
  58. const pets = ref(petMockData.map(p => ({
  59. id: p.id, name: p.name, breed: p.breed, age: p.age,
  60. ownerName: p.ownerName, health: p.health, vaccine: p.vaccine, avatar: p.avatar
  61. })))
  62. </script>
  63. <style lang="scss" scoped>
  64. /* 此部分与原文件保持一致 */
  65. .pet-list-page {
  66. min-height: 100vh;
  67. background-color: #f2f2f2;
  68. padding-bottom: 40rpx;
  69. }
  70. .action-bar {
  71. display: flex;
  72. align-items: center;
  73. padding: 20rpx 24rpx;
  74. background-color: #fff;
  75. gap: 16rpx;
  76. }
  77. .search-box {
  78. flex: 1;
  79. display: flex;
  80. align-items: center;
  81. background: #f5f5f5;
  82. border-radius: 32rpx;
  83. padding: 12rpx 20rpx;
  84. gap: 12rpx;
  85. }
  86. .search-input {
  87. flex: 1;
  88. font-size: 26rpx;
  89. background: transparent;
  90. }
  91. .add-btn {
  92. font-size: 24rpx;
  93. font-weight: bold;
  94. background: linear-gradient(90deg, #ffd53f, #ff9500);
  95. color: #333;
  96. border: none;
  97. border-radius: 32rpx;
  98. padding: 12rpx 28rpx;
  99. white-space: nowrap;
  100. }
  101. .list-container {
  102. padding: 24rpx;
  103. }
  104. .pet-card {
  105. display: flex;
  106. background: #fff;
  107. border-radius: 24rpx;
  108. overflow: hidden;
  109. margin-bottom: 24rpx;
  110. box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
  111. }
  112. .pet-photo {
  113. width: 210rpx;
  114. height: 280rpx;
  115. flex-shrink: 0;
  116. }
  117. .card-info {
  118. flex: 1;
  119. padding: 24rpx;
  120. display: flex;
  121. flex-direction: column;
  122. }
  123. .info-top {
  124. display: flex;
  125. justify-content: space-between;
  126. align-items: center;
  127. margin-bottom: 8rpx;
  128. }
  129. .pet-name {
  130. font-size: 34rpx;
  131. font-weight: 800;
  132. color: #333;
  133. }
  134. .owner-name {
  135. font-size: 24rpx;
  136. color: #999;
  137. }
  138. .pet-meta {
  139. font-size: 26rpx;
  140. color: #666;
  141. margin-bottom: 16rpx;
  142. }
  143. .health-overview {
  144. display: flex;
  145. align-items: center;
  146. gap: 16rpx;
  147. margin-bottom: 20rpx;
  148. }
  149. .health-badge {
  150. font-size: 22rpx;
  151. color: #2e7d32;
  152. background: #e8f5e9;
  153. padding: 4rpx 16rpx;
  154. border-radius: 8rpx;
  155. }
  156. .vaccine-info {
  157. font-size: 22rpx;
  158. color: #795548;
  159. background: #efebe9;
  160. padding: 4rpx 16rpx;
  161. border-radius: 8rpx;
  162. }
  163. .card-footer {
  164. margin-top: auto;
  165. border-top: 1rpx solid #f8f8f8;
  166. padding-top: 16rpx;
  167. }
  168. .action-btn-group {
  169. display: flex;
  170. justify-content: flex-end;
  171. gap: 16rpx;
  172. }
  173. .btn-item {
  174. font-size: 24rpx;
  175. padding: 8rpx 20rpx;
  176. border-radius: 12rpx;
  177. border: 1rpx solid #eee;
  178. color: #666;
  179. }
  180. .btn-item.detail {
  181. background: #fdf6ec;
  182. border-color: #faecd8;
  183. color: #e6a23c;
  184. }
  185. .btn-item.delete {
  186. color: #f56c6c;
  187. border-color: #fde2e2;
  188. background: #fef0f0;
  189. }
  190. </style>