console.uvue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. <template>
  2. <scroll-view style="flex:1">
  3. <view class="page">
  4. <image class="upContent" src="@/static/imagesInfo/bg-color.png" mode="aspectFill">
  5. </image>
  6. <view class="city-info">
  7. <view>
  8. <text class="city-text-box">
  9. 当前城市:{{ cityInfo }}
  10. </text>
  11. </view>
  12. <u-icon name="notification" :size="24" />
  13. </view>
  14. <!-- 用户卡片 -->
  15. <view class="user-card ">
  16. <image class="user-bg" src="@/static/imagesInfo/bg-icon.png" mode="scaleToFill">
  17. </image>
  18. <view class="user-info" style="padding: 20rpx;">
  19. <view class="user-left">
  20. <view class="user-info">
  21. <text class="user-name">
  22. 刘大锤
  23. </text>
  24. <view class="tags">
  25. <text class="tag-new">
  26. 新人实习
  27. </text>
  28. </view>
  29. <u-icon name="edit" :size="18" @click="jumpMasterInfo" />
  30. <text class="tag">
  31. 编辑
  32. </text>
  33. </view>
  34. <view class="user-info">
  35. <u-icon name="customer-interests" :size="18" />
  36. <text class="user-role">
  37. 小丁理疗师
  38. </text>
  39. <u-icon name="store" :size="18" />
  40. <text class="user-shop">
  41. 佳人有约
  42. </text>
  43. </view>
  44. <view class="online-switch">
  45. <u-switch :checked="isOnline" @change="toggleOnline" />
  46. </view>
  47. </view>
  48. <view class="user-right" @click="jumpMasterInfo">
  49. <text class="text-time-box">
  50. 入驻时间
  51. </text>
  52. <text class="text-time-box" style="margin-top: 5rpx;">2026.03.01{{
  53. coachInfo?.created_at.split(' ')[0] }}
  54. </text>
  55. <image v-if="coachInfo!=null && coachInfo.avatar_url!=null"
  56. :src="coachInfo!.avatar_url!.url"
  57. style="width: 138rpx;height:138rpx;border-radius: 69rpx;margin-top: 15rpx;"
  58. mode="aspectFit">
  59. </image>
  60. <image v-else src="/static/testInfo/boy-nickname.png"
  61. style="width: 138rpx;height:138rpx;border-radius: 69rpx;margin-top: 15rpx;"
  62. mode="aspectFit">
  63. </image>
  64. </view>
  65. </view>
  66. <view class="location-bar user-info">
  67. <u-icon name="navigation" :size="18" />
  68. <text class="location-text">
  69. 当前定位:烟台市楚凤一街1号楚凤花园
  70. </text>
  71. <text class="location-btn">
  72. 手动更新
  73. </text>
  74. </view>
  75. </view>
  76. <!-- 本月数据 -->
  77. <view class="stats-row">
  78. <view class="stat-item">
  79. <text class="stat-label">
  80. 本月收益(元)
  81. </text>
  82. <text class="stat-value">
  83. 2234.88
  84. </text>
  85. </view>
  86. <view class="stat-divider">
  87. </view>
  88. <view class="stat-item">
  89. <text class="stat-label">
  90. 本月接单量(单)
  91. </text>
  92. <text class="stat-value">
  93. 2234.88
  94. </text>
  95. </view>
  96. <view class="stat-divider">
  97. </view>
  98. <view class="stat-item">
  99. <text class="stat-label">
  100. 本月退单率
  101. </text>
  102. <text class="stat-value">
  103. 30%
  104. </text>
  105. </view>
  106. </view>
  107. <!-- 功能按钮 -->
  108. <view class="func-grid">
  109. <view class="func-item" v-for="(item, i) in funcList" :key="i">
  110. <view @click.stop="jumpSetProject(item.label as string)">
  111. <image style=" width: 92rpx;height: 92rpx;" :src="item.iconUrl" mode="aspectFit">
  112. </image>
  113. <text class="func-label">
  114. {{ item.label }}
  115. </text>
  116. </view>
  117. </view>
  118. </view>
  119. <!-- 数据统计 -->
  120. <view class="data-section">
  121. <view class="section-header">
  122. <text class="section-title">
  123. 数据统计
  124. </text>
  125. <text class="section-more">
  126. 查看全部 >
  127. </text>
  128. </view>
  129. <view class="data-grid">
  130. <view class="data-item" v-for="(item, i) in dataStats" :key="i">
  131. <text class="data-value">
  132. {{ item.value }}
  133. </text>
  134. <text class="data-label">
  135. {{ item.label }}
  136. </text>
  137. </view>
  138. </view>
  139. </view>
  140. <!-- 客户评价 -->
  141. <view class="eval-section">
  142. <view class="section-header">
  143. <text class="section-title">
  144. 客户评价
  145. </text>
  146. <text class="section-more">
  147. 查看全部 >
  148. </text>
  149. </view>
  150. <view class="eval-tags">
  151. <text class="eval-tag" v-for="(tag, i) in evalTags" :key="i">
  152. {{ tag.text }} {{ tag.count > 0 ? tag.count : '' }}
  153. </text>
  154. </view>
  155. <view class="eval-item">
  156. <image class="eval-avatar" src="/static/testInfo/boy-nickname.png" mode="aspectFill" />
  157. <view class="eval-content">
  158. <view class="eval-top">
  159. <text class="eval-name">
  160. 匿名评价
  161. </text>
  162. <text class="eval-date">
  163. 2025-04-24
  164. </text>
  165. </view>
  166. <view class="eval-stars">
  167. <text>
  168. ⭐⭐⭐⭐☆
  169. </text>
  170. <view class="stat-divider">
  171. </view>
  172. <text class="eval-service">
  173. 泰式松骨
  174. </text>
  175. </view>
  176. <text class="eval-comment">
  177. 服务到位
  178. </text>
  179. </view>
  180. </view>
  181. </view>
  182. <!-- 做一个悬浮球 -->
  183. <u-floating @dblclick="callPolice" />
  184. </view>
  185. </scroll-view>
  186. </template>
  187. <script setup>
  188. import { ref, computed } from 'vue';
  189. // import { colors } from '@/common/theme';
  190. // 状态
  191. const isOnline = ref(true);
  192. const cityInfo = ref('')
  193. // 头像url类型
  194. type AvatarUrl = {
  195. url : string
  196. }
  197. // 技师信息(空对象,字段可为null)
  198. type CoachInfo = {
  199. created_at : string | null
  200. avatar_url : AvatarUrl | null
  201. }
  202. type FuncItem = {
  203. label : string | undefined;
  204. iconUrl : string;
  205. // 补充其他可能的字段(如id、desc等)
  206. }
  207. const coachInfo = ref<CoachInfo | null>(null);
  208. // 切换上线状态
  209. const toggleOnline = () => {
  210. isOnline.value = !isOnline.value;
  211. // 这里可以调用 API 更新状态
  212. console.log('Status changed:', isOnline.value);
  213. };
  214. // 功能列表
  215. const funcList = [
  216. { iconUrl: '/static/imagesInfo/cx-shop.png', label: '接单时间' },
  217. { iconUrl: '/static/imagesInfo/item-icon.png', label: '服务项目' },
  218. { iconUrl: '/static/imagesInfo/jied-time.png', label: '重选店铺' },
  219. { iconUrl: '/static/imagesInfo/gengxin-wz.png', label: '位置更新' }
  220. ];
  221. // 跳转到技师详情
  222. const jumpMasterInfo = () => {
  223. uni.navigateTo({
  224. url: '/pages/myEdit/myEdit'
  225. });
  226. };
  227. // 功能按钮点击处理
  228. const jumpSetProject = (label : string) => {
  229. console.log(label, 'jumpSetProject invoked');
  230. switch (label) {
  231. case '接单时间':
  232. uni.navigateTo({
  233. url: '/pages/console/setOrderTime'
  234. });
  235. break;
  236. case '服务项目':
  237. uni.navigateTo({
  238. url: '/pages/console/serviceProject'
  239. });
  240. break;
  241. default:
  242. break;
  243. }
  244. };
  245. // 悬浮球双击处理
  246. const callPolice = () => {
  247. console.log('callPolice triggered');
  248. // 可在此触发紧急呼叫等操作
  249. };
  250. // 统计数据
  251. const dataStats = [
  252. { value: '456', label: '接单量' },
  253. { value: '10%', label: '加钟率' },
  254. { value: '70%', label: '好评率' },
  255. { value: '3%', label: '复购率' },
  256. { value: '19%', label: '退单率' }
  257. ];
  258. // 评价标签数据
  259. // 使用类型别名避免 UTS 对内联对象字面量的限制
  260. type EvalTag = { text : string; count : number };
  261. const evalTags : EvalTag[] = [
  262. { text: '不良引导', count: 0 },
  263. { text: '手法不好', count: 101 },
  264. { text: '性格温柔', count: 198 },
  265. { text: '服务到位', count: 10 }
  266. ];
  267. </script>
  268. <style>
  269. .page {
  270. /* width: 100%;
  271. commented out because percentage unsupported
  272. */
  273. padding: 20rpx;
  274. }
  275. .upContent {
  276. height: 900rpx;
  277. width: 750rpx;
  278. position: fixed;
  279. top: 0;
  280. left: 0;
  281. z-index: -1;
  282. }
  283. .city-info {
  284. flex-direction: row;
  285. justify-content: space-between;
  286. }
  287. .city-text-box {
  288. font-size: 28rpx;
  289. }
  290. /* 用户卡片 */
  291. .user-card {
  292. border-radius: 16rpx;
  293. /* padding: 20rpx; */
  294. /* margin-top: 16rpx; */
  295. margin-bottom: 32rpx;
  296. box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
  297. /* border: 1rpx solid #f5f5f5; */
  298. position: relative;
  299. }
  300. .user-bg {
  301. position: absolute;
  302. width: 100%;
  303. height: 100%;
  304. }
  305. .user-info {
  306. /* display: flex; */
  307. flex-direction: row;
  308. align-items: center;
  309. margin-bottom: 16rpx;
  310. justify-content: space-between;
  311. }
  312. .user-name {
  313. font-size: 40rpx;
  314. font-weight: bold;
  315. color: #333333;
  316. /* margin-bottom: 16rpx; */
  317. }
  318. .tag {
  319. font-size: 24rpx;
  320. }
  321. .tag-new {
  322. /* 绿色透明度渐变 */
  323. background: linear-gradient(180deg, rgba(207, 221, 62, 0.69) 0%, rgba(162, 184, 29, 1) 100%);
  324. color: #FFFFFF;
  325. border-radius: 24rpx;
  326. margin: 0 16rpx;
  327. font-size: 28rpx;
  328. padding: 6rpx 12rpx;
  329. }
  330. .tag-edit {
  331. color: #999999;
  332. }
  333. .user-role,
  334. .user-shop {
  335. font-size: 26rpx;
  336. color: #999999;
  337. margin-right: 32rpx;
  338. }
  339. .online-switch {
  340. margin-top: 24rpx;
  341. }
  342. .online-text {
  343. font-size: 26rpx;
  344. color: #333333;
  345. margin-right: 16rpx;
  346. }
  347. .user-right {
  348. align-items: center;
  349. width: 180rpx;
  350. height: 245rpx;
  351. z-index: 1;
  352. margin-right: 14rpx;
  353. }
  354. .text-time-box {
  355. margin-top: 10rpx;
  356. font-size: 24rpx;
  357. color: #fff;
  358. letter-spacing: 1rpx;
  359. text-align: center;
  360. }
  361. .join-time {
  362. text-align: center;
  363. font-size: 24rpx;
  364. color: #FFFFFF;
  365. background-color: rgba(0, 0, 0, 0.6);
  366. padding: 8rpx 16rpx;
  367. border-radius: 8rpx;
  368. margin-bottom: 16rpx;
  369. }
  370. .avatar {
  371. width: 120rpx;
  372. height: 120rpx;
  373. border-radius: 60rpx;
  374. /* half of width/height */
  375. border: 4rpx solid #FFFFFF;
  376. }
  377. .location-bar {
  378. display: flex;
  379. align-items: center;
  380. background-image: linear-gradient(to right, #FFF9E1 0%, #FFF1BF 100%);
  381. padding: 10rpx 20rpx;
  382. border-radius: 18rpx;
  383. margin-top: 30rpx;
  384. font-size: 24rpx;
  385. justify-content: space-between;
  386. }
  387. .location-icon {
  388. font-size: 28rpx;
  389. margin-right: 16rpx;
  390. }
  391. .location-text {
  392. /* flex: 1; */
  393. font-size: 26rpx;
  394. /* color: #333333; */
  395. }
  396. .location-btn {
  397. font-size: 26rpx;
  398. border: 2rpx solid #0a0a0a;
  399. padding: 8rpx 8rpx;
  400. border-radius: 16rpx;
  401. }
  402. /* 本月数据 */
  403. .stats-row {
  404. display: flex;
  405. flex-direction: row;
  406. /* width: 100%; removed percentage, flex children will stretch */
  407. text-align: center;
  408. background-color: #FFFFFF;
  409. margin-bottom: 32rpx;
  410. border-radius: 24rpx;
  411. padding: 32rpx;
  412. box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
  413. /* border: 1rpx solid #e9e9e9; */
  414. }
  415. .stat-item {
  416. flex: 1;
  417. text-align: center;
  418. }
  419. .stat-label {
  420. font-size: 26rpx;
  421. color: #999999;
  422. /* display: block not supported; default inline behavior is fine */
  423. margin-bottom: 24rpx;
  424. text-align: center;
  425. }
  426. .stat-value {
  427. font-size: 40rpx;
  428. font-weight: bold;
  429. color: #333333;
  430. text-align: center;
  431. }
  432. .stat-divider {
  433. width: 2rpx;
  434. background-color: #EEEEEE;
  435. margin: 0 16rpx;
  436. }
  437. /* 功能网格 */
  438. .func-grid {
  439. display: flex;
  440. justify-content: space-around;
  441. background-color: #FFFFFF;
  442. margin-bottom: 32rpx;
  443. border-radius: 24rpx;
  444. padding: 32rpx 0;
  445. flex-direction: row;
  446. box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
  447. border: 1rpx solid #f9f9f9;
  448. }
  449. .func-item {
  450. display: flex;
  451. flex-direction: column;
  452. align-items: center;
  453. }
  454. .func-label {
  455. font-size: 24rpx;
  456. color: #666666;
  457. margin-top: 16rpx;
  458. }
  459. /* 数据统计 */
  460. .data-section {
  461. background-color: #FFFFFF;
  462. margin-bottom: 32rpx;
  463. border-radius: 24rpx;
  464. padding: 32rpx;
  465. box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
  466. border: 1rpx solid #f9f9f9;
  467. }
  468. .section-header {
  469. /* display: flex; */
  470. justify-content: space-between;
  471. align-items: center;
  472. margin-bottom: 32rpx;
  473. flex-direction: row;
  474. }
  475. .section-title {
  476. font-size: 32rpx;
  477. font-weight: 400;
  478. color: #333333;
  479. }
  480. .section-more {
  481. font-size: 26rpx;
  482. color: #999999;
  483. }
  484. .data-grid {
  485. /* display: flex; */
  486. justify-content: space-between;
  487. flex-direction: row;
  488. }
  489. .data-item {
  490. text-align: center;
  491. }
  492. .data-value {
  493. font-size: 36rpx;
  494. font-weight: bold;
  495. color: #333333;
  496. /* display property not needed */
  497. margin-bottom: 8rpx;
  498. }
  499. .data-label {
  500. font-size: 24rpx;
  501. color: #999999;
  502. }
  503. /* 客户评价 */
  504. .eval-section {
  505. background-color: #FFFFFF;
  506. margin-bottom: 32rpx;
  507. border-radius: 24rpx;
  508. padding: 32rpx;
  509. box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
  510. border: 1rpx solid #f9f9f9;
  511. }
  512. .eval-tags {
  513. display: flex;
  514. /* flex-wrap: wrap; */
  515. flex-direction: row;
  516. /* gap: 16rpx; */
  517. margin-bottom: 32rpx;
  518. }
  519. .eval-tag {
  520. font-size: 24rpx;
  521. padding: 8rpx 24rpx;
  522. background-color: #F5F5F5;
  523. border-radius: 24rpx;
  524. /* color: #666666; */
  525. }
  526. .eval-item {
  527. /* display: flex; */
  528. /* gap: 24rpx; */
  529. flex-direction: row;
  530. }
  531. .eval-avatar {
  532. width: 80rpx;
  533. height: 80rpx;
  534. border-radius: 40rpx;
  535. }
  536. .eval-content {
  537. flex: 1;
  538. }
  539. .eval-top {
  540. /* display: flex; */
  541. justify-content: space-between;
  542. margin-bottom: 8rpx;
  543. flex-direction: row;
  544. }
  545. .eval-name {
  546. /* font-size: 28rpx; */
  547. font-weight: 400;
  548. color: #333333;
  549. }
  550. .eval-date {
  551. font-size: 24rpx;
  552. color: #999999;
  553. }
  554. .eval-stars {
  555. font-size: 24rpx;
  556. color: #FFD740;
  557. margin-bottom: 8rpx;
  558. flex-direction: row;
  559. }
  560. .eval-service {
  561. color: #999999;
  562. margin-left: 16rpx;
  563. font-size: 28rpx;
  564. }
  565. .eval-comment {
  566. font-size: 26rpx;
  567. color: #333333;
  568. }
  569. </style>