猫妈狗爸伴宠师小程序前端代码
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.

351 lines
8.9 KiB

  1. <template>
  2. <view class="service-items-card">
  3. <view class="card-title">
  4. <text>服务项目及费用</text>
  5. </view>
  6. <!-- 服务项目列表 -->
  7. <view class="service-items-list">
  8. <view class="service-item" v-for="(item, index) in items" :key="index">
  9. <view class="item-header">
  10. <view class="item-id">{{item.day}}</view>
  11. <text style="margin: 0 10rpx;">|</text>
  12. <view class="item-name">
  13. <text>{{ item.itemsText[0] }}</text>
  14. <text v-if="item.itemsText.length >= 2">
  15. {{ item.itemsText[0] }}+{{ item.itemsText[item.itemsText.length - 1] }}{{ item.itemsText.length }}
  16. </text>
  17. </view>
  18. <view class="item-price-action">
  19. <view class="item-price">¥{{item.price.toFixed(2)}}</view>
  20. <!-- 展开按钮 -->
  21. <view class="expand-btn" @click="toggleExpand(index)" v-if="item.pet || (item.pets && item.pets.length > 0)">
  22. <!-- <text>{{ expandedItems.includes(index) ? '收起' : '展开' }}</text> -->
  23. <view class="expand-icon" :class="{'expanded': expandedItems.includes(index)}">
  24. <text class="icon-arrow">{{ expandedItems.includes(index) ? '∧' : '∨' }}</text>
  25. </view>
  26. </view>
  27. </view>
  28. </view>
  29. <!-- 详细信息区域 -->
  30. <view class="detail-area" v-if="expandedItems.includes(index)">
  31. <view class="detail-area-item" v-for="(pet, petIndex) in item.pets" :key="petIndex">
  32. <!-- 宠物名称和头像 -->
  33. <view class="item-pet" v-if="pet">
  34. <view class="pet-avatar">
  35. <image :src="pet.photo" mode="aspectFill"></image>
  36. </view>
  37. <text>{{pet.name}}</text>
  38. </view>
  39. <!-- 定制服务 -->
  40. <view class="custom-services-list" v-if="pet.itemList && pet.itemList.length > 0">
  41. <view class="custom-service-item" v-for="(t, itemIndex) in pet.itemList" :key="itemIndex">
  42. <view class="service-name">{{t.productName}}</view>
  43. <view class="service-price">¥{{ t.salePrice && t.salePrice.toFixed(2) }} × {{t.quantity}} </view>
  44. </view>
  45. </view>
  46. </view>
  47. </view>
  48. </view>
  49. </view>
  50. <!-- 费用合计 -->
  51. <view class="cost-summary" v-if="totalAmount">
  52. <view class="cost-item">
  53. <text class="cost-label">费用合计</text>
  54. <text class="cost-value">¥{{totalAmount.toFixed(2)}}</text>
  55. </view>
  56. <view class="cost-item discount" v-if="discount > 0">
  57. <text class="cost-label">平台优惠</text>
  58. <text class="cost-value">- ¥{{discount.toFixed(2)}}</text>
  59. </view>
  60. <view class="cost-item discount" v-if="memberDiscount > 0">
  61. <text class="cost-label">会员优惠</text>
  62. <text class="cost-value">- ¥{{memberDiscount.toFixed(2)}}</text>
  63. </view>
  64. <view class="cost-item total">
  65. <text class="cost-label">应付金额</text>
  66. <text class="cost-value">¥{{finalAmount.toFixed(2)}}</text>
  67. </view>
  68. </view>
  69. </view>
  70. </template>
  71. <script>
  72. export default {
  73. props: {
  74. items: {
  75. type: Array,
  76. default: () => []
  77. },
  78. totalAmount: {
  79. type: Number,
  80. default: 0
  81. },
  82. discount: {
  83. type: Number,
  84. default: 0
  85. },
  86. memberDiscount: {
  87. type: Number,
  88. default: 0
  89. },
  90. finalAmount: {
  91. type: Number,
  92. default: 0
  93. }
  94. },
  95. data() {
  96. return {
  97. expandedItems: [] // 存储已展开的项目索引
  98. }
  99. },
  100. methods: {
  101. toggleExpand(index) {
  102. const position = this.expandedItems.indexOf(index);
  103. if (position === -1) {
  104. // 如果不在数组中,则添加(展开)
  105. this.expandedItems.push(index);
  106. } else {
  107. // 如果在数组中,则移除(折叠)
  108. this.expandedItems.splice(position, 1);
  109. }
  110. }
  111. }
  112. }
  113. </script>
  114. <style lang="scss" scoped>
  115. .service-items-card {
  116. padding: 30rpx 10rpx;
  117. padding-bottom: 0;
  118. }
  119. .card-title {
  120. font-size: 30rpx;
  121. font-weight: bold;
  122. color: #333;
  123. margin-bottom: 20rpx;
  124. display: flex;
  125. align-items: center;
  126. &::before {
  127. content: '';
  128. display: inline-block;
  129. width: 8rpx;
  130. height: 32rpx;
  131. background-color: #FFAA48;
  132. margin-right: 16rpx;
  133. border-radius: 4rpx;
  134. }
  135. }
  136. .service-items-list {
  137. .service-item {
  138. padding: 20rpx 0;
  139. border-bottom: 1px solid #EEEEEE;
  140. &:last-child {
  141. border-bottom: none;
  142. }
  143. .item-header {
  144. display: flex;
  145. align-items: center;
  146. margin-bottom: 10rpx;
  147. .item-id {
  148. font-size: 26rpx;
  149. margin-right: 10rpx;
  150. }
  151. .item-name {
  152. font-size: 26rpx;
  153. color: #333;
  154. flex: 1;
  155. display: flex;
  156. }
  157. .item-price-action {
  158. display: flex;
  159. align-items: center;
  160. gap: 15rpx;
  161. .item-price {
  162. font-size: 28rpx;
  163. font-weight: bold;
  164. }
  165. }
  166. }
  167. // 展开按钮样式
  168. .expand-btn {
  169. display: flex;
  170. align-items: center;
  171. justify-content: center;
  172. // padding: 6rpx 12rpx;
  173. width: 40rpx;
  174. height: 40rpx;
  175. font-size: 24rpx;
  176. color: #666;
  177. background-color: #FFF5E6;
  178. border-radius: 20rpx;
  179. border: 1px solid #FFAA48;
  180. .expand-icon {
  181. // margin-left: 6rpx;
  182. transition: transform 0.3s ease;
  183. &.expanded {
  184. transform: rotate(180deg);
  185. }
  186. .icon-arrow {
  187. font-size: 24rpx;
  188. color: #FFAA48;
  189. }
  190. }
  191. }
  192. // 详细信息区域
  193. .detail-area {
  194. animation: fadeIn 0.3s ease;
  195. display: flex;
  196. flex-direction: column;
  197. gap: 10rpx;
  198. .detail-area-item{
  199. background-color: #F8F8F8;
  200. border-radius: 10rpx;
  201. margin-top: 10rpx;
  202. padding: 15rpx;
  203. }
  204. .item-pet {
  205. font-size: 28rpx;
  206. color: #333;
  207. margin-bottom: 20rpx;
  208. display: flex;
  209. align-items: center;
  210. .pet-avatar {
  211. width: 80rpx;
  212. height: 80rpx;
  213. border-radius: 50%;
  214. margin-right: 20rpx;
  215. image {
  216. width: 100%;
  217. height: 100%;
  218. border-radius: 50%;
  219. }
  220. }
  221. text {
  222. font-weight: 500;
  223. font-size: 32rpx;
  224. }
  225. }
  226. .custom-services-list {
  227. .custom-service-item {
  228. display: flex;
  229. justify-content: space-between;
  230. align-items: center;
  231. padding: 15rpx 0;
  232. border-bottom: 1px solid #F0F0F0;
  233. &:last-child {
  234. border-bottom: none;
  235. }
  236. .service-name {
  237. font-size: 28rpx;
  238. color: #333;
  239. font-weight: 400;
  240. }
  241. .service-price {
  242. font-size: 28rpx;
  243. color: #999;
  244. font-weight: 400;
  245. }
  246. }
  247. }
  248. }
  249. .custom-services {
  250. padding: 10rpx 0 10rpx 20rpx;
  251. .custom-service-item {
  252. display: flex;
  253. justify-content: space-between;
  254. align-items: center;
  255. margin-bottom: 6rpx;
  256. .service-name {
  257. font-size: 24rpx;
  258. color: #666;
  259. }
  260. .service-price {
  261. font-size: 24rpx;
  262. color: #999;
  263. }
  264. }
  265. }
  266. }
  267. }
  268. @keyframes fadeIn {
  269. from { opacity: 0; }
  270. to { opacity: 1; }
  271. }
  272. .cost-summary {
  273. margin-top: 30rpx;
  274. padding-top: 20rpx;
  275. border-top: 1px dashed #EEEEEE;
  276. .cost-item {
  277. display: flex;
  278. justify-content: space-between;
  279. align-items: center;
  280. margin-bottom: 10rpx;
  281. .cost-label {
  282. font-size: 26rpx;
  283. color: #666;
  284. }
  285. .cost-value {
  286. font-size: 26rpx;
  287. color: #333;
  288. }
  289. &.discount {
  290. .cost-value {
  291. color: #FF5252;
  292. }
  293. }
  294. &.total {
  295. margin-top: 20rpx;
  296. padding-top: 20rpx;
  297. border-top: 1px dashed #EEEEEE;
  298. .cost-label {
  299. font-size: 28rpx;
  300. font-weight: bold;
  301. color: #333;
  302. }
  303. .cost-value {
  304. font-size: 32rpx;
  305. font-weight: bold;
  306. color: #FF5252;
  307. }
  308. }
  309. }
  310. }
  311. </style>