学习:uniapp全栈微信小程序vue3后台(28)

136.创建硬币使用记录展示页面,展示硬币列表数据

/uniCloud-alipay/database/wallpaper-activity-coin.schema.json

添加ip字段

/uniCloud-alipay/cloudfunctions/admin-data-record/index.obj.js

coinRecord方法

复制代码
async coinRecord({ size = 5, current = 1, dataRange = [] } = {}) {

		size = Math.min(100, size);
		let skip = (current - 1) * size;
		let wre = dataRange.length ?
			`createTime >= ${dayjs(dataRange[0]).startOf("day").valueOf()} && 
		createTime<=${dayjs(dataRange[1]).endOf("day").valueOf()}` : {};

		const dbJQL = uniCloud.databaseForJQL({
			clientInfo: this.getClientInfo()
		})
		let coinTemp = dbJQL.collection("wallpaper-activity-coin")
			.where(wre)
			.orderBy("createTime desc")
			.skip(skip)
			.limit(size)
			.getTemp();
		let userTemp = dbJQL.collection("uni-id-users")
			.field("_id,nickname")
			.getTemp();
		let res = await dbJQL.collection(coinTemp, userTemp)
			.field(`
		createTime,
		dayGet,
		total,		
		ip,
		record,
		user_id.nickname as nickname
		`)
			.get({ getCount: true })
		let data = res.data.map(item => {
			return {
				...item,
				nickname: item.nickname[0]
			}
		})

		return { ...res, data };

	},

新建coin-record

按照日期选择展示范围内的数据

uni-datetime-picker 日期选择器 | uni-app官网

复制代码
<script setup>
	/**
	 * 导入Vue和dayjs相关依赖
	 * ref: Vue的响应式引用API
	 * dayjs: 处理日期的库
	 */
	import { ref } from 'vue';
	import dayjs from "dayjs"
	/**
	 * 导入uniCloud云函数对象
	 * 用于与后端云函数进行数据交互
	 */
	const dataCloudObj = uniCloud.importObject("admin-data-record", { customUI: true });
	// 弹出框引用
	const popup = ref(null);
	// 列表数据
	const listData = ref([]);
	// 记录列表数据
	const recordList = ref([]);
	// 请求参数
	const params = ref({
		current: 1, // 当前页码
		total: 0, // 总记录数
		size: 20, // 每页显示数量
		dataRange: [] // 日期范围
	});
	// 默认日期范围(当前时间往前推6个月)
	const deftData = ref([
		dayjs().subtract(6, "M").startOf("day").valueOf(),
		dayjs().endOf("day").valueOf()
	]);

	/**
	 * 获取数据函数
	 * 从后端获取硬币记录数据
	 */
	const getData = async () => {
		let { errCode, data = [], count = 0 } = await dataCloudObj.coinRecord(params.value);
		listData.value = data
		params.value.total = count
	}
	/**
	 * 处理链接点击事件
	 * @param {number} index - 当前点击的记录索引
	 */
	const handleLink = (index) => {
		recordList.value = listData.value[index].record
		popup.value.open();
	}

	/**
	 * 分页改变事件处理
	 * @param {Object} e - 分页事件对象
	 */
	const pageChange = (e) => {
		params.value.current = e.current;
		getData();
	}

	/**
	 * 日期改变事件处理
	 */
	const dataChange = () => {
		getData();
	}
	getData(); // 初始加载数据

</script>
<template>
	<!-- 主容器 -->
	<view class="coin">
		<!-- 自定义头部 -->
		<custom-head-top>
			<!-- 左侧标题 -->
			<template #left>
				硬币记录
			</template>

			<!-- 右侧日期选择器 -->
			<template #right>
				<uni-datetime-picker style="width: 300px;" :start="deftData[0]" :end="deftData[1]" @change="dataChange"
					v-model="params.dataRange" type="daterange" />
			</template>
		</custom-head-top>
		<!-- 主要内容区域 -->
		<view class="main">
			<!-- 表格组件 -->
			<uni-table class="table" ref="tableRef" border stripe emptyText="暂无更多数据">
				<!-- 表头 -->
				<uni-tr>
					<uni-th align="left">用户名</uni-th>
					<uni-th align="left">积分</uni-th>
					<uni-th align="left">每日领币</uni-th>
					<uni-th align="left">操作记录</uni-th>
					<uni-th align="left">IP</uni-th>
					<uni-th align="left">创建时间</uni-th>
				</uni-tr>

				<!-- 表格数据行 -->
				<uni-tr v-for="item,index in listData" :key="item._id">
					<uni-td>{{item.nickname}}</uni-td>
					<uni-td>{{item.total}}</uni-td>
					<uni-td>
						<uni-tag v-if="item.dayGet" text="已领取" type="primary" size="mini" />
						<uni-tag v-else text="未领取" type="default" size="mini" inverted />
					</uni-td>
					<uni-td>
						<view class="link" @click="handleLink(index)">{{item.record.length}}条记录</view>
					</uni-td>
					<uni-td>{{item.ip || '-'}}</uni-td>
					<uni-td>{{dayjs(item.createTime).format("YYYY-MM-DD HH:mm:ss")}}</uni-td>
				</uni-tr>
			</uni-table>
		</view>

		<!-- 分页组件 -->
		<view class="paging">
			<uni-pagination :current="params.current" :total="params.total" :page-size="params.size" :show-icon="true"
				@change="pageChange" />
		</view>

	</view>


	<!-- 记录详情弹窗 -->
	<uni-popup ref="popup">
		<view class="recordPop">
			<!-- 可滚动区域 -->
			<scroll-view scroll-y style="max-height: 600px;">
				<!-- 记录列表 -->
				<uni-list border-full>
					<uni-list-item :title="item.desc" :note="dayjs(item.time).format('YYYY-MM-DD HH:mm:ss')"
						:rightText="item.score+''" v-for="item,index in recordList" :key="index" />
				</uni-list>
			</scroll-view>
		</view>
	</uni-popup>

</template>
<style lang="scss" scoped>
	.main {
		padding: 20px;

		.table {
			.link {
				text-decoration: underline;
				color: var(--primary-color);
				cursor: pointer;
			}
		}
	}

	.recordPop {
		width: 600px;
		min-height: 400px;
		background: #fff;
		border-radius: 10px;
		background: #fff;
		padding: 30px;
	}

	// 深度选择器样式调整
	:deep(.uni-date-range--x) {
		right: 0;
	}

	:deep(.uni-popper__arrow) {
		left: 80%;
	}

</style>

添加二级菜单

137.使用grid网格布局做响应式栅格布局

创建页面

新建二级菜单

复制代码
<template>
	<view class="index">
		<custom-head-top>
			<template #left>
				数据概览				
			</template>
			
			<template #right>				
				<uni-datetime-picker v-model="dataRange" @change="dateChange" type="daterange" style="width: 300px" :start="dataDeft[0]" :end="dataDeft[1]"/>				
			</template>
		</custom-head-top>
		
		<view class="main">
			<view class="grid">
				<view class="section">
					<uni-card title="使用量" margin="0" :is-shadow="false">
						<view class="box">
							<view class="icon">
								<uni-icons type="eye-filled" size="40" color="#9A60B4"></uni-icons>
							</view>
							<view class="text">
								<view class="big">2345<text class="unit">次</text></view>
								<view class="small">数据库请求次数</view>
							</view>
						</view>
					</uni-card>
				</view>
				<view class="section">
					<uni-card title="使用人数" margin="0" :is-shadow="false">
						<view class="box">
							<view class="icon">
								<uni-icons type="person-filled" size="40" color="#1890FF"></uni-icons>
							</view>
							<view class="text">
								<view class="big">8899<text class="unit">人</text></view>
								<view class="small">IP用户量统计</view>
							</view>
						</view>
					</uni-card>
				</view>
				<view class="section">
					<uni-card title="壁纸总量" margin="0" :is-shadow="false">
						<view class="box">
							<view class="icon">
								<uni-icons type="cloud-download-filled" size="40" color="#91CB74"></uni-icons>
							</view>
							<view class="text">
								<view class="big">189<text class="unit">张</text></view>
								<view class="small">系统内壁纸总数</view>
							</view>
						</view>
					</uni-card>
				</view>
				<view class="section">
					<uni-card title="上传量" margin="0" :is-shadow="false">
						<view class="box">
							<view class="icon">
								<uni-icons type="upload-filled" size="40" color="#FC8452"></uni-icons>
							</view>
							<view class="text">
								<view class="big">12<text class="unit">张</text></view>
								<view class="small">上传图片量</view>
							</view>
						</view>
					</uni-card>
				</view>
				
				<view class="section">					
					<uni-card title="使用趋势图" margin="0" :is-shadow="false">
						折线图
					</uni-card>					
				</view>
				<view class="section">
					<uni-card title="分类喜好度" margin="0" :is-shadow="false">
						饼形图
					</uni-card>
				</view>
				
				<view class="section">
					<uni-card title="下载Top5" margin="0" :is-shadow="false">
						<view style="padding:30px 0">
							<uni-load-more status="loading" :showText="false"></uni-load-more>
						</view>						
						柱形图
					</uni-card>
				</view>
				<view class="section">
					<uni-card title="下载Top5" margin="0" :is-shadow="false">
						<view style="padding:30px 0">
							<uni-load-more status="loading" :showText="false"></uni-load-more>
						</view>						
						柱形图
					</uni-card>
				</view>
			</view>
			
		</view>
	</view>
</template>

<script setup>
import dayjs from "dayjs";
import {onMounted, ref} from "vue";
import { showToast } from "../../utils/common";
const dataDeft = ref([dayjs().subtract(6, 'M').startOf('day').valueOf(),
dayjs().endOf('day').valueOf()]);

const dataRange = ref([])


const dateChange = (e)=>{
	getData();
}

const getData = ()=>{
	
}


getData();
</script>

<style lang="scss" scoped>
:deep(.uni-date-range--x){
	right:0;
}
.main{
	padding:20px;
	.grid{
		display: grid;
		grid-template-columns: repeat(24,1fr);
		gap:20px;		
		.section{			
			grid-column: span 6;
			.box{
				display: flex;
				flex-direction: column;
				align-items: center;
				text-align: center;
				padding:30px 0;
				.text{
					.big{
						font-weight: bolder;
						color:#333;
						font-size: 25px;
						padding:10px 0 2px;
						.unit{
							font-size: 14px;
						}
					}
					.small{
						font-size: 12px;
						color:#999;
					}
				}
			}
		}
		.section:nth-child(5){
			grid-column: span 16;
		}
		.section:nth-child(6){
			grid-column: span 8;
		}
		.section:nth-child(7){
			grid-column: span 12;
		}
		.section:nth-child(8){
			grid-column: span 12;
		}
	}
}
@media (max-width:992px){
	.main{
		.grid{
			.section{
				grid-column: span 24 !important;
			}
		}
	}
}
</style>

138.云对象常用的API调用方法获取客户端信息

新建数据集合Schema文件

复制代码
// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
	"bsonType": "object",
	"required": [],
	"permission": {
		"read": true,
		"create": true,
		"update": true,
		"delete": true
	},
	"properties": {
		"_id": {
			"description": "ID,系统自动生成"
		},
		"user_id": {
			"description": "用户id",
			"bsonType": "string",
			"foreignKey": "uni-id-users._id"
		},
		"ip": {
			"description": "操作者ip地址",
			"bsonType": "string",
			"defaultValue": {
				"$env": "clientIP"
			}
		},
		"methodName": {
			"description": "调用的方法名",
			"bsonType": "string"
		},
		"params": {
			"description": "请求参数",
			"bsonType": "string"
		},
		"functionName": {
			"description": "云对象名称",
			"bsonType": "string"
		},
		"uniPlatform": {
			"description": "平台名称",
			"bsonType": "string"
		},
		"createTime": {
			"description": "产生时间",
			"bsonType": "timestamp",
			"defaultValue": {
				"$env": "now"
			}
		}
	}
}

139.获取客户端token解析checkToken用户角色信息

管理公共模块或扩展库依赖

复制代码
// 解构获取客户端IP和平台信息
		let clientInfo = this.getClientInfo()
		let { clientIP, uniPlatform } = clientInfo
		const methodName = this.getMethodName()
		const params = this.getParams()
		const token = this.getUniIdToken()
		this.uniID = uniID.createInstance({ //仓
			clientInfo
		})
		let { uid = '' } = await this.uniID.checkToken(token)
		console.log(res)

140.创建云函数公用模块将使用量数据统计封装统计入库

封装方法

/uniCloud-alipay/cloudfunctions/common/custom-utils/index.js

复制代码
async useRecord(that) {
		let clientInfo = that.getClientInfo()
		let { clientIP, uniPlatform } = clientInfo
		const methodName = that.getMethodName()
		const params = that.getParams()
		// const token = that.getUniIdToken()
		// let uniIDins = uniID.createInstance( {
		// 	//创建uni-id实例,其上方法同uniID
		// 	clientInfo
		// )
		// let { uid = '' } = await uniIDins.checkToken(token)
		const dbJQL = uniCloud.databaseForJQL({
			clientInfo
		})
		dbJQL.collection("wallpaper-data-usage").add({
			ip: clientIP,
			uniPlatform,
			methodName,
			params: JSON.stringify(params),
			functionName
		})
	}

管理本云函数的扩展库/公共模块依赖

补充,名称

相关推荐
珍宝商店2 小时前
原生 JavaScript 方法实战指南
开发语言·前端·javascript
计算机学姐2 小时前
基于微信小程序的扶贫助农系统【2026最新】
java·vue.js·spring boot·mysql·微信小程序·小程序·mybatis
蓝莓味的口香糖2 小时前
【企业微信】VUE项目在企微中自定义转发内容
前端·vue.js·企业微信
IT_陈寒2 小时前
告别低效!用这5个Python技巧让你的数据处理速度提升300% 🚀
前端·人工智能·后端
—Qeyser2 小时前
Laravel + UniApp AES加密/解密
前端·uni-app·laravel
发财北2 小时前
房屋管理系统开发流程
小程序
C++chaofan2 小时前
游标查询在对话历史场景下的独特优势
java·前端·javascript·数据库·spring boot
游戏开发爱好者82 小时前
Nginx HTTPS 深入实战 配置、性能与排查全流程(Nginx https
运维·nginx·ios·小程序·https·uni-app·iphone
cg.family2 小时前
Vue3 v-slot 详解与示例
前端·javascript·vue.js