【小程序】微信小程序课程 -4 项目实战
目录
1、 效果图
2、创建项目
2.1 创建小程序端
2.1.1 先创建纯净项目
2.1.2 删除components
2.1.4 删除app.json红色部分
2.1.5 删除index.json红色部分
2.1.6 删除index.wxss全部内容
2.1.7 删除index.wxml全部内容
2.1.8 app.json创建4个页面
2.1.9 app.json添加底部导航
2.1.10 app.json设置窗口栏
2.1.11 删除app.wxss全部内容
2.1.12 不校验http
2.2 创建小程序后端项目
2.2.1 创建项目
2.2.2 安装配置mysql数据库
2.2.3 settings配置修改(国际化修改)
2.2.4 运行后端
2.2.5 后期涉及需要安装的库
3、小程序中集成的vant-app
3.1 node介绍
3.2 使用vant样式引用(这里是示例,代码不需要)
4、欢迎页面
4.1 纯静态
4.1.1 welcome. wxml
4.1.2 welcome.wxss
4.1.3 welcome.js
4.2 后端加载欢迎页
4.2.1 创建表模型
4.2.2 开启media访问
4.2.3 使用admin上传图片
4.2.3.1 配置
4.2.3.2 上传图片
4.2.4 写视图函数(后期使用cbv改造)
4.3 小程序端改造(动态获取广告)
4.3.1 welcome. wxml
4.3.2 welcome. wxss
5、 首页
5.1 首页静态页面
5.1.1 index.wxml
5.1.2 index.wxss
5.1.3 app.json
5.2 首页菜单跳转
5.2.1 app.json创建菜单新页面
5.2.2 index.wxjs设置跳转
5.3 首页轮播图和公告接口
5.3.1 models
5.3.2 admin.py注册好新表和创建文件目录
5.3.3 admin录入数据
5.3.4 轮播图接口
5.3.4.1 smart应用下新建serializer
5.3.4.2 views.py实现BannerViewSet
5.3.4.3 分发路由urls.py
5.3.4.4 settings项目当中注册rest_framework
5.3.4.5 启动服务验证
5.3.4.6 整合通知到一个接口
5.3.4.6.1 serializer.py
5.3.4.6.2 views.py
5.3.4.6.3 查看接口返回数据
5.4 小程序轮播图与公告获取后端数据
5.4.1 index.wxjs
5.4.2 index.wxml
5.5 接口全局IP设置
5.5.1 新建全局settings.js
5.5.3 welcome.js引入应用
5.5.3 index.js引入应用
6、信息采集
6.1 信息采集静态页面
6.1.1 collection.json
6.1.2 collection.wxml
6.1.3 collection.wxjs
6.1.4 collection.wxss
6.2 信息采集后端接口
6.2.1 新建model.py创建表
6.2.2 录入数据
6.2.3 serializer.py
6.2.4 views.py实现数据采集查询接口
6.2.5 分发路由
6.2.6 验证
6.3 引入矢量图标库
6.4 小程序信息采集打通接口
6.4.1 完成全局配置信息采集页面
6.4.2 完成collection.wxjs
6.4.3 实现删除功能
6.4.3.1 views实现删除
6.4.3.2 collection.js实现删除
6.4.3.3 删除查询总数那有个bug总数不对
7、信息采集详情页
7.1 小程序端--拍照页面-- camera
7.1.1 app.json新增camera页面与form页面
7.1.2 camera.wxml
7.1.3 camera.wxss
7.1.4 camera.js
7.2 小程序端--采集页面--form
7.2.1 collection.wxjs新增跳转到form页面
7.2.2 form.wxml
7.2.3 form.wxss
7.2.3 form.js
7.3 后端接口
7.3.1 Serializer新增AreaSerializer
7.3.2 views新增AreaViewSet
7.3.3 urls配置
7.4 小程序实现form.js
7.4.1 全局配置添加form后端路径
7.4.2 后端处理接口
7.4.2.1 serializer新增CollectionSaveSerializer
7.4.2.2 views修改Collectionviewset
7.4.3 form.js
7.4.4 collection.js 新增一个刷新查询
8、信息统计-采集统计页面实现
8.1 小程序端
8.1.1 app.json新增采集统计
8.1.2 statistics.wxml
8.1.3 statistics.wxss
8.1.4 更新iconfont.wxss
8.2 后端接口
8.2.1 serializer新增StatisticsListSerializer
8.2.2 views
8.2.3 urls路由
8.3 采集统计联调
8.3.1 settings.js注册
8.3.2 collection.js添加点击跳转
9、 人脸识别
9.1 人脸识别
9.1.1 使用步骤
9.1.2 上传-删除-匹配人脸
10、个人中心
10.1 个人中心静态页面
10.1.1 my.json
10.1.2 my.wxss
10.1.3 my.wxml
10.1.4 my.wxjs
前言:通过前面学习,来做一个智慧社区的小程序,包含:
1、 效果图
2、创建项目
2.1 创建小程序端
2.1.1 先创建纯净项目
2.1.2 删除components
2.1.4 删除app.json红色部分
2.1.5 删除index.json红色部分
2.1.6 删除index.wxss全部内容
2.1.7 删除index.wxml全部内容
2.1.8 app.json创建4个页面
"pages": ["pages/index/index","pages/my/my","pages/activity/activity","pages/notice/notice"]
2.1.9 app.json添加底部导航
"tabBar": {"selectedColor": "#1c1c1b","position": "bottom","list": [{"pagePath": "pages/index/index","text": "首页","iconPath": "static/images/icon/home.png","selectedIconPath": "static/images/icon/home-o.png"},{"pagePath": "pages/activity/activity","text": "活动","iconPath": "static/images/icon/activity.png","selectedIconPath": "static/images/icon/activity-o.png"},{"pagePath": "pages/notice/notice","text": "公告","iconPath": "static/images/icon/notice.png","selectedIconPath": "static/images/icon/notice-o.png"},{"pagePath": "pages/my/my","text": "我的","iconPath": "static/images/icon/my.png","selectedIconPath": "static/images/icon/my-o.png"}]},
2.1.10 app.json设置窗口栏
"window": {"navigationBarTitleText": "智慧社区","navigationBarBackgroundColor": "#fff","enablePullDownRefresh": false,"backgroundColor": "#00FFFF","backgroundTextStyle":"light","navigationBarTextStyle": "black"},
完整代码
{"pages": ["pages/index/index","pages/my/my","pages/activity/activity","pages/notice/notice"],"window": {"navigationBarTitleText": "智慧社区","navigationBarBackgroundColor": "#fff","enablePullDownRefresh": false,"backgroundColor": "#00FFFF","backgroundTextStyle":"light","navigationBarTextStyle": "black"}, "tabBar": {"selectedColor": "#1c1c1b","position": "bottom","list": [{"pagePath": "pages/index/index","text": "首页","iconPath": "static/images/icon/home.png","selectedIconPath": "static/images/icon/home-o.png"},{"pagePath": "pages/activity/activity","text": "活动","iconPath": "static/images/icon/activity.png","selectedIconPath": "static/images/icon/activity-o.png"},{"pagePath": "pages/notice/notice","text": "公告","iconPath": "static/images/icon/notice.png","selectedIconPath": "static/images/icon/notice-o.png"},{"pagePath": "pages/my/my","text": "我的", "iconPath": "static/images/icon/my.png","selectedIconPath": "static/images/icon/my-o.png"}]},"sitemapLocation": "sitemap.json"}
2.1.11 删除app.wxss全部内容
2.1.12 不校验http
2.2 创建小程序后端项目
django+ drf +mysql
2.2.1 创建项目
2.2.2 安装配置mysql数据库
pip install pymysql
项目__init__.py添加
import pymysql
pymysql.install_as_MySQLdb()
修改为mysql数据库,这时候去把mysql数据库创建好,与下面name匹配的数据库
DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql',#数据库的类型'NAME': '33', #所使用的的数据库的名字'USER': 'root', #数据库服务器的用户'PASSWORD': '33#33', #密码'HOST': '192.168.1.13', #主机'PORT': '3306', #端口}
}
2.2.3 settings配置修改(国际化修改)
LANGUAGE_CODE = 'zh-hans'TIME_ZONE = 'Asia/Shanghai'USE_TZ = False
'rest_framework', 'django_filters',
2.2.4 运行后端
python manage.py runserver 0.0.0.0:8000
2.2.5 后期涉及需要安装的库
# 上传图片
pip install pillow# django后台页面美化 simpleui
pip install django-simpleui -i https://pypi.tuna.tsinghua.edu.cn/simple# rest_framework
pip install djangorestframework# baidu人脸识别
pip install baidu-aip
3、小程序中集成的vant-app
使用谷歌浏览器打开
https://vant-ui.github.io/vant-weapp/#/home
3.1 node介绍
安装node(略)
npm install -g cnpm --registry=https://registry.npm.taobao.org#上面地址不行了,然后注意这个要使用管理员身份打开cmd
npm install -g cnpm --registry=https://registry.npmmirror.com
npm init -y
#npm i @vant/weapp -S # 慢# 这个快
cnpm i @vant/weapp -S
(第6步 在之前步骤已经删除)
修改之前
修改之后
"packNpmManually": true,"packNpmRelationList": [{"packageJsonPath": "./package.json","miniprogramNpmDistDir": "./"}]
3.2 使用vant样式引用(这里是示例,代码不需要)
需要什么样式就引入,参照官网
"usingComponents": {"van-cell": "@vant/weapp/cell/index","van-cell-group":"@vant/weapp/cell-group/index","van-calendar":"@vant/weapp/calendar/index","van-notice-bar":"@vant/weapp/notice-bar/index","van-grid": "@vant/weapp/grid/index","van-grid-item": "@vant/weapp/grid-item/index"},
4、欢迎页面
app.json新增welcome 放第一位,作为首页
"pages": ["pages/welcome/welcome","pages/index/index","pages/my/my","pages/activity/activity","pages/notice/notice" ],
4.1 纯静态
4.1.1 welcome. wxml
<view class="container"><text class="jump" bindtap="doJump">跳过{{second}}秒</text><image class="img" src="/static/images/bg/splash.png" />
</view>
4.1.2 welcome.wxss
page{height: 100%;
}.container{width: 100%;height: 100%;
}
.container .img{width: 100%;height: 100%;
}
.jump{font-size: 30rpx;position: absolute;left: 600rpx;top: 80rpx;background-color: #dddddd;padding: 10rpx 20rpx;border-radius: 20rpx;
}
4.1.3 welcome.js
主要实现前端广告默认3秒倒计时自动跳转到首页
// pages/welcome/welcome.js
Page({/*** 页面的初始数据*/data: {second: 3},doJump(){// 点击跳转到首页wx.switchTab({url: '/pages/index/index',})},/*** 生命周期函数--监听页面加载*/onLoad(options) {// 启动广告的定时器,倒计时// 清除定时器var instance = setInterval(() =>{if(this.data.second<=0) {// 清除定时器clearInterval(instance)// 跳转到index页面this.doJump()}else{this.setData({second: this.data.second-1})}},1000)},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
4.2 后端加载欢迎页
4.2.1 创建表模型
models
from django.db import models# 开启app广页业模型表
class Welcome(models.Model):# upload_to 图片上传后,放到media文件夹下的welcome文件夹下# 必须安装pillo库 pip install pillowimg = models.ImageField(upload_to='welcome', default='/welcome/splash.png', verbose_name="图片")order = models.IntegerField(verbose_name="排序")# 这个字段不用穿,自动生成时间created_time = models.DateTimeField(auto_now=True, verbose_name="创建时间")is_delete = models.BooleanField(default=False, verbose_name="是否删除")# 如果表已存在且你不想Django管理它(如迁移),可以设置managed=Falseclass Meta:managed = Truedb_table = 'welcome'verbose_name_plural = '欢迎表'
将数据迁移到mysql数据库
执行命令
# 默认所有修改过的model层转为迁移文件
makemigrations
# 默认将所有的迁移文件都执行,更新数据库
migrate
小知识:上你我使用的是第2种方法
4.2.2 开启media访问
django根目录下创建media文件夹(存储上传的图片),然后在settings设置
我使用的是这个,我认为一样
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
在django项目当中进行如下设置
下面是我的设置,有一些差别
from django.contrib import admin
from django.urls import path, re_path
from django.views.static import serve
from django.conf import settingsurlpatterns = [path('admin/', admin.site.urls),re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT,}),
]
4.2.3 使用admin上传图片
4.2.3.1 配置
# 输入命令
createsuperuser# 创建用户root
root# 邮箱
market@163.com#密码
123456# 再次输入密码
123456# 提示密码不安全,输入Y
y
from django.contrib import admin
from .models import Welcome# Register your models here.
admin.site.register(Welcome)
http://127.0.0.1:8000/admin/login/?next=/admin
美化上面的django管理页面
# simpleui
https://github.com/newpanjing/simpleui# simpleui文档
https://newpanjing.github.io/simpleui_docs/# 快速上手
https://newpanjing.github.io/simpleui_docs/config.html
安装库(略,前面安装了),再settings注册simpleui
INSTALLED_APPS = ['simpleui','django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','smart.apps.SmartConfig',
]
apps.py 新增下图
from django.apps import AppConfigclass SmartConfig(AppConfig):default_auto_field = 'django.db.models.BigAutoField'name = 'smart'verbose_name = "首页欢迎"
4.2.3.2 上传图片
输入地址验证
http://127.0.0.1:8000/media/welcome/splash.png
4.2.4 写视图函数(后期使用cbv改造)
views
from django.shortcuts import render
from .models import Welcome
from django.http import JsonResponse
# Create your views here.def welcome(request):# 查询order最大的一张图片result = Welcome.objects.all().order_by('-order').first()img = 'http://127.0.0.1:8000/media/'+str(result.img)return JsonResponse({'code': 100, 'msg': '成功', 'result': img})
项目路由urls
from django.contrib import admin
from django.urls import path, re_path,include
from django.views.static import serve
from django.conf import settingsurlpatterns = [path('admin/', admin.site.urls),path('smart/', include('smart.urls')),re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT,}),
]
在smart下新建urls 应用路由
from django.contrib import admin
from django.urls import path
from .views import welcomeurlpatterns = [# http://127.0.0.1:8000/smart/welcome/ --> 就能获得突破数据path('welcome/', welcome),
]
输入地址验证(没有使用postman接口调用,偷懒)
http://127.0.0.1:8000/smart/welcome/
4.3 小程序端改造(动态获取广告)
4.3.1 welcome. wxml
img做成变量获取
<view class="container"><text class="jump" bindtap="doJump">跳过{{second}}秒</text><image class="img" src="{{img}}" />
</view>
4.3.2 welcome. wxss
加载页面的时候调用后端接口
// pages/welcome/welcome.js
Page({/*** 页面的初始数据*/data: {second: 3,img: '/static/images/bg/splash.png'},doJump(){// 点击跳转到首页wx.switchTab({url: '/pages/index/index',})},/*** 生命周期函数--监听页面加载*/onLoad(options) {// 向后端发送请求--》 获取广告页 --》 赋值给imgwx.request({url: 'http://127.0.0.1:8000/smart/welcome/',method: "GET",success:(res) => {if(res.data.code == 100){console.log(res)this.setData({img: res.data.result})}else{wx.showToast({title: '网络请求异常',})}}})// 启动广告的定时器,倒计时// 清除定时器var instance = setInterval(() =>{if(this.data.second<=0) {// 清除定时器clearInterval(instance)// 跳转到index页面this.doJump()}else{this.setData({second: this.data.second-1})}},1000)},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
5、 首页
5.1 首页静态页面
5.1.1 index.wxml
<view class="container"><!-- 轮播图 --><view class="banner"><swiper autoplay indicator-dots circular indicator-color="#FFFFFF" interval="3000"><swiper-item><image src="/static/images/index/banner/banner1.png" mode="widthFix" /></swiper-item><swiper-item><image src="/static/images/index/banner/banner2.png" mode="widthFix" /></swiper-item><swiper-item><image src="/static/images/index/banner/banner3.png" mode="widthFix" /></swiper-item></swiper></view><!-- 通知 --><van-notice-bar left-icon="volume-o" text="在代码阅读过程中人们说脏话的频率是衡量代码质量的唯一标准。" /><!-- 快捷入口 --><van-grid column-num="3"><van-grid-item icon="/static/images/index/menu/xx.png" text="信息采集" bind:click="gotoCollection" /><van-grid-item icon="/static/images/index/menu/sq.png" text="社区活动" bind:click="gotoActivity" /><van-grid-item icon="/static/images/index/menu/rl.png" text="人脸检测" bind:click="gotoFace" /><van-grid-item icon="/static/images/index/menu/yy.png" text="语言识别" bind:click="gotoVoice" /><van-grid-item icon="/static/images/index/menu/xl.png" text="心率检测" bind:click="gotoHeart" /><van-grid-item icon="/static/images/index/menu/jf.png" text="积分商城" bind:click="gotoGoods" /></van-grid><!-- 底部 --><view class="bottom"><view class="btv"><image class="btimg" src="/static/images/index/bottom/cute1.png" mode="scaleToFill" /> </view> <view class="btv"><image class="btimg" src="/static/images/index/bottom/cute2.png" mode="scaleToFill" /> </view> <view class="btv"><image class="btimg" src="/static/images/index/bottom/cute3.png" mode="scaleToFill" /> </view> <view class="btv"><image class="btimg" src="/static/images/index/bottom/cute4.png" mode="scaleToFill" /> </view> <view class="btv"><image class="btimg" src="/static/images/index/bottom/cute5.png" mode="scaleToFill" /> </view> <view class="btv"><image class="btimg" src="/static/images/index/bottom/cute6.png" mode="scaleToFill" /> </view> </view></view>
5.1.2 index.wxss
.banner image{width: 100%; /* 图片宽度拉伸至容器宽度 */height: 100%; /* 图片高度拉伸至容器宽度 */object-fit: cover; /* 图片将覆盖整个容器区域,可能被裁剪 */
}.bottom{display: flex;justify-content: space-evenly;margin-top: 20rpx;flex-wrap: wrap;
}
.bottom .btv .btimg{width: 345rpx;height: 200rpx;
}
5.1.3 app.json
"usingComponents": {"van-cell": "@vant/weapp/cell/index","van-cell-group":"@vant/weapp/cell-group/index","van-calendar":"@vant/weapp/calendar/index","van-notice-bar":"@vant/weapp/notice-bar/index","van-grid": "@vant/weapp/grid/index","van-grid-item": "@vant/weapp/grid-item/index"},
5.2 首页菜单跳转
5.2.1 app.json创建菜单新页面
"pages": ["pages/welcome/welcome","pages/index/index","pages/my/my","pages/activity/activity","pages/notice/notice","pages/collection/collection","pages/face/face","pages/voice/voice","pages/heart/heart","pages/goods/goods" ],
5.2.2 index.wxjs设置跳转
// index.js
Page({gotoCollection(){wx.navigateTo({url: '/pages/collection/collection',})},gotoActivity(){wx.switchTab({url: '/pages/activity/activity',})},gotoFace(){wx.navigateTo({url: '/pages/face/face',})},gotoVoice(){wx.navigateTo({url: '/pages/voice/voice',})},gotoHeart(){wx.navigateTo({url: '/pages/heart/heart',})},gotoGoods(){wx.navigateTo({url: '/pages/goods/goods',})}
})
5.3 首页轮播图和公告接口
5.3.1 models
新增两张表,迁移不再累述
from django.db import models# 开启app广页业模型表
class Welcome(models.Model):# upload_to 图片上传后,放到media文件夹下的welcome文件夹下# 必须安装pillo库 pip install pillowimg = models.ImageField(upload_to='welcome', default='/welcome/splash.png', verbose_name="图片")order = models.IntegerField(verbose_name="排序")# 这个字段不用穿,自动生成时间created_time = models.DateTimeField(auto_now=True, verbose_name="创建时间")is_delete = models.BooleanField(default=False, verbose_name="是否删除")# 如果表已存在且你不想Django管理它(如迁移),可以设置managed=Falseclass Meta:managed = Truedb_table = 'welcome'verbose_name_plural = '欢迎表'def __str__(self):return str(self.img)# 轮播图模型表
class Banner(models.Model):img = models.ImageField(upload_to='banner', default='/banner/banner.png', verbose_name="图片")order = models.IntegerField(verbose_name="排序")# 这个字段不用传,自动生成时间created_time = models.DateTimeField(auto_now=True, verbose_name="创建时间")is_delete = models.BooleanField(default=False, verbose_name="是否删除")# 如果表已存在且你不想Django管理它(如迁移),可以设置managed=Falseclass Meta:managed = Truedb_table = 'banner'verbose_name_plural = '轮播图表'def __str__(self):return str(self.img)# 通知表
class Notice(models.Model):title = models.CharField(max_length=64, verbose_name="公告标题")content = models.TextField(verbose_name="公告内容")img = models.ImageField(upload_to='notice', default='/notice/notice.png', verbose_name="公告图片")created_time = models.DateTimeField(auto_now=True, verbose_name="创建时间")is_delete = models.BooleanField(default=False, verbose_name="是否删除")class Meta:managed = Truedb_table = 'notice'verbose_name_plural = '通知公告表'def __str__(self):return self.title
5.3.2 admin.py注册好新表和创建文件目录
from django.contrib import admin
from .models import Banner, Welcome, Notice# Register your models here.
admin.site.register(Welcome)
admin.site.register(Banner)
admin.site.register(Notice)
media下新建2个文件夹
5.3.3 admin录入数据
登录后台系统
5.3.4 轮播图接口
5.3.4.1 smart应用下新建serializer
# -*- coding: utf-8 -*-
# @Time : 2024/9/26 9:20
# @Author : super
# @File : serializer.py
# @Software: PyCharm
# @Describe:
from rest_framework import serializers
from .models import Bannerclass BannerSerializer(serializers.ModelSerializer):class Meta:model = Bannerfields = "__all__"
5.3.4.2 views.py实现BannerViewSet
from django.shortcuts import render
from .models import Welcome
from django.http import JsonResponse
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from .models import Banner
from .serializer import BannerSerializer
# Create your views here.# 比较low 使用fbv实现
def welcome(request):# 查询order最大的一张图片result = Welcome.objects.all().order_by('-order').first()img = 'http://127.0.0.1:8000/media/'+str(result.img)return JsonResponse({'code': 100, 'msg': '成功', 'result': img})class BannerViewSet(GenericViewSet,ListModelMixin):queryset = Banner.objects.filter(is_delete=False).order_by('-order')[:3]serializer_class = BannerSerializer
5.3.4.3 分发路由urls.py
from django.contrib import admin
from django.urls import path
from .views import welcome
from rest_framework.routers import SimpleRouter
from .views import BannerViewSetrouter = SimpleRouter()
router.register('banner', BannerViewSet, basename='banners')
urlpatterns = [# http://127.0.0.1:8000/smart/welcome/ --> 就能获得突破数据path('welcome/', welcome),
]
urlpatterns += router.urls
5.3.4.4 settings项目当中注册rest_framework
INSTALLED_APPS = ['simpleui','django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','smart.apps.SmartConfig','rest_framework'
]
5.3.4.5 启动服务验证
python manage.py runserver
http://127.0.0.1:8000/smart/banner/
5.3.4.6 整合通知到一个接口
5.3.4.6.1 serializer.py
# -*- coding: utf-8 -*-
# @Time : 2024/9/26 9:20
# @Author : super
# @File : serializer.py
# @Software: PyCharm
# @Describe:
from rest_framework import serializers
from .models import Banner, Noticeclass BannerSerializer(serializers.ModelSerializer):class Meta:model = Bannerfields = "__all__"class NoticeSerializer(serializers.ModelSerializer):class Meta:model = Noticefields = "__all__"
5.3.4.6.2 views.py
from django.shortcuts import render
from .models import Welcome
from django.http import JsonResponse
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from .models import Banner, Notice
from .serializer import BannerSerializer, NoticeSerializer
from rest_framework.response import Response
# Create your views here.# 比较low 使用fbv实现
def welcome(request):# 查询order最大的一张图片result = Welcome.objects.all().order_by('-order').first()img = 'http://127.0.0.1:8000/media/'+str(result.img)return JsonResponse({'code': 100, 'msg': '成功', 'result': img})class BannerViewSet(GenericViewSet, ListModelMixin):queryset = Banner.objects.filter(is_delete=False).order_by('-order')[:3]serializer_class = BannerSerializer# 重写list方法,将通知也整合进去def list(self, request, *args, **kwargs):response = super().list(request, *args, **kwargs)# 获取最后一条通知notice = Notice.objects.filter(is_delete=False).order_by('-create_time').first()serializer = NoticeSerializer(instance=notice)return Response({'code': 100,'msg': '成功', 'banner': response.data, 'notice': serializer.data})
5.3.4.6.3 查看接口返回数据
5.4 小程序轮播图与公告获取后端数据
5.4.1 index.wxjs
新增获取轮播图的接口
// index.js
Page({data:{banner_list:[{'img': '/static/images/index/banner/banner1.png'},{'img': '/static/images/index/banner/banner3.png'}],notice: '春天的菠菜是来自china的中国小伙,为了成为棒棒的,我必须红旗飘飘!'},/*** 生命周期函数--监听页面加载*/onLoad(options) {wx.request({url: 'http://127.0.0.1:8000/smart/banner/',method: 'GET',success: (res) =>{this.setData({banner_list:res.data.banner,notice: res.data.notice.title})}})},gotoCollection(){wx.navigateTo({url: '/pages/collection/collection',})},gotoActivity(){wx.switchTab({url: '/pages/activity/activity',})},gotoFace(){wx.navigateTo({url: '/pages/face/face',})},gotoVoice(){wx.navigateTo({url: '/pages/voice/voice',})},gotoHeart(){wx.navigateTo({url: '/pages/heart/heart',})},gotoGoods(){wx.navigateTo({url: '/pages/goods/goods',})}
})
5.4.2 index.wxml
<view class="container"><!-- 轮播图 --><view class="banner"><swiper autoplay indicator-dots circular indicator-color="#FFFFFF" interval="3000"><swiper-item wx:for="{{banner_list}}" wx:key="index"><image src="{{item.img}}" mode="widthFix" /></swiper-item> </swiper></view><!-- 通知 --><van-notice-bar left-icon="volume-o" text="{{notice}}" /><!-- 快捷入口 --><van-grid column-num="3"><van-grid-item icon="/static/images/index/menu/xx.png" text="信息采集" bindtap="gotoCollection" /><van-grid-item icon="/static/images/index/menu/sq.png" text="社区活动" bind:click="gotoActivity" /><van-grid-item icon="/static/images/index/menu/rl.png" text="人脸检测" bind:click="gotoFace" /><van-grid-item icon="/static/images/index/menu/yy.png" text="语言识别" bind:click="gotoVoice" /><van-grid-item icon="/static/images/index/menu/xl.png" text="心率检测" bind:click="gotoHeart" /><van-grid-item icon="/static/images/index/menu/jf.png" text="积分商城" bind:click="gotoGoods" /></van-grid><!-- 底部 --><view class="bottom"><view class="btv"><image class="btimg" src="/static/images/index/bottom/cute1.png" mode="scaleToFill" /> </view> <view class="btv"><image class="btimg" src="/static/images/index/bottom/cute2.png" mode="scaleToFill" /> </view> <view class="btv"><image class="btimg" src="/static/images/index/bottom/cute3.png" mode="scaleToFill" /> </view> <view class="btv"><image class="btimg" src="/static/images/index/bottom/cute4.png" mode="scaleToFill" /> </view> <view class="btv"><image class="btimg" src="/static/images/index/bottom/cute5.png" mode="scaleToFill" /> </view> <view class="btv"><image class="btimg" src="/static/images/index/bottom/cute6.png" mode="scaleToFill" /> </view> </view></view>
5.5 接口全局IP设置
5.5.1 新建全局settings.js
根目录新增config目录 --》 新建settings.js
const rootUrl='http://127.0.0.1:8000/smart/'
// 表示导出, 在任意js中可以导入 导入就是这个对象
module.exports={welcome:rootUrl + 'welcome/',banner:rootUrl + 'banner/',
}
5.5.3 welcome.js引入应用
import api from '../../config/settings'
Page({/*** 页面的初始数据*/data: {second: 3,img: '/static/images/bg/splash.png'},doJump(){// 点击跳转到首页wx.switchTab({url: '/pages/index/index',})},/*** 生命周期函数--监听页面加载*/onLoad(options) {// 向后端发送请求--》 获取广告页 --》 赋值给imgwx.request({url: api.welcome,method: "GET",success:(res) => {if(res.data.code == 100){console.log(res)this.setData({img: res.data.result})}else{wx.showToast({title: '网络请求异常',})}}})// 启动广告的定时器,倒计时// 清除定时器var instance = setInterval(() =>{if(this.data.second<=0) {// 清除定时器clearInterval(instance)// 跳转到index页面this.doJump()}else{this.setData({second: this.data.second-1})}},1000)},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
5.5.3 index.js引入应用
import api from '../../config/settings'
Page({data:{banner_list:[{'img': '/static/images/index/banner/banner1.png'},{'img': '/static/images/index/banner/banner3.png'}],notice: '春天的菠菜是来自china的中国小伙,为了成为棒棒的,我必须红旗飘飘!'},/*** 生命周期函数--监听页面加载*/onLoad(options) {wx.request({url: api.banner,method: 'GET',success: (res) =>{this.setData({banner_list:res.data.banner,notice: res.data.notice.title})}})},gotoCollection(){wx.navigateTo({url: '/pages/collection/collection',})},gotoActivity(){wx.switchTab({url: '/pages/activity/activity',})},gotoFace(){wx.navigateTo({url: '/pages/face/face',})},gotoVoice(){wx.navigateTo({url: '/pages/voice/voice',})},gotoHeart(){wx.navigateTo({url: '/pages/heart/heart',})},gotoGoods(){wx.navigateTo({url: '/pages/goods/goods',})}
})
6、信息采集
6.1 信息采集静态页面
6.1.1 collection.json
{"usingComponents": {},"navigationBarBackgroundColor": "#01ccb6","navigationBarTitleText": "","enablePullDownRefresh": true,"navigationBarTextStyle":"white","backgroundColor": "#01ccb6"
}
6.1.2 collection.wxml
<!--三部分-->
<view class="container"><!--第一部分 top --><view class="top"><view class="tip">今日采集数量(人)</view><view class="count">{{dataDict.today_count}}</view></view><!--第二部分 top 下方function --><view class="function"><view class="menu" style="border-right:1rpx solid #ddd;" bindtap="bindToForm"><text class="fa fa-camera-retro">信息采集</text></view><view class="menu" bindtap="bindToStatistics"><text class="fa fa-camera-retro">数据统计</text></view></view><!--第三部分 列表 --><view class="table"><view class="item"><view class="title">社区信息列表({{dataDict.today_count}}人)</view></view><!-- 循环 --><view class="item" wx:for="{{dataDict.result}}" wx:for-item="row" wx:key="index"><view class="record"><view class="avatar"><image src="{{row.avatar}}"></image></view><view class="desc"><view class="username">{{row.name}}</view><view><view class="txt-group"><label class="zh">网格区域</label><label class="en"> | {{row.area.desc}}</label></view><view class="area"><label class="fa fa-map-marker"></label>{{row.area.name}}</view></view></view><view class="delete" bindtap="doDeleteRow" data-nid="{{row.id}}" data-index="{{index}}"><label class="iconfont icon-shanchu"></label></view></view></view></view>
</view>
6.1.3 collection.wxjs
// pages/collection/collection.js
Page({/*** 页面的初始数据*/data: {dataDict:{result:[{"id": 1,"name": "张学友","area": "#19","avatar": "/static/images/collection/zxy.png"},{"id": 2,"name": "黎姿","area": "#18","avatar": "/static/images/collection/lz.png"}],today_count: 66}},/*** 生命周期函数--监听页面加载*/onLoad(options) {},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
6.1.4 collection.wxss
/* pages/collection/collection.wxss */
.top{background-color: #01ccb6;height: 200rpx;display: flex;flex-direction: column;align-items: center;color: white;
}.top .tip{font-size: 22rpx;font-weight: 100;
}
.top .count{padding: 10rpx;font-size: 58rpx;
}
.function{display: flex;flex-direction: row;justify-content: space-around;background-color: #02bfae;
}.function .menu{font-size: 28rpx;margin: 25rpx 0;color: white;width: 50%;text-align: center;flex-direction: row;flex-direction: column;align-items: center;
}
.table .item{border-bottom: 1rpx solid #e7e7e7;
}
.table .item .title{margin: 20rpx 30rpx;padding-left: 10rpx;border-left: 5rpx solid #02bfae;font-size: 26rpx;
}.record{margin: 30rpx 40rpx;display: flex;flex-direction: row;justify-content: flex-start;
}.record .avatar{width: 200rpx;height: 200rpx;
}.record .avatar image{width: 100%;height: 100%;border-radius: 30%;
}.record .desc{margin: 0 40rpx
}.desc{width: 290rpx;display: flex;flex-direction: column;justify-content: space-between;
}.desc .username{margin-top: 25rpx;font-size: 38rpx;
}.txt-group{font-size: 27rpx;margin: 10rpx 0;
}.txt-group zh{color: #8c8c8c
}.txt-group .en{color: #cccccc;
}.area{color: #00c8b6;font-weight: bold;
}.delete{width: 100rpx;color: red;text-align: center;display: flex;flex-direction: column;justify-content: center;
}
6.2 信息采集后端接口
6.2.1 新建model.py创建表
新建采集表collection、区域表area与用户userinfo表,迁移不再累述
from django.db import models# 开启app广页业模型表
class Welcome(models.Model):# upload_to 图片上传后,放到media文件夹下的welcome文件夹下# 必须安装pillo库 pip install pillowimg = models.ImageField(upload_to='welcome', default='/welcome/splash.png', verbose_name="图片")order = models.IntegerField(verbose_name="排序")# 这个字段不用穿,自动生成时间created_time = models.DateTimeField(auto_now=True, verbose_name="创建时间")is_delete = models.BooleanField(default=False, verbose_name="是否删除")# 如果表已存在且你不想Django管理它(如迁移),可以设置managed=Falseclass Meta:managed = Truedb_table = 'welcome'verbose_name_plural = '欢迎表'def __str__(self):return str(self.img)# 轮播图模型表
class Banner(models.Model):img = models.ImageField(upload_to='banner', default='/banner/banner.png', verbose_name="图片")order = models.IntegerField(verbose_name="排序")# 这个字段不用传,自动生成时间create_time = models.DateTimeField(auto_now=True, verbose_name="创建时间")is_delete = models.BooleanField(default=False, verbose_name="是否删除")# 如果表已存在且你不想Django管理它(如迁移),可以设置managed=Falseclass Meta:managed = Truedb_table = 'banner'verbose_name_plural = '轮播图表'def __str__(self):return str(self.img)# 通知表
class Notice(models.Model):title = models.CharField(max_length=64, verbose_name="公告标题")content = models.TextField(verbose_name="公告内容")img = models.ImageField(upload_to='notice', default='/notice/notice.png', verbose_name="公告图片")create_time = models.DateTimeField(auto_now=True, verbose_name="创建时间")is_delete = models.BooleanField(default=False, verbose_name="是否删除")class Meta:managed = Truedb_table = 'notice'verbose_name_plural = '通知公告表'def __str__(self):return self.title##采集表
class Collection(models.Model):name = models.CharField(max_length=32, verbose_name="采集人员名称")# 姓名拼音作为后期人脸识别的ID号name_pinyin = models.CharField(max_length=32, verbose_name="采集人员姓名拼音")avatar = models.ImageField(upload_to='collection/%Y/%m/%d/', default='/collection/default.png', verbose_name="头像")create_time = models.DateTimeField(auto_now=True, verbose_name="采集时间")# face_token 后期使用 人脸识别token唯一码area = models.ForeignKey(to='Area', null=True, verbose_name="网格区域", on_delete=models.CASCADE)class Meta:managed = Truedb_table = 'collection'verbose_name_plural = '采集表'def __str__(self):return self.name## 区域表
class Area(models.Model):name = models.CharField(max_length=32, verbose_name="网格区域员")desc = models.CharField(max_length=32, verbose_name="网格简称")# 跟用户是一对多的关系 一个网格员可以采集多个网格user = models.ForeignKey(to='UserInfo', null=True, verbose_name="负责用户", on_delete=models.CASCADE)create_time = models.DateTimeField(auto_now=True, verbose_name="创建时间")class Meta:managed = Truedb_table = 'area'verbose_name_plural = '区域表'def __str__(self):return self.name### 用户表
class UserInfo(models.Model):username = models.CharField(max_length=32, verbose_name="用户名")password = models.CharField(max_length=100, verbose_name="密码")avatar = models.ImageField(upload_to='avatar', default='/avatar/avatar.png', verbose_name="头像")phone = models.CharField(max_length=111, verbose_name="手机号")email = models.EmailField(null=True, blank=True, verbose_name="邮箱")score = models.IntegerField(default=0, verbose_name="积分")create_time = models.DateTimeField(auto_now=True, verbose_name="创建时间")class Meta:managed = Truedb_table = 'userinfo'verbose_name_plural = '用户表'def __str__(self):return self.username
6.2.2 录入数据
在admin.py注册三张表
from django.contrib import admin
from .models import Banner, Welcome, Notice, Collection, Area, UserInfo# Register your models here.
admin.site.register(Welcome)
admin.site.register(Banner)
admin.site.register(Notice)
admin.site.register(Collection)
admin.site.register(Area)
admin.site.register(UserInfo)
用户
区域表
采集表
6.2.3 serializer.py
新增CollectionSerializer类
# -*- coding: utf-8 -*-
# @Time : 2024/9/26 9:20
# @Author : super
# @File : serializer.py
# @Software: PyCharm
# @Describe:
from rest_framework import serializers
from .models import Banner, Notice, Collectionclass BannerSerializer(serializers.ModelSerializer):class Meta:model = Bannerfields = "__all__"# 通知
class NoticeSerializer(serializers.ModelSerializer):class Meta:model = Noticefields = "__all__"## 采集
class CollectionSerializer(serializers.ModelSerializer):class Meta:model = Collectionfields = ['id', 'name', 'avatar', 'area']depth = 1 # area 外键关联详情拿到
6.2.4 views.py实现数据采集查询接口
from django.shortcuts import render
from .models import Welcome
from django.http import JsonResponse
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from .models import Banner, Notice, Collection
from .serializer import BannerSerializer, NoticeSerializer, CollectionSerializer
from rest_framework.response import Response
from datetime import datetime# Create your views here.# 比较low 使用fbv实现
def welcome(request):# 查询order最大的一张图片result = Welcome.objects.all().order_by('-order').first()img = 'http://127.0.0.1:8000/media/'+str(result.img)return JsonResponse({'code': 100, 'msg': '成功', 'result': img})class BannerViewSet(GenericViewSet, ListModelMixin):queryset = Banner.objects.filter(is_delete=False).order_by('-order')[:3]serializer_class = BannerSerializer# 重写list方法,将通知也整合进去def list(self, request, *args, **kwargs):response = super().list(request, *args, **kwargs)# 获取最后一条通知notice = Notice.objects.filter(is_delete=False).order_by('-create_time').first()serializer = NoticeSerializer(instance=notice)return Response({'code': 100, 'msg': '成功', 'banner': response.data, 'notice': serializer.data})# 信息采集接口 -- 查询登录用户当天采集的所有数据 ---因为还有登录实现 所以暂时先查询当天采集所有数据
class Collectionviewset(GenericViewSet, ListModelMixin):queryset = Collection.objects.all().filter(create_time__gte=datetime.now().date()).order_by('-create_time')serializer_class = CollectionSerializerdef list(self, request, *args, **kwargs):response = super().list(request, *args, **kwargs)today_count = len(self.queryset)return Response({'code': 100, 'msg': '成功', 'result': response.data, 'today_count': today_count})
6.2.5 分发路由
from django.contrib import admin
from django.urls import path
from .views import welcome
from rest_framework.routers import SimpleRouter
from .views import BannerViewSet, Collectionviewsetrouter = SimpleRouter()
router.register('banner', BannerViewSet, 'banner')
router.register('collection', Collectionviewset, 'collection')
urlpatterns = [# http://127.0.0.1:8000/smart/welcome/ --> 就能获得突破数据path('welcome/', welcome),
]
urlpatterns += router.urls
6.2.6 验证
6.3 引入矢量图标库
@font-face {font-family: "iconfont"; /* Project id 4696732 */src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAM8AAsAAAAABygAAALuAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACCcAqCIIIHATYCJAMICwYABCAFhGcHNBtHBhHVk+Fkf0w67908UWFIIi6ywu0mJysC2auri1yWN5DW8ZhD7ENMmiZ4vubI93c3udzmCEgeF4mSqUKyCLqqdcCO0ZHsxANuhAs6RJnUCzlkN0prYAOOuAgSsOUcyRjMhwI23dww6ULvGgxJeYg/wnMSNuBknp9jWM9LXuMk0DAvBJrFOadkhBnKW/ToCynw0pwCwOf/3mljalHHL4C3J421aeIDywP6QO1p2Rbv5AXAKajXdLoAZfIlCGBp0kn17T90LAlLZ61dTg6D0ymQV8rSRQtm4RlBDAYZD8FlVxrkIBxQu+QhcCB+v/yiJQSFo3FqRs7vN5fbyx2jgw2gXxMs14TzFOAAGqgDBmRsf3I4GmkTaqzTUIJ6g8BX0YYO5NB/HuLilMcBkAfZM8l9xaP+UgFgABeYCyyalAuutaWJzv5bgmzc7hEncXbIj9/jEJdoJZyWOQ/s0QoupfsI/jp63Vs3xPH3nPDywmCw6DDO7z57FBW0LfJPJO2k4FjHM0NNes8eTU+dnZx1PsnZy3LOvvlOtv+y0uZxbxVHVhLh3ckre5pLa09xvr+Xs2xRQp/8vvfXllB7QFO8cUNC2zH3lb7Y0NIghii+bUIi0663DQl96QYgej/ocb/9Oww+9af9H98A8KmHiv3RB+cG776cAj9ZP5UkGjMEyrTJjaxiLu5911ksEHG8Kd5ONaW+TFbwSH0ldwy5OTQeJXTDroGDTwtcPDpgqdVvvU+qlWjExAIVdgoISS5BkcBNaJLcoRv2Mzhk+AaXJP9hGS/xu/lURFFHQsGoQf7Bq1qMZ+SY6g3tOwlqir2QukcE1mmpZq5YkOaY0z92YzZgqGa4aOdhShUa1YCKJ8fcDvNs2q4yqZqHI6Fg1CD/4FUtJiRz+fNuaN9JEEl/Jal7UId1Wgj6VVeotgfZp3/sxmzAkEhnuBjDMKUKrX1YQMWTmxBvh9klGVY3bW/Iv7YLgDhmEXeRhrPG7kRR7r0OAwAA') format('woff2'),url('//at.alicdn.com/t/c/font_4696732_24c374vcgqo.woff?t=1727339436396') format('woff'),url('//at.alicdn.com/t/c/font_4696732_24c374vcgqo.ttf?t=1727339436396') format('truetype');
}.iconfont {font-family: "iconfont" !important;font-size: 16px;font-style: normal;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;
}.icon-a-shanchu1:before {content: "\e604";
}
app.wxss
@import "/static/css/iconfont.wxss";
collection,wxml根据实际情况调整
6.4 小程序信息采集打通接口
6.4.1 完成全局配置信息采集页面
const rootUrl='http://127.0.0.1:8000/smart/'
// 表示导出, 在任意js中可以导入 导入就是这个对象
module.exports={welcome:rootUrl + 'welcome/',banner:rootUrl + 'banner/',collection:rootUrl + 'collection/',
}
6.4.2 完成collection.wxjs
import api from '../../config/settings'
Page({/*** 页面的初始数据*/data: {dataDict:{result:[{"id": 1,"name": "张学友","area": "#19","avatar": "/static/images/collection/zxy.png"},{"id": 2,"name": "黎姿","area": "#18","avatar": "/static/images/collection/lz.png"}],today_count: 66}},refresh(){// 加载wx.showLoading({mask: true})wx.request({url: api.collection,method: "GET",success: (res)=>{if(res.data.code == 100){this.setData({dataDict: res.data})}else{wx.showToast({title: '网络加载失败',})}},complete: ()=>{wx.hideLoading()},})},/*** 生命周期函数--监听页面加载*/onLoad(options) {// 一进页面就调用这个函数this.refresh()},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {// 下拉重新加载this.refresh()},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
6.4.3 实现删除功能
6.4.3.1 views实现删除
from django.shortcuts import render
from .models import Welcome
from django.http import JsonResponse
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from .models import Banner, Notice, Collection
from .serializer import BannerSerializer, NoticeSerializer, CollectionSerializer
from rest_framework.response import Response
from datetime import datetime
from rest_framework.mixins import DestroyModelMixin
# Create your views here.# 比较low 使用fbv实现
def welcome(request):# 查询order最大的一张图片result = Welcome.objects.all().order_by('-order').first()img = 'http://127.0.0.1:8000/media/'+str(result.img)return JsonResponse({'code': 100, 'msg': '成功', 'result': img})class BannerViewSet(GenericViewSet, ListModelMixin):queryset = Banner.objects.filter(is_delete=False).order_by('-order')[:3]serializer_class = BannerSerializer# 重写list方法,将通知也整合进去def list(self, request, *args, **kwargs):response = super().list(request, *args, **kwargs)# 获取最后一条通知notice = Notice.objects.filter(is_delete=False).order_by('-create_time').first()serializer = NoticeSerializer(instance=notice)return Response({'code': 100, 'msg': '成功', 'banner': response.data, 'notice': serializer.data})# 信息采集接口 -- 查询登录用户当天采集的所有数据 ---因为还有登录实现 所以暂时先查询当天采集所有数据
class Collectionviewset(GenericViewSet, ListModelMixin, DestroyModelMixin):queryset = Collection.objects.all().filter(create_time__gte=datetime.now().date()).order_by('-create_time')serializer_class = CollectionSerializerdef list(self, request, *args, **kwargs):response = super().list(request, *args, **kwargs)today_count = len(self.queryset)print(today_count)return Response({'code': 100, 'msg': '成功', 'result': response.data, 'today_count': today_count})
6.4.3.2 collection.js实现删除
import api from '../../config/settings'
Page({/*** 页面的初始数据*/data: {dataDict:{result:[{"id": 1,"name": "张学友","area": "#19","avatar": "/static/images/collection/zxy.png"},{"id": 2,"name": "黎姿","area": "#18","avatar": "/static/images/collection/lz.png"}],today_count: 66}},/*** 查询后台数据接口*/refresh(){// 加载wx.showLoading({mask: true})wx.request({url: api.collection,method: "GET",success: (res)=>{if(res.data.code == 100){console.log(res)this.setData({dataDict: res.data})}else{wx.showToast({title: '网络加载失败',})}},complete: ()=>{wx.hideLoading()},})},/*** 生命周期函数--监听页面加载*/onLoad(options) {// 一进页面就调用这个函数this.refresh()},/*** 删除接口*/doDeleteRow(e){wx.showModal({title: '确认是否删除',complete: (res) => {if (res.cancel) { return } if (res.confirm) {// 真删除var nid = e.currentTarget.dataset.nidwx.showLoading({title: '删除中。。。',mask: true})wx.request({url: api.collection + nid + '/',method: "DELETE",success: (res)=>{// 删除完成或没有完成,都刷新页面this.refresh()},complete:()=>{wx.hideLoading()}})}}})},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {// 下拉重新加载this.refresh()},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
6.4.3.3 删除查询总数那有个bug总数不对
修改后端代码
from django.shortcuts import render
from .models import Welcome
from django.http import JsonResponse
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from .models import Banner, Notice, Collection
from .serializer import BannerSerializer, NoticeSerializer, CollectionSerializer
from rest_framework.response import Response
from datetime import datetime
from rest_framework.mixins import DestroyModelMixin
# Create your views here.# 比较low 使用fbv实现
def welcome(request):# 查询order最大的一张图片result = Welcome.objects.all().order_by('-order').first()img = 'http://127.0.0.1:8000/media/'+str(result.img)return JsonResponse({'code': 100, 'msg': '成功', 'result': img})class BannerViewSet(GenericViewSet, ListModelMixin):queryset = Banner.objects.filter(is_delete=False).order_by('-order')[:3]serializer_class = BannerSerializer# 重写list方法,将通知也整合进去def list(self, request, *args, **kwargs):response = super().list(request, *args, **kwargs)# 获取最后一条通知notice = Notice.objects.filter(is_delete=False).order_by('-create_time').first()serializer = NoticeSerializer(instance=notice)return Response({'code': 100, 'msg': '成功', 'banner': response.data, 'notice': serializer.data})# 信息采集接口 -- 查询登录用户当天采集的所有数据 ---因为还有登录实现 所以暂时先查询当天采集所有数据
class Collectionviewset(GenericViewSet, ListModelMixin, DestroyModelMixin):serializer_class = CollectionSerializerdef get_queryset(self):# 获取当前日期today = datetime.now().date()# 返回今天及之后创建的所有集合return Collection.objects.filter(create_time__gte=today).order_by('-create_time')def list(self, request, *args, **kwargs):queryset = self.get_queryset()serializer = self.get_serializer(queryset, many=True)today_count = queryset.count()print(today_count)return Response({'code': 100, 'msg': '成功', 'result': serializer.data, 'today_count': today_count})# # 信息采集接口 -- 查询登录用户当天采集的所有数据 ---因为还有登录实现 所以暂时先查询当天采集所有数据
# class Collectionviewset(GenericViewSet, ListModelMixin, DestroyModelMixin):
# queryset = Collection.objects.all().filter(create_time__gte=datetime.now().date()).order_by('-create_time')
# serializer_class = CollectionSerializer
# def list(self, request, *args, **kwargs):
# response = super().list(request, *args, **kwargs)
# today_count = len(self.queryset)
# print(today_count)
# return Response({'code': 100, 'msg': '成功', 'result': response.data, 'today_count': today_count})
7、信息采集详情页
7.1 小程序端--拍照页面-- camera
7.1.1 app.json新增camera页面与form页面
"pages": ["pages/welcome/welcome","pages/index/index","pages/my/my","pages/activity/activity","pages/notice/notice","pages/collection/collection","pages/face/face","pages/voice/voice","pages/heart/heart","pages/goods/goods","pages/camera/camera","pages/form/form" ],
7.1.2 camera.wxml
<!--pages/camera/camera.wxml-->
<camera class="camera" device-position="{{backFont ? 'back' : 'font'}}" flash="off" frame-size="medium"></camera><view class="function"><view class="switch"></view><view class="record" bindtap="takePhoto"><image src="/static/images/camera/record-on.png"></image></view><view class="switch" bindtap="switchCamera"><image src="/static/images/camera/rotate-camera-white.png"></image> </view>
</view>
7.1.3 camera.wxss
page{height: 100%;}
.camera{height: 80%;width: 100%;
}.function{height: 20%; background-color: black;display: flex;flex-direction: row;justify-content: space-around;align-items: center;
}.record image{width: 160rpx;height: 160rpx;
}
.switch{color: white;width: 80rpx;height: 80rpx;
}
.switch image{width: 80rpx;height: 80rpx;
}
7.1.4 camera.js
// pages/camera/camera.js
Page({/*** 页面的初始数据*/data: {backFont: true},/*** 翻转摄像头*/switchCamera(){this.setData({backFont: !this.data.backFont})},/*** 拍照*/takePhoto() {const ctx = wx.createCameraContext()ctx.takePhoto({quality: 'high',success: (res) => {// 这里我是要把拍的照片 返回给上个页面var pages = getCurrentPages() //取到当前打开的所有页面var prevPage = pages[pages.length-2] //拿到上个页面prevPage.setData({avatar: res.tempImagePath //上个页面的avatar赋值图片路径})// this.setData({// 如果当前页面data中有src属性 的到的就是图片地址// src: res.tempImagePath // })// 拍完就跳到上个页面wx.navigateBack({});}})},error(e) {console.log(e.detail)},/*** 生命周期函数--监听页面加载*/onLoad(options) {},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
7.2 小程序端--采集页面--form
7.2.1 collection.wxjs新增跳转到form页面
/*** 跳转到信息采集列表*/bindToForm(){wx.navigateTo({url: '/pages/form/form',})},/*** 信息统计*/bindToStatistics(){// 先占位},
7.2.2 form.wxml
<view class="avatar"><image src="{{avatar}}" bindtap="bindToCamera"></image>
</view><view class="form"><view class="row-group"><input placeholder="请填写姓名" placeholder-class='txt' model:value="{{name}}" bindinput="bindNameChange" /><!-- <input placeholder="请填写姓名" placeholder-class='txt' model:value="{{name}}" bindinput="bindNameChange" /> --></view><view class="picker-group"><picker bindchange="bindPickerChange" value="{{index}}" range="{{objectArray}}" range-key="name" ><view wx:if="{{index > -1}}" class="picker-txt picker">当前网格:{{objectArray[index].name}}</view><view wx:else class="picker-txt">请选择网格</view></picker> </view><view><button class="submit" bindtap="postUser"> 提 交</button> <!-- <van-button class="submit" bintap="postUser" type="primary" size="large">提 交</van-button> --></view>
</view>
7.2.3 form.wxss
.avatar{display: flex;flex-direction: column;align-items: center;
}
.avatar image{margin-top: 140rpx;width: 300rpx;height: 300rpx;border-radius: 30rpx;border: 1px sold #ddd;
}.form{padding: 40rpx;
}.form .row-group{padding: 10rpx 0;border-bottom: 1rpx solid#ddd;position: relative;margin-top: 30rpx;
}.form .row-group text{font-size: 28rpx;padding: 20rpx 0;
}.form .row-group input{padding: 10rpx 0;
}.form .row-group .txt{color: #ccc;font-size: 28rpx;
}.form .picker-group{border-bottom: 1rpx solid #ddd;
}.form .picker-group .picker-txt{color: #ccc;font-size: 28rpx;padding: 40rpx 0 20rpx 0;
}.form .picker-group .picker{color:black
}.form .submit{margin-top: 80rpx;color: #fff;border: 2rpx solid #00c8b6;background-color:#00c8b6;font-size: 32rpx;font-weight: bold
}
/*
.form .submit{margin-top: 80rpx;
} */
7.2.3 form.js
// pages/form/form.js
Page({/*** 页面的初始数据*/data: {avatar: '/static/images/camera/camera.png'},
/*** 点击图片跳转到form页面*/bindToCamera(){wx.navigateTo({url: '/pages/camera/camera',})},/*** 生命周期函数--监听页面加载*/onLoad(options) {},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
7.3 后端接口
7.3.1 Serializer新增AreaSerializer
# -*- coding: utf-8 -*-
# @Time : 2024/9/26 9:20
# @Author : super
# @File : serializer.py
# @Software: PyCharm
# @Describe:
from rest_framework import serializers
from .models import Banner, Notice, Collection,Areaclass BannerSerializer(serializers.ModelSerializer):class Meta:model = Bannerfields = "__all__"# 通知
class NoticeSerializer(serializers.ModelSerializer):class Meta:model = Noticefields = "__all__"## 采集
class CollectionSerializer(serializers.ModelSerializer):class Meta:model = Collectionfields = ['id', 'name', 'avatar', 'area']depth = 1 # area 外键关联详情拿到## 网格系列化列
class AreaSerializer(serializers.ModelSerializer):class Meta:model = Areafields = ['id', 'name', 'desc']
7.3.2 views新增AreaViewSet
from django.shortcuts import render
from .models import Welcome
from django.http import JsonResponse
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from .models import Banner, Notice, Collection, Area
from .serializer import BannerSerializer, NoticeSerializer, CollectionSerializer ,AreaSerializer
from rest_framework.response import Response
from datetime import datetime
from rest_framework.mixins import DestroyModelMixin
# Create your views here.# 比较low 使用fbv实现
def welcome(request):# 查询order最大的一张图片result = Welcome.objects.all().order_by('-order').first()img = 'http://127.0.0.1:8000/media/'+str(result.img)return JsonResponse({'code': 100, 'msg': '成功', 'result': img})class BannerViewSet(GenericViewSet, ListModelMixin):queryset = Banner.objects.filter(is_delete=False).order_by('-order')[:3]serializer_class = BannerSerializer# 重写list方法,将通知也整合进去def list(self, request, *args, **kwargs):response = super().list(request, *args, **kwargs)# 获取最后一条通知notice = Notice.objects.filter(is_delete=False).order_by('-create_time').first()serializer = NoticeSerializer(instance=notice)return Response({'code': 100, 'msg': '成功', 'banner': response.data, 'notice': serializer.data})# 信息采集接口 -- 查询登录用户当天采集的所有数据 ---因为还有登录实现 所以暂时先查询当天采集所有数据
class Collectionviewset(GenericViewSet, ListModelMixin, DestroyModelMixin):serializer_class = CollectionSerializerdef get_queryset(self):# 获取当前日期today = datetime.now().date()# 返回今天及之后创建的所有集合return Collection.objects.filter(create_time__gte=today).order_by('-create_time')def list(self, request, *args, **kwargs):queryset = self.get_queryset()serializer = self.get_serializer(queryset, many=True)today_count = queryset.count()print(today_count)return Response({'code': 100, 'msg': '成功', 'result': serializer.data, 'today_count': today_count})# # 信息采集接口 -- 查询登录用户当天采集的所有数据 ---因为还有登录实现 所以暂时先查询当天采集所有数据
# class Collectionviewset(GenericViewSet, ListModelMixin, DestroyModelMixin):
# queryset = Collection.objects.all().filter(create_time__gte=datetime.now().date()).order_by('-create_time')
# serializer_class = CollectionSerializer
# def list(self, request, *args, **kwargs):
# response = super().list(request, *args, **kwargs)
# today_count = len(self.queryset)
# print(today_count)
# return Response({'code': 100, 'msg': '成功', 'result': response.data, 'today_count': today_count})# 查询当前用户负责的网格-- 暂时拿全部
class AreaViewSet(GenericViewSet, ListModelMixin):queryset = Area.objects.all()serializer_class = AreaSerializer
7.3.3 urls配置
from django.contrib import admin
from django.urls import path
from .views import welcome
from rest_framework.routers import SimpleRouter
from .views import BannerViewSet, Collectionviewset, AreaViewSetrouter = SimpleRouter()
router.register('banner', BannerViewSet, 'banner')
router.register('collection', Collectionviewset, 'collection')
router.register('area', AreaViewSet, 'area')
urlpatterns = [# http://127.0.0.1:8000/smart/welcome/ --> 就能获得突破数据path('welcome/', welcome),
]
urlpatterns += router.urls
7.4 小程序实现form.js
7.4.1 全局配置添加form后端路径
settings里面
const rootUrl='http://127.0.0.1:8000/smart/'
// 表示导出, 在任意js中可以导入 导入就是这个对象
module.exports={welcome:rootUrl + 'welcome/',banner:rootUrl + 'banner/',collection:rootUrl + 'collection/', area:rootUrl + 'area/',
}
7.4.2 后端处理接口
7.4.2.1 serializer新增CollectionSaveSerializer
# -*- coding: utf-8 -*-
# @Time : 2024/9/26 9:20
# @Author : super
# @File : serializer.py
# @Software: PyCharm
# @Describe:
from rest_framework import serializers
from .models import Banner, Notice, Collection,Areaclass BannerSerializer(serializers.ModelSerializer):class Meta:model = Bannerfields = "__all__"# 通知
class NoticeSerializer(serializers.ModelSerializer):class Meta:model = Noticefields = "__all__"## 采集--查询所有的序列化类
class CollectionSerializer(serializers.ModelSerializer):class Meta:model = Collectionfields = ['id', 'name', 'avatar', 'area']depth = 1 # area 外键关联详情拿到## 采集--新增
class CollectionSaveSerializer(serializers.ModelSerializer):class Meta:model = Collectionfields = ['name', 'avatar','area']## 网格系列化列
class AreaSerializer(serializers.ModelSerializer):class Meta:model = Areafields = ['id', 'name', 'desc']def create(self, validated_data):instance = super().create(validated_data)return instance
7.4.2.2 views修改Collectionviewset
from django.shortcuts import render
from .models import Welcome
from django.http import JsonResponse
from rest_framework.viewsets import GenericViewSet
from .models import Banner, Notice, Collection, Area
from .serializer import BannerSerializer, NoticeSerializer, CollectionSerializer ,AreaSerializer, CollectionSaveSerializer
from rest_framework.response import Response
from datetime import datetime
from rest_framework.mixins import ListModelMixin,DestroyModelMixin,CreateModelMixin
# Create your views here.# 比较low 使用fbv实现
def welcome(request):# 查询order最大的一张图片result = Welcome.objects.all().order_by('-order').first()img = 'http://127.0.0.1:8000/media/'+str(result.img)return JsonResponse({'code': 100, 'msg': '成功', 'result': img})class BannerViewSet(GenericViewSet, ListModelMixin):queryset = Banner.objects.filter(is_delete=False).order_by('-order')[:3]serializer_class = BannerSerializer# 重写list方法,将通知也整合进去def list(self, request, *args, **kwargs):response = super().list(request, *args, **kwargs)# 获取最后一条通知notice = Notice.objects.filter(is_delete=False).order_by('-create_time').first()serializer = NoticeSerializer(instance=notice)return Response({'code': 100, 'msg': '成功', 'banner': response.data, 'notice': serializer.data})# 信息采集接口 -- 查询登录用户当天采集的所有数据 ---因为还有登录实现 所以暂时先查询当天采集所有数据
class Collectionviewset(GenericViewSet, ListModelMixin, DestroyModelMixin, CreateModelMixin):serializer_class = CollectionSerializerdef get_serializer_class(self):if self.action == 'create':return CollectionSaveSerializerelse:return self.serializer_classdef get_queryset(self):# 获取当前日期today = datetime.now().date()# 返回今天及之后创建的所有集合return Collection.objects.filter(create_time__gte=today).order_by('-create_time')def list(self, request, *args, **kwargs):queryset = self.get_queryset()serializer = self.get_serializer(queryset, many=True)today_count = queryset.count()print(today_count)return Response({'code': 100, 'msg': '成功', 'result': serializer.data, 'today_count': today_count})# # 信息采集接口 -- 查询登录用户当天采集的所有数据 ---因为还有登录实现 所以暂时先查询当天采集所有数据
# class Collectionviewset(GenericViewSet, ListModelMixin, DestroyModelMixin):
# queryset = Collection.objects.all().filter(create_time__gte=datetime.now().date()).order_by('-create_time')
# serializer_class = CollectionSerializer
# def list(self, request, *args, **kwargs):
# response = super().list(request, *args, **kwargs)
# today_count = len(self.queryset)
# print(today_count)
# return Response({'code': 100, 'msg': '成功', 'result': response.data, 'today_count': today_count})# 查询当前用户负责的网格-- 暂时拿全部
class AreaViewSet(GenericViewSet, ListModelMixin):queryset = Area.objects.all()serializer_class = AreaSerializer
新增接口完成
7.4.3 form.js
import api from '../../config/settings'
Page({/*** 页面的初始数据*/data: {avatar: '/static/images/camera/camera.png',name: '',objectArray:[{id: 1,name: '1号楼2单元',desc: '1#2'},{id: 2,name: '2号楼2单元',desc: '2#2'}],index: -1},
/*** 点击图片跳转到form页面*/bindToCamera(){wx.navigateTo({url: '/pages/camera/camera',})},/*** 查询后台数据接口*/refresh(){// 加载wx.showLoading({mask: true})wx.request({url: api.area,method: "GET",success: (res)=>{this.setData({objectArray:res.data})},complete: ()=>{wx.hideLoading()},})},/*** 生命周期函数--监听页面加载*/onLoad(options) {this.refresh()},/*** 选择网格*/bindPickerChange(e){this.setData({index: e.detail.value})},/*** 提交数据,上传图片等*/postUser(e){wx.showLoading({title: '提交中',mask: true})wx.uploadFile({filePath: this.data.avatar,name: 'avatar',url: 'api.collection',formData:{name:this.data.name,area:this.data.objectArray[this.data.index].id},success:()=>{// 跳转回上一页wx.navigateBack({})},complete: ()=>{wx.hideLoading()}})},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
7.4.4 collection.js 新增一个刷新查询
onShow() {this.refresh()},
8、信息统计-采集统计页面实现
8.1 小程序端
8.1.1 app.json新增采集统计
"pages": ["pages/welcome/welcome","pages/index/index","pages/my/my","pages/activity/activity","pages/notice/notice","pages/collection/collection","pages/face/face","pages/voice/voice","pages/heart/heart","pages/goods/goods","pages/camera/camera","pages/form/form","pages/statistics/statistics" ],
8.1.2 statistics.wxml
<view class="container"><view class="menu" wx:for="{{dataList}}" wx:key="index"><view><label class="iconfont icon-rilitianchong"></label> {{item.date}}</view><label>{{item.count}}个</label></view>
</view>
8.1.3 statistics.wxss
.container{border-top: 1px solid #ddd;
}.container .menu{font-size: small;padding: 10px 40rpx;border-bottom: 1px dotted #ddd;text-align: center;display: flex;flex-direction: row;justify-content: space-between;background-color: white;
}
8.1.4 更新iconfont.wxss
@font-face {font-family: "iconfont"; /* Project id 4696732 */src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAPoAAsAAAAACIQAAAOaAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACDBgqEUIN/ATYCJAMMCwgABCAFhGcHRBtpBxHVmwfJfiSmWwzyTfON5bbaKd4ED6gz/8mSU0U+AtpKMBGT03KuwLAS4/RhdgMEyEHfmrN6IHzUXFHWjjz6hzwV0sunA+HFLi5NU6qGkvEF8NTWKHhg8QAFqLRqXfy7Pb+Y/iK7M8iLugQBGCo0YDVr0bIjYSP7TRxNEoVVLSDNFiOHDemHFlWolmyBRuCDTlSIldhgLbHuAivCtxd/qEqDhS2xlmk7uPlALn5X349L13NBvsWvQoA7W4ANSKBkYxrRu93UFRmHSkhMnUiRZB8KgTWp1/MIWbrAZ//DAwsBwoeVGQJAAQlb8F25rFR8HHOumv2EEt+AyDPgo2iJQX0jn8pJjwgNNSY73JoyxbHMCIN7MHhYiJDwz5ngyaMo99gpJ7z2zAlhB46fHirctcYE1wc2OI5A7tp1DGrRCJn/wejaDUIE1gfXgrsuVGo2wz1rQoLnhR3eH4YOpRISbgTna4acBbP2oHso1lHupXsNijMXFo5zao8EDg/1GCO3WL8/uHctlnvIZMkbNqM2UtYdCsUGBLEtQ7vm3e16N6HbuLrhzdObh9edEpLSOt1gXPLrY8kjUo69Tv6T/PtYyojkY7+vjkIf8f+nz0Sc0R83fUSoDU1PR57W//kP6/lz9BkeOKJdfbhL3mldvtV/19/ZFUX5hpvmLFedjcbLUPHSxMiE/QmRiaOS9g61B9uJ9GXZlZ3eZ2d6WYlZXmb2h4fZKTkPh43MLt6VvT/xn5oGSaOGhTVNbXZ7XnhN2BSzQkfpFWZKWM26sGZZuz/gj8F0TAut6RKONdv7p4Q1oy8A3v/yhewO3hH5SXb6+7/D74pOf/uE1/tfOwqALynJFaHTO6KAp6GxQGD9a3FPIKLS3SBVHcstRwCScfzKfhZgMICHbFHeD7dEIzUItMjGYFGHZJBostAKXwQ2DlXgQ1MfDMWaT3eINhaJUH4gzzwEggiHwCKMUyCJcAOt8C/AJs4P8BGB/sPGq/1iW4fMkVEJWtA/iIZm50glrPeGfh0VV/lfyDliL7RVU4xecUYeY0h++07EgWOa4MK3w3EkWJgSGqmCyNLXtau7SmVoKo4YUgSygPYDIoPMnI8s+Y93g7zVSGEg+hViWcT1g1alAaCvohlUcSPNszevI4Sj3RxGJuCiG9BohwhY6tslyBCVMCCw6NUEyUFF1fKS6eXWAIZ1iswSUij2i2OUqGYTaPYbVeaQOte2KAAAAA==') format('woff2'),url('//at.alicdn.com/t/c/font_4696732_u0hsdlhku1.woff?t=1727425200183') format('woff'),url('//at.alicdn.com/t/c/font_4696732_u0hsdlhku1.ttf?t=1727425200183') format('truetype');
}.iconfont {font-family: "iconfont" !important;font-size: 16px;font-style: normal;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;
}.icon-rilitianchong:before {content: "\e6ae";
}.icon-a-shanchu1:before {content: "\e604";
}
8.2 后端接口
8.2.1 serializer新增StatisticsListSerializer
# -*- coding: utf-8 -*-
# @Time : 2024/9/26 9:20
# @Author : super
# @File : serializer.py
# @Software: PyCharm
# @Describe:
from rest_framework import serializers
from .models import Banner, Notice, Collection,Areaclass BannerSerializer(serializers.ModelSerializer):class Meta:model = Bannerfields = "__all__"# 通知
class NoticeSerializer(serializers.ModelSerializer):class Meta:model = Noticefields = "__all__"## 采集--查询所有的序列化类
class CollectionSerializer(serializers.ModelSerializer):class Meta:model = Collectionfields = ['id', 'name', 'avatar', 'area']depth = 1 # area 外键关联详情拿到## 采集--新增
class CollectionSaveSerializer(serializers.ModelSerializer):class Meta:model = Collectionfields = ['name', 'avatar','area']## 网格系列化列
class AreaSerializer(serializers.ModelSerializer):class Meta:model = Areafields = ['id', 'name', 'desc']def create(self, validated_data):instance = super().create(validated_data)return instance# 统计信息
class StatisticsListSerializer(serializers.Serializer):date = serializers.DateTimeField(format='%Y-%m-%d')count = serializers.IntegerField()
8.2.2 views
from django.shortcuts import renderfrom django.http import JsonResponse
from rest_framework.viewsets import GenericViewSet
from .models import Welcome,Banner, Notice, Collection, Area
from .serializer import BannerSerializer, NoticeSerializer, CollectionSerializer ,AreaSerializer, CollectionSaveSerializer,StatisticsListSerializer
from rest_framework.response import Response
from datetime import datetime
from rest_framework.mixins import ListModelMixin,DestroyModelMixin,CreateModelMixin
from django.db.models.functions import Trunc
from django.db.models import Count
# Create your views here.# 比较low 使用fbv实现
def welcome(request):# 查询order最大的一张图片result = Welcome.objects.all().order_by('-order').first()img = 'http://127.0.0.1:8000/media/'+str(result.img)return JsonResponse({'code': 100, 'msg': '成功', 'result': img})class BannerViewSet(GenericViewSet, ListModelMixin):queryset = Banner.objects.filter(is_delete=False).order_by('-order')[:3]serializer_class = BannerSerializer# 重写list方法,将通知也整合进去def list(self, request, *args, **kwargs):response = super().list(request, *args, **kwargs)# 获取最后一条通知notice = Notice.objects.filter(is_delete=False).order_by('-create_time').first()serializer = NoticeSerializer(instance=notice)return Response({'code': 100, 'msg': '成功', 'banner': response.data, 'notice': serializer.data})# 信息采集接口 -- 查询登录用户当天采集的所有数据 ---因为还有登录实现 所以暂时先查询当天采集所有数据
class Collectionviewset(GenericViewSet, ListModelMixin, DestroyModelMixin, CreateModelMixin):serializer_class = CollectionSerializerdef get_serializer_class(self):if self.action == 'create':return CollectionSaveSerializerelse:return self.serializer_classdef get_queryset(self):# 获取当前日期today = datetime.now().date()# 返回今天及之后创建的所有集合return Collection.objects.filter(create_time__gte=today).order_by('-create_time')def list(self, request, *args, **kwargs):queryset = self.get_queryset()serializer = self.get_serializer(queryset, many=True)today_count = queryset.count()print(today_count)return Response({'code': 100, 'msg': '成功', 'result': serializer.data, 'today_count': today_count})# # 信息采集接口 -- 查询登录用户当天采集的所有数据 ---因为还有登录实现 所以暂时先查询当天采集所有数据
# class Collectionviewset(GenericViewSet, ListModelMixin, DestroyModelMixin):
# queryset = Collection.objects.all().filter(create_time__gte=datetime.now().date()).order_by('-create_time')
# serializer_class = CollectionSerializer
# def list(self, request, *args, **kwargs):
# response = super().list(request, *args, **kwargs)
# today_count = len(self.queryset)
# print(today_count)
# return Response({'code': 100, 'msg': '成功', 'result': response.data, 'today_count': today_count})# 查询当前用户负责的网格-- 暂时拿全部
class AreaViewSet(GenericViewSet, ListModelMixin):queryset = Area.objects.all()serializer_class = AreaSerializer# 统计每天采集人数接口
class StatisticsViewSet(GenericViewSet, ListModelMixin):queryset = Collection.objects.annotate(date=Trunc("create_time","day")).values("date").\annotate(count=Count("id")).values("date", "count")serializer_class = StatisticsListSerializer
8.2.3 urls路由
from django.contrib import admin
from django.urls import path
from .views import welcome
from rest_framework.routers import SimpleRouter
from .views import BannerViewSet, Collectionviewset, AreaViewSet,StatisticsViewSetrouter = SimpleRouter()
router.register('banner', BannerViewSet, 'banner')
router.register('collection', Collectionviewset, 'collection')
router.register('area', AreaViewSet, 'area')
router.register('statistics', StatisticsViewSet, 'statistics')
urlpatterns = [# http://127.0.0.1:8000/smart/welcome/ --> 就能获得突破数据path('welcome/', welcome),
]
urlpatterns += router.urls
8.3 采集统计联调
8.3.1 settings.js注册
const rootUrl='http://127.0.0.1:8000/smart/'
// 表示导出, 在任意js中可以导入 导入就是这个对象
module.exports={welcome:rootUrl + 'welcome/',banner:rootUrl + 'banner/',collection:rootUrl + 'collection/', area:rootUrl + 'area/',statistics:rootUrl + 'statistics/',
}
8.3.2 collection.js添加点击跳转
import api from '../../config/settings'
Page({/*** 页面的初始数据*/data: {dataDict:{result:[{"id": 1,"name": "张学友","area": "#19","avatar": "/static/images/collection/zxy.png"},{"id": 2,"name": "黎姿","area": "#18","avatar": "/static/images/collection/lz.png"}],today_count: 66}},/*** 查询后台数据接口*/refresh(){// 加载wx.showLoading({mask: true})wx.request({url: api.collection,method: "GET",success: (res)=>{if(res.data.code == 100){console.log(res)this.setData({dataDict: res.data})}else{wx.showToast({title: '网络加载失败',})}},complete: ()=>{wx.hideLoading()},})},/*** 生命周期函数--监听页面加载*/onLoad(options) {// 一进页面就调用这个函数this.refresh()},/*** 删除接口*/doDeleteRow(e){wx.showModal({title: '确认是否删除',complete: (res) => {if (res.cancel) { return } if (res.confirm) {// 真删除var nid = e.currentTarget.dataset.nidwx.showLoading({title: '删除中。。。',mask: true})wx.request({url: api.collection + nid + '/',method: "DELETE",success: (res)=>{// 删除完成或没有完成,都刷新页面this.refresh()},complete:()=>{wx.hideLoading()}})}}})},/*** 跳转到信息采集列表*/bindToForm(){wx.navigateTo({url: '/pages/form/form',})},/*** 信息统计*/bindToStatistics(){wx.navigateTo({url: '/pages/statistics/statistics',})},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {this.refresh()},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {// 下拉重新加载this.refresh()},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
8.3.3 statistics.js
import api from '../../config/settings'
Page({/*** 页面的初始数据*/data: {dataList: [{"date": "2023-09-26","count": 1},{"date": "2023-09-27","count": 3}]},/*** 查询数据*/getRecord(){wx.showLoading({title: '加载中',mask: true})wx.request({url: api.statistics,method:"GET",success:(res)=>{this.setData({dataList: res.data})},complete:()=>{wx.hideLoading()}})},/*** 生命周期函数--监听页面加载*/onLoad(options) {this.getRecord()},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
9、 人脸识别
9.1 人脸识别
9.1.1 使用步骤
后端代码根目录新增文件夹script
9.1.2 上传-删除-匹配人脸
10、个人中心
10.1 个人中心静态页面
10.1.1 my.json
{"usingComponents": {},"navigationBarTitleText": "个人中心"
}
10.1.2 my.wxss
page{height: 100%;
}.login-area{height: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;
}.login-area .btn{width: 200rpx;height: 200rpx;border-radius: 500%;background-color: #5cb85c;color: white;display: flex;flex-direction: row;align-items: center;justify-content: center;
}
.user-area{height: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;
}
.user-area image{width: 200rpx;height: 200rpx;border-radius: 500%;}
.user-area .name{font-size: 30rpx;padding: 30rpx 0;
}
.user-area .logout{color: #a94442;
}.top-view{background-color: #01ccb6;color: white;padding: 40rpx;
}.top-view .user{display: flex;flex-direction: row;justify-content: space-between;align-items: center;
}.top-view .user .row{display: flex;flex-direction: row;justify-content: flex-start;align-items: center;
}.top-view .user .avatar{width: 100rpx;height: 100rpx;border-radius: 50%;
}.top-view .user .name{display: flex;flex-direction: row;justify-content: flex-start;padding-left: 20rpx;
}.top-view .user .name navigator{padding: 0 5rpx;
}.top-view .site{background-color: rgba(0, 0, 0, 0.16);padding: 20rpx;border-top-left-radius: 32rpx;border-bottom-left-radius: 32rpx;
}.top-view .numbers{display: flex;flex-direction: row;justify-content: space-between;font-size: 28rpx;padding: 40rpx;padding-bottom: 0rpx;
}.top-view .numbers .row{display: flex;flex-direction: column;align-items: center;
}
10.1.3 my.wxml
<!--pages/my/my.wxml--><block wx:if="{{userInfo==null}}"><navigator class="login-area" url="/pages/login/login"><view class="btn">一键登录</view></navigator>
</block>
<block wx:else><view class="container"><view class="top-view"><!--绿色区域=====用户部分--><view class="user"><view class="row"><image class="avatar" src="{{userInfo.avatar}}"></image><view class="name"><view bindtap="logout">{{userInfo.name}}</view></view> </view> </view><!--绿色区域======数字部分--><view class="numbers"><view class="row"><text>{{userInfo.score}}</text><text>积分</text></view><view class="row"><text>55</text><text>其他</text></view><view class="row"><text>77</text><text>其他</text></view><view class="row"><text>56</text><text>其他</text></view> </view> </view><van-list><van-cell title="积分兑换记录" is-link /><van-cell title="我参加的活动" is-link /><van-cell title="分享应用" is-link /><van-cell title="联系客服" is-link /></van-list></view></block>
10.1.4 my.wxjs
// pages/my/my.js
Page({/*** 页面的初始数据*/data: {userInfo:{avatar: '/static/images/tx.png',name: '卢卡斯',score: 100},},/*** 生命周期函数--监听页面加载*/onLoad(options) {},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})
相关文章:

【小程序】微信小程序课程 -4 项目实战
目录 1、 效果图 2、创建项目 2.1 创建小程序端 2.1.1 先创建纯净项目 2.1.2 删除components 2.1.4 删除app.json红色部分 2.1.5 删除index.json红色部分 2.1.6 删除index.wxss全部内容 2.1.7 删除index.wxml全部内容 2.1.8 app.json创建4个页面 2.1.9 app.json添加…...

【期刊】论文索引库-SCI\SSCI\IE\南大核心\北大核心\CSCD等
外文期刊检索 SCI SCI即《科学引文索引》(Science Citation Index),是由美国科学信息研究所(Institute for Scientific Information)创建于1961年,收录文献的作者、题目、源期刊、摘要、关键词,不仅可以从文献引证的角度评估文章的学术价值,还可以迅速方便地组建研究课…...

开源链动 2+1 模式 S2B2C 商城小程序:社交电商团队为王的新引擎
摘要:本文深入探讨在社交电商领域中,团队的重要性以及如何借助开源链动 21 模式 S2B2C 商城小程序,打造具有强大竞争力的团队,实现个人价值与影响力的放大,创造被动收入,迈向财富自由之路,同时为…...

使用Fiddler Classic抓包工具批量下载音频资料
1. 通过F12开发者工具,下载音频文件 浏览器打开音频列表->F12快捷键->网络->媒体,播放一个音频文件,右边媒体下生成一个音频文件,右击“在新标签页中打开”,可以下载这个音频文件。 2.通过Fiddler Classic抓…...

QT开发:基于Qt实现的交通信号灯模拟器:实现一个带有倒计时功能的图形界面应用
介绍 本文将介绍如何使用Qt框架实现一个简单的交通信号灯控制程序。本程序包括一个图形界面,显示红、黄、绿三色信号灯,并通过定时器控制信号灯的切换。同时,我们还将实现一个带有按钮的界面,用于展示信号灯的状态。 1. 安装Qt开…...
【编程基础知识】网络I/O模型详解:从阻塞到异步
引言 网络I/O模型是网络编程的核心,它们决定了应用程序如何进行读写操作以与网络进行数据交换。了解不同的网络I/O模型对于设计高效、可扩展的网络应用程序至关重要。 一、阻塞I/O(Blocking I/O) 1. 定义 阻塞调用:当应用程序…...

yolo自动化项目实例解析(六)自建UI(主窗口、预览窗口)
前面我们大致把各个代码块梳理出来了,但是还是不知道从那块开始,我们这里主要先通过ui页面的元素去推理整个执行过程,我们首先需要知道ui功能里面有那些组件 qt设计师基础控件 Qt Designer 是一个图形界面设计工具,用于创建 Qt 应…...
Unity优质教程分类汇总 【持续更新中】
以下收录的均为作者自己看过的觉得比较好的教程 基础 Unity入门: https://www.bilibili.com/video/BV1HX4y1V71E?p13 生命周期 https://docs.unity.cn/cn/2022.3/uploads/Main/monobehaviour_flowchart.svg https://zhuanlan.zhihu.com/p/551294000 编程技巧…...
真正掌握left join on 和 where 的差别
总结 用 where 是先连接然后再筛选用 on 是先筛选再连接数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户。在使用left jion时,on和where条件的区别如下: on条件是在生成临时表…...

神经网络在多分类问题中的应用
作者简介:热爱数据分析,学习Python、Stata、SPSS等统计语言的小高同学~个人主页:小高要坚强的博客当前专栏:Python之机器学习本文内容:神经网络在多分类问题中的应用作者“三要”格言:要坚强、要努力、要学习 目录 1. 引言 2.数据构造 3.划分数据集 4.神经网络实现多…...

nginx的安装和使用
源码安装 1.环境准备:卸载其他方式安装的web应用,防止端口冲突 2.下载nginx源码包 wget https://nginx.org/download/nginx-1.20.2.tar.gz 3.源码编译安装 yum install -y gcc pcre-devel zlib-devel #安装依赖包 useradd -M -s /sbin/nologin ngi…...
js采用覆盖键、覆盖鼠标滑动事件实现禁止网页通过 ctrl + +/- 和 ctrl + 滚轮 对页面进行缩放
一、兼容电脑端的禁止通过 ctrl /- 和 ctrl 滚轮 对页面进行缩放 const keyCodeMap {// 91: true, // command61: true,107: true, // 数字键盘 109: true, // 数字键盘 -173: true, // 火狐 - 号187: true, // 189: true, // -};二、覆盖ctrl||command ‘’/‘-’ // 覆…...

某客户Oracle RAC无法启动故障快速解决
某日,9:50左右接到好友协助需求,某个客户Oracle RAC无法启动,并发过来一个报错截图,如下: 和客户维护人员对接后,远程登录服务端进行故障分析。 查看hosts信息,首先进行心跳测试,测…...

【计算机网络 - 基础问题】每日 3 题(二十八)
✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏&…...

探索甘肃非遗:Spring Boot网站开发案例
1 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大,随着当前时代的信息化,科学化发展,让社会各行业领域都争相使用新的信息技术,对行业内的各种相关数据进行科学化,规范化管理。这样的大环境让那些止步不前&#…...

产品管理- 互联网产品(6):产品测试
可用性测试 招募有代表性用户作为测试代表参与者,评估某产品符合特定可用性及符合程度。以具有代表性的用户为测试样本。 测试中多关注用户表情与动作。多鼓励与测试的用户更多的操作以用户角度发现问题。同时要做好询问工作,耐心聆听用户的意见&#x…...

奖金高达 110 万元,Spatial Joy 2024 全球 AR 应用开发大赛启动
今年是AR应用开发大赛第三届,恰逢Rokid成立十周年,我们推出全新的大赛品牌“Spatial Joy”,引领开发者享受开发乐趣,为其打造充满挑战和惊喜的开发之旅,逐渐成为空间计算时代全球最大AR应用开发大赛。回顾大赛发展&…...

git add成功后忘记commit的文件丢了?
本文目标:开发人员,在了解git fsck命令用法的条件下,进行git add成功但由于误操作导致丢失的文件找回,达到找回丢失文件的程度。 文章目录 1 痛点2 解决方案3 总结/练习 1 痛点 开发过程中,分支太多(基线分…...
Python Web 开发中的DevOps 实践与自动化运维
Python Web 开发中的DevOps 实践与自动化运维 📚 目录 🔧 基础设施即代码(IaC) 使用 Terraform、AWS CloudFormation 实现基础设施即代码使用 Python 进行云服务资源的管理与自动化配置编写和部署基础设施的自动化脚本 …...

探索私有化聊天软件:即时通讯与音视频技术的结合
在数字化转型的浪潮中,企业对于高效、安全、定制化的通讯解决方案的需求日益迫切。鲸信,作为音视频通信技术的佼佼者,凭借其强大的即时通讯与音视频SDK(软件开发工具包)结合能力,为企业量身打造了私有化聊天…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...

算法—栈系列
一:删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...

2025-05-08-deepseek本地化部署
title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek:小白也能轻松搞定! 如何给本地部署的 DeepSeek 投喂数据,让他更懂你 [实验目的]:理解系统架构与原…...