【私域操盘手】 操盘手端UI - 部分页面草图

This commit is contained in:
柳清爽
2025-03-27 11:46:55 +08:00
parent 1790d1719f
commit 80b239c1ea
14 changed files with 5346 additions and 9 deletions

View File

@@ -28,6 +28,55 @@
"navigationBarTitleText": "设备管理"
}
},
{
"path": "pages/device/detail",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "设备详情"
}
},
{
"path": "pages/wechat/index",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "微信号管理"
}
},
{
"path": "pages/wechat/detail",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "账号详情"
}
},
{
"path": "pages/traffic/index",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "流量池"
}
},
{
"path": "pages/traffic/create",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "新建分发"
}
},
{
"path": "pages/content/index",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "内容库"
}
},
{
"path": "pages/content/detail",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "内容库详情"
}
},
{
"path": "pages/scenarios/index",
"style": {

View File

@@ -0,0 +1,325 @@
<template>
<u-popup
:show="show"
@close="onClose"
mode="bottom"
:safeAreaInsetBottom="true"
:round="10"
:closeable="true"
closeIconPos="top-right"
closeIconColor="#999"
:maskCloseAble="true"
height="85%"
>
<view class="friend-selector">
<!-- 标题栏 -->
<view class="selector-header">
<text class="selector-title">选择微信好友</text>
<view class="close-icon" @click="onClose">
<u-icon name="close" size="28" color="#999"></u-icon>
</view>
</view>
<!-- 搜索框 -->
<view class="search-box">
<u-search
v-model="searchKeyword"
placeholder="搜索好友"
:showAction="false"
clearabled
shape="round"
:clearabled="true"
height="70"
bgColor="#f4f4f4"
></u-search>
</view>
<!-- 好友列表 -->
<scroll-view scroll-y class="friend-list">
<view
class="friend-item"
v-for="(friend, index) in filteredFriends"
:key="index"
@click="toggleSelect(friend)"
>
<view class="friend-checkbox">
<u-radio
:name="friend.id"
v-model="friend.selected"
:disabled="disabled"
@change="() => toggleSelect(friend)"
shape="circle"
activeColor="#4080ff"
></u-radio>
</view>
<view class="friend-avatar">
<image :src="friend.avatar || '/static/images/avatar.png'" mode="aspectFill" class="avatar-img"></image>
</view>
<view class="friend-info">
<view class="friend-name">{{friend.name}}</view>
<view class="friend-id">{{friend.wechatId}}</view>
<view class="friend-client">归属客户{{friend.client}}</view>
</view>
</view>
</scroll-view>
<!-- 底部按钮 -->
<view class="action-buttons">
<view class="cancel-btn" @click="onCancel">取消</view>
<view class="confirm-btn" @click="onConfirm">确定</view>
</view>
</view>
</u-popup>
</template>
<script>
export default {
name: 'FriendSelector',
props: {
show: {
type: Boolean,
default: false
},
selected: {
type: Array,
default: () => []
},
multiple: {
type: Boolean,
default: true
},
disabled: {
type: Boolean,
default: false
}
},
data() {
return {
searchKeyword: '',
friends: [
{
id: '1',
name: '好友1',
wechatId: 'wxid_0y06hq00',
client: '客户1',
avatar: '/static/images/avatar.png',
selected: false
},
{
id: '2',
name: '好友2',
wechatId: 'wxid_mt5oz9fz',
client: '客户2',
avatar: '/static/images/avatar.png',
selected: false
},
{
id: '3',
name: '好友3',
wechatId: 'wxid_bma8xfh8',
client: '客户3',
avatar: '/static/images/avatar.png',
selected: false
},
{
id: '4',
name: '好友4',
wechatId: 'wxid_9xazw62h',
client: '客户4',
avatar: '/static/images/avatar.png',
selected: false
},
{
id: '5',
name: '好友5',
wechatId: 'wxid_v1fv02q3',
avatar: '/static/images/avatar.png',
selected: false
}
]
}
},
computed: {
filteredFriends() {
if (!this.searchKeyword) {
return this.friends;
}
return this.friends.filter(friend =>
friend.name.includes(this.searchKeyword) ||
friend.wechatId.includes(this.searchKeyword) ||
(friend.client && friend.client.includes(this.searchKeyword))
);
}
},
watch: {
show(newVal) {
if (newVal) {
this.initSelection();
}
},
selected: {
handler: function(newVal) {
this.initSelection();
},
immediate: true
}
},
methods: {
// 初始化选择状态
initSelection() {
this.friends.forEach(friend => {
friend.selected = this.selected.includes(friend.id);
});
},
// 切换选择状态
toggleSelect(friend) {
if (this.disabled) return;
if (!this.multiple) {
// 单选模式
this.friends.forEach(item => {
item.selected = item.id === friend.id;
});
} else {
// 多选模式
friend.selected = !friend.selected;
}
},
// 取消按钮
onCancel() {
this.$emit('cancel');
this.$emit('update:show', false);
},
// 确定按钮
onConfirm() {
const selectedFriends = this.friends.filter(friend => friend.selected);
this.$emit('confirm', selectedFriends);
this.$emit('update:show', false);
},
// 关闭弹窗
onClose() {
this.$emit('cancel');
this.$emit('update:show', false);
}
}
}
</script>
<style lang="scss" scoped>
.friend-selector {
display: flex;
flex-direction: column;
height: 100%;
.selector-header {
display: flex;
justify-content: center;
align-items: center;
padding: 30rpx;
position: relative;
border-bottom: 1px solid #f0f0f0;
.selector-title {
font-size: 34rpx;
font-weight: 500;
color: #333;
}
.close-icon {
position: absolute;
right: 30rpx;
top: 30rpx;
padding: 10rpx;
}
}
.search-box {
padding: 20rpx 30rpx;
}
.friend-list {
flex: 1;
padding: 0 30rpx;
overflow-y: auto;
.friend-item {
display: flex;
align-items: center;
padding: 20rpx 0;
border-bottom: 1px solid #f5f5f5;
.friend-checkbox {
margin-right: 20rpx;
}
.friend-avatar {
width: 80rpx;
height: 80rpx;
margin-right: 20rpx;
border-radius: 50%;
overflow: hidden;
background-color: #f5f5f5;
.avatar-img {
width: 100%;
height: 100%;
}
}
.friend-info {
flex: 1;
.friend-name {
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 4rpx;
}
.friend-id {
font-size: 26rpx;
color: #999;
margin-bottom: 4rpx;
}
.friend-client {
font-size: 26rpx;
color: #999;
}
}
}
}
.action-buttons {
display: flex;
padding: 20rpx 30rpx;
border-top: 1px solid #f0f0f0;
.cancel-btn, .confirm-btn {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 40rpx;
font-size: 30rpx;
}
.cancel-btn {
background-color: #f5f5f5;
color: #666;
margin-right: 20rpx;
}
.confirm-btn {
background-color: #4080ff;
color: #fff;
}
}
}
</style>

View File

@@ -0,0 +1,325 @@
<template>
<u-popup
:show="show"
@close="onClose"
mode="bottom"
:safeAreaInsetBottom="true"
:round="10"
:closeable="true"
closeIconPos="top-right"
closeIconColor="#999"
:maskCloseAble="true"
height="85%"
>
<view class="group-selector">
<!-- 标题栏 -->
<view class="selector-header">
<text class="selector-title">选择聊天群</text>
<view class="close-icon" @click="onClose">
<u-icon name="close" size="28" color="#999"></u-icon>
</view>
</view>
<!-- 搜索框 -->
<view class="search-box">
<u-search
v-model="searchKeyword"
placeholder="搜索聊天群"
:showAction="false"
clearabled
shape="round"
:clearabled="true"
height="70"
bgColor="#f4f4f4"
></u-search>
</view>
<!-- 群列表 -->
<scroll-view scroll-y class="group-list">
<view
class="group-item"
v-for="(group, index) in filteredGroups"
:key="index"
@click="toggleSelect(group)"
>
<view class="group-checkbox">
<u-radio
:name="group.id"
v-model="group.selected"
:disabled="disabled"
@change="() => toggleSelect(group)"
shape="circle"
activeColor="#4080ff"
></u-radio>
</view>
<view class="group-avatar">
<image :src="group.avatar || '/static/images/avatar.png'" mode="aspectFill" class="avatar-img"></image>
</view>
<view class="group-info">
<view class="group-name">{{group.name}}</view>
<view class="group-id">{{group.groupId}}</view>
<view class="group-member-count">{{group.memberCount}}</view>
</view>
</view>
</scroll-view>
<!-- 底部按钮 -->
<view class="action-buttons">
<view class="cancel-btn" @click="onCancel">取消</view>
<view class="confirm-btn" @click="onConfirm">确定</view>
</view>
</view>
</u-popup>
</template>
<script>
export default {
name: 'GroupSelector',
props: {
show: {
type: Boolean,
default: false
},
selected: {
type: Array,
default: () => []
},
multiple: {
type: Boolean,
default: true
},
disabled: {
type: Boolean,
default: false
}
},
data() {
return {
searchKeyword: '',
groups: [
{
id: '1',
name: '产品讨论群',
groupId: '12345678910',
memberCount: 120,
avatar: '/static/images/avatar.png',
selected: false
},
{
id: '2',
name: '客户交流群',
groupId: '28374656374',
memberCount: 88,
avatar: '/static/images/avatar.png',
selected: false
},
{
id: '3',
name: '企业内部群',
groupId: '98374625162',
memberCount: 56,
avatar: '/static/images/avatar.png',
selected: false
},
{
id: '4',
name: '推广活动群',
groupId: '38273645123',
memberCount: 240,
avatar: '/static/images/avatar.png',
selected: false
},
{
id: '5',
name: '售后服务群',
groupId: '73645182934',
memberCount: 178,
avatar: '/static/images/avatar.png',
selected: false
}
]
}
},
computed: {
filteredGroups() {
if (!this.searchKeyword) {
return this.groups;
}
return this.groups.filter(group =>
group.name.includes(this.searchKeyword) ||
group.groupId.includes(this.searchKeyword)
);
}
},
watch: {
show(newVal) {
if (newVal) {
this.initSelection();
}
},
selected: {
handler: function(newVal) {
this.initSelection();
},
immediate: true
}
},
methods: {
// 初始化选择状态
initSelection() {
this.groups.forEach(group => {
group.selected = this.selected.includes(group.id);
});
},
// 切换选择状态
toggleSelect(group) {
if (this.disabled) return;
if (!this.multiple) {
// 单选模式
this.groups.forEach(item => {
item.selected = item.id === group.id;
});
} else {
// 多选模式
group.selected = !group.selected;
}
},
// 取消按钮
onCancel() {
this.$emit('cancel');
this.$emit('update:show', false);
},
// 确定按钮
onConfirm() {
const selectedGroups = this.groups.filter(group => group.selected);
this.$emit('confirm', selectedGroups);
this.$emit('update:show', false);
},
// 关闭弹窗
onClose() {
this.$emit('cancel');
this.$emit('update:show', false);
}
}
}
</script>
<style lang="scss" scoped>
.group-selector {
display: flex;
flex-direction: column;
height: 100%;
.selector-header {
display: flex;
justify-content: center;
align-items: center;
padding: 30rpx;
position: relative;
border-bottom: 1px solid #f0f0f0;
.selector-title {
font-size: 34rpx;
font-weight: 500;
color: #333;
}
.close-icon {
position: absolute;
right: 30rpx;
top: 30rpx;
padding: 10rpx;
}
}
.search-box {
padding: 20rpx 30rpx;
}
.group-list {
flex: 1;
padding: 0 30rpx;
overflow-y: auto;
.group-item {
display: flex;
align-items: center;
padding: 20rpx 0;
border-bottom: 1px solid #f5f5f5;
.group-checkbox {
margin-right: 20rpx;
}
.group-avatar {
width: 80rpx;
height: 80rpx;
margin-right: 20rpx;
border-radius: 10rpx;
overflow: hidden;
background-color: #f5f5f5;
.avatar-img {
width: 100%;
height: 100%;
}
}
.group-info {
flex: 1;
.group-name {
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 4rpx;
}
.group-id {
font-size: 26rpx;
color: #999;
margin-bottom: 4rpx;
}
.group-member-count {
font-size: 26rpx;
color: #999;
}
}
}
}
.action-buttons {
display: flex;
padding: 20rpx 30rpx;
border-top: 1px solid #f0f0f0;
.cancel-btn, .confirm-btn {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 40rpx;
font-size: 30rpx;
}
.cancel-btn {
background-color: #f5f5f5;
color: #666;
margin-right: 20rpx;
}
.confirm-btn {
background-color: #4080ff;
color: #fff;
}
}
}
</style>

View File

@@ -0,0 +1,504 @@
<template>
<view class="detail-container">
<!-- 顶部导航栏 -->
<view class="header">
<view class="back-icon" @click="goBack">
<u-icon name="arrow-left" size="42" color="black"></u-icon>
</view>
<view class="title">内容库详情</view>
<view class="header-right">
<view class="save-btn" @click="saveContent">
<u-icon name="checkbox-mark" size="28" color="#fff"></u-icon>
<text class="save-text">保存</text>
</view>
</view>
</view>
<!-- 表单内容 -->
<view class="form-container">
<!-- 内容库名称 -->
<view class="form-item">
<view class="form-label">内容库名称</view>
<view class="form-input-box">
<input type="text" v-model="form.title" placeholder="示例内容库" class="form-input" />
</view>
</view>
<!-- 数据来源配置 -->
<view class="form-item">
<view class="form-label">数据来源配置</view>
<view class="source-buttons">
<view class="source-btn" :class="{ active: form.dataSource === 'friend' }" @click="setDataSource('friend')">
<text>选择微信好友</text>
</view>
<view class="source-btn" :class="{ active: form.dataSource === 'group' }" @click="setDataSource('group')">
<text>选择聊天群</text>
</view>
</view>
<!-- 当选择微信好友时显示 -->
<view class="friend-list-box" v-if="form.dataSource === 'friend'">
<view class="friend-select-btn" @click="showFriendSelector">
<text>选择微信好友</text>
</view>
<view class="selected-friends" v-if="form.selectedFriends.length > 0">
<view class="friend-tag" v-for="(friend, index) in form.selectedFriends" :key="index">
<text>{{friend.name || friend}}</text>
</view>
</view>
</view>
<!-- 当选择聊天群时显示 -->
<view class="group-list-box" v-if="form.dataSource === 'group'">
<view class="group-select-btn" @click="showGroupSelector">
<text>选择聊天群</text>
</view>
<view class="selected-groups" v-if="form.selectedGroups.length > 0">
<view class="group-tag" v-for="(group, index) in form.selectedGroups" :key="index">
<text>{{group.name || group}}</text>
</view>
</view>
</view>
</view>
<!-- 关键字设置 -->
<view class="form-item">
<view class="form-label">
<text>关键字设置</text>
<u-icon name="arrow-down" size="28" color="#666" @click="toggleKeywordSection"></u-icon>
</view>
</view>
<!-- 是否启用AI -->
<view class="form-item">
<view class="form-label-with-desc">
<view class="label-row">
<text>是否启用AI</text>
<u-switch v-model="form.enableAI" activeColor="#4080ff"></u-switch>
</view>
<view class="label-desc">
<text>当启用AI之后该内容库下的所有内容都会通过AI重新生成内容</text>
</view>
</view>
</view>
<!-- AI提示词 -->
<view class="form-item" v-if="form.enableAI">
<view class="form-label">AI 提示词</view>
<view class="form-textarea-box">
<textarea v-model="form.aiPrompt" placeholder="AI提示词示例" class="form-textarea" />
</view>
</view>
<!-- 时间限制 -->
<view class="form-item">
<view class="form-label">时间限制</view>
<view class="form-date-box" @click="showDatePicker">
<u-icon name="calendar" size="28" color="#666"></u-icon>
<text class="date-text">{{form.dateRange || '选择日期范围'}}</text>
</view>
</view>
<!-- 是否启用 -->
<view class="form-item">
<view class="form-label-with-switch">
<text>是否启用</text>
<u-switch v-model="form.isEnabled" activeColor="#4080ff"></u-switch>
</view>
</view>
</view>
<!-- 底部导航栏 -->
<CustomTabBar active="work"></CustomTabBar>
<!-- 微信好友选择器 -->
<FriendSelector
:show="showFriendSelectorFlag"
:selected="selectedFriendIds"
:multiple="true"
@update:show="showFriendSelectorFlag = $event"
@confirm="handleFriendConfirm"
@cancel="showFriendSelectorFlag = false"
/>
<!-- 聊天群选择器 -->
<GroupSelector
:show="showGroupSelectorFlag"
:selected="selectedGroupIds"
:multiple="true"
@update:show="showGroupSelectorFlag = $event"
@confirm="handleGroupConfirm"
@cancel="showGroupSelectorFlag = false"
/>
</view>
</template>
<script>
import CustomTabBar from '@/components/CustomTabBar.vue'
import FriendSelector from './components/FriendSelector.vue'
import GroupSelector from './components/GroupSelector.vue'
export default {
components: {
CustomTabBar,
FriendSelector,
GroupSelector
},
data() {
return {
id: '', // 编辑时的内容库ID
form: {
title: '', // 内容库名称
dataSource: 'friend', // 数据来源: friend-微信好友, group-聊天群
selectedFriends: [], // 已选择的好友
selectedGroups: [], // 已选择的群组
enableAI: true, // 是否启用AI
aiPrompt: 'AI提示词示例', // AI提示词
isKeywordExpanded: false, // 关键字设置是否展开
dateRange: '', // 时间限制
isEnabled: true // 是否启用
},
isEdit: false, // 是否为编辑模式
showFriendSelectorFlag: false, // 是否显示好友选择器
showGroupSelectorFlag: false, // 是否显示群组选择器
}
},
computed: {
// 获取已选择的好友ID列表
selectedFriendIds() {
return this.form.selectedFriends.map(friend => {
return typeof friend === 'object' ? friend.id : friend;
});
},
// 获取已选择的群组ID列表
selectedGroupIds() {
return this.form.selectedGroups.map(group => {
return typeof group === 'object' ? group.id : group;
});
}
},
onLoad(options) {
if (options.id) {
this.id = options.id;
this.isEdit = true;
this.loadContentDetail();
}
},
methods: {
// 返回上一页
goBack() {
uni.navigateBack();
},
// 设置数据来源
setDataSource(source) {
this.form.dataSource = source;
},
// 显示好友选择器
showFriendSelector() {
this.showFriendSelectorFlag = true;
},
// 显示群组选择器
showGroupSelector() {
this.showGroupSelectorFlag = true;
},
// 处理好友选择确认
handleFriendConfirm(selectedFriends) {
this.form.selectedFriends = selectedFriends;
},
// 处理群组选择确认
handleGroupConfirm(selectedGroups) {
this.form.selectedGroups = selectedGroups;
},
// 切换关键字设置区域
toggleKeywordSection() {
this.form.isKeywordExpanded = !this.form.isKeywordExpanded;
},
// 显示日期选择器
showDatePicker() {
// 这里应该调用日期选择器组件
uni.showToast({
title: '日期选择功能开发中',
icon: 'none'
});
},
// 保存内容库
saveContent() {
// 表单验证
if (!this.form.title) {
uni.showToast({
title: '请输入内容库名称',
icon: 'none'
});
return;
}
// 验证是否选择了数据来源
if (this.form.dataSource === 'friend' && this.form.selectedFriends.length === 0) {
uni.showToast({
title: '请选择微信好友',
icon: 'none'
});
return;
}
if (this.form.dataSource === 'group' && this.form.selectedGroups.length === 0) {
uni.showToast({
title: '请选择聊天群',
icon: 'none'
});
return;
}
// 在实际应用中,这里应该提交表单数据到服务器
uni.showLoading({
title: '保存中...'
});
// 模拟API请求
setTimeout(() => {
uni.hideLoading();
uni.showToast({
title: '保存成功',
icon: 'success'
});
// 返回上一页
setTimeout(() => {
uni.navigateBack();
}, 1500);
}, 1000);
},
// 加载内容库详情数据
loadContentDetail() {
// 在实际应用中,这里应该从服务器获取内容库详情
console.log('加载内容库详情:', this.id);
// 模拟数据加载
if (this.isEdit) {
// 模拟已有数据
this.form = {
title: '示例内容库',
dataSource: 'friend',
selectedFriends: ['张三', '李四'],
selectedGroups: [],
enableAI: true,
aiPrompt: 'AI提示词示例',
isKeywordExpanded: false,
dateRange: '',
isEnabled: true
};
}
}
}
}
</script>
<style lang="scss" scoped>
.detail-container {
min-height: 100vh;
background-color: #f9fafb;
padding-bottom: 150rpx; /* 为底部导航栏预留空间 */
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 25rpx 30rpx;
background-color: #fff;
border-bottom: 1px solid #f0f0f0;
.back-icon {
width: 60rpx;
color: #000;
padding: 10rpx;
border-radius: 50%;
&:active {
background-color: rgba(0, 0, 0, 0.05);
}
}
.title {
font-size: 38rpx;
font-weight: 600;
margin-left: -60rpx; /* 使标题居中 */
flex: 1;
text-align: center;
}
.header-right {
.save-btn {
display: flex;
align-items: center;
justify-content: center;
background-color: #4080ff;
border-radius: 30rpx;
padding: 12rpx 24rpx;
color: #fff;
.save-text {
font-size: 28rpx;
}
}
}
}
.form-container {
padding: 20rpx 30rpx;
.form-item {
background-color: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 20rpx;
.form-label {
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.form-label-with-desc {
.label-row {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 10rpx;
}
.label-desc {
font-size: 24rpx;
color: #999;
line-height: 1.4;
}
}
.form-label-with-switch {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 30rpx;
font-weight: 500;
color: #333;
}
.form-input-box {
.form-input {
width: 100%;
height: 80rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
}
}
.form-textarea-box {
.form-textarea {
width: 100%;
height: 200rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 20rpx;
font-size: 28rpx;
}
}
.source-buttons {
display: flex;
margin-bottom: 20rpx;
.source-btn {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #f5f5f5;
font-size: 28rpx;
color: #666;
&:first-child {
border-top-left-radius: 8rpx;
border-bottom-left-radius: 8rpx;
border-right: 1px solid #e0e0e0;
}
&:last-child {
border-top-right-radius: 8rpx;
border-bottom-right-radius: 8rpx;
}
&.active {
background-color: #e6f7ff;
color: #4080ff;
font-weight: 500;
}
}
}
.friend-list-box, .group-list-box {
.friend-select-btn, .group-select-btn {
width: 100%;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #f5f5f5;
border-radius: 8rpx;
font-size: 28rpx;
color: #666;
margin-bottom: 20rpx;
}
.selected-friends, .selected-groups {
display: flex;
flex-wrap: wrap;
.friend-tag, .group-tag {
background-color: #f5f5f5;
border-radius: 30rpx;
padding: 10rpx 20rpx;
margin-right: 15rpx;
margin-bottom: 15rpx;
font-size: 26rpx;
color: #666;
}
}
}
.form-date-box {
width: 100%;
height: 80rpx;
display: flex;
align-items: center;
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 0 20rpx;
.date-text {
margin-left: 10rpx;
font-size: 28rpx;
color: #999;
}
}
}
}
</style>

View File

@@ -0,0 +1,741 @@
<template>
<view class="content-container">
<!-- 顶部导航栏 -->
<view class="header">
<view class="back-icon" @click="goBack">
<u-icon name="arrow-left" size="42" color="black"></u-icon>
</view>
<view class="title">内容库</view>
<view class="header-right">
<view class="add-btn" @click="createContent">
<text class="add-icon">+</text>
<text class="add-text">新建</text>
</view>
</view>
</view>
<!-- 内容区 -->
<view class="content-wrapper">
<!-- 搜索框 -->
<view class="search-box">
<u-search
v-model="searchKeyword"
placeholder="搜索内容库..."
:showAction="false"
shape="round"
:clearabled="true"
height="70"
bgColor="#f4f4f4"
></u-search>
<view class="filter-btn" @click="showFilter">
<u-icon name="filter" size="36" color="#000"></u-icon>
</view>
<view class="refresh-btn" @click="refreshData">
<u-icon name="reload" size="36" color="#000"></u-icon>
</view>
</view>
<!-- 标签页 -->
<view class="tabs">
<view
class="tab-item"
:class="{ active: currentTab === 'all' }"
@click="switchTab('all')"
>
全部
</view>
<view
class="tab-item"
:class="{ active: currentTab === 'friends' }"
@click="switchTab('friends')"
>
微信好友
</view>
<view
class="tab-item"
:class="{ active: currentTab === 'groups' }"
@click="switchTab('groups')"
>
聊天群
</view>
</view>
<!-- 内容列表 -->
<view class="content-list" v-if="filteredContents.length > 0">
<view class="content-item" v-for="(item, index) in filteredContents" :key="index">
<view class="content-header">
<text class="content-title">{{item.title}}</text>
<view class="usage-tag" :class="item.used ? 'used' : 'unused'">
{{item.used ? '已使用' : '未使用'}}
</view>
<view class="more-icon" @click.stop="showOptions(item)">
<u-icon name="more-dot-fill" size="32" color="#333"></u-icon>
</view>
</view>
<view class="content-info">
<view class="info-row">
<text class="info-label">来源</text>
<view class="source-avatars">
<image v-for="(avatar, i) in item.sourceAvatars" :key="i" :src="avatar" mode="aspectFill" class="source-avatar"></image>
</view>
</view>
<view class="info-row">
<text class="info-label">创建人</text>
<text class="info-value">{{item.creator}}</text>
</view>
<view class="info-row">
<text class="info-label">内容数量</text>
<text class="info-value">{{item.contentCount}}</text>
</view>
<view class="info-row">
<text class="info-label">更新时间</text>
<text class="info-value">{{item.updateTime}}</text>
</view>
</view>
</view>
</view>
<!-- 加载中提示 -->
<view class="loading-container" v-else-if="loading">
<text class="loading-text">加载中...</text>
</view>
<!-- 空状态 -->
<view class="empty-container" v-else>
<image src="/static/images/empty.png" mode="aspectFit" class="empty-img"></image>
<text class="empty-text">暂无内容</text>
</view>
</view>
<!-- 底部导航栏 -->
<CustomTabBar active="work"></CustomTabBar>
<!-- 筛选弹窗 -->
<u-popup :show="showFilterPopup" @close="closeFilterPopup" mode="bottom">
<view class="popup-content">
<view class="popup-header">
<text class="popup-title">筛选条件</text>
<view class="popup-close" @click="closeFilterPopup">
<u-icon name="close" size="28" color="#999"></u-icon>
</view>
</view>
<view class="popup-body">
<view class="filter-section">
<view class="filter-title">使用状态</view>
<view class="filter-options">
<view
class="filter-option"
:class="{ active: selectedUsage === 'all' }"
@click="selectUsage('all')"
>
全部
</view>
<view
class="filter-option"
:class="{ active: selectedUsage === 'used' }"
@click="selectUsage('used')"
>
已使用
</view>
<view
class="filter-option"
:class="{ active: selectedUsage === 'unused' }"
@click="selectUsage('unused')"
>
未使用
</view>
</view>
</view>
<view class="filter-section">
<view class="filter-title">更新时间</view>
<view class="filter-options">
<view
class="filter-option"
:class="{ active: selectedTime === 'all' }"
@click="selectTime('all')"
>
全部时间
</view>
<view
class="filter-option"
:class="{ active: selectedTime === 'today' }"
@click="selectTime('today')"
>
今天
</view>
<view
class="filter-option"
:class="{ active: selectedTime === 'week' }"
@click="selectTime('week')"
>
本周
</view>
<view
class="filter-option"
:class="{ active: selectedTime === 'month' }"
@click="selectTime('month')"
>
本月
</view>
</view>
</view>
<view class="filter-buttons">
<view class="reset-btn" @click="resetFilter">重置</view>
<view class="confirm-btn" @click="applyFilter">确定</view>
</view>
</view>
</view>
</u-popup>
<!-- 内容操作弹窗 -->
<u-popup :show="showActionPopup" @close="closeActionPopup" mode="bottom">
<view class="action-list">
<view class="action-item" @click="editContent">
<u-icon name="edit-pen" size="32" color="#333"></u-icon>
<text>编辑内容</text>
</view>
<view class="action-item" @click="shareContent">
<u-icon name="share" size="32" color="#333"></u-icon>
<text>分享内容</text>
</view>
<view class="action-item delete" @click="deleteContent">
<u-icon name="trash" size="32" color="#fa5151"></u-icon>
<text>删除内容</text>
</view>
<view class="action-item cancel" @click="closeActionPopup">
<text>取消</text>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import CustomTabBar from '@/components/CustomTabBar.vue'
export default {
components: {
CustomTabBar
},
data() {
return {
searchKeyword: '',
currentTab: 'all',
showFilterPopup: false,
showActionPopup: false,
selectedUsage: 'all',
selectedTime: 'all',
tempSelectedUsage: 'all',
tempSelectedTime: 'all',
loading: true,
currentContent: null,
contents: [
{
id: 1,
title: '微信好友广告',
used: true,
sourceAvatars: ['/static/images/avatar.png'],
creator: '海尼',
contentCount: 0,
updateTime: '2024-02-09 12:30'
},
{
id: 2,
title: '开发群',
used: true,
sourceAvatars: ['/static/images/avatar.png'],
creator: 'karuo',
contentCount: 0,
updateTime: '2024-02-09 12:30'
}
]
}
},
computed: {
filteredContents() {
let result = [...this.contents];
// 搜索关键词筛选
if (this.searchKeyword) {
result = result.filter(item =>
item.title.includes(this.searchKeyword) ||
item.creator.includes(this.searchKeyword)
);
}
// 标签页筛选
if (this.currentTab === 'friends') {
result = result.filter(item => item.title.includes('好友'));
} else if (this.currentTab === 'groups') {
result = result.filter(item => item.title.includes('群'));
}
// 使用状态筛选
if (this.selectedUsage === 'used') {
result = result.filter(item => item.used);
} else if (this.selectedUsage === 'unused') {
result = result.filter(item => !item.used);
}
// 时间筛选
if (this.selectedTime !== 'all') {
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
const weekAgo = today - 7 * 24 * 60 * 60 * 1000;
const monthAgo = new Date(now.getFullYear(), now.getMonth() - 1, now.getDate()).getTime();
result = result.filter(item => {
const itemTime = new Date(item.updateTime).getTime();
if (this.selectedTime === 'today') {
return itemTime >= today;
} else if (this.selectedTime === 'week') {
return itemTime >= weekAgo;
} else if (this.selectedTime === 'month') {
return itemTime >= monthAgo;
}
return true;
});
}
return result;
}
},
onLoad() {
this.loadData();
},
methods: {
// 返回上一页
goBack() {
uni.navigateBack();
},
// 刷新数据
refreshData() {
this.loading = true;
setTimeout(() => {
this.loading = false;
uni.showToast({
title: '刷新成功',
icon: 'none'
});
}, 1000);
},
// 显示筛选弹窗
showFilter() {
this.tempSelectedUsage = this.selectedUsage;
this.tempSelectedTime = this.selectedTime;
this.showFilterPopup = true;
},
// 关闭筛选弹窗
closeFilterPopup() {
this.showFilterPopup = false;
},
// 切换标签页
switchTab(tab) {
this.currentTab = tab;
},
// 选择使用状态
selectUsage(usage) {
this.tempSelectedUsage = usage;
},
// 选择时间范围
selectTime(time) {
this.tempSelectedTime = time;
},
// 重置筛选条件
resetFilter() {
this.tempSelectedUsage = 'all';
this.tempSelectedTime = 'all';
},
// 应用筛选条件
applyFilter() {
this.selectedUsage = this.tempSelectedUsage;
this.selectedTime = this.tempSelectedTime;
this.closeFilterPopup();
},
// 显示内容操作弹窗
showOptions(content) {
this.currentContent = content;
this.showActionPopup = true;
},
// 关闭内容操作弹窗
closeActionPopup() {
this.showActionPopup = false;
},
// 创建内容
createContent() {
uni.navigateTo({
url: '/pages/content/detail'
});
},
// 编辑内容
editContent() {
uni.showToast({
title: `编辑内容:${this.currentContent.title}`,
icon: 'none'
});
this.closeActionPopup();
},
// 分享内容
shareContent() {
uni.showToast({
title: `分享内容:${this.currentContent.title}`,
icon: 'none'
});
this.closeActionPopup();
},
// 删除内容
deleteContent() {
uni.showModal({
title: '提示',
content: `确定要删除内容"${this.currentContent.title}"吗?`,
success: (res) => {
if (res.confirm) {
this.contents = this.contents.filter(item => item.id !== this.currentContent.id);
uni.showToast({
title: '删除成功',
icon: 'success'
});
}
this.closeActionPopup();
}
});
},
// 加载数据
loadData() {
this.loading = true;
setTimeout(() => {
this.loading = false;
}, 1000);
}
}
}
</script>
<style lang="scss" scoped>
.content-container {
min-height: 100vh;
background-color: #f9fafb;
padding-bottom: 150rpx; /* 为底部导航栏预留空间 */
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 25rpx 30rpx;
background-color: #fff;
border-bottom: 1px solid #f0f0f0;
.back-icon {
width: 60rpx;
color: #000;
padding: 10rpx;
border-radius: 50%;
&:active {
background-color: rgba(0, 0, 0, 0.05);
}
}
.title {
font-size: 38rpx;
font-weight: 600;
margin-left: -60rpx; /* 使标题居中 */
flex: 1;
text-align: center;
}
.header-right {
.add-btn {
display: flex;
align-items: center;
justify-content: center;
background-color: #4080ff;
border-radius: 30rpx;
padding: 12rpx 24rpx;
color: #fff;
.add-icon {
font-size: 36rpx;
font-weight: bold;
margin-right: 6rpx;
line-height: 1;
}
.add-text {
font-size: 28rpx;
}
}
}
}
.content-wrapper {
padding: 20rpx 0;
}
.search-box {
display: flex;
align-items: center;
padding: 0 30rpx 20rpx;
.u-search {
flex: 1;
}
.filter-btn, .refresh-btn {
margin-left: 20rpx;
padding: 10rpx;
}
}
.tabs {
display: flex;
margin: 0 30rpx 20rpx;
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
.tab-item {
flex: 1;
text-align: center;
padding: 24rpx 0;
font-size: 28rpx;
color: #666;
&.active {
color: #4080ff;
font-weight: 500;
position: relative;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 4rpx;
background-color: #4080ff;
border-radius: 2rpx;
}
}
}
}
.content-list {
padding: 0 30rpx;
.content-item {
background-color: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
.content-header {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.content-title {
font-size: 32rpx;
font-weight: 500;
color: #333;
flex: 1;
}
.usage-tag {
font-size: 24rpx;
padding: 4rpx 12rpx;
border-radius: 8rpx;
margin-right: 16rpx;
&.used {
background-color: #e6f7ff;
color: #1890ff;
}
&.unused {
background-color: #f6ffed;
color: #52c41a;
}
}
.more-icon {
padding: 10rpx;
}
}
.content-info {
.info-row {
display: flex;
align-items: center;
margin-bottom: 10rpx;
font-size: 28rpx;
color: #666;
.info-label {
color: #999;
min-width: 150rpx;
}
.source-avatars {
display: flex;
.source-avatar {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
margin-right: 10rpx;
}
}
}
}
}
}
.loading-container, .empty-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 300rpx;
.loading-text, .empty-text {
font-size: 30rpx;
color: #999;
margin-top: 20rpx;
}
.empty-img {
width: 200rpx;
height: 200rpx;
}
}
.popup-content {
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #f0f0f0;
.popup-title {
font-size: 32rpx;
font-weight: 500;
}
.popup-close {
padding: 10rpx;
}
}
.popup-body {
padding: 30rpx;
.filter-section {
margin-bottom: 30rpx;
.filter-title {
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 20rpx;
}
.filter-options {
display: flex;
flex-wrap: wrap;
.filter-option {
padding: 16rpx 30rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
font-size: 28rpx;
color: #666;
margin-right: 20rpx;
margin-bottom: 20rpx;
&.active {
background-color: #e6f7ff;
color: #4080ff;
font-weight: 500;
}
}
}
}
.filter-buttons {
display: flex;
margin-top: 40rpx;
.reset-btn, .confirm-btn {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
border-radius: 8rpx;
}
.reset-btn {
background-color: #f5f5f5;
color: #666;
margin-right: 20rpx;
}
.confirm-btn {
background-color: #4080ff;
color: #fff;
}
}
}
}
.action-list {
background-color: #fff;
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
.action-item {
display: flex;
align-items: center;
justify-content: center;
padding: 30rpx 0;
font-size: 32rpx;
color: #333;
border-bottom: 1px solid #f5f5f5;
u-icon {
margin-right: 15rpx;
}
&.delete {
color: #fa5151;
}
&.cancel {
color: #666;
margin-top: 16rpx;
border-bottom: none;
}
}
}
</style>

View File

@@ -0,0 +1,668 @@
<template>
<view class="device-detail-container">
<!-- 顶部导航栏 -->
<view class="navbar">
<view class="navbar-left" @click="goBack">
<u-icon name="arrow-left" size="44" color="#333"></u-icon>
</view>
<text class="navbar-title">设备详情</text>
<view class="navbar-right">
<u-icon name="setting" size="44" color="#333" @click="openSettings"></u-icon>
</view>
</view>
<!-- 设备信息卡片 -->
<view class="device-card">
<view class="device-icon-box">
<u-icon name="smartphone" size="54" color="#4080ff"></u-icon>
</view>
<view class="device-title">
<text class="device-name">{{ deviceInfo.name }}</text>
<text class="device-status" :class="deviceInfo.status === '在线' ? 'online' : 'offline'">{{ deviceInfo.status }}</text>
</view>
<view class="device-info-row">
<text class="device-info-label">IMEI: </text>
<text class="device-info-value">{{ deviceInfo.imei }}</text>
</view>
<view class="device-info-row">
<text class="device-info-label">历史ID: </text>
<text class="device-info-value">{{ deviceInfo.historyId }}</text>
</view>
<view class="device-stats">
<!-- 电量指示器 -->
<view class="battery-indicator">
<u-icon name="integral" size="40" :color="deviceInfo.status === '在线' ? '#07c160' : '#909399'"></u-icon>
<text class="battery-percentage">{{ deviceInfo.battery }}</text>
</view>
<!-- 网络状态 -->
<view class="wifi-indicator">
<u-icon name="wifi" size="40" :color="deviceInfo.status === '在线' ? '#4080ff' : '#909399'"></u-icon>
<text class="wifi-status">{{ deviceInfo.wifiStatus }}</text>
</view>
</view>
<view class="device-last-active">
<text class="last-active-label">最后活跃: </text>
<text class="last-active-time">{{ deviceInfo.lastActive }}</text>
</view>
</view>
<!-- 标签切换栏 -->
<u-tabs
:list="tabsList"
:current="tabCurrent"
@change="handleTabChange"
activeStyle="color: #333; font-weight: bold;"
inactiveStyle="color: #888;"
itemStyle="height: 90rpx; font-size: 30rpx;"
lineColor="#4080ff"
lineWidth="60rpx"
lineHeight="4rpx"
></u-tabs>
<!-- 基本信息内容 -->
<view v-if="tabCurrent === 0" class="tab-content">
<view class="features-list">
<!-- 自动加好友 -->
<view class="feature-item">
<view class="feature-left">
<text class="feature-title">自动加好友</text>
<text class="feature-desc">自动通过好友验证</text>
</view>
<view class="feature-right">
<u-switch v-model="features.autoAddFriend" activeColor="#4080ff"></u-switch>
</view>
</view>
<!-- 自动回复 -->
<view class="feature-item">
<view class="feature-left">
<text class="feature-title">自动回复</text>
<text class="feature-desc">自动回复好友消息</text>
</view>
<view class="feature-right">
<u-switch v-model="features.autoReply" activeColor="#4080ff"></u-switch>
</view>
</view>
<!-- 朋友圈同步 -->
<view class="feature-item">
<view class="feature-left">
<text class="feature-title">朋友圈同步</text>
<text class="feature-desc">自动同步朋友圈内容</text>
</view>
<view class="feature-right">
<u-switch v-model="features.momentSync" activeColor="#4080ff"></u-switch>
</view>
</view>
<!-- AI会话 -->
<view class="feature-item">
<view class="feature-left">
<text class="feature-title">AI会话</text>
<text class="feature-desc">启用AI智能对话</text>
</view>
<view class="feature-right">
<u-switch v-model="features.aiChat" activeColor="#4080ff"></u-switch>
</view>
</view>
</view>
<!-- 统计数据卡片 -->
<view class="stats-container">
<view class="stats-card">
<view class="stats-icon">
<u-icon name="account" size="40" color="#4080ff"></u-icon>
</view>
<text class="stats-title">好友总数</text>
<text class="stats-value">768</text>
</view>
<view class="stats-card">
<view class="stats-icon">
<u-icon name="chat" size="40" color="#4080ff"></u-icon>
</view>
<text class="stats-title">消息数量</text>
<text class="stats-value">5,678</text>
</view>
</view>
</view>
<!-- 关联账号内容 -->
<view v-if="tabCurrent === 1" class="tab-content">
<view class="wechat-accounts-list">
<!-- 账号项 1 -->
<view class="wechat-account-item">
<view class="wechat-avatar">
<u-avatar src="/static/images/avatar.png" size="80"></u-avatar>
</view>
<view class="wechat-info">
<view class="wechat-name-row">
<text class="wechat-name">老张</text>
<text class="wechat-status normal">正常</text>
</view>
<view class="wechat-id-row">
<text class="wechat-id-label">微信号: </text>
<text class="wechat-id-value">wxid_abc123</text>
</view>
<view class="wechat-gender-row">
<text class="wechat-gender-label">性别: </text>
<text class="wechat-gender-value"></text>
</view>
<view class="wechat-friends-row">
<text class="wechat-friends-label">好友数: </text>
<text class="wechat-friends-value">523</text>
<text class="wechat-add-friends">可加友</text>
</view>
</view>
</view>
<!-- 账号项 2 -->
<view class="wechat-account-item">
<view class="wechat-avatar">
<u-avatar src="/static/images/avatar.png" size="80"></u-avatar>
</view>
<view class="wechat-info">
<view class="wechat-name-row">
<text class="wechat-name">老李</text>
<text class="wechat-status warning">异常</text>
</view>
<view class="wechat-id-row">
<text class="wechat-id-label">微信号: </text>
<text class="wechat-id-value">wxid_xyz789</text>
</view>
<view class="wechat-gender-row">
<text class="wechat-gender-label">性别: </text>
<text class="wechat-gender-value"></text>
</view>
<view class="wechat-friends-row">
<text class="wechat-friends-label">好友数: </text>
<text class="wechat-friends-value">245</text>
<text class="wechat-add-friends used">已使用</text>
</view>
</view>
</view>
</view>
</view>
<!-- 操作记录内容 -->
<view v-if="tabCurrent === 2" class="tab-content">
<view class="operation-logs">
<!-- 操作记录项 1 -->
<view class="operation-item">
<view class="operation-icon">
<u-icon name="reload" size="36" color="#4080ff"></u-icon>
</view>
<view class="operation-info">
<text class="operation-title">开启自动加好友</text>
<text class="operation-meta">操作人: 系统 · 2024-02-09 15:30:45</text>
</view>
</view>
<!-- 操作记录项 2 -->
<view class="operation-item">
<view class="operation-icon">
<u-icon name="reload" size="36" color="#4080ff"></u-icon>
</view>
<view class="operation-info">
<text class="operation-title">添加微信号</text>
<text class="operation-meta">操作人: 管理员 · 2024-02-09 14:20:33</text>
</view>
</view>
</view>
</view>
<!-- 底部导航栏 -->
<CustomTabBar active="home"></CustomTabBar>
</view>
</template>
<script>
import CustomTabBar from '@/components/CustomTabBar.vue';
export default {
components: {
CustomTabBar
},
data() {
return {
tabsList: [
{ name: '基本信息' },
{ name: '关联账号' },
{ name: '操作记录' }
],
tabCurrent: 0,
features: {
autoAddFriend: true,
autoReply: true,
momentSync: false,
aiChat: true
},
deviceInfo: {
name: '设备 1',
imei: 'sd123123',
historyId: 'vx412321, vfbadasd',
battery: '85%',
wifiStatus: '已连接',
lastActive: '2024-02-09 15:30:45',
status: '在线'
},
wechatAccounts: [
{
avatar: '/static/images/avatar.png',
name: '老张',
status: '正常',
id: 'wxid_abc123',
gender: '男',
friends: 523,
canAddFriends: true
},
{
avatar: '/static/images/avatar.png',
name: '老李',
status: '异常',
id: 'wxid_xyz789',
gender: '男',
friends: 245,
canAddFriends: false
}
],
operationLogs: [
{
title: '开启自动加好友',
operator: '系统',
time: '2024-02-09 15:30:45'
},
{
title: '添加微信号',
operator: '管理员',
time: '2024-02-09 14:20:33'
}
],
deviceId: null
}
},
onLoad(options) {
// 获取路由参数中的设备ID
if (options && options.id) {
this.deviceId = options.id;
console.log('设备ID:', this.deviceId);
}
// 加载设备详情数据
this.loadDeviceDetail();
},
methods: {
goBack() {
uni.navigateBack();
},
openSettings() {
uni.showToast({
title: '设置功能即将上线',
icon: 'none',
duration: 2000
});
},
handleTabChange(index) {
this.tabCurrent = index;
},
loadDeviceDetail() {
// 这里模拟API调用获取设备详情数据
uni.showLoading({
title: '加载中...'
});
// 模拟网络请求延迟
setTimeout(() => {
// 根据设备ID获取不同的设备数据
// 在实际应用中,这里应该是从服务器获取数据
if (this.deviceId) {
// 使用预设数据实际项目中应替换为API调用
console.log('加载设备ID为', this.deviceId, '的详情数据');
// 模拟不同的设备数据
if (this.deviceId === '1') {
// 设备1数据保持不变已在data中预设
} else if (this.deviceId === '2') {
this.deviceInfo.name = '设备 2';
this.deviceInfo.imei = 'sd123124';
this.deviceInfo.battery = '65%';
this.deviceInfo.lastActive = '2024-02-08 10:15:23';
} else if (this.deviceId === '3') {
this.deviceInfo.name = '设备 3';
this.deviceInfo.imei = 'sd123125';
this.deviceInfo.battery = '92%';
this.deviceInfo.lastActive = '2024-02-09 08:45:12';
} else if (this.deviceId === '4') {
this.deviceInfo.name = '设备 4';
this.deviceInfo.imei = 'sd123126';
this.deviceInfo.battery = '23%';
this.deviceInfo.status = '离线';
this.deviceInfo.wifiStatus = '未连接';
this.deviceInfo.lastActive = '2024-02-07 16:20:35';
}
}
uni.hideLoading();
}, 500);
}
}
}
</script>
<style lang="scss" scoped>
.device-detail-container {
min-height: 100vh;
background-color: #f9fafb;
padding-bottom: 150rpx; /* 为底部导航栏预留空间 */
}
/* 顶部导航栏 */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 25rpx 30rpx;
background-color: #fff;
position: relative;
.navbar-left {
width: 80rpx;
}
.navbar-title {
font-size: 36rpx;
font-weight: bold;
}
.navbar-right {
width: 80rpx;
display: flex;
justify-content: flex-end;
}
}
/* 设备信息卡片 */
.device-card {
margin: 20rpx;
padding: 30rpx;
background-color: #fff;
border-radius: 16rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
.device-icon-box {
display: flex;
justify-content: center;
align-items: center;
width: 120rpx;
height: 120rpx;
border-radius: 60rpx;
background-color: #f0f5ff;
margin: 0 auto;
}
.device-title {
display: flex;
justify-content: center;
align-items: center;
margin: 16rpx 0;
.device-name {
font-size: 36rpx;
font-weight: bold;
margin-right: 16rpx;
}
.device-status {
font-size: 26rpx;
padding: 4rpx 16rpx;
border-radius: 20rpx;
&.online {
background-color: rgba(7, 193, 96, 0.1);
color: #07c160;
}
&.offline {
background-color: rgba(144, 147, 153, 0.1);
color: #909399;
}
}
}
.device-info-row {
display: flex;
justify-content: center;
margin: 8rpx 0;
font-size: 28rpx;
color: #666;
.device-info-value {
color: #333;
}
}
.device-stats {
display: flex;
justify-content: center;
margin: 20rpx 0;
.battery-indicator, .wifi-indicator {
display: flex;
align-items: center;
margin: 0 30rpx;
.battery-percentage, .wifi-status {
margin-left: 8rpx;
font-size: 28rpx;
color: #333;
}
}
}
.device-last-active {
text-align: center;
font-size: 26rpx;
color: #999;
margin-top: 16rpx;
.last-active-time {
color: #666;
}
}
}
/* 选项卡内容 */
.tab-content {
padding: 20rpx;
}
/* 功能设置列表 */
.features-list {
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
margin-bottom: 30rpx;
.feature-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.feature-left {
display: flex;
flex-direction: column;
.feature-title {
font-size: 32rpx;
color: #333;
margin-bottom: 4rpx;
}
.feature-desc {
font-size: 24rpx;
color: #999;
}
}
}
}
/* 统计数据卡片 */
.stats-container {
display: flex;
justify-content: space-between;
.stats-card {
flex: 1;
background-color: #fff;
border-radius: 16rpx;
padding: 30rpx;
margin: 0 10rpx;
text-align: center;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
.stats-icon {
margin-bottom: 16rpx;
}
.stats-title {
font-size: 26rpx;
color: #666;
display: block;
margin-bottom: 10rpx;
}
.stats-value {
font-size: 48rpx;
color: #4080ff;
font-weight: bold;
font-family: 'Digital-Bold', sans-serif;
}
}
}
/* 微信账号列表 */
.wechat-accounts-list {
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
.wechat-account-item {
display: flex;
padding: 30rpx;
border-bottom: 1rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.wechat-avatar {
margin-right: 20rpx;
}
.wechat-info {
flex: 1;
.wechat-name-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
.wechat-name {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.wechat-status {
font-size: 24rpx;
padding: 4rpx 16rpx;
border-radius: 20rpx;
&.normal {
background-color: rgba(7, 193, 96, 0.1);
color: #07c160;
}
&.warning {
background-color: rgba(250, 81, 81, 0.1);
color: #fa5151;
}
}
}
.wechat-id-row, .wechat-gender-row, .wechat-friends-row {
font-size: 26rpx;
color: #666;
margin: 6rpx 0;
}
.wechat-friends-row {
display: flex;
justify-content: space-between;
align-items: center;
.wechat-add-friends {
padding: 4rpx 16rpx;
border-radius: 20rpx;
font-size: 24rpx;
&:not(.used) {
background-color: rgba(7, 193, 96, 0.1);
color: #07c160;
}
&.used {
background-color: rgba(144, 147, 153, 0.1);
color: #909399;
}
}
}
}
}
}
/* 操作记录 */
.operation-logs {
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
.operation-item {
display: flex;
padding: 30rpx;
border-bottom: 1rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.operation-icon {
margin-right: 20rpx;
}
.operation-info {
flex: 1;
.operation-title {
font-size: 30rpx;
color: #333;
margin-bottom: 6rpx;
}
.operation-meta {
font-size: 24rpx;
color: #999;
}
}
}
}
</style>

View File

@@ -68,9 +68,9 @@
<!-- 设备列表 -->
<view class="device-list">
<!-- 设备项 1 -->
<view class="device-item">
<view class="device-item" @click="goToDeviceDetail(1)">
<view class="device-checkbox">
<u-checkbox size="40" iconSize="35" v-model="device1Selected" shape="circle" activeColor="#4080ff"></u-checkbox>
<u-checkbox size="40" iconSize="35" v-model="device1Selected" shape="circle" activeColor="#4080ff" @click.stop></u-checkbox>
</view>
<view class="device-info">
<view class="device-header">
@@ -87,10 +87,10 @@
</view>
<!-- 设备项 2 -->
<view class="device-item">
<view class="device-item" @click="goToDeviceDetail(2)">
<view class="device-checkbox">
<u-checkbox v-model="device2Selected" shape="circle" activeColor="#4080ff"
size="40" iconSize="35"
size="40" iconSize="35" @click.stop
></u-checkbox>
</view>
<view class="device-info">
@@ -108,9 +108,9 @@
</view>
<!-- 设备项 3 -->
<view class="device-item">
<view class="device-item" @click="goToDeviceDetail(3)">
<view class="device-checkbox">
<u-checkbox size="40" iconSize="35" v-model="device3Selected" shape="circle" activeColor="#4080ff"></u-checkbox>
<u-checkbox size="40" iconSize="35" v-model="device3Selected" shape="circle" activeColor="#4080ff" @click.stop></u-checkbox>
</view>
<view class="device-info">
<view class="device-header">
@@ -127,9 +127,9 @@
</view>
<!-- 设备项 4 -->
<view class="device-item">
<view class="device-item" @click="goToDeviceDetail(4)">
<view class="device-checkbox">
<u-checkbox size="40" iconSize="35" v-model="device4Selected" shape="circle" activeColor="#4080ff"></u-checkbox>
<u-checkbox size="40" iconSize="35" v-model="device4Selected" shape="circle" activeColor="#4080ff" @click.stop></u-checkbox>
</view>
<view class="device-info">
<view class="device-header">
@@ -356,6 +356,13 @@ export default {
}
}
});
},
// 跳转到设备详情页
goToDeviceDetail(deviceId) {
uni.navigateTo({
url: `/pages/device/detail?id=${deviceId}`
});
}
},
watch: {

View File

@@ -0,0 +1,578 @@
<template>
<view class="traffic-create-container">
<!-- 顶部导航栏 -->
<view class="header">
<view class="back-icon" @click="goBack">
<u-icon name="arrow-left" size="42" color="black"></u-icon>
</view>
<view class="title">{{pageTitle}}</view>
<view class="header-right">
<view class="save-btn" @click="saveTraffic">
<text class="save-text">保存</text>
</view>
</view>
</view>
<!-- 表单内容 -->
<view class="form-container">
<!-- 流量包名称 -->
<view class="form-item">
<view class="form-label">流量包名称</view>
<view class="form-input-box">
<input type="text" v-model="form.title" placeholder="例如:普通流量包" class="form-input" />
</view>
</view>
<!-- 价格设置 -->
<view class="form-item">
<view class="form-label">价格设置/流量包</view>
<view class="form-input-box">
<input type="digit" v-model="form.price" placeholder="0.00" class="form-input" />
</view>
</view>
<!-- 流量规模 -->
<view class="form-item">
<view class="form-label">流量规模人数</view>
<view class="form-input-box">
<input type="number" v-model="form.quantity" placeholder="0" class="form-input" />
</view>
</view>
<!-- 标签管理 -->
<view class="form-item">
<view class="form-label">标签管理</view>
<view class="tags-container">
<view class="tags-list">
<view
v-for="(tag, index) in form.tags"
:key="index"
class="tag-item"
>
<text class="tag-text">{{tag}}</text>
<text class="tag-delete" @click="removeTag(index)">×</text>
</view>
<view class="tag-add" @click="showAddTagModal">
<text>+ 添加标签</text>
</view>
</view>
</view>
</view>
<!-- 流量来源 -->
<view class="form-item">
<view class="form-label">流量来源</view>
<view class="source-radios">
<view
class="source-radio"
:class="{ active: form.source === 'platform' }"
@click="form.source = 'platform'"
>
<view class="radio-dot">
<view class="inner-dot" v-if="form.source === 'platform'"></view>
</view>
<text>平台</text>
</view>
<view
class="source-radio"
:class="{ active: form.source === 'custom' }"
@click="form.source = 'custom'"
>
<view class="radio-dot">
<view class="inner-dot" v-if="form.source === 'custom'"></view>
</view>
<text>自定义</text>
</view>
</view>
</view>
<!-- 地区限制 -->
<view class="form-item">
<view class="form-label">地区限制</view>
<view class="region-select" @click="showRegionSelector">
<text>{{form.region || '选择地区'}}</text>
<u-icon name="arrow-right" size="28" color="#999"></u-icon>
</view>
</view>
<!-- 流量时间 -->
<view class="form-item">
<view class="form-label">流量时间</view>
<view class="datetime-select" @click="showDatetimePicker">
<text>{{form.datetime || '选择时间'}}</text>
<u-icon name="arrow-right" size="28" color="#999"></u-icon>
</view>
</view>
<!-- 流量限制 -->
<view class="form-item">
<view class="form-label-with-switch">
<text>流量限制</text>
<u-switch v-model="form.enableLimit" activeColor="#4080ff"></u-switch>
</view>
<view class="limit-input-box" v-if="form.enableLimit">
<input type="number" v-model="form.limitPerDay" placeholder="每日限制数量" class="form-input" />
</view>
</view>
</view>
<!-- 添加标签弹窗 -->
<u-popup :show="showTagModal" @close="hideAddTagModal" mode="center">
<view class="tag-modal">
<view class="tag-modal-header">
<text class="modal-title">添加标签</text>
</view>
<view class="tag-modal-body">
<input type="text" v-model="newTagText" placeholder="请输入标签名称" class="tag-input" />
</view>
<view class="tag-modal-footer">
<view class="modal-btn cancel-btn" @click="hideAddTagModal">取消</view>
<view class="modal-btn confirm-btn" @click="addNewTag">确定</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
export default {
data() {
return {
isEdit: false, // 是否为编辑模式
trafficId: null, // 流量包ID
form: {
title: '', // 流量包名称
price: '', // 价格
quantity: '', // 流量规模
tags: [], // 标签数组
source: 'platform', // 流量来源platform-平台custom-自定义
region: '', // 地区限制
datetime: '', // 流量时间
enableLimit: false, // 是否启用流量限制
limitPerDay: '' // 每日限制数量
},
showTagModal: false, // 是否显示添加标签弹窗
newTagText: '' // 新标签的文本
}
},
onLoad(options) {
// 判断是否为编辑模式
if (options.id) {
this.isEdit = true;
this.trafficId = options.id;
this.loadTrafficData();
}
},
computed: {
// 页面标题
pageTitle() {
return this.isEdit ? '编辑分发' : '新建分发';
}
},
methods: {
// 加载流量包数据
loadTrafficData() {
uni.showLoading({
title: '加载中...'
});
// 模拟API请求获取数据
setTimeout(() => {
// 根据ID获取对应的数据
// 这里使用模拟数据
let mockData = {
1: {
title: '普通流量包',
price: '0.50',
quantity: '10',
tags: ['新用户', '低活跃度', '全国'],
source: 'platform',
region: '全国',
datetime: '2023-09-01',
enableLimit: true,
limitPerDay: '5'
},
2: {
title: '高质量流量',
price: '2.50',
quantity: '25',
tags: ['高消费', '高活跃度', '一线城市'],
source: 'custom',
region: '一线城市',
datetime: '2023-09-05',
enableLimit: false,
limitPerDay: ''
},
3: {
title: '精准营销流量',
price: '3.80',
quantity: '50',
tags: ['潜在客户', '有购买意向', '华东地区'],
source: 'platform',
region: '华东地区',
datetime: '2023-09-10',
enableLimit: true,
limitPerDay: '10'
}
};
// 获取数据并填充表单
if (mockData[this.trafficId]) {
this.form = mockData[this.trafficId];
uni.hideLoading();
} else {
uni.hideLoading();
uni.showToast({
title: '未找到对应数据',
icon: 'none'
});
setTimeout(() => {
uni.navigateBack();
}, 1500);
}
}, 1000);
},
// 返回上一页
goBack() {
uni.navigateBack();
},
// 保存流量包
saveTraffic() {
// 表单验证
if (!this.form.title) {
uni.showToast({
title: '请输入流量包名称',
icon: 'none'
});
return;
}
if (!this.form.price) {
uni.showToast({
title: '请输入价格',
icon: 'none'
});
return;
}
if (!this.form.quantity) {
uni.showToast({
title: '请输入流量规模',
icon: 'none'
});
return;
}
// 在实际应用中,这里应该提交表单数据到服务器
uni.showLoading({
title: this.isEdit ? '更新中...' : '保存中...'
});
// 模拟API请求
setTimeout(() => {
uni.hideLoading();
uni.showToast({
title: this.isEdit ? '更新成功' : '创建成功',
icon: 'success'
});
// 返回上一页
setTimeout(() => {
uni.navigateBack();
}, 1500);
}, 1000);
},
// 显示添加标签弹窗
showAddTagModal() {
this.showTagModal = true;
this.newTagText = '';
},
// 隐藏添加标签弹窗
hideAddTagModal() {
this.showTagModal = false;
},
// 添加新标签
addNewTag() {
if (this.newTagText.trim()) {
this.form.tags.push(this.newTagText.trim());
this.hideAddTagModal();
} else {
uni.showToast({
title: '标签名称不能为空',
icon: 'none'
});
}
},
// 删除标签
removeTag(index) {
this.form.tags.splice(index, 1);
},
// 显示地区选择器
showRegionSelector() {
// 这里应该调用地区选择器组件
uni.showToast({
title: '地区选择功能开发中',
icon: 'none'
});
},
// 显示时间选择器
showDatetimePicker() {
// 这里应该调用时间选择器组件
uni.showToast({
title: '时间选择功能开发中',
icon: 'none'
});
}
}
}
</script>
<style lang="scss" scoped>
.traffic-create-container {
min-height: 100vh;
background-color: #f9fafb;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 25rpx 30rpx;
background-color: #fff;
border-bottom: 1px solid #f0f0f0;
.back-icon {
width: 60rpx;
color: #000;
padding: 10rpx;
border-radius: 50%;
&:active {
background-color: rgba(0, 0, 0, 0.05);
}
}
.title {
font-size: 38rpx;
font-weight: 600;
margin-left: -60rpx; /* 使标题居中 */
flex: 1;
text-align: center;
}
.header-right {
.save-btn {
display: flex;
align-items: center;
justify-content: center;
background-color: #4080ff;
border-radius: 30rpx;
padding: 12rpx 24rpx;
color: #fff;
.save-text {
font-size: 28rpx;
}
}
}
}
.form-container {
padding: 20rpx 30rpx;
.form-item {
background-color: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 20rpx;
.form-label {
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 20rpx;
}
.form-label-with-switch {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 20rpx;
}
.form-input-box, .limit-input-box {
.form-input {
width: 100%;
height: 80rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
}
}
.tags-container {
.tags-list {
display: flex;
flex-wrap: wrap;
.tag-item {
display: flex;
align-items: center;
background-color: #f0f7ff;
border-radius: 8rpx;
padding: 10rpx 16rpx;
margin-right: 16rpx;
margin-bottom: 16rpx;
.tag-text {
font-size: 26rpx;
color: #4080ff;
}
.tag-delete {
font-size: 28rpx;
color: #999;
margin-left: 10rpx;
padding: 0 5rpx;
}
}
.tag-add {
display: flex;
align-items: center;
justify-content: center;
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 10rpx 16rpx;
margin-bottom: 16rpx;
text {
font-size: 26rpx;
color: #666;
}
}
}
}
.source-radios {
display: flex;
.source-radio {
display: flex;
align-items: center;
margin-right: 40rpx;
.radio-dot {
width: 36rpx;
height: 36rpx;
border-radius: 50%;
border: 2rpx solid #999;
margin-right: 10rpx;
display: flex;
align-items: center;
justify-content: center;
.inner-dot {
width: 20rpx;
height: 20rpx;
border-radius: 50%;
background-color: #4080ff;
}
}
text {
font-size: 28rpx;
color: #333;
}
&.active {
.radio-dot {
border-color: #4080ff;
}
}
}
}
.region-select, .datetime-select {
display: flex;
justify-content: space-between;
align-items: center;
height: 80rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 0 20rpx;
text {
font-size: 28rpx;
color: #333;
}
}
}
}
.tag-modal {
width: 600rpx;
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
.tag-modal-header {
padding: 30rpx;
text-align: center;
border-bottom: 1rpx solid #f0f0f0;
.modal-title {
font-size: 34rpx;
font-weight: 500;
color: #333;
}
}
.tag-modal-body {
padding: 30rpx;
.tag-input {
width: 100%;
height: 80rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
}
}
.tag-modal-footer {
display: flex;
border-top: 1rpx solid #f0f0f0;
.modal-btn {
flex: 1;
height: 90rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
&.cancel-btn {
color: #666;
border-right: 1rpx solid #f0f0f0;
}
&.confirm-btn {
color: #4080ff;
}
}
}
}
</style>

View File

@@ -0,0 +1,305 @@
<template>
<view class="traffic-container">
<!-- 顶部导航栏 -->
<view class="header">
<view class="back-icon" @click="goBack">
<u-icon name="arrow-left" size="42" color="black"></u-icon>
</view>
<view class="title">流量分发</view>
<view class="header-right">
<view class="add-btn" @click="createTraffic">
<u-icon name="plus" size="28" color="#fff"></u-icon>
<text class="add-text">新建分发</text>
</view>
</view>
</view>
<!-- 流量包列表 -->
<view class="traffic-list">
<!-- 普通流量包 -->
<view class="traffic-item">
<view class="traffic-header">
<text class="traffic-title">普通流量包</text>
<view class="traffic-actions">
<u-icon name="edit-pen" size="36" color="#999" @click="editTraffic(1)"></u-icon>
<u-icon name="trash" size="36" color="#999" @click="deleteTraffic(1)" class="trash-icon"></u-icon>
</view>
</view>
<view class="traffic-price">
<text class="price-symbol">¥</text>
<text class="price-value">0.50</text>
<text class="price-unit">/ 流量包</text>
</view>
<view class="traffic-info">
<text class="total-added">总添加人数: 10 </text>
</view>
<view class="traffic-tags">
<view class="tag">新用户</view>
<view class="tag">低活跃度</view>
<view class="tag">全国</view>
</view>
</view>
<!-- 高质量流量 -->
<view class="traffic-item">
<view class="traffic-header">
<text class="traffic-title">高质量流量</text>
<view class="traffic-actions">
<u-icon name="edit-pen" size="36" color="#999" @click="editTraffic(2)"></u-icon>
<u-icon name="trash" size="36" color="#999" @click="deleteTraffic(2)" class="trash-icon"></u-icon>
</view>
</view>
<view class="traffic-price">
<text class="price-symbol">¥</text>
<text class="price-value">2.50</text>
<text class="price-unit">/ 流量包</text>
</view>
<view class="traffic-info">
<text class="total-added">总添加人数: 25 </text>
</view>
<view class="traffic-tags">
<view class="tag">高消费</view>
<view class="tag">高活跃度</view>
<view class="tag">一线城市</view>
</view>
</view>
<!-- 精准营销流量 -->
<view class="traffic-item">
<view class="traffic-header">
<text class="traffic-title">精准营销流量</text>
<view class="traffic-actions">
<u-icon name="edit-pen" size="36" color="#999" @click="editTraffic(3)"></u-icon>
<u-icon name="trash" size="36" color="#999" @click="deleteTraffic(3)" class="trash-icon"></u-icon>
</view>
</view>
<view class="traffic-price">
<text class="price-symbol">¥</text>
<text class="price-value">3.80</text>
<text class="price-unit">/ 流量包</text>
</view>
<view class="traffic-info">
<text class="total-added">总添加人数: 50 </text>
</view>
<view class="traffic-tags">
<view class="tag">潜在客户</view>
<view class="tag">有购买意向</view>
<view class="tag">华东地区</view>
</view>
</view>
</view>
<!-- 底部导航栏 -->
<CustomTabBar active="work"></CustomTabBar>
</view>
</template>
<script>
import CustomTabBar from '@/components/CustomTabBar.vue'
export default {
components: {
CustomTabBar
},
data() {
return {
trafficItems: [
{
id: 1,
title: '普通流量包',
price: 0.5,
totalAdded: 10,
tags: ['新用户', '低活跃度', '全国']
},
{
id: 2,
title: '高质量流量',
price: 2.5,
totalAdded: 25,
tags: ['高消费', '高活跃度', '一线城市']
},
{
id: 3,
title: '精准营销流量',
price: 3.8,
totalAdded: 50,
tags: ['潜在客户', '有购买意向', '华东地区']
}
]
}
},
methods: {
// 返回上一页
goBack() {
uni.navigateBack();
},
// 创建新的流量分发
createTraffic() {
uni.navigateTo({
url: '/pages/traffic/create'
})
},
// 编辑流量分发
editTraffic(id) {
uni.navigateTo({
url: `/pages/traffic/create?id=${id}`
})
},
// 删除流量分发
deleteTraffic(id) {
uni.showModal({
title: '提示',
content: '确定要删除该流量分发吗?',
success: (res) => {
if (res.confirm) {
// 模拟删除操作
this.trafficItems = this.trafficItems.filter(item => item.id !== id);
uni.showToast({
title: '删除成功',
icon: 'success'
});
}
}
});
}
}
}
</script>
<style lang="scss" scoped>
.traffic-container {
min-height: 100vh;
background-color: #f9fafb;
padding-bottom: 150rpx; /* 为底部导航栏预留空间 */
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 25rpx 30rpx;
background-color: #fff;
border-bottom: 1px solid #f0f0f0;
.back-icon {
width: 60rpx;
color: #000;
padding: 10rpx;
border-radius: 50%;
&:active {
background-color: rgba(0, 0, 0, 0.05);
}
}
.title {
font-size: 38rpx;
font-weight: 600;
margin-left: -60rpx; /* 使标题居中 */
flex: 1;
text-align: center;
}
.header-right {
.add-btn {
display: flex;
align-items: center;
justify-content: center;
background-color: #4080ff;
border-radius: 30rpx;
padding: 12rpx 24rpx;
color: #fff;
.add-text {
font-size: 28rpx;
margin-left: 8rpx;
}
}
}
}
.traffic-list {
padding: 30rpx;
.traffic-item {
background-color: #fff;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
.traffic-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
.traffic-title {
font-size: 34rpx;
font-weight: 600;
color: #333;
}
.traffic-actions {
display: flex;
.trash-icon {
margin-left: 20rpx;
}
}
}
.traffic-price {
display: flex;
align-items: baseline;
margin-bottom: 20rpx;
.price-symbol {
font-size: 30rpx;
color: #1cc15e;
font-weight: 600;
}
.price-value {
font-size: 60rpx;
color: #1cc15e;
font-weight: 700;
font-family: 'Digital-Bold', sans-serif;
margin: 0 8rpx;
}
.price-unit {
font-size: 28rpx;
color: #666;
}
}
.traffic-info {
margin-bottom: 20rpx;
.total-added {
font-size: 28rpx;
color: #666;
}
}
.traffic-tags {
display: flex;
flex-wrap: wrap;
.tag {
background-color: #f5f5f5;
border-radius: 8rpx;
padding: 8rpx 16rpx;
font-size: 24rpx;
color: #666;
margin-right: 16rpx;
margin-bottom: 16rpx;
}
}
}
}
</style>

View File

@@ -0,0 +1,919 @@
<template>
<view class="detail-container">
<!-- 顶部导航栏 -->
<view class="header">
<view class="back-icon" @click="goBack">
<u-icon name="arrow-left" size="42" color="black"></u-icon>
</view>
<view class="title">账号详情</view>
<view class="header-right"></view>
</view>
<!-- 账号信息卡片 -->
<view class="account-card">
<view class="avatar-section">
<image :src="accountInfo.avatar || '/static/images/avatar.png'" mode="aspectFill" class="avatar-img"></image>
</view>
<view class="basic-info">
<view class="name-status">
<text class="account-name">{{accountInfo.name}}</text>
<text class="status-tag" :class="getStatusClass(accountInfo.status)">{{accountInfo.status}}</text>
</view>
<view class="account-id">微信号{{accountInfo.wechatId}}</view>
<view class="action-buttons">
<view class="action-btn device-btn" @click="goToDeviceDetail">
<u-icon name="setting" size="28" color="#333"></u-icon>
<text>设备{{accountInfo.deviceNumber}}</text>
</view>
<view class="action-btn friends-btn" @click="showTransferModal">
<u-icon name="account" size="28" color="#333"></u-icon>
<text>好友转移</text>
</view>
</view>
</view>
</view>
<!-- 好友转移模态框 -->
<view class="transfer-modal" v-if="showTransferModalFlag">
<view class="modal-mask" @click="hideTransferModal"></view>
<view class="modal-content">
<view class="modal-header">
<text class="modal-title">好友转移确认</text>
<view class="close-btn" @click="hideTransferModal">
<text class="close-icon">×</text>
</view>
</view>
<view class="modal-body">
<view class="transfer-title">即将导出该微信号的好友列表用于创建新的获客计划</view>
<view class="account-info-box">
<view class="account-avatar">
<image :src="accountInfo.avatar || '/static/images/avatar.png'" mode="aspectFill" class="avatar-small"></image>
</view>
<view class="account-detail">
<text class="account-name-text">{{accountInfo.name}}</text>
<text class="account-id-text">{{accountInfo.wechatId}}</text>
</view>
</view>
<view class="transfer-tips">
<view class="tip-item">
<text class="dot"></text>
<text class="tip-text">将导出该账号下的所有好友信息</text>
</view>
<view class="tip-item">
<text class="dot"></text>
<text class="tip-text">好友信息将用于创建新的订单获客计划</text>
</view>
<view class="tip-item">
<text class="dot"></text>
<text class="tip-text">导出过程中请勿关闭页面</text>
</view>
</view>
</view>
<view class="modal-footer">
<view class="cancel-btn" @click="hideTransferModal">取消</view>
<view class="confirm-btn" @click="confirmTransfer">确认转移</view>
</view>
</view>
</view>
<!-- 标签栏 -->
<view class="tab-section">
<view class="tab-item" :class="{ active: activeTab === 'overview' }" @click="activeTab = 'overview'">
<text>账号概览</text>
</view>
<view class="tab-item" :class="{ active: activeTab === 'friends' }" @click="activeTab = 'friends'">
<text>好友列表 ({{accountInfo.friendsCount}})</text>
</view>
</view>
<!-- 账号概览内容 -->
<block v-if="activeTab === 'overview'">
<!-- 年龄卡片 -->
<view class="info-card">
<view class="card-header">
<u-icon name="calendar" size="28" color="#666"></u-icon>
<text class="card-title">账号年龄</text>
</view>
<view class="age-content">
<view class="age-value">{{accountInfo.age}}</view>
<view class="age-register">注册时间{{accountInfo.registerDate}}</view>
</view>
</view>
<!-- 活跃度卡片 -->
<view class="info-card">
<view class="card-header">
<u-icon name="chat" size="28" color="#666"></u-icon>
<text class="card-title">活跃程度</text>
</view>
<view class="activity-content">
<view class="activity-value">{{accountInfo.activityRate}}/</view>
<view class="total-days">总聊天数{{accountInfo.totalChatDays}}</view>
</view>
</view>
<!-- 账号权重评估 -->
<view class="info-card">
<view class="card-header">
<u-icon name="star" size="28" color="#FFAD33"></u-icon>
<text class="card-title">账号权重评估</text>
<text class="score">{{accountInfo.score}} </text>
</view>
<view class="evaluate-content">
<view class="evaluate-text">账号状态良好</view>
<!-- 账号年龄评分 -->
<view class="evaluate-item">
<view class="item-header">
<text class="item-name">账号年龄</text>
<text class="item-percent">{{accountInfo.ageScore}}%</text>
</view>
<view class="progress-bar">
<view class="progress-bg"></view>
<view class="progress-value" :style="{width: accountInfo.ageScore + '%', backgroundColor: '#4080ff'}"></view>
</view>
</view>
<!-- 活跃度评分 -->
<view class="evaluate-item">
<view class="item-header">
<text class="item-name">活跃度</text>
<text class="item-percent">{{accountInfo.activityScore}}%</text>
</view>
<view class="progress-bar">
<view class="progress-bg"></view>
<view class="progress-value" :style="{width: accountInfo.activityScore + '%', backgroundColor: '#4080ff'}"></view>
</view>
</view>
<!-- 限制影响评分 -->
<view class="evaluate-item">
<view class="item-header">
<text class="item-name">限制影响</text>
<text class="item-percent">{{accountInfo.limitScore}}%</text>
</view>
<view class="progress-bar">
<view class="progress-bg"></view>
<view class="progress-value" :style="{width: accountInfo.limitScore + '%', backgroundColor: '#4080ff'}"></view>
</view>
</view>
<!-- 实名认证评分 -->
<view class="evaluate-item">
<view class="item-header">
<text class="item-name">实名认证</text>
<text class="item-percent">{{accountInfo.verifyScore}}%</text>
</view>
<view class="progress-bar">
<view class="progress-bg"></view>
<view class="progress-value" :style="{width: accountInfo.verifyScore + '%', backgroundColor: '#4080ff'}"></view>
</view>
</view>
</view>
</view>
<!-- 添加好友统计 -->
<view class="info-card">
<view class="card-header">
<u-icon name="account-add" size="28" color="#4080ff"></u-icon>
<text class="card-title">添加好友统计</text>
<u-icon name="info-circle" size="28" color="#999"></u-icon>
</view>
<view class="friends-stat-content">
<view class="stat-row">
<text class="stat-label">今日已添加</text>
<text class="stat-value blue">{{accountInfo.todayAdded}}</text>
</view>
<view class="stat-row">
<text class="stat-label">添加进度</text>
<text class="stat-progress">{{accountInfo.todayAdded}}/{{accountInfo.dailyLimit}}</text>
</view>
<view class="progress-bar">
<view class="progress-bg"></view>
<view class="progress-value" :style="{width: (accountInfo.todayAdded / accountInfo.dailyLimit * 100) + '%', backgroundColor: '#4080ff'}"></view>
</view>
<view class="limit-tip">
<text>根据当前账号权重({{accountInfo.score}})每日最多可添加 {{accountInfo.dailyLimit}} 个好友</text>
</view>
</view>
</view>
<!-- 限制记录 -->
<view class="info-card">
<view class="card-header">
<u-icon name="warning" size="28" color="#fa5151"></u-icon>
<text class="card-title">限制记录</text>
<text class="limit-count"> {{accountInfo.limitRecords.length}} </text>
</view>
<view class="limit-records">
<view class="limit-item" v-for="(record, index) in accountInfo.limitRecords" :key="index">
<text class="limit-reason">{{record.reason}}</text>
<text class="limit-date">{{record.date}}</text>
</view>
</view>
</view>
</block>
<!-- 好友列表内容 -->
<block v-if="activeTab === 'friends'">
<view class="friends-list-container">
<view class="search-filter">
<u-search
v-model="searchKeyword"
placeholder="搜索好友"
:showAction="false"
shape="round"
bgColor="#f4f4f4"
></u-search>
</view>
<view class="friends-list">
<view class="empty-tip" v-if="filteredFriends.length === 0">
<text>暂无好友数据</text>
</view>
<view class="friend-item" v-for="(friend, index) in filteredFriends" :key="index">
<image :src="friend.avatar" mode="aspectFill" class="friend-avatar"></image>
<view class="friend-info">
<view class="friend-name">{{friend.name}}</view>
<view class="friend-remark">备注{{friend.remark || '无'}}</view>
</view>
<view class="friend-action">
<view class="action-button">
<u-icon name="chat" size="24" color="#4080ff"></u-icon>
<text>聊天</text>
</view>
</view>
</view>
</view>
</view>
</block>
<!-- 底部导航栏 -->
<CustomTabBar active="profile"></CustomTabBar>
</view>
</template>
<script>
import CustomTabBar from '@/components/CustomTabBar.vue'
export default {
components: {
CustomTabBar
},
data() {
return {
id: '', // 微信账号ID
activeTab: 'overview', // 当前激活的标签页overview 或 friends
searchKeyword: '', // 搜索关键词
showTransferModalFlag: false, // 是否显示好友转移模态框
accountInfo: {
avatar: '/static/images/avatar.png',
name: '卡若-25vig',
status: '正常',
wechatId: 'wxid_hahphr2h',
deviceNumber: '1',
friendsCount: 192,
age: '2年8个月',
registerDate: '2021-06-15',
activityRate: '42',
totalChatDays: '15,234',
score: 85,
ageScore: 90,
activityScore: 85,
limitScore: 80,
verifyScore: 100,
todayAdded: 12,
dailyLimit: 17,
limitRecords: [
{ reason: '添加好友过于频繁', date: '2024-02-25' },
{ reason: '营销内容违规', date: '2024-01-15' }
]
},
friends: [] // 好友列表
}
},
computed: {
// 过滤后的好友列表
filteredFriends() {
if (!this.searchKeyword) return this.friends;
return this.friends.filter(friend =>
friend.name.includes(this.searchKeyword) ||
(friend.remark && friend.remark.includes(this.searchKeyword))
);
}
},
onLoad(options) {
if (options.id) {
this.id = options.id;
this.loadAccountInfo();
}
},
methods: {
// 返回上一页
goBack() {
uni.navigateBack();
},
// 获取状态样式类
getStatusClass(status) {
if (status === '正常') return 'status-normal';
if (status === '运营') return 'status-running';
return '';
},
// 跳转到设备详情页
goToDeviceDetail() {
// 根据账号关联的设备编号跳转
uni.navigateTo({
url: `/pages/device/detail?id=${this.accountInfo.deviceNumber}`
});
},
// 显示好友转移模态框
showTransferModal() {
this.showTransferModalFlag = true;
},
// 隐藏好友转移模态框
hideTransferModal() {
this.showTransferModalFlag = false;
},
// 确认好友转移
confirmTransfer() {
// 在实际应用中这里应该调用API进行好友转移
uni.showLoading({
title: '转移中...'
});
// 模拟API调用
setTimeout(() => {
uni.hideLoading();
uni.showToast({
title: '好友转移成功',
icon: 'success'
});
this.hideTransferModal();
}, 1500);
},
// 加载账号信息
loadAccountInfo() {
// 这里应该是API调用现在使用模拟数据
console.log(`加载账号信息: ${this.id}`);
// 模拟加载好友数据
this.friends = [
{
id: 1,
name: '张三',
avatar: '/static/images/avatar.png',
remark: '客户-北京'
},
{
id: 2,
name: '李四',
avatar: '/static/images/avatar.png',
remark: '客户-上海'
},
{
id: 3,
name: '王五',
avatar: '/static/images/avatar.png',
remark: '客户-广州'
}
];
}
}
}
</script>
<style lang="scss" scoped>
.detail-container {
min-height: 100vh;
background-color: #f9fafb;
padding-bottom: 150rpx; /* 为底部导航栏预留空间 */
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 25rpx 30rpx;
background-color: #fff;
border-bottom: 1px solid #f0f0f0;
.back-icon {
width: 60rpx;
color: #000;
padding: 10rpx;
border-radius: 50%;
&:active {
background-color: rgba(0, 0, 0, 0.05);
}
}
.title {
font-size: 38rpx;
font-weight: 600;
margin-left: -60rpx; /* 使标题居中 */
flex: 1;
text-align: center;
}
.header-right {
width: 60rpx;
}
}
.account-card {
margin: 30rpx;
background-color: #fff;
border-radius: 16rpx;
padding: 30rpx;
display: flex;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
.avatar-section {
margin-right: 30rpx;
.avatar-img {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
}
}
.basic-info {
flex: 1;
.name-status {
display: flex;
align-items: center;
margin-bottom: 10rpx;
.account-name {
font-size: 36rpx;
font-weight: 600;
margin-right: 20rpx;
}
.status-tag {
font-size: 24rpx;
padding: 2rpx 16rpx;
border-radius: 8rpx;
&.status-normal {
background-color: #4cd964;
color: #fff;
}
&.status-running {
background-color: #ff6b6b;
color: #fff;
}
}
}
.account-id {
font-size: 28rpx;
color: #666;
margin-bottom: 20rpx;
}
.action-buttons {
display: flex;
.action-btn {
display: flex;
align-items: center;
justify-content: center;
padding: 10rpx 20rpx;
border-radius: 8rpx;
background-color: #f5f5f5;
margin-right: 20rpx;
text {
font-size: 26rpx;
margin-left: 10rpx;
}
}
}
}
}
.tab-section {
display: flex;
background-color: #fff;
margin: 0 30rpx 20rpx;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
.tab-item {
flex: 1;
text-align: center;
padding: 24rpx 0;
font-size: 30rpx;
color: #666;
position: relative;
&.active {
color: #4080ff;
font-weight: 500;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60rpx;
height: 6rpx;
background-color: #4080ff;
border-radius: 3rpx;
}
}
}
}
.info-card {
margin: 0 30rpx 20rpx;
background-color: #fff;
border-radius: 16rpx;
padding: 30rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
.card-header {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.card-title {
font-size: 30rpx;
font-weight: 500;
margin-left: 10rpx;
flex: 1;
}
.score {
font-size: 36rpx;
font-weight: 600;
color: #4cd964;
}
.limit-count {
font-size: 26rpx;
color: #999;
}
}
.age-content, .activity-content {
padding: 20rpx 0;
.age-value, .activity-value {
font-size: 48rpx;
font-weight: 600;
color: #4080ff;
margin-bottom: 10rpx;
}
.age-register, .total-days {
font-size: 28rpx;
color: #999;
}
}
.evaluate-content {
.evaluate-text {
font-size: 28rpx;
color: #666;
margin-bottom: 20rpx;
}
.evaluate-item {
margin-bottom: 20rpx;
.item-header {
display: flex;
justify-content: space-between;
margin-bottom: 10rpx;
.item-name {
font-size: 28rpx;
color: #666;
}
.item-percent {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
}
}
}
.friends-stat-content {
.stat-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
.stat-label {
font-size: 28rpx;
color: #666;
}
.stat-value {
font-size: 36rpx;
font-weight: 600;
&.blue {
color: #4080ff;
}
}
.stat-progress {
font-size: 28rpx;
color: #666;
}
}
.limit-tip {
margin-top: 20rpx;
font-size: 26rpx;
color: #999;
}
}
.limit-records {
.limit-item {
display: flex;
justify-content: space-between;
padding: 20rpx 0;
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.limit-reason {
font-size: 28rpx;
color: #fa5151;
}
.limit-date {
font-size: 28rpx;
color: #999;
}
}
}
}
.progress-bar {
position: relative;
height: 10rpx;
margin: 10rpx 0;
.progress-bg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #ebeef5;
border-radius: 10rpx;
}
.progress-value {
position: absolute;
left: 0;
top: 0;
height: 100%;
border-radius: 10rpx;
}
}
.friends-list-container {
margin: 0 30rpx;
.search-filter {
margin-bottom: 20rpx;
}
.friends-list {
background-color: #fff;
border-radius: 16rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
overflow: hidden;
.empty-tip {
padding: 40rpx 0;
text-align: center;
color: #999;
font-size: 28rpx;
}
.friend-item {
display: flex;
align-items: center;
padding: 20rpx 30rpx;
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.friend-avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
margin-right: 20rpx;
}
.friend-info {
flex: 1;
.friend-name {
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 8rpx;
}
.friend-remark {
font-size: 26rpx;
color: #999;
}
}
.friend-action {
.action-button {
display: flex;
flex-direction: column;
align-items: center;
font-size: 24rpx;
color: #4080ff;
}
}
}
}
}
/* 好友转移模态框样式 */
.transfer-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
.modal-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
position: relative;
width: 650rpx;
background-color: #fff;
border-radius: 20rpx;
overflow: hidden;
z-index: 1001;
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #f5f5f5;
.modal-title {
font-size: 34rpx;
font-weight: bold;
color: #333;
}
.close-btn {
width: 44rpx;
height: 44rpx;
display: flex;
align-items: center;
justify-content: center;
.close-icon {
font-size: 44rpx;
color: #999;
line-height: 1;
}
}
}
.modal-body {
padding: 30rpx;
.transfer-title {
font-size: 30rpx;
color: #333;
margin-bottom: 30rpx;
}
.account-info-box {
display: flex;
align-items: center;
background-color: #f8f9fc;
padding: 20rpx;
border-radius: 10rpx;
margin-bottom: 30rpx;
.account-avatar {
margin-right: 20rpx;
.avatar-small {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}
}
.account-detail {
display: flex;
flex-direction: column;
.account-name-text {
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 4rpx;
}
.account-id-text {
font-size: 26rpx;
color: #999;
}
}
}
.transfer-tips {
margin-top: 20rpx;
.tip-item {
display: flex;
align-items: flex-start;
margin-bottom: 15rpx;
.dot {
margin-right: 10rpx;
font-size: 30rpx;
color: #666;
}
.tip-text {
font-size: 28rpx;
color: #666;
line-height: 1.5;
}
}
}
}
.modal-footer {
display: flex;
padding: 20rpx 30rpx 40rpx;
.cancel-btn, .confirm-btn {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 40rpx;
font-size: 30rpx;
}
.cancel-btn {
background-color: #f5f5f5;
color: #666;
margin-right: 20rpx;
}
.confirm-btn {
background-color: #4080ff;
color: #fff;
}
}
}
}
</style>

View File

@@ -0,0 +1,439 @@
<template>
<view class="wechat-container">
<!-- 顶部导航栏 -->
<view class="header">
<view class="back-icon" @click="goBack">
<u-icon name="arrow-left" size="42" color="black"></u-icon>
</view>
<view class="title">微信号</view>
<view class="header-right"></view>
</view>
<!-- 搜索框 -->
<view class="search-box">
<view class="search-input">
<u-search
v-model="searchKeyword"
placeholder="搜索微信号/昵称"
:showAction="false"
shape="round"
:clearabled="true"
height="70"
bgColor="#f4f4f4"
></u-search>
</view>
<view class="filter-icon">
<u-icon name="filter" size="36" color="#000"></u-icon>
</view>
<view class="refresh-icon">
<u-icon name="reload" size="36" color="#000"></u-icon>
</view>
</view>
<!-- 微信号列表 -->
<view class="wechat-list">
<!-- 微信号项 1 -->
<view class="wechat-item" @click="goToDetail(wechatAccounts[0])">
<view class="wechat-avatar">
<image src="/static/images/avatar.png" mode="aspectFill" class="avatar-img"></image>
</view>
<view class="wechat-info">
<view class="wechat-header">
<view class="wechat-name">卡若-25vig</view>
<view class="wechat-status">
<text class="status-tag status-running">运营</text>
</view>
</view>
<view class="wechat-id">微信号wxid_8evmgz0y</view>
<view class="friends-info">
<text class="friends-count">好友数量6095</text>
<text class="friends-added">今日新增<text class="added-count">+7</text></text>
</view>
<view class="daily-limit">
<text class="limit-text">今日可添加8</text>
<view class="limit-progress">
<view class="progress-bg"></view>
<view class="progress-value" style="width: 35%;"></view>
</view>
<text class="limit-count">7/20</text>
</view>
<view class="device-info">
<text class="device-label">所属设备</text>
<text class="device-value">设备1</text>
<text class="last-active-label">最后活跃</text>
<text class="last-active-value">2025/3/26 12:25:10</text>
</view>
</view>
<view class="wechat-action" @click.stop="transferFriends(wechatAccounts[0].wechatId)">
<view class="transfer-btn">
<u-icon name="swap-right" size="28" color="#333"></u-icon>
<text>好友转移</text>
</view>
</view>
</view>
<!-- 微信号项 2 -->
<view class="wechat-item" @click="goToDetail(wechatAccounts[1])">
<view class="wechat-avatar">
<image src="/static/images/avatar.png" mode="aspectFill" class="avatar-img"></image>
</view>
<view class="wechat-info">
<view class="wechat-header">
<view class="wechat-name">卡若-zok7e</view>
<view class="wechat-status">
<text class="status-tag status-normal">正常</text>
</view>
</view>
<view class="wechat-id">微信号wxid_7mlqr91i</view>
<view class="friends-info">
<text class="friends-count">好友数量4149</text>
<text class="friends-added">今日新增<text class="added-count">+11</text></text>
</view>
<view class="daily-limit">
<text class="limit-text">今日可添加5</text>
<view class="limit-progress">
<view class="progress-bg"></view>
<view class="progress-value" style="width: 55%;"></view>
</view>
<text class="limit-count">11/20</text>
</view>
<view class="device-info">
<text class="device-label">所属设备</text>
<text class="device-value">设备1</text>
<text class="last-active-label">最后活跃</text>
<text class="last-active-value">2025/3/26 11:30:34</text>
</view>
</view>
<view class="wechat-action" @click.stop="transferFriends(wechatAccounts[1].wechatId)">
<view class="transfer-btn">
<u-icon name="swap-right" size="28" color="#333"></u-icon>
<text>好友转移</text>
</view>
</view>
</view>
<!-- 微信号项 3 -->
<view class="wechat-item" @click="goToDetail(wechatAccounts[2])">
<view class="wechat-avatar">
<image src="/static/images/avatar.png" mode="aspectFill" class="avatar-img"></image>
</view>
<view class="wechat-info">
<view class="wechat-header">
<view class="wechat-name">卡若-ip9ob</view>
<view class="wechat-status">
<text class="status-tag status-normal">正常</text>
</view>
</view>
<view class="wechat-id">微信号wxid_jzfn1nmr</view>
<view class="friends-info">
<text class="friends-count">好友数量4131</text>
<text class="friends-added">今日新增<text class="added-count">+11</text></text>
</view>
<view class="daily-limit">
<text class="limit-text">今日可添加11</text>
<view class="limit-progress">
<view class="progress-bg"></view>
<view class="progress-value" style="width: 55%;"></view>
</view>
<text class="limit-count">11/20</text>
</view>
<view class="device-info">
<text class="device-label">所属设备</text>
<text class="device-value">设备1</text>
<text class="last-active-label">最后活跃</text>
<text class="last-active-value">2025/3/26 10:45:22</text>
</view>
</view>
<view class="wechat-action" @click.stop="transferFriends(wechatAccounts[2].wechatId)">
<view class="transfer-btn">
<u-icon name="swap-right" size="28" color="#333"></u-icon>
<text>好友转移</text>
</view>
</view>
</view>
</view>
<!-- 底部导航栏 -->
<CustomTabBar active="profile"></CustomTabBar>
</view>
</template>
<script>
import CustomTabBar from '@/components/CustomTabBar.vue'
export default {
components: {
CustomTabBar
},
data() {
return {
searchKeyword: '',
wechatAccounts: [
{
name: '卡若-25vig',
status: '运营',
wechatId: 'wxid_8evmgz0y',
friendsCount: 6095,
todayAdded: 7,
todayLimit: 8,
maxLimit: 20,
device: '设备1',
lastActive: '2025/3/26 12:25:10'
},
{
name: '卡若-zok7e',
status: '正常',
wechatId: 'wxid_7mlqr91i',
friendsCount: 4149,
todayAdded: 11,
todayLimit: 5,
maxLimit: 20,
device: '设备1',
lastActive: '2025/3/26 11:30:34'
},
{
name: '卡若-ip9ob',
status: '正常',
wechatId: 'wxid_jzfn1nmr',
friendsCount: 4131,
todayAdded: 11,
todayLimit: 11,
maxLimit: 20,
device: '设备1',
lastActive: '2025/3/26 10:45:22'
}
]
}
},
methods: {
// 返回上一页
goBack() {
uni.navigateBack();
},
// 好友转移
transferFriends(wechatId) {
uni.showToast({
title: `${wechatId} 好友转移功能即将上线`,
icon: 'none',
duration: 2000
});
},
// 跳转到详情页
goToDetail(account) {
uni.navigateTo({
url: `/pages/wechat/detail?id=${account.wechatId}`
});
}
}
}
</script>
<style lang="scss" scoped>
.wechat-container {
min-height: 100vh;
background-color: #f9fafb;
padding-bottom: 150rpx; /* 为底部导航栏预留空间 */
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 25rpx 30rpx;
background-color: #fff;
border-bottom: 1px solid #f0f0f0;
.back-icon {
width: 60rpx;
color: #000;
padding: 10rpx;
border-radius: 50%;
&:active {
background-color: rgba(0, 0, 0, 0.05);
}
}
.title {
font-size: 38rpx;
font-weight: 600;
margin-left: -60rpx; /* 使标题居中 */
flex: 1;
text-align: center;
}
.header-right {
width: 60rpx;
}
}
.search-box {
display: flex;
align-items: center;
padding: 20rpx 30rpx;
background-color: #fff;
.search-input {
flex: 1;
}
.filter-icon, .refresh-icon {
margin-left: 20rpx;
padding: 10rpx;
}
}
.wechat-list {
padding: 20rpx 30rpx;
.wechat-item {
background-color: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 20rpx;
display: flex;
position: relative;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
.wechat-avatar {
width: 80rpx;
height: 80rpx;
margin-right: 20rpx;
.avatar-img {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.wechat-info {
flex: 1;
.wechat-header {
display: flex;
align-items: center;
margin-bottom: 8rpx;
.wechat-name {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-right: 16rpx;
}
.wechat-status {
.status-tag {
font-size: 24rpx;
padding: 2rpx 12rpx;
border-radius: 6rpx;
&.status-running {
background-color: #ff6b6b;
color: #fff;
}
&.status-normal {
background-color: #4cd964;
color: #fff;
}
}
}
}
.wechat-id {
font-size: 28rpx;
color: #666;
margin-bottom: 8rpx;
}
.friends-info {
display: flex;
align-items: center;
font-size: 28rpx;
color: #666;
margin-bottom: 8rpx;
.friends-count {
margin-right: 20rpx;
}
.added-count {
color: #4cd964;
}
}
.daily-limit {
display: flex;
align-items: center;
font-size: 28rpx;
color: #666;
margin-bottom: 16rpx;
.limit-text {
width: 200rpx;
}
.limit-progress {
flex: 1;
position: relative;
height: 10rpx;
margin: 0 16rpx;
.progress-bg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #ebeef5;
border-radius: 10rpx;
}
.progress-value {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: #4080ff;
border-radius: 10rpx;
}
}
.limit-count {
width: 100rpx;
text-align: right;
}
}
.device-info {
font-size: 26rpx;
color: #999;
.device-label, .last-active-label {
margin-right: 8rpx;
}
.device-value {
margin-right: 20rpx;
}
}
}
.wechat-action {
display: flex;
align-items: center;
.transfer-btn {
display: flex;
flex-direction: column;
align-items: center;
font-size: 24rpx;
color: #666;
}
}
}
}
</style>

View File

@@ -1 +1,477 @@
<template>
<view class="work-container">
<!-- 顶部标题 -->
<view class="header">
<text class="title">工作台</text>
</view>
<!-- 统计卡片 -->
<view class="stats-cards">
<view class="stats-card">
<view class="stats-label">总任务数</view>
<view class="stats-value blue">42</view>
<view class="progress-bar">
<view class="progress-filled blue" style="width: 70%;"></view>
</view>
<view class="stats-detail">
<text>进行中12 / 已完成30</text>
</view>
</view>
<view class="stats-card light-green">
<view class="stats-label">今日任务</view>
<view class="stats-value green">12</view>
<view class="trend-info">
<u-icon name="arrow-up" color="#2fc25b" size="20"></u-icon>
<text class="trend-text">活跃度 98%</text>
</view>
</view>
</view>
<!-- 常用功能 -->
<view class="section-title">常用功能</view>
<view class="function-grid">
<!-- 流量分发 -->
<view class="function-card" @click="navigateTo('/pages/traffic/index')">
<view class="icon-wrapper light-green">
<text class="icon">$</text>
</view>
<view class="function-content">
<view class="function-name">流量分发</view>
<view class="function-desc">定义你的流量价格</view>
</view>
</view>
<!-- 自动点赞 -->
<view class="function-card" @click="handleAutoLike">
<view class="icon-wrapper light-blue">
<u-icon name="thumb-up" color="#4080ff" size="28"></u-icon>
</view>
<view class="function-content">
<view class="function-name">自动点赞</view>
<view class="function-desc">定时对好友朋友圈点赞</view>
</view>
</view>
<!-- 朋友圈同步 -->
<view class="function-card" @click="handleMomentSync">
<view class="icon-wrapper light-purple">
<u-icon name="reload" color="#7551ff" size="28"></u-icon>
</view>
<view class="function-content">
<view class="function-name">朋友圈同步</view>
<view class="function-desc">多微信朋友圈同步发布</view>
</view>
</view>
<!-- 微信号管理 -->
<view class="function-card" @click="navigateTo('/pages/wechat/index')">
<view class="icon-wrapper light-green">
<u-icon name="weixin-fill" color="#48d2a0" size="28"></u-icon>
</view>
<view class="function-content">
<view class="function-name">微信号管理</view>
<view class="function-desc">管理已绑定的微信账号</view>
</view>
</view>
<!-- 群消息推送 -->
<view class="function-card" @click="handleGroupMessage">
<view class="icon-wrapper light-orange">
<u-icon name="chat" color="#ff9e45" size="28"></u-icon>
</view>
<view class="function-content">
<view class="function-name">群消息推送</view>
<view class="function-desc">批量向群内自动发消息</view>
</view>
</view>
<!-- 自动建群 -->
<view class="function-card" @click="handleAutoGroup">
<view class="icon-wrapper light-green">
<u-icon name="team" color="#48d2a0" size="28"></u-icon>
</view>
<view class="function-content">
<view class="function-name">自动建群</view>
<view class="function-desc">智能匹分好友建群</view>
</view>
</view>
<!-- AI话术助手 -->
<view class="function-card" @click="handleAIChatAssistant">
<view class="icon-wrapper light-blue">
<u-icon name="tv" color="#4080ff" size="28"></u-icon>
</view>
<view class="function-content">
<view class="function-name">AI话术助手</view>
<view class="function-desc">智能回复提高互动质量</view>
</view>
</view>
</view>
<!-- AI智能助手 -->
<view class="section-title">AI 智能助手</view>
<view class="function-grid">
<!-- AI数据分析 -->
<view class="function-card" @click="handleAIDataAnalysis">
<view class="icon-wrapper light-blue">
<u-icon name="tv" color="#4080ff" size="28"></u-icon>
</view>
<view class="function-content">
<view class="function-name">AI数据分析</view>
<view class="function-desc">智能分析客户行为特征</view>
</view>
</view>
<!-- AI策略优化 -->
<view class="function-card" @click="handleAIStrategy">
<view class="icon-wrapper light-cyan">
<u-icon name="tv" color="#36cfc9" size="28"></u-icon>
</view>
<view class="function-content">
<view class="function-name">AI策略优化</view>
<view class="function-desc">智能优化获客策略</view>
</view>
</view>
</view>
<!-- 内容库卡片 -->
<view class="func-card" @click="goToTraffic">
<view class="func-card-icon traffic-icon">
<u-icon name="man-add-fill" color="#fff" size="44"></u-icon>
</view>
<view class="func-card-info">
<text class="func-card-title">流量池</text>
<text class="func-card-desc">管理您的流量用户</text>
</view>
<view class="func-card-arrow">
<u-icon name="arrow-right" color="#ccc" size="28"></u-icon>
</view>
</view>
<view class="func-card" @click="goToContent">
<view class="func-card-icon content-icon">
<u-icon name="folder" color="#fff" size="44"></u-icon>
</view>
<view class="func-card-info">
<text class="func-card-title">内容库</text>
<text class="func-card-desc">管理微信内容素材</text>
</view>
<view class="func-card-arrow">
<u-icon name="arrow-right" color="#ccc" size="28"></u-icon>
</view>
</view>
<!-- 底部TabBar -->
<CustomTabBar active="work"></CustomTabBar>
</view>
</template>
<script>
import CustomTabBar from '@/components/CustomTabBar.vue'
export default {
components: {
CustomTabBar
},
data() {
return {
// 将来可从API获取的数据
totalTasks: 42,
completedTasks: 30,
todayTasks: 12,
activeRate: 98
}
},
methods: {
// 页面导航
navigateTo(url) {
uni.navigateTo({
url: url
});
},
// 自动点赞功能处理
handleAutoLike() {
// 由于尚未实现该页面我们显示一个toast提示
this.showFunctionMessage('自动点赞');
},
// 朋友圈同步功能处理
handleMomentSync() {
this.showFunctionMessage('朋友圈同步');
},
// 群消息推送功能处理
handleGroupMessage() {
this.showFunctionMessage('群消息推送');
},
// 自动建群功能处理
handleAutoGroup() {
this.showFunctionMessage('自动建群');
},
// AI话术助手功能处理
handleAIChatAssistant() {
this.showFunctionMessage('AI话术助手');
},
// AI数据分析功能处理
handleAIDataAnalysis() {
this.showFunctionMessage('AI数据分析');
},
// AI策略优化功能处理
handleAIStrategy() {
this.showFunctionMessage('AI策略优化');
},
// 显示功能消息
showFunctionMessage(functionName) {
uni.showToast({
title: `${functionName}功能即将上线`,
icon: 'none',
duration: 2000
});
},
// 跳转到流量池页面
goToTraffic() {
uni.navigateTo({
url: '/pages/traffic/index'
});
},
// 跳转到内容库页面
goToContent() {
uni.navigateTo({
url: '/pages/content/index'
});
}
}
}
</script>
<style lang="scss" scoped>
.work-container {
min-height: 100vh;
background-color: #f9fafb;
padding: 0 30rpx 150rpx;
}
.header {
padding: 30rpx 0 20rpx;
.title {
font-size: 42rpx;
font-weight: 600;
color: #000;
}
}
.stats-cards {
display: flex;
margin: 20rpx 0 30rpx;
.stats-card {
flex: 1;
background-color: #fff;
border-radius: 16rpx;
padding: 20rpx 24rpx;
margin-right: 15rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
&:last-child {
margin-right: 0;
background-color: #f5fffa;
}
.stats-label {
font-size: 28rpx;
color: #666;
margin-bottom: 10rpx;
}
.stats-value {
font-size: 50rpx;
font-weight: bold;
margin-bottom: 10rpx;
&.blue {
color: #4080ff;
}
&.green {
color: #2fc25b;
}
}
.progress-bar {
height: 10rpx;
background-color: #f0f0f0;
border-radius: 10rpx;
overflow: hidden;
margin-bottom: 10rpx;
.progress-filled {
height: 100%;
background-color: #4080ff;
border-radius: 10rpx;
&.blue {
background-color: #4080ff;
}
}
}
.stats-detail {
font-size: 24rpx;
color: #999;
}
.trend-info {
display: flex;
align-items: center;
margin-top: 10rpx;
.trend-text {
font-size: 24rpx;
color: #2fc25b;
margin-left: 6rpx;
}
}
}
}
.section-title {
font-size: 34rpx;
font-weight: 500;
color: #000;
margin: 30rpx 0 20rpx;
}
.function-grid {
display: flex;
flex-wrap: wrap;
margin: 0 -10rpx;
.function-card {
width: calc(50% - 20rpx);
background-color: #fff;
border-radius: 16rpx;
margin: 0 10rpx 20rpx;
padding: 24rpx 20rpx;
display: flex;
align-items: center;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
.icon-wrapper {
width: 80rpx;
height: 80rpx;
border-radius: 16rpx;
display: flex;
justify-content: center;
align-items: center;
margin-right: 16rpx;
&.light-green {
background-color: rgba(47, 194, 91, 0.1);
}
&.light-pink {
background-color: rgba(255, 87, 122, 0.1);
}
&.light-purple {
background-color: rgba(112, 102, 224, 0.1);
}
&.light-orange {
background-color: rgba(255, 153, 0, 0.1);
}
&.light-blue {
background-color: rgba(64, 128, 255, 0.1);
}
&.light-cyan {
background-color: rgba(54, 207, 201, 0.1);
}
.icon {
font-size: 34rpx;
color: #2fc25b;
font-weight: bold;
}
}
.function-content {
flex: 1;
.function-name {
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 8rpx;
}
.function-desc {
font-size: 24rpx;
color: #999;
}
}
}
}
.func-card {
display: flex;
align-items: center;
padding: 20rpx;
background-color: #fff;
border-radius: 16rpx;
margin-bottom: 20rpx;
.func-card-icon {
width: 80rpx;
height: 80rpx;
border-radius: 16rpx;
display: flex;
justify-content: center;
align-items: center;
margin-right: 16rpx;
&.traffic-icon {
background-color: #4080ff;
}
&.content-icon {
background-color: #2fc25b;
}
}
.func-card-info {
flex: 1;
.func-card-title {
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 8rpx;
}
.func-card-desc {
font-size: 24rpx;
color: #999;
}
}
.func-card-arrow {
width: 28rpx;
height: 28rpx;
margin-left: 16rpx;
}
}
</style>

View File

@@ -0,0 +1 @@

Binary file not shown.