|
|
- <template>
- <view class="user-manager-container">
- <!-- 顶部导航栏 -->
- <view class="navbar" :style="navbarStyle">
- <view class="nav-left" @tap="goBack">
- <uni-icons type="back" size="24" color="#222" />
- </view>
- <view class="nav-title">用户管理</view>
- <view class="nav-right">
- <!-- <uni-icons type="more-filled" size="24" color="#222" style="margin-right: 16rpx;" />
- <uni-icons type="scan" size="24" color="#222" /> -->
- </view>
- </view>
- <!-- 搜索栏 -->
- <view class="search-bar-fixed" :style="{top: navBarRealHeight + 'px'}">
- <uni-icons type="search" size="22" color="#bfbfbf" />
- <input class="search-input" placeholder="请输入要查询的内容" v-model="searchText" @input="onInput" />
- <view v-if="searchText.length" class="clear-btn" @tap="clearInput">
- <uni-icons type="closeempty" size="22" color="#bfbfbf" />
- </view>
- <text v-if="searchText.length" class="cancel-btn" @tap="cancelSearch">取消</text>
- </view>
- <!-- 联想手机号列表 -->
- <view v-if="showSuggestList" class="suggest-list" :style="{paddingTop: (navBarRealHeight + searchBarHeight) + 'px'}">
- <view v-for="(item, idx) in suggestList" :key="idx" class="suggest-item">
- <uni-icons type="search" size="22" color="#bfbfbf" style="margin-right: 12rpx;" />
- <rich-text :nodes="highlightMatch(item, searchText)" />
- </view>
- </view>
- <!-- 用户列表(无搜索时显示) -->
- <view class="user-list" v-if="!showSuggestList" :style="{paddingTop: (navBarRealHeight + searchBarHeight) + 'px'}">
- <view v-for="(user, idx) in filteredUsers" :key="idx" class="user-card" @tap="goUserDetail(user)">
- <view class="user-info-row">
- <text class="user-label">姓名:</text>
- <text class="user-value">{{ user.name }}</text>
- </view>
- <view class="user-info-row">
- <text class="user-label">电话:</text>
- <text class="user-value">{{ user.phone }}</text>
- </view>
- <view class="user-info-row">
- <text class="user-label">角色:</text>
- <template v-if="user.role">
- <text class="role-tag" v-if="user.role === '推广官'">推广官</text>
- <text v-else class="user-value">{{ user.role }}</text>
- </template>
- <template v-else>
- <text class="user-value">-</text>
- </template>
- </view>
- <view v-if="user.blocked" class="blocked-tag">已拉黑</view>
- </view>
- </view>
- </view>
- </template>
-
- <script>
- import pullRefreshMixin from '../mixins/pullRefreshMixin.js'
- export default {
- mixins: [pullRefreshMixin],
- data() {
- return {
- searchText: '',
- users: [
- { name: '周海', phone: '18899102278', role: '', blocked: true },
- { name: '郑文锦', phone: '18827381111', role: '推广官', blocked: true },
- { name: '钱若霖', phone: '18827381112', role: '推广官', blocked: false },
- { name: '吴彦琛', phone: '18827381113', role: '推广官', blocked: false },
- { name: '赵莫艳', phone: '18827381116', role: '', blocked: false },
- { name: '李晓明', phone: '18827381119', role: '', blocked: false },
- { name: '王小刚', phone: '18827381110', role: '', blocked: false },
- ],
- statusBarHeight: 0,
- showSuggestList: false,
- suggestList: [],
- searchBarOffset: 0,
- searchBarTop: 0,
- contentOffset: 0,
- navBarRealHeight: 0,
- searchBarHeight: 70, // px
- }
- },
- computed: {
- filteredUsers() {
- if (!this.searchText) return this.users;
- return this.users.filter(u =>
- u.name.includes(this.searchText) ||
- u.phone.includes(this.searchText) ||
- (u.role && u.role.includes(this.searchText))
- );
- },
- navbarStyle() {
- // 适配不同设备顶部安全区
- return `padding-top: ${this.statusBarHeight}px;`;
- }
- },
- onLoad() {
- // 获取系统状态栏高度,适配顶部导航
- uni.getSystemInfo({
- success: (res) => {
- this.statusBarHeight = res.statusBarHeight || 20;
- }
- });
- this.$nextTick(() => {
- uni.createSelectorQuery().select('.navbar').boundingClientRect(rect => {
- if (rect) {
- this.navBarRealHeight = rect.height;
- }
- }).exec();
- });
- },
- methods: {
- goBack() {
- uni.navigateBack();
- },
- onInput(e) {
- const val = e.detail.value;
- this.searchText = val;
- if (val) {
- // 只对手机号做联想
- this.suggestList = this.users
- .map(u => u.phone)
- .filter(phone => phone.includes(val));
- this.showSuggestList = this.suggestList.length > 0;
- } else {
- this.showSuggestList = false;
- }
- },
- clearInput() {
- this.searchText = '';
- this.showSuggestList = false;
- },
- cancelSearch() {
- this.clearInput();
- },
- highlightMatch(phone, keyword) {
- if (!keyword) return [{ name: 'span', children: [phone] }];
- // 高亮匹配部分
- const idx = phone.indexOf(keyword);
- if (idx === -1) return [{ name: 'span', children: [phone] }];
- const before = phone.slice(0, idx);
- const match = phone.slice(idx, idx + keyword.length);
- const after = phone.slice(idx + keyword.length);
- return [
- { name: 'span', children: [before] },
- { name: 'span', attrs: { style: 'color:#ff8917' }, children: [match] },
- { name: 'span', children: [after] }
- ];
- },
- goUserDetail(user) {
- uni.navigateTo({
- url: '/pages/manager/user-detail',
- success: (res) => {
- res.eventChannel.emit('userDetail', user);
- }
- });
- },
- refreshData() {
- // TODO: 实现用户列表刷新逻辑,如重新请求接口
- },
- async onRefresh() {
- await this.refreshData && this.refreshData()
- },
- },
- onPullDownRefresh() {
- this.refreshData && this.refreshData()
- uni.stopPullDownRefresh()
- }
- }
- </script>
-
- <style lang="scss" scoped>
- .user-manager-container {
- min-height: 100vh;
- background: #f7f7f7;
- padding-bottom: 40rpx;
- }
- .navbar {
- position: fixed;
- top: 0;
- left: 0;
- width: 100vw;
- height: 100rpx;
- background: #fff;
- z-index: 10;
- display: flex;
- align-items: flex-end;
- justify-content: space-between;
- box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
- padding: 0 32rpx;
- .nav-left {
- flex: 0 0 48rpx;
- display: flex;
- align-items: center;
- height: 100%;
- }
- .nav-title {
- flex: 1;
- text-align: center;
- font-size: 36rpx;
- font-weight: bold;
- color: #222;
- line-height: 100rpx;
- }
- .nav-right {
- flex: 0 0 80rpx;
- display: flex;
- align-items: center;
- justify-content: flex-end;
- height: 100%;
- }
- }
- .search-bar-fixed {
- position: fixed;
- left: 0;
- width: 100vw;
- z-index: 20;
- background: #f3f3f3;
- border-radius: 0 0 40rpx 40rpx;
- display: flex;
- align-items: center;
- padding: 0 28rpx;
- height: 70rpx;
- margin: 0;
- box-sizing: border-box;
- }
- .search-bar {
- margin-top: 120rpx;
- margin-bottom: 0;
- margin-left: 32rpx;
- margin-right: 32rpx;
- background: #f3f3f3;
- border-radius: 40rpx;
- display: flex;
- align-items: center;
- padding: 0 28rpx;
- height: 70rpx;
- position: relative;
- .search-input {
- flex: 1;
- border: none;
- background: transparent;
- font-size: 28rpx;
- color: #222;
- margin-left: 16rpx;
- outline: none;
- }
- .clear-btn {
- margin-left: 10rpx;
- margin-right: 10rpx;
- }
- .cancel-btn {
- color: #bfbfbf;
- font-size: 28rpx;
- margin-left: 10rpx;
- }
- }
- .suggest-list {
- margin-top: 24rpx;
- background: #fff;
- border-radius: 24rpx;
- margin-left: 0;
- margin-right: 0;
- box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
- overflow: hidden;
- }
- .suggest-item {
- display: flex;
- align-items: center;
- padding: 28rpx 32rpx;
- font-size: 32rpx;
- color: #222;
- border-bottom: 1rpx solid #f3f3f3;
- background: #fff;
- &:last-child {
- border-bottom: none;
- }
- }
- .user-list {
- margin: 0 0 0 0;
- padding: 0 0 0 0;
- }
- .user-card {
- background: #fff;
- border-radius: 32rpx;
- margin: 32rpx 32rpx 32rpx 32rpx;
- padding: 36rpx 36rpx 36rpx 36rpx;
- position: relative;
- box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
- }
- .user-info-row {
- display: flex;
- align-items: center;
- margin-bottom: 18rpx;
- .user-label {
- font-size: 30rpx;
- color: #888;
- width: 110rpx;
- font-weight: 400;
- }
- .user-value {
- font-size: 32rpx;
- color: #222;
- font-weight: 500;
- }
- .role-tag {
- font-size: 26rpx;
- color: #ff8917;
- border: 2rpx solid #ff8917;
- border-radius: 12rpx;
- padding: 2rpx 18rpx;
- margin-left: 0rpx;
- font-weight: 400;
- background: #fff7f0;
- display: inline-block;
- vertical-align: middle;
- }
- }
- .blocked-tag {
- position: absolute;
- right: 0;
- top: 0;
- background: #ffeaea;
- color: #ff5b5b;
- font-size: 28rpx;
- border-radius: 0 0 0 20rpx;
- padding: 12rpx 32rpx 12rpx 32rpx;
- font-weight: 400;
- }
- </style>
|