目录
[1、 效果图](#1、 效果图)
[2.1 创建小程序端](#2.1 创建小程序端)
[2.1.1 先创建纯净项目](#2.1.1 先创建纯净项目)
[2.1.2 删除components](#2.1.2 删除components)
[2.1.4 删除app.json红色部分](#2.1.4 删除app.json红色部分)
[2.1.5 删除index.json红色部分](#2.1.5 删除index.json红色部分)
[2.1.6 删除index.wxss全部内容](#2.1.6 删除index.wxss全部内容)
[2.1.7 删除index.wxml全部内容](#2.1.7 删除index.wxml全部内容)
[2.1.8 app.json创建4个页面](#2.1.8 app.json创建4个页面)
[2.1.9 app.json添加底部导航](#2.1.9 app.json添加底部导航)
[2.1.10 app.json设置窗口栏](#2.1.10 app.json设置窗口栏)
[2.1.11 删除app.wxss全部内容](#2.1.11 删除app.wxss全部内容)
[2.1.12 不校验http](#2.1.12 不校验http)
[2.2 创建小程序后端项目](#2.2 创建小程序后端项目)
[2.2.1 创建项目](#2.2.1 创建项目)
[2.2.2 安装配置mysql数据库](#2.2.2 安装配置mysql数据库)
[2.2.3 settings配置修改(国际化修改)](#2.2.3 settings配置修改(国际化修改))
[2.2.4 运行后端](#2.2.4 运行后端)
[2.2.5 后期涉及需要安装的库](#2.2.5 后期涉及需要安装的库)
[3.1 node介绍](#3.1 node介绍)
[3.2 使用vant样式引用(这里是示例,代码不需要)](#3.2 使用vant样式引用(这里是示例,代码不需要))
[4.1 纯静态](#4.1 纯静态)
[4.1.1 welcome. wxml](#4.1.1 welcome. wxml)
[4.1.2 welcome.wxss](#4.1.2 welcome.wxss)
[4.1.3 welcome.js](#4.1.3 welcome.js)
[4.2 后端加载欢迎页](#4.2 后端加载欢迎页)
[4.2.1 创建表模型](#4.2.1 创建表模型)
[4.2.2 开启media访问](#4.2.2 开启media访问)
[4.2.3 使用admin上传图片](#4.2.3 使用admin上传图片)
[4.2.3.1 配置](#4.2.3.1 配置)
[4.2.3.2 上传图片](#4.2.3.2 上传图片)
[4.2.4 写视图函数(后期使用cbv改造)](#4.2.4 写视图函数(后期使用cbv改造))
[4.3 小程序端改造(动态获取广告)](#4.3 小程序端改造(动态获取广告))
[4.3.1 welcome. wxml](#4.3.1 welcome. wxml)
[4.3.2 welcome. wxss](#4.3.2 welcome. wxss)
[5、 首页](#5、 首页)
[5.1 首页静态页面](#5.1 首页静态页面)
[5.1.1 index.wxml](#5.1.1 index.wxml)
[5.1.2 index.wxss](#5.1.2 index.wxss)
[5.1.3 app.json](#5.1.3 app.json)
[5.2 首页菜单跳转](#5.2 首页菜单跳转)
[5.2.1 app.json创建菜单新页面](#5.2.1 app.json创建菜单新页面)
[5.2.2 index.wxjs设置跳转](#5.2.2 index.wxjs设置跳转)
[5.3 首页轮播图和公告接口](#5.3 首页轮播图和公告接口)
[5.3.1 models](#5.3.1 models)
[5.3.2 admin.py注册好新表和创建文件目录](#5.3.2 admin.py注册好新表和创建文件目录)
[5.3.3 admin录入数据](#5.3.3 admin录入数据)
[5.3.4 轮播图接口](#5.3.4 轮播图接口)
[5.3.4.1 smart应用下新建serializer](#5.3.4.1 smart应用下新建serializer)
[5.3.4.2 views.py实现BannerViewSet](#5.3.4.2 views.py实现BannerViewSet)
[5.3.4.3 分发路由urls.py](#5.3.4.3 分发路由urls.py)
[5.3.4.4 settings项目当中注册rest_framework](#5.3.4.4 settings项目当中注册rest_framework)
[5.3.4.5 启动服务验证](#5.3.4.5 启动服务验证)
[5.3.4.6 整合通知到一个接口](#5.3.4.6 整合通知到一个接口)
[5.3.4.6.1 serializer.py](#5.3.4.6.1 serializer.py)
[5.3.4.6.2 views.py](#5.3.4.6.2 views.py)
[5.3.4.6.3 查看接口返回数据](#5.3.4.6.3 查看接口返回数据)
[5.4 小程序轮播图与公告获取后端数据](#5.4 小程序轮播图与公告获取后端数据)
[5.4.1 index.wxjs](#5.4.1 index.wxjs)
[5.4.2 index.wxml](#5.4.2 index.wxml)
[5.5 接口全局IP设置](#5.5 接口全局IP设置)
[5.5.1 新建全局settings.js](#5.5.1 新建全局settings.js)
[5.5.3 welcome.js引入应用](#5.5.3 welcome.js引入应用)
[5.5.3 index.js引入应用](#5.5.3 index.js引入应用)
[6.1 信息采集静态页面](#6.1 信息采集静态页面)
[6.1.1 collection.json](#6.1.1 collection.json)
[6.1.2 collection.wxml](#6.1.2 collection.wxml)
[6.1.3 collection.wxjs](#6.1.3 collection.wxjs)
[6.1.4 collection.wxss](#6.1.4 collection.wxss)
[6.2 信息采集后端接口](#6.2 信息采集后端接口)
[6.2.1 新建model.py创建表](#6.2.1 新建model.py创建表)
[6.2.2 录入数据](#6.2.2 录入数据)
[6.2.3 serializer.py](#6.2.3 serializer.py)
[6.2.4 views.py实现数据采集查询接口](#6.2.4 views.py实现数据采集查询接口)
[6.2.5 分发路由](#6.2.5 分发路由)
[6.2.6 验证](#6.2.6 验证)
[6.3 引入矢量图标库](#6.3 引入矢量图标库)
[6.4 小程序信息采集打通接口](#6.4 小程序信息采集打通接口)
[6.4.1 完成全局配置信息采集页面](#6.4.1 完成全局配置信息采集页面)
[6.4.2 完成collection.wxjs](#6.4.2 完成collection.wxjs)
[6.4.3 实现删除功能](#6.4.3 实现删除功能)
[6.4.3.1 views实现删除](#6.4.3.1 views实现删除)
[6.4.3.2 collection.js实现删除](#6.4.3.2 collection.js实现删除)
[6.4.3.3 删除查询总数那有个bug总数不对](#6.4.3.3 删除查询总数那有个bug总数不对)
[7.1 小程序端--拍照页面-- camera](#7.1 小程序端--拍照页面-- camera)
[7.1.1 app.json新增camera页面与form页面](#7.1.1 app.json新增camera页面与form页面)
[7.1.2 camera.wxml](#7.1.2 camera.wxml)
[7.1.3 camera.wxss](#7.1.3 camera.wxss)
[7.1.4 camera.js](#7.1.4 camera.js)
[7.2 小程序端--采集页面--form](#7.2 小程序端--采集页面--form)
[7.2.1 collection.wxjs新增跳转到form页面](#7.2.1 collection.wxjs新增跳转到form页面)
[7.2.2 form.wxml](#7.2.2 form.wxml)
[7.2.3 form.wxss](#7.2.3 form.wxss)
[7.2.3 form.js](#7.2.3 form.js)
[7.3 后端接口](#7.3 后端接口)
[7.3.1 Serializer新增AreaSerializer](#7.3.1 Serializer新增AreaSerializer)
[7.3.2 views新增AreaViewSet](#7.3.2 views新增AreaViewSet)
[7.3.3 urls配置](#7.3.3 urls配置)
[7.4 小程序实现form.js](#7.4 小程序实现form.js)
[7.4.1 全局配置添加form后端路径](#7.4.1 全局配置添加form后端路径)
[7.4.2 后端处理接口](#7.4.2 后端处理接口)
[7.4.2.1 serializer新增CollectionSaveSerializer](#7.4.2.1 serializer新增CollectionSaveSerializer)
[7.4.2.2 views修改Collectionviewset](#7.4.2.2 views修改Collectionviewset)
[7.4.3 form.js](#7.4.3 form.js)
[7.4.4 collection.js 新增一个刷新查询](#7.4.4 collection.js 新增一个刷新查询)
[8.1 小程序端](#8.1 小程序端)
[8.1.1 app.json新增采集统计](#8.1.1 app.json新增采集统计)
[8.1.2 statistics.wxml](#8.1.2 statistics.wxml)
[8.1.3 statistics.wxss](#8.1.3 statistics.wxss)
[8.1.4 更新iconfont.wxss](#8.1.4 更新iconfont.wxss)
[8.2 后端接口](#8.2 后端接口)
[8.2.1 serializer新增StatisticsListSerializer](#8.2.1 serializer新增StatisticsListSerializer)
[8.2.2 views](#8.2.2 views)
[8.2.3 urls路由](#8.2.3 urls路由)
[8.3 采集统计联调](#8.3 采集统计联调)
[8.3.1 settings.js注册](#8.3.1 settings.js注册)
[8.3.2 collection.js添加点击跳转](#8.3.2 collection.js添加点击跳转)
[9、 人脸识别](#9、 人脸识别)
[9.1 人脸识别](#9.1 人脸识别)
[9.1.1 使用步骤](#9.1.1 使用步骤)
[9.1.2 上传-删除-匹配人脸](#9.1.2 上传-删除-匹配人脸)
[10.1 个人中心静态页面](#10.1 个人中心静态页面)
[10.1.1 my.json](#10.1.1 my.json)
[10.1.2 my.wxss](#10.1.2 my.wxss)
[10.1.3 my.wxml](#10.1.3 my.wxml)
[10.1.4 my.wxjs](#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 pillow
img = 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=False
class Meta:
managed = True
db_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 settings
urlpatterns = [
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 AppConfig
class 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 settings
urlpatterns = [
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 welcome
urlpatterns = [
# 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) {
// 向后端发送请求--》 获取广告页 --》 赋值给img
wx.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 pillow
img = 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=False
class Meta:
managed = True
db_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=False
class Meta:
managed = True
db_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 = True
db_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 Banner
class BannerSerializer(serializers.ModelSerializer):
class Meta:
model = Banner
fields = "__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 BannerViewSet
router = 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, Notice
class BannerSerializer(serializers.ModelSerializer):
class Meta:
model = Banner
fields = "__all__"
class NoticeSerializer(serializers.ModelSerializer):
class Meta:
model = Notice
fields = "__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) {
// 向后端发送请求--》 获取广告页 --》 赋值给img
wx.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 pillow
img = 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=False
class Meta:
managed = True
db_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=False
class Meta:
managed = True
db_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 = True
db_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 = True
db_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 = True
db_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 = True
db_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, Collection
class BannerSerializer(serializers.ModelSerializer):
class Meta:
model = Banner
fields = "__all__"
# 通知
class NoticeSerializer(serializers.ModelSerializer):
class Meta:
model = Notice
fields = "__all__"
## 采集
class CollectionSerializer(serializers.ModelSerializer):
class Meta:
model = Collection
fields = ['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 = CollectionSerializer
def 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, Collectionviewset
router = 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 = 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})
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.nid
wx.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 = CollectionSerializer
def 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,Area
class BannerSerializer(serializers.ModelSerializer):
class Meta:
model = Banner
fields = "__all__"
# 通知
class NoticeSerializer(serializers.ModelSerializer):
class Meta:
model = Notice
fields = "__all__"
## 采集
class CollectionSerializer(serializers.ModelSerializer):
class Meta:
model = Collection
fields = ['id', 'name', 'avatar', 'area']
depth = 1 # area 外键关联详情拿到
## 网格系列化列
class AreaSerializer(serializers.ModelSerializer):
class Meta:
model = Area
fields = ['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 = CollectionSerializer
def 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, AreaViewSet
router = 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,Area
class BannerSerializer(serializers.ModelSerializer):
class Meta:
model = Banner
fields = "__all__"
# 通知
class NoticeSerializer(serializers.ModelSerializer):
class Meta:
model = Notice
fields = "__all__"
## 采集--查询所有的序列化类
class CollectionSerializer(serializers.ModelSerializer):
class Meta:
model = Collection
fields = ['id', 'name', 'avatar', 'area']
depth = 1 # area 外键关联详情拿到
## 采集--新增
class CollectionSaveSerializer(serializers.ModelSerializer):
class Meta:
model = Collection
fields = ['name', 'avatar','area']
## 网格系列化列
class AreaSerializer(serializers.ModelSerializer):
class Meta:
model = Area
fields = ['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 = CollectionSerializer
def get_serializer_class(self):
if self.action == 'create':
return CollectionSaveSerializer
else:
return self.serializer_class
def 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,Area
class BannerSerializer(serializers.ModelSerializer):
class Meta:
model = Banner
fields = "__all__"
# 通知
class NoticeSerializer(serializers.ModelSerializer):
class Meta:
model = Notice
fields = "__all__"
## 采集--查询所有的序列化类
class CollectionSerializer(serializers.ModelSerializer):
class Meta:
model = Collection
fields = ['id', 'name', 'avatar', 'area']
depth = 1 # area 外键关联详情拿到
## 采集--新增
class CollectionSaveSerializer(serializers.ModelSerializer):
class Meta:
model = Collection
fields = ['name', 'avatar','area']
## 网格系列化列
class AreaSerializer(serializers.ModelSerializer):
class Meta:
model = Area
fields = ['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 render
from 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 = CollectionSerializer
def get_serializer_class(self):
if self.action == 'create':
return CollectionSaveSerializer
else:
return self.serializer_class
def 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,StatisticsViewSet
router = 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.nid
wx.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() {
}
})