爱简收旧衣按件回收前端代码仓库
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.

334 lines
8.1 KiB

1 week ago
1 week ago
1 week ago
1 week ago
1 week ago
  1. <template>
  2. <view class="user-detail-container">
  3. <!-- 顶部导航栏 -->
  4. <view class="navbar" :style="navbarStyle">
  5. <view class="nav-left" @tap="goBack">
  6. <uni-icons type="back" size="24" color="#222" />
  7. </view>
  8. <view class="nav-title">用户管理详情</view>
  9. <view class="nav-right">
  10. <!-- <uni-icons type="more-filled" size="24" color="#222" style="margin-right: 16rpx;" />
  11. <uni-icons type="scan" size="24" color="#222" /> -->
  12. </view>
  13. </view>
  14. <view class="main-content">
  15. <!-- 个人信息卡片 -->
  16. <view class="info-card info-card-personal">
  17. <view class="card-title-row">
  18. <view class="card-title">个人信息</view>
  19. <text v-if="user.role==='推广官'" class="role-tag">推广官</text>
  20. </view>
  21. <view v-if="user.blocked" class="blocked-tag">已拉黑</view>
  22. <view class="info-row">
  23. <text class="label">姓名</text>
  24. <text class="value">{{ user.name }}</text>
  25. </view>
  26. <view class="divider"></view>
  27. <view class="info-row">
  28. <text class="label">电话</text>
  29. <text class="value">{{ user.phone }}</text>
  30. </view>
  31. <view class="divider"></view>
  32. <view class="info-row avatar-row">
  33. <text class="label">头像</text>
  34. <image class="avatar" :src="user.avatar" mode="aspectFill" />
  35. </view>
  36. </view>
  37. <!-- 平台信息卡片 -->
  38. <view class="info-card">
  39. <view class="card-title">平台信息</view>
  40. <view class="info-row">
  41. <text class="label">回收总次数</text>
  42. <text class="value">{{ user.recycleCount }}</text>
  43. </view>
  44. <view class="divider"></view>
  45. <view class="info-row">
  46. <text class="label">总件数</text>
  47. <text class="value">{{ user.totalItems }}</text>
  48. </view>
  49. <view class="divider"></view>
  50. <view class="info-row">
  51. <text class="label">回收总额</text>
  52. <text class="value">{{ user.totalAmount }}</text>
  53. </view>
  54. <view class="divider"></view>
  55. <view class="info-row address-row">
  56. <text class="label">用户下单地址</text>
  57. <text class="value address">{{ user.address }}</text>
  58. </view>
  59. <view class="divider"></view>
  60. <view class="info-row order-row">
  61. <text class="label">历史订单</text>
  62. <text class="value link" @tap="viewOrders">点击查看</text>
  63. </view>
  64. </view>
  65. </view>
  66. <!-- 底部操作栏 -->
  67. <view class="bottom-bar">
  68. <button v-if="user.blocked" class="action-btn danger" @tap="unblockUser">解除拉黑</button>
  69. <template v-else>
  70. <button class="action-btn danger" @tap="blockUser">拉黑</button>
  71. <button v-if="user.role!=='推广官'" class="action-btn primary" @tap="upgradeUser">升级推广官</button>
  72. </template>
  73. </view>
  74. </view>
  75. </template>
  76. <script>
  77. import pullRefreshMixin from '../mixins/pullRefreshMixin.js'
  78. export default {
  79. mixins: [pullRefreshMixin],
  80. data() {
  81. return {
  82. user: {
  83. name: '赵莫艳',
  84. phone: '15888977617',
  85. avatar: 'https://img1.baidu.com/it/u=1234567890,1234567890&fm=253&fmt=auto&app=138&f=JPEG?w=400&h=400',
  86. recycleCount: 2412,
  87. totalItems: 32,
  88. totalAmount: '8273.99',
  89. address: '海南省海口市秀英区秀英街道5单元183室',
  90. },
  91. statusBarHeight: 0,
  92. }
  93. },
  94. computed: {
  95. navbarStyle() {
  96. return `padding-top: ${this.statusBarHeight}px;`;
  97. }
  98. },
  99. onLoad(options) {
  100. // 这里可以通过 options 传递用户id并请求详情
  101. uni.getSystemInfo({
  102. success: (res) => {
  103. this.statusBarHeight = res.statusBarHeight || 20;
  104. }
  105. });
  106. // 获取上个页面传递的用户信息
  107. const eventChannel = this.getOpenerEventChannel && this.getOpenerEventChannel();
  108. if (eventChannel) {
  109. eventChannel.on('userDetail', (user) => {
  110. this.user = Object.assign({}, this.user, user);
  111. });
  112. }
  113. },
  114. methods: {
  115. goBack() {
  116. uni.navigateBack();
  117. },
  118. blockUser() {
  119. uni.showToast({ title: '已拉黑', icon: 'none' });
  120. },
  121. upgradeUser() {
  122. uni.showToast({ title: '已升级为推广官', icon: 'none' });
  123. },
  124. viewOrders() {
  125. uni.navigateTo({
  126. url: '/pages/manager/order?historyOrder=true'
  127. });
  128. },
  129. unblockUser() {
  130. uni.showToast({ title: '已解除拉黑', icon: 'none' });
  131. this.user.blocked = false;
  132. },
  133. refreshData() {
  134. // TODO: 实现用户详情刷新逻辑,如重新请求接口
  135. },
  136. async onRefresh() {
  137. await this.refreshData && this.refreshData()
  138. }
  139. },
  140. onPullDownRefresh() {
  141. this.refreshData && this.refreshData()
  142. uni.stopPullDownRefresh()
  143. }
  144. }
  145. </script>
  146. <style lang="scss" scoped>
  147. .user-detail-container {
  148. min-height: 100vh;
  149. background: #f7f7f7;
  150. padding-bottom: 160rpx;
  151. }
  152. .navbar {
  153. position: fixed;
  154. top: 0;
  155. left: 0;
  156. width: 100vw;
  157. height: 100rpx;
  158. background: #fff;
  159. z-index: 10;
  160. display: flex;
  161. align-items: flex-end;
  162. justify-content: space-between;
  163. box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
  164. padding: 0 32rpx;
  165. .nav-left {
  166. flex: 0 0 48rpx;
  167. display: flex;
  168. align-items: center;
  169. height: 100%;
  170. }
  171. .nav-title {
  172. flex: 1;
  173. text-align: center;
  174. font-size: 36rpx;
  175. font-weight: bold;
  176. color: #222;
  177. line-height: 100rpx;
  178. }
  179. .nav-right {
  180. flex: 0 0 80rpx;
  181. display: flex;
  182. align-items: center;
  183. justify-content: flex-end;
  184. height: 100%;
  185. }
  186. }
  187. .main-content {
  188. margin-top: 120rpx;
  189. margin-bottom: 40rpx;
  190. }
  191. .info-card {
  192. background: #fff;
  193. border-radius: 40rpx;
  194. margin: 0 32rpx 32rpx 32rpx;
  195. padding: 40rpx 36rpx 36rpx 36rpx;
  196. box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
  197. }
  198. .card-title-row {
  199. display: flex;
  200. align-items: center;
  201. margin-bottom: 32rpx;
  202. }
  203. .card-title {
  204. font-size: 32rpx;
  205. font-weight: bold;
  206. color: #222;
  207. margin-right: 18rpx;
  208. }
  209. .role-tag {
  210. font-size: 26rpx;
  211. color: #ff8917;
  212. border: 2rpx solid #ff8917;
  213. border-radius: 12rpx;
  214. padding: 2rpx 18rpx;
  215. font-weight: 400;
  216. background: #fff7f0;
  217. display: inline-block;
  218. vertical-align: middle;
  219. }
  220. .info-row {
  221. display: flex;
  222. align-items: center;
  223. min-height: 60rpx;
  224. margin-bottom: 0;
  225. .label {
  226. font-size: 26rpx;
  227. color: #b3b3b3;
  228. width: 180rpx;
  229. font-weight: 400;
  230. }
  231. .value {
  232. font-size: 30rpx;
  233. color: #222;
  234. font-weight: 500;
  235. flex: 1;
  236. word-break: break-all;
  237. }
  238. .link {
  239. color: #ff8917;
  240. font-size: 30rpx;
  241. font-weight: 500;
  242. text-decoration: underline;
  243. margin-left: 0;
  244. }
  245. }
  246. .avatar-row {
  247. align-items: flex-start;
  248. .avatar {
  249. width: 120rpx;
  250. height: 120rpx;
  251. border-radius: 20rpx;
  252. margin-top: 8rpx;
  253. margin-left: 0;
  254. object-fit: cover;
  255. }
  256. }
  257. .address-row {
  258. align-items: flex-start;
  259. .address {
  260. font-size: 28rpx;
  261. color: #222;
  262. font-weight: 400;
  263. margin-top: 0;
  264. line-height: 1.5;
  265. }
  266. }
  267. .order-row {
  268. .link {
  269. color: #ff8917;
  270. font-size: 30rpx;
  271. font-weight: 500;
  272. text-decoration: underline;
  273. margin-left: 0;
  274. }
  275. }
  276. .divider {
  277. height: 2rpx;
  278. background: #f3f3f3;
  279. margin: 18rpx 0 18rpx 0;
  280. border: none;
  281. }
  282. .bottom-bar {
  283. position: fixed;
  284. left: 0;
  285. right: 0;
  286. bottom: 0;
  287. display: flex;
  288. justify-content: space-around;
  289. align-items: center;
  290. background: #f7f7f7;
  291. padding-bottom: env(safe-area-inset-bottom);
  292. padding-top: 24rpx;
  293. padding-bottom: 24rpx;
  294. z-index: 20;
  295. }
  296. .action-btn {
  297. flex: 1;
  298. margin: 0 32rpx;
  299. height: 80rpx;
  300. border-radius: 40rpx;
  301. font-size: 30rpx;
  302. font-weight: 500;
  303. border: 2rpx solid #ffd36d;
  304. background: #fffbe6;
  305. color: #ffb800;
  306. box-shadow: 0 2rpx 8rpx rgba(255, 156, 0, 0.03);
  307. }
  308. .action-btn.primary {
  309. color: #ffb800;
  310. border: 2rpx solid #ffd36d;
  311. background: #fffbe6;
  312. }
  313. .action-btn.danger {
  314. color: #ffb800;
  315. border: 2rpx solid #ffd36d;
  316. background: #fffbe6;
  317. }
  318. .info-card-personal {
  319. position: relative;
  320. }
  321. .blocked-tag {
  322. position: absolute;
  323. right: 0;
  324. top: 0;
  325. background: #ffeaea;
  326. color: #ff5b5b;
  327. font-size: 28rpx;
  328. border-radius: 0 0 0 20rpx;
  329. padding: 12rpx 32rpx 12rpx 32rpx;
  330. font-weight: 400;
  331. z-index: 2;
  332. }
  333. </style>