index.vue 4.4 KB

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