serviceProject.uvue 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. <template>
  2. <!-- #ifdef APP -->
  3. <scroll-view class="page-scroll">
  4. <!-- #endif -->
  5. <view class="page">
  6. <view v-for="service in serviceList" :key="service.id" class="service-card">
  7. <view class="service-top">
  8. <image
  9. :src="(((service as UTSJSONObject).cover_urls as UTSArray<UTSJSONObject>)[0] as UTSJSONObject).url ?? ''"
  10. class=" service-image" mode="aspectFill" />
  11. <view class="service-info">
  12. <text class="service-title">
  13. {{ service.title }}
  14. </text>
  15. <text class="service-desc">
  16. 服务时长:{{ service.duration }} 分钟
  17. </text>
  18. <text class="service-price">
  19. {{ service.price }}
  20. </text>
  21. </view>
  22. <switch class="service-switch" :checked="service.is_opened== 1 ? true : false" color="#ffcf3a"
  23. @change="toggleService(service.id as Number)">
  24. </switch>
  25. </view>
  26. <view class=" service-bottom">
  27. <text class="service-bottom-label">
  28. 路费设置
  29. </text>
  30. <view class="fare-group">
  31. <view class="fare-chip"
  32. :class="service.traffic_fee_type == 0 ? 'fare-chip-active' : 'fare-chip-idle'"
  33. @click="setFareType(service.id as Number, 0)">
  34. <text class="fare-chip-text"
  35. :class="service.traffic_fee_type == 0 ? 'fare-chip-text-active' : 'fare-chip-text-idle'">
  36. 免路费
  37. </text>
  38. </view>
  39. <view class="fare-chip"
  40. :class="service.traffic_fee_type == 1 ? 'fare-chip-active' : 'fare-chip-idle'"
  41. @click="setFareType(service.id as Number, 1)">
  42. <text class="fare-chip-text"
  43. :class="service.traffic_fee_type == 1 ? 'fare-chip-text-active' : 'fare-chip-text-idle'">
  44. 单程
  45. </text>
  46. </view>
  47. <view class="fare-chip"
  48. :class="service.traffic_fee_type == 2 ? 'fare-chip-active' : 'fare-chip-idle'"
  49. @click="setFareType(service.id as Number, 2)">
  50. <text class="fare-chip-text"
  51. :class="service.traffic_fee_type == 2 ? 'fare-chip-text-active' : 'fare-chip-text-idle'">
  52. 双程
  53. </text>
  54. </view>
  55. </view>
  56. </view>
  57. </view>
  58. <view class="footer-button" @click="saveServiceSetting">
  59. <text class="footer-button-text">
  60. 保存设置
  61. </text>
  62. </view>
  63. </view>
  64. <!-- #ifdef APP -->
  65. </scroll-view>
  66. <!-- #endif -->
  67. </template>
  68. <script setup lang="uts">
  69. import { ref } from 'vue'
  70. import { getCoachItems, getAvailableProjects, toggleProject } from '@/utils/api/workbenches'
  71. type FareType = 'free' | 'single' | 'double'
  72. const serviceList = ref<UTSJSONObject[]>([
  73. { id: 1, title: '中式推拿', duration: 60, price: '¥199', cover_urls: [{ url: '/static/imagesInfo/anmo.png' }], is_opened: 1, traffic_fee_type: 2 },
  74. { id: 2, title: '足疗按摩', duration: 45, price: '¥149', cover_urls: [{ url: '/static/imagesInfo/anmo.png' }], is_opened: 1, traffic_fee_type: 2 },
  75. { id: 3, title: '肩颈放松', duration: 50, price: '¥99', cover_urls: [{ url: '/static/imagesInfo/anmo.png' }], is_opened: 1, traffic_fee_type: 2 },
  76. ])
  77. const toggleService = (serviceId : number) : void => {
  78. for (let i = 0; i < serviceList.value.length; i++) {
  79. const item = serviceList.value[i]
  80. if (item.id == serviceId) {
  81. item.is_opened = item.is_opened == 1 ? false : true
  82. return
  83. }
  84. }
  85. }
  86. const setFareType = (serviceId : number, fareType : Number) : void => {
  87. for (let i = 0; i < serviceList.value.length; i++) {
  88. const item = serviceList.value[i]
  89. if (item.id == serviceId) {
  90. item.traffic_fee_type = fareType
  91. return
  92. }
  93. }
  94. }
  95. // 获取可开通服务项目接口
  96. const httpGetServiceList = async () => {
  97. try {
  98. const response = await getAvailableProjects() as UTSJSONObject
  99. const code = response["code"] as number
  100. // const data = response["data"] as UTSJSONObject
  101. if (code !== 200) return
  102. serviceList.value = response["data"] as UTSArray<UTSJSONObject>;
  103. console.log(serviceList.value, 'sssss');
  104. } catch (err : any) {
  105. console.error('获取服务项目接口异常', err)
  106. }
  107. }
  108. // 获取技师服务项目接口
  109. const httpGetCoachItems = async () => {
  110. // try {
  111. // const response = await getCoachItems() as UTSJSONObject
  112. // const code = response["code"] as number
  113. // const data = response["data"] as UTSJSONObject
  114. // if (code !== 200) return
  115. // } catch (err : any) {
  116. // console.error('获取技师服务项目接口异常', err)
  117. // }
  118. }
  119. // 保存服务设置
  120. const saveServiceSetting = async () => {
  121. // 构建保存参数
  122. const params = serviceList.value.map((service) => {
  123. // 检查路费设置是否为空
  124. if (service["is_opened"] == true && service["traffic_fee_type"] == null) {
  125. uni.showToast({ title: '请设置路费类型', icon: 'none' })
  126. throw new Error('请设置路费类型')
  127. }
  128. return {
  129. project_id: service["id"],
  130. is_opened: service["is_opened"] == true ? 1 : 0,
  131. traffic_fee_type: service["traffic_fee_type"]
  132. } as UTSJSONObject
  133. })
  134. try {
  135. const response = await toggleProject(params) as UTSJSONObject
  136. const code = response["code"] as number
  137. if (code !== 200) {
  138. uni.showToast({ title: '保存失败', icon: 'none' })
  139. return
  140. }
  141. uni.showToast({ title: '服务设置已保存', icon: 'success' })
  142. } catch (err : any) {
  143. console.error('保存服务设置接口异常', err)
  144. uni.showToast({ title: '保存失败', icon: 'none' })
  145. }
  146. }
  147. // 页面加载时获取服务项目
  148. onLoad(() => {
  149. httpGetServiceList();
  150. httpGetCoachItems()
  151. })
  152. </script>
  153. <style>
  154. .page-scroll {
  155. flex: 1;
  156. }
  157. .page {
  158. min-height: 1000rpx;
  159. padding: 24rpx;
  160. box-sizing: border-box;
  161. background-color: #f5f1e9;
  162. flex-direction: column;
  163. }
  164. .hero-card {
  165. margin-bottom: 20rpx;
  166. padding: 28rpx;
  167. border-radius: 26rpx;
  168. background-color: #fff0af;
  169. flex-direction: column;
  170. }
  171. .hero-title {
  172. font-size: 38rpx;
  173. font-weight: 700;
  174. color: #352f24;
  175. }
  176. .hero-desc {
  177. margin-top: 10rpx;
  178. font-size: 24rpx;
  179. line-height: 34rpx;
  180. color: #6c624f;
  181. }
  182. .service-card {
  183. margin-bottom: 20rpx;
  184. padding: 24rpx;
  185. background-color: #ffffff;
  186. border-radius: 20rpx;
  187. flex-direction: column;
  188. border-width: 2rpx;
  189. border-style: solid;
  190. border-color: #f0eadf;
  191. }
  192. .service-top {
  193. flex-direction: row;
  194. align-items: center;
  195. }
  196. .service-image {
  197. width: 120rpx;
  198. height: 120rpx;
  199. border-radius: 12rpx;
  200. }
  201. .service-info {
  202. flex: 1;
  203. margin-left: 20rpx;
  204. flex-direction: column;
  205. }
  206. .service-title {
  207. font-size: 32rpx;
  208. font-weight: 700;
  209. color: #333333;
  210. }
  211. .service-desc {
  212. margin-top: 8rpx;
  213. font-size: 26rpx;
  214. color: #7c7c7c;
  215. }
  216. .service-price {
  217. margin-top: 8rpx;
  218. font-size: 28rpx;
  219. color: #f36b3d;
  220. }
  221. .service-bottom {
  222. margin-top: 20rpx;
  223. padding-top: 20rpx;
  224. border-top-width: 1px;
  225. border-top-style: solid;
  226. border-top-color: #efefef;
  227. flex-direction: row;
  228. align-items: center;
  229. }
  230. .service-bottom-label {
  231. font-size: 26rpx;
  232. color: #6f6f6f;
  233. }
  234. .fare-group {
  235. flex: 1;
  236. margin-left: 16rpx;
  237. flex-direction: row;
  238. }
  239. .fare-chip {
  240. flex: 1;
  241. height: 62rpx;
  242. margin-left: 12rpx;
  243. border-radius: 12rpx;
  244. flex-direction: row;
  245. justify-content: center;
  246. align-items: center;
  247. }
  248. .fare-chip-active {
  249. background-color: #ffcf3a;
  250. }
  251. .fare-chip-idle {
  252. background-color: #f7f7f7;
  253. border-width: 1px;
  254. border-style: solid;
  255. border-color: #dddddd;
  256. }
  257. .fare-chip-text {
  258. font-size: 24rpx;
  259. }
  260. .fare-chip-text-active {
  261. color: #ffffff;
  262. }
  263. .fare-chip-text-idle {
  264. color: #666666;
  265. }
  266. .footer-button {
  267. margin-top: 8rpx;
  268. height: 96rpx;
  269. border-radius: 24rpx;
  270. background-color: #ffd54d;
  271. flex-direction: row;
  272. justify-content: center;
  273. align-items: center;
  274. }
  275. .footer-button-text {
  276. font-size: 32rpx;
  277. font-weight: 700;
  278. color: #3d3528;
  279. }
  280. </style>