212 lines
8.7 KiB
Vue
212 lines
8.7 KiB
Vue
<template>
|
|
<div class="divBox">
|
|
<el-card shadow="never" class="ivu-mt">
|
|
<div class="padding-add">
|
|
<!-- 搜索区域 -->
|
|
<el-form inline size="small" :model="searchForm" class="mb20">
|
|
<el-form-item label="主播信息">
|
|
<el-input v-model="searchForm.anchorKeyword" placeholder="主播名/ID" clearable style="width: 150px" />
|
|
</el-form-item>
|
|
<el-form-item label="粉丝信息">
|
|
<el-input v-model="searchForm.fansKeyword" placeholder="粉丝名/ID" clearable style="width: 150px" />
|
|
</el-form-item>
|
|
<el-form-item label="粉丝等级">
|
|
<el-select v-model="searchForm.level" placeholder="全部" clearable style="width: 100px">
|
|
<el-option label="全部" value="" />
|
|
<el-option v-for="i in 10" :key="i" :label="`Lv.${i}`" :value="i" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="关注时间">
|
|
<el-date-picker v-model="searchForm.dateRange" type="daterange" range-separator="至" start-placeholder="开始" end-placeholder="结束" value-format="yyyy-MM-dd" style="width: 220px" />
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
|
|
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
|
|
<!-- 数据表格 -->
|
|
<el-table :data="tableData" v-loading="loading" border size="mini">
|
|
<el-table-column prop="id" label="ID" width="60" align="center" />
|
|
<el-table-column label="主播信息" width="180">
|
|
<template slot-scope="scope">
|
|
<div class="user-info">
|
|
<el-avatar :src="scope.row.anchor_avatar" :size="36" />
|
|
<div class="user-detail">
|
|
<div class="user-name">{{ scope.row.anchor_name }}</div>
|
|
<div class="user-id">ID: {{ scope.row.anchor_id }}</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="粉丝信息" width="180">
|
|
<template slot-scope="scope">
|
|
<div class="user-info">
|
|
<el-avatar :src="scope.row.fans_avatar" :size="36" />
|
|
<div class="user-detail">
|
|
<div class="user-name">{{ scope.row.fans_name }}</div>
|
|
<div class="user-id">ID: {{ scope.row.fans_id }}</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="粉丝等级" width="100" align="center">
|
|
<template slot-scope="scope">
|
|
<el-tag size="mini" :type="getLevelType(scope.row.level)">Lv.{{ scope.row.level }}</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="intimacy" label="亲密度" width="100" align="center">
|
|
<template slot-scope="scope">
|
|
<span style="color: #e6a23c;">{{ scope.row.intimacy || 0 }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="gift_value" label="送礼价值" width="100" align="center">
|
|
<template slot-scope="scope">
|
|
<span style="color: #f56c6c;">¥{{ scope.row.gift_value || 0 }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="follow_time" label="关注时间" width="160" align="center" />
|
|
<el-table-column prop="last_visit" label="最近访问" width="160" align="center" />
|
|
<el-table-column label="操作" width="120" align="center" fixed="right">
|
|
<template slot-scope="scope">
|
|
<el-button type="primary" size="mini" @click="handleDetail(scope.row)">详情</el-button>
|
|
<el-button type="danger" size="mini" @click="handleRemove(scope.row)">移除</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<!-- 分页 -->
|
|
<div class="acea-row row-right page mt20">
|
|
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="searchForm.page" :page-sizes="[10, 20, 50, 100]" :page-size="searchForm.limit" layout="total, sizes, prev, pager, next, jumper" :total="total" />
|
|
</div>
|
|
</div>
|
|
</el-card>
|
|
|
|
<!-- 详情弹窗 -->
|
|
<el-dialog title="粉丝详情" :visible.sync="detailDialogVisible" width="600px" :close-on-click-modal="false">
|
|
<el-descriptions :column="2" border v-if="detailData">
|
|
<el-descriptions-item label="主播ID">{{ detailData.anchor_id }}</el-descriptions-item>
|
|
<el-descriptions-item label="主播昵称">{{ detailData.anchor_name }}</el-descriptions-item>
|
|
<el-descriptions-item label="粉丝ID">{{ detailData.fans_id }}</el-descriptions-item>
|
|
<el-descriptions-item label="粉丝昵称">{{ detailData.fans_name }}</el-descriptions-item>
|
|
<el-descriptions-item label="粉丝等级">
|
|
<el-tag size="small" :type="getLevelType(detailData.level)">Lv.{{ detailData.level }}</el-tag>
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="亲密度">{{ detailData.intimacy || 0 }}</el-descriptions-item>
|
|
<el-descriptions-item label="累计送礼">¥{{ detailData.gift_value || 0 }}</el-descriptions-item>
|
|
<el-descriptions-item label="送礼次数">{{ detailData.gift_count || 0 }}次</el-descriptions-item>
|
|
<el-descriptions-item label="关注时间">{{ detailData.follow_time }}</el-descriptions-item>
|
|
<el-descriptions-item label="最近访问">{{ detailData.last_visit }}</el-descriptions-item>
|
|
<el-descriptions-item label="观看时长">{{ detailData.watch_duration || 0 }}分钟</el-descriptions-item>
|
|
<el-descriptions-item label="互动次数">{{ detailData.interact_count || 0 }}次</el-descriptions-item>
|
|
</el-descriptions>
|
|
<div slot="footer">
|
|
<el-button @click="detailDialogVisible = false">关闭</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { fansListApi, fansDetailApi, fansRemoveApi } from '@/api/fans';
|
|
|
|
export default {
|
|
name: 'FansManage',
|
|
data() {
|
|
return {
|
|
searchForm: {
|
|
anchorKeyword: '',
|
|
fansKeyword: '',
|
|
level: '',
|
|
dateRange: [],
|
|
page: 1,
|
|
limit: 10
|
|
},
|
|
tableData: [],
|
|
total: 0,
|
|
loading: false,
|
|
detailDialogVisible: false,
|
|
detailData: null
|
|
};
|
|
},
|
|
mounted() {
|
|
this.getList();
|
|
},
|
|
methods: {
|
|
async getList() {
|
|
this.loading = true;
|
|
try {
|
|
const params = {
|
|
...this.searchForm,
|
|
startTime: this.searchForm.dateRange && this.searchForm.dateRange[0],
|
|
endTime: this.searchForm.dateRange && this.searchForm.dateRange[1]
|
|
};
|
|
delete params.dateRange;
|
|
const res = await fansListApi(params);
|
|
this.tableData = res.list || (res.data && res.data.list) || [];
|
|
this.total = res.total || (res.data && res.data.total) || 0;
|
|
} catch (error) {
|
|
this.$message.error(error.message || '获取列表失败');
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
handleSearch() {
|
|
this.searchForm.page = 1;
|
|
this.getList();
|
|
},
|
|
handleReset() {
|
|
this.searchForm = { anchorKeyword: '', fansKeyword: '', level: '', dateRange: [], page: 1, limit: 10 };
|
|
this.getList();
|
|
},
|
|
handleSizeChange(val) {
|
|
this.searchForm.limit = val;
|
|
this.getList();
|
|
},
|
|
handleCurrentChange(val) {
|
|
this.searchForm.page = val;
|
|
this.getList();
|
|
},
|
|
getLevelType(level) {
|
|
if (level >= 8) return 'danger';
|
|
if (level >= 5) return 'warning';
|
|
if (level >= 3) return 'success';
|
|
return 'info';
|
|
},
|
|
async handleDetail(row) {
|
|
try {
|
|
const res = await fansDetailApi(row.id);
|
|
this.detailData = res.data || res;
|
|
} catch {
|
|
this.detailData = row;
|
|
}
|
|
this.detailDialogVisible = true;
|
|
},
|
|
handleRemove(row) {
|
|
this.$confirm(`确定要移除 ${row.fans_name} 与 ${row.anchor_name} 的粉丝关系吗?`, '提示', { type: 'warning' })
|
|
.then(async () => {
|
|
try {
|
|
await fansRemoveApi(row.id);
|
|
this.$message.success('移除成功');
|
|
this.getList();
|
|
} catch (error) {
|
|
this.$message.error(error.message || '移除失败');
|
|
}
|
|
}).catch(() => {});
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.mb20 { margin-bottom: 20px; }
|
|
.mt20 { margin-top: 20px; }
|
|
.user-info {
|
|
display: flex;
|
|
align-items: center;
|
|
.user-detail { margin-left: 10px; text-align: left; }
|
|
.user-name { font-weight: 500; font-size: 13px; }
|
|
.user-id { font-size: 12px; color: #999; }
|
|
}
|
|
</style>
|