Compare commits

..

24 Commits

@ -0,0 +1,14 @@
# Windows
[Dd]esktop.ini
Thumbs.db
$RECYCLE.BIN/
# macOS
.DS_Store
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
# Node.js
node_modules/

@ -0,0 +1,6 @@
{
"permissions": {
"openapi": [
]
}
}

@ -0,0 +1,72 @@
// 云函数入口文件
const cloud = require('wx-server-sdk')
const TcbRouter = require('tcb-router');
const axios = require('axios')
const Qs= require('qs')
cloud.init({
env: "cloud1-0gle9p5m591ea29f"
})
let db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
let {
APPID,
OPENID
} = wxContext
const app = new TcbRouter({
event
})
//提供通过文本进行垃圾分类查询的能力
app.router('garbageTextSearch', async (ctx, next) => {
let {
text,
} = event
ctx.body = axios({
method:'post',
url:'https://apis.tianapi.com/lajifenlei/index',
data:Qs.stringify({key:'ff5c44567b996ea8090d1abb7c1f3bc9',word:text}),
headers:{'Content-Type': 'application/x-www-form-urlencoded'}
}).then(res => {
return res.data
})
})
//通过图片进行垃圾分类查询的能力
app.router('garbageImageSearch', async (ctx, next) => {
let {
imgBase64,
} = event
const img = await cloud.downloadFile({
fileID: imgBase64
})
let buffer = new Buffer.from(img.fileContent)
cloud.deleteFile({
fileList: [imgBase64]
})
let str = buffer.toString('base64')
ctx.body = axios({
method:'post',
url:'https://apis.tianapi.com/imglajifenlei/index',
data:Qs.stringify({key:'ff5c44567b996ea8090d1abb7c1f3bc9',img:str}),
headers:{'Content-Type': 'application/x-www-form-urlencoded'}
}).then(res => {
return res.data
})
});
//获取用户openID
app.router('openId', async (ctx, next) => {
ctx.body = {
openId: OPENID
}
})
return app.serve()
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,20 @@
{
"name": "api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.20.0",
"debug": "^4.3.1",
"jdcloud-sdk-signer": "^2.0.2",
"md5-node": "^1.0.1",
"qs": "^6.9.4",
"tcb-router": "^1.1.2",
"wx-server-sdk": "~2.3.0"
}
}

@ -0,0 +1,6 @@
{
"permissions": {
"openapi": [
]
}
}

@ -0,0 +1,520 @@
const cloud = require('wx-server-sdk')
const TcbRouter = require('tcb-router');
const xlsx = require('node-xlsx');
let {
FormatData
} = require('./util.js');
cloud.init({
env: "cloud1-0gle9p5m591ea29f"
})
let db = cloud.database()
const _ = db.command
const $ = db.command.aggregate
const MAXANSWER = 10
const MAX_LIMIT = 100
const INTEGRAL = {
SHARE: 50
}
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
let {
APPID,
OPENID
} = wxContext
const app = new TcbRouter({
event
})
//添加搜索历史
app.router('addHot', async (ctx, next) => {
let {
hot_text,
} = event
let hot = db.collection('hot')
let {
total
} = await hot.where({
hot_text: hot_text
}).count()
if (total) {
await hot.where({
hot_text: hot_text
})
.update({
data: {
hot_num: _.inc(1)
}
})
} else {
await hot.add({
data: {
hot_text: hot_text,
hot_time: new Date(),
hot_num: 1
}
})
}
ctx.body = {
code: 1,
msg: "添加成功"
}
})
//获取热点搜索
app.router('getHot', async (ctx, next) => {
let hot = db.collection('hot')
let {
data
} = await hot.orderBy('hot_num', 'desc').limit(10).get()
ctx.body = {
code: 1,
data
}
})
//用户登录
app.router('login', async (ctx, next) => {
let {
userInfo
} = event
let user = db.collection('user')
let {
total
} = await user.where({
OPENID: OPENID
}).count()
if (total) {
await user.where({
OPENID: OPENID
})
.update({
data: userInfo
})
} else {
await user.add({
data: {
nickName: userInfo.nickName,
gender: userInfo.gender,
avatarUrl: userInfo.avatarUrl,
OPENID: OPENID,
integral: 0,
answerIntegral: 0
}
})
}
let {
data
} = await user.where({
OPENID: OPENID
}).get()
ctx.body = {
code: 1,
msg: "添加成功",
userInfo: data[0]
}
})
//获取个人信息
app.router('getUserInfo', async (ctx, next) => {
let user = db.collection('user')
let {
data
} = await user.where({
OPENID: OPENID
}).get()
ctx.body = {
code: 1,
userInfo: data[0]
}
})
//获得题目
app.router('answerList', async (ctx, next) => {
let answer = db.collection('answer')
let {
list
} = await answer.aggregate()
.sample({
size: MAXANSWER
}).end()
ctx.body = {
code: 1,
data: list
}
})
//添加题目
app.router('addAnswer', async (ctx, next) => {
let {
name,
type
} = event
let answer = db.collection('answer')
let {
total
} = await answer.where({
name
}).count()
if (total) {
ctx.body = {
code: 2,
data: "无法重复添加"
}
} else {
await answer.add({
data: {
name,
type
}
})
ctx.body = {
code: 1,
data: "添加成功"
}
}
})
//扫码获取积分
app.router('scanCode', async (ctx, next) => {
let {
integral
} = event
let user = db.collection('user')
/**
* 添加用户积分
*/
await user.where({
OPENID: OPENID
}).update({
data: {
integral: _.inc(Number(integral))
}
})
ctx.body = {
code: 1
}
})
//添加反馈
app.router('addFeedback', async (ctx, next) => {
let {
content
} = event
let feedback = db.collection('feedback')
await feedback.add({
data: {
content,
isRead: false,
time: db.serverDate(),
OPENID
}
})
ctx.body = {
code: 1,
data: "添加成功"
}
})
//删除错题
app.router('delWrongUser', async (ctx, next) => {
let {
_id
} = event
let wrong = db.collection('wrong')
await wrong.where({
_id: _id
}).remove()
ctx.body = {
code: 1,
msg: "删除成功",
data: ''
}
})
//获取用户答题积分排名列表
app.router('getUserAnswerlist', async (ctx, next) => {
let user = db.collection('user')
let {
data
} = await user.orderBy('answerIntegral', 'desc').limit(MAX_LIMIT).get()
ctx.body = {
code: 1,
data: data
}
})
//获取用户答题积分排名
app.router('getUseRanking', async (ctx, next) => {
let user = db.collection('user')
const countResult = await user.count()
const total = countResult.total
const batchTimes = Math.ceil(total / MAX_LIMIT)
const tasks = []
for (let i = 0; i < batchTimes; i++) {
const promise = user.orderBy('answerIntegral', 'desc').skip(i * MAX_LIMIT).limit(MAX_LIMIT).get()
tasks.push(promise)
}
let allData = (await Promise.all(tasks)).reduce((acc, cur) => {
return acc.concat(cur.data)
}, [])
let userIndex = allData.findIndex(item => item.OPENID == OPENID)
if (~userIndex) {
userIndex += 1
}
ctx.body = {
code: 1,
data: {
userIndex
}
}
})
//获取用户答题记录
app.router('getHistoryList', async (ctx, next) => {
let answerHistory = db.collection('answer-history')
let {
data
} = await answerHistory.where({
OPENID: OPENID
}).orderBy('historyDate', 'desc').get()
ctx.body = {
code: 1,
data: FormatData(data, {
historyDate: "time"
})
}
})
/**
* 分享他人他人进入小程序
*/
app.router('shareOther', async (ctx, next) => {
let user = db.collection('user')
let share = db.collection('share')
let {
otherOPENID
} = event
let {
total
} = await user.where({
OPENID: OPENID
}).count()
if (total) {
ctx.body = {
code: 2,
msg: "用户已注册"
}
} else {
await share.add({
data: {
OPENID: OPENID,
otherOPENID: otherOPENID,
addIntegral: INTEGRAL.SHARE,
time: new Date()
}
})
await user.where({
OPENID: otherOPENID
}).update({
data: {
integral: _.inc(Number(INTEGRAL.SHARE))
}
})
ctx.body = {
code: 1,
msg: "分享成功"
}
}
})
/**
* 获取我邀请的用户
*/
app.router('shareUser', async (ctx, next) => {
let share = db.collection('share')
let {
list
} = await share.aggregate()
.lookup({
from: "user",
localField: 'OPENID',
foreignField: 'OPENID',
as: 'uapproval'
}).match({
otherOPENID: OPENID
})
.project({
otherOPENID: 1,
time: 1,
addIntegral: 1,
OPENID: 1,
userInfo: $.arrayElemAt(['$uapproval', 0])
}).end()
ctx.body = {
code: 1,
data: FormatData(list, {
time: "time"
})
}
})
/**
* 后台代码
*/
//获取用户列表
app.router('getUserlist', async (ctx, next) => {
let {
page,
limit
} = event
let goods = db.collection('user')
let {
data
} = await goods.skip((page - 1) * limit)
.limit(limit).get()
ctx.body = {
code: 1,
data: data
}
})
//获取用户反馈未读的数量
app.router('getUserFeedbackNoreadNum', async (ctx, next) => {
let feedback = db.collection('feedback')
let {
total
} = await feedback.where({
isRead: false
}).count()
ctx.body = {
code: 1,
msg: "获取成功",
data: total
}
})
//获取用户反馈
app.router('getFeedbackAdminlist', async (ctx, next) => {
let {
page,
limit
} = event
let feedback = db.collection('feedback')
let {
list
} = await feedback.aggregate()
.lookup({
from: "user",
localField: 'OPENID',
foreignField: 'OPENID',
as: 'userInfo'
})
.unwind('$userInfo')
.project({
content: true,
time: true,
isRead: true,
nickName: "$userInfo.nickName",
avatarUrl: "$userInfo.avatarUrl",
gender: "$userInfo.gender",
integral: "$userInfo.integral",
userId: "$userInfo._id"
})
.skip((page - 1) * limit)
.limit(limit)
.end()
console.log(list)
ctx.body = {
code: 1,
data: FormatData(list, {
time: "date"
})
}
})
//改变反馈状态
app.router('updataFeedbackReadAdmin', async (ctx, next) => {
let {
_id
} = event
let feedback = db.collection('feedback')
await feedback.where({
_id: _id
}).update({
data: {
isRead: true
}
})
ctx.body = {
code: 1,
msg: "修改成功",
data: ''
}
})
/**
* 导入垃圾分类的题目
*/
app.router('importAnswer', async (ctx, next) => {
const answer = db.collection('answer')
let {
fileID
} = event
const res = await cloud.downloadFile({
fileID: fileID
})
const buffer = res.fileContent
const tasks = []
var sheets = xlsx.parse(buffer);
sheets.forEach(async function (sheet) {
for (var rowId in sheet['data']) {
var row = sheet['data'][rowId];
if (rowId > 0 && row) {
let name = row[0]
let type = row[1]
let {
total
} = await answer.where({
name
}).count()
if (!total) {
tasks.push(answer.add({
data: {
name: name,
type: type
}
}))
}
}
}
})
await Promise.all(tasks)
ctx.body = {
code: 1,
msg: "导入成功"
}
})
return app.serve();
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,16 @@
{
"name": "db",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"node-xlsx": "^0.16.1",
"tcb-router": "^1.1.2",
"wx-server-sdk": "~2.3.0"
}
}

@ -0,0 +1,56 @@
function formateDate(datetime, type = 's') {
function addDateZero(num) {
return (num < 10 ? "0" + num : num);
}
let d = new Date(datetime);
console.log(d)
let formatdatetime;
if (type == 's') {
formatdatetime = d.getFullYear() + '-' + addDateZero(d.getMonth() + 1) + '-' + addDateZero(d.getDate()) + ' ' + addDateZero(d.getHours()) + ':' + addDateZero(d.getMinutes()) + ':' + addDateZero(d.getSeconds());
} else if (type == 'd') {
formatdatetime = d.getFullYear() + '-' + addDateZero(d.getMonth() + 1) + '-' + addDateZero(d.getDate());
}
return formatdatetime;
}
function FormatData(data, obj) {
let val = data
if (Array.isArray(val)) {
val.forEach(info => {
Object.entries(obj).forEach(item => {
if (item[1] === '' || item[1] === null || item[1] === undefined) {
return;
}
let format = item[1].split('|')
format.forEach(k => {
if (k == 'json') {
info[item[0]] = JSON.parse(info[item[0]])
} else if (k == 'date') {
info[item[0]] = formateDate(info[item[0]])
} else if (k == 'time') {
info[item[0]] = formateDate(info[item[0]], 'd')
}
})
})
})
} else {
Object.entries(obj).forEach(item => {
if (item[1] === '' || item[1] === null || item[1] === undefined) {
return;
}
let format = item[1].split('|')
format.forEach(k => {
if (k == 'json') {
console.log(val, val[item[0]])
val[item[0]] = JSON.parse(val[item[0]])
} else if (k == 'date') {
val[item[0]] = formateDate(val[item[0]])
} else if (k == 'time') {
val[item[0]] = formateDate(val[item[0]], 'd')
}
})
})
}
return val
}
exports.FormatData = FormatData;

@ -0,0 +1 @@
{"_id":"79550af260aa3c441974adb65a2c8c6c","OPENID":"obt995TUKes91H6qGLsCC96JP324","historyIntervalTime":"00:03","historyDate":{"$date":"2021-05-23T11:28:04.056Z"},"historyFraction":10,"historyIntegral":10}

@ -0,0 +1,3 @@
{"_id":"8e5be7055f65d4e80021de7315079ff7","name":"苹果","type":"厨余垃圾"}
{"_id":"d782d4875f66e939001e664f58227153","name":"电视机","type":"可回收物"}
{"_id":"1b64dd7b5f66ea3300252d952d0238cc","name":"电冰箱","type":"可回收物"}

@ -0,0 +1 @@
{"_id":"28ee4e3e604d85b70a86bcb269744214","content":"测试","time":{"$date":"2021-03-14T03:40:39.911Z"},"OPENID":"omiwO5CUdC1CeXVAoxvcBbLFkYb8","isRead":true}

@ -0,0 +1,17 @@
{"_id":"6518b7395f5e0d15016bcfda4cc9c437","hot_num":10.0,"hot_text":"面包","hot_time":{"$date":"2020-09-13T12:13:44.018Z"}}
{"_id":"65825b355f5e11aa01384e29526eebd2","hot_text":"桌子","hot_time":{"$date":"2020-09-13T12:33:47.019Z"},"hot_num":3}
{"_id":"aa133ce55f5e14540127c6ab10096d0d","hot_text":"洗衣机","hot_time":{"$date":"2020-09-13T12:45:08.316Z"},"hot_num":3}
{"_id":"aa133ce55f5e14ed0127cb5863456447","hot_text":"洗面奶","hot_time":{"$date":"2020-09-13T12:47:42.143Z"},"hot_num":2}
{"_id":"7498b5fe5f5e15450175c1612fe4be17","hot_text":"豆浆","hot_time":{"$date":"2020-09-13T12:49:09.704Z"},"hot_num":2}
{"_id":"aa133ce55f5e35fc0128bcf7038438ef","hot_text":"土豆","hot_time":{"$date":"2020-09-13T15:08:44.497Z"},"hot_num":2}
{"_id":"ac5f38825f5ebf4b017d60ab56cc4d58","hot_text":"电饭煲","hot_time":{"$date":"2020-09-14T00:54:35.443Z"},"hot_num":4}
{"_id":"b333e0365fa40a6f004a72707c95dc5e","hot_text":"平板电脑","hot_time":{"$date":"2020-11-05T14:21:35.762Z"},"hot_num":1}
{"_id":"9f2a34705fdcb60d002154d7644a9a97","hot_text":"女朋友","hot_time":{"$date":"2020-12-18T14:00:45.379Z"},"hot_num":2}
{"_id":"a8831daa5fddc3870033081c622cbbaa","hot_text":"手机","hot_time":{"$date":"2020-12-19T09:10:31.37Z"},"hot_num":1}
{"_id":"2f6ab8515fdef0f8002e88c048099659","hot_text":"被子","hot_time":{"$date":"2020-12-20T06:36:40.943Z"},"hot_num":1}
{"_id":"73f70d5c5fe412af006f5fec64a5323b","hot_text":"水杯","hot_time":{"$date":"2020-12-24T04:01:51.847Z"},"hot_num":1}
{"_id":"85ff8afa5fe88ab600c5e1ac4d8e5bab","hot_text":"牛奶","hot_time":{"$date":"2020-12-27T13:23:02.176Z"},"hot_num":1}
{"_id":"be7fb3985ff6ae360315d712395d9107","hot_text":"水浒","hot_time":{"$date":"2021-01-07T06:46:14.844Z"},"hot_num":1}
{"_id":"b45a21d55ff6ae4203f810da27b8e00e","hot_text":"苹果","hot_time":{"$date":"2021-01-07T06:46:26.624Z"},"hot_num":1}
{"_id":"ce805e785ffaa6f503e146e5121750f4","hot_text":"香蕉","hot_time":{"$date":"2021-01-10T07:04:21.778Z"},"hot_num":1}
{"_id":"1526e12a6006b0980015dbdc35c85841","hot_text":"口罩","hot_time":{"$date":"2021-01-19T10:12:40.008Z"},"hot_num":1}

@ -0,0 +1,2 @@
{"_id":"407a0a0563491b9a0229898b5a7a1e53"}
{"_id":"8655d51b63552272001431cf1595c687","nickName":"。","gender":0,"avatarUrl":"https://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83er8FogaAiaPVKLZOIEiaCLnajQ1AjZmC1IZ6V4SmZg7h1nXMqyHZ4Xbzf5C4OjSbyABks8pHXvQ5LJQ/132","OPENID":"o58l05K41tf8fcoDL_TjEnLc1PJM","integral":35,"answerIntegral":90}

@ -0,0 +1,3 @@
{"_id":"79550af2600982c7005f48324cb1fb7f","OPENID":"omiwO5HzbJGkXCAUm0s1EnoHgkQ8","name":"苹果","type":"厨余垃圾","check":"有害垃圾"}
{"_id":"b00064a7600982c7006665990505577e","OPENID":"omiwO5HzbJGkXCAUm0s1EnoHgkQ8","name":"电视机","type":"可回收物","check":"有害垃圾"}
{"_id":"79550af2600982c7005f48334f8edd02","OPENID":"omiwO5HzbJGkXCAUm0s1EnoHgkQ8","name":"电冰箱","type":"可回收物","check":"厨余垃圾"}

@ -0,0 +1,137 @@
import * as db from './util/db.js';
import * as util from './util/util.js';
let userInfo = db.get("userInfo") || {}
let isLogin = JSON.stringify(userInfo) != "{}"
var plugin = requirePlugin("chatbot");
App({
onLaunch: function () {
this.autoUpdate()
if (!wx.cloud) {
console.error('请使用 2.2.3 或以上的基础库以使用云能力')
} else {
wx.cloud.init({
env:'cloud1-0gle9p5m591ea29f',
TraceUser:true
})
}
wx.cloud.callFunction({
name: 'api',
data: {
$url: "openId"
}
}).then(res => {
plugin.init({
appid: "wxb410947324244ff9",
openid: res.result.openId,
guideList: ['苹果是什么垃圾?', '帮我查下垃圾分类'],
welcome: "你好",
guideCardHeight: 36,
operateCardHeight: 56,
textToSpeech: false,
hideMovableButton: false,
success: () => {},
fail: error => {}
});
})
},
onShow() {
this.onNetworkStatusChange()
},
onNetworkStatusChange() {
var that = this
wx.getNetworkType({
success: function (res) {
const networkType = res.networkType
if ('none' != networkType) {
that.globalData.nonetwork = true
wx.onNetworkStatusChange(function (res) {
if (res.isConnected) {
that.globalData.nonetwork = true
} else {
that.globalData.nonetwork = false
}
})
} else {
wx.onNetworkStatusChange(function (res) {
if (res.isConnected) {
that.globalData.nonetwork = true
} else {
that.globalData.nonetwork = false
}
})
}
},
})
},
$db: db,
$util: util,
globalData: {
nonetwork: false,
userInfo: userInfo,
isLogin: isLogin,
appInfo: {
appName: "垃圾分类管理"
}
},
autoUpdate: function () {
var self = this
// 获取小程序更新机制兼容
if (wx.canIUse('getUpdateManager')) {
const updateManager = wx.getUpdateManager()
updateManager.onCheckForUpdate(function (res) {
if (res.hasUpdate) {
//检测到新版本,需要更新,给出提示
wx.showModal({
title: '更新提示',
content: '检测到新版本,是否下载新版本并重启小程序?',
success: function (res) {
if (res.confirm) {
self.downLoadAndUpdate(updateManager)
} else if (res.cancel) {
wx.showModal({
title: '温馨提示~',
content: '本次版本更新涉及到新的功能添加',
confirmText: "确定更新",
success: function (res) {
if (res.confirm) {
self.downLoadAndUpdate(updateManager)
}
}
})
}
}
})
}
})
}
},
/**
* 下载小程序新版本并重启应用
*/
downLoadAndUpdate: function (updateManager) {
wx.showLoading();
updateManager.onUpdateReady(function () {
wx.hideLoading()
updateManager.applyUpdate()
})
updateManager.onUpdateFailed(function () {
wx.showModal({
title: '已经有新版本了哟~',
content: '新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~',
})
})
},
deductionIntegral: new Map([
//使用文字识别垃圾消耗的积分数目
['garbageTextSearch', 0],
//使用图片识别垃圾消耗的积分数目
['garbageImageSearch', 0]
])
})

@ -0,0 +1,74 @@
{
"pages": [
"pages/index/index",
"pages/search/search",
"pages/photo/photo",
"pages/detail/detail",
"pages/answer/answer-home/answer-home",
"pages/answer/answer-run/answer-run",
"pages/user/user",
"pages/result/result",
"pages/admin/admin",
"pages/adminList/adminList",
"pages/adminAnswer/adminAnswer",
"pages/download/download",
"pages/feedback/feedback",
"pages/adminUser/userList/userList",
"pages/adminFeedback/feedbackList/feedbackList",
"pages/answer/answer-ranking/answer-ranking",
"pages/answer/answer-history/answer-history",
"pages/shareList/shareList"
],
"window": {
"backgroundColor": "#F6F6F6",
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#F6F6F6",
"navigationBarTitleText": "垃圾分类",
"navigationBarTextStyle": "black"
},
"plugins": {
"chatbot": {
"version": "1.1.24",
"provider": "wx8c631f7e9f2465e1"
},
"WechatSI": {
"version": "0.3.1",
"provider": "wx069ba97219f66d99"
}
},
"requiredBackgroundModes": [
"audio"
],
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
},
"tabBar": {
"color": "#000000",
"selectedColor": "#00cc77",
"backgroundColor": "#FFFFFF",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "/static/image/home.png",
"selectedIconPath": "/static/image/home_action.png"
},
{
"pagePath": "pages/answer/answer-home/answer-home",
"text": " 答题",
"iconPath": "/static/image/answer.png",
"selectedIconPath": "/static/image/answer_action.png"
},
{
"pagePath": "pages/user/user",
"text": " 用户",
"iconPath": "/static/image/user.png",
"selectedIconPath": "/static/image/user_action.png"
}
]
},
"sitemapLocation": "sitemap.json",
"style": "v2"
}

@ -0,0 +1,29 @@
@import '/miniprogram_npm/weui-miniprogram/weui-wxss/dist/style/weui.wxss';
@import "./static/css/animation.wxss";
@import "./static/css/icon.wxss";
@import "./static/css/main.wxss";
@import "./static/css/my-icon.wxss";
page {
color: #333;
background: #fff;
--indexL: #00cc77;
--bg-c241: rgb(241, 241, 241);
--font-black6: rgba(0, 0, 0, 0.5);
}
.m-btn {
border-radius: 16rpx;
background-color: var(--indexL);
}
.info-lable {
position: fixed;
left: 0;
right: 0;
bottom: 20rpx;
color: #aaaaaa;
font-size: 22rpx;
text-align: center;
}

@ -0,0 +1,87 @@
let timter = null
Component({
properties: {
minuteTnterval: {
type: Number,
value: false
},
},
data: {
startTime: 0,
endTime: 0,
hour: 0,
minute: 0,
secondsec: 0
},
attached: function () {
var startTime = new Date().getTime()
var endTime = startTime + this.data.minuteTnterval * 60000
this.setData({
startTime: startTime,
endTime: endTime
})
this.countDown()
},
methods: {
countDown() {
var nowTime = new Date().getTime();
let timeLeft = this.data.endTime - nowTime;
if (timeLeft >= 0) {
var {
h,
m,
s
} = this.formatTime(timeLeft)
this.setData({
hour: h,
minute: m,
secondsec: s
})
timter = setTimeout(() => {
this.countDown()
}, 1000);
} else {
this.triggerEvent('stopTime');
this.setData({
hour: '00',
minute: '00',
secondsec: '00'
})
}
},
formatTime(time) {
var h, m, s;
h = Math.floor(time / 1000 / 60 / 60 % 24);
m = Math.floor(time / 1000 / 60 % 60);
s = Math.floor(time / 1000 % 60);
s = s < 10 ? "0" + s : s
m = m < 10 ? "0" + m : m
h = h < 10 ? "0" + h : h
return {
s,
m,
h
}
},
getIntervalTime() {
clearTimeout(timter)
var nowTime = new Date().getTime();
let timeLeft = nowTime - this.data.startTime;
let timeStrArr = []
var {
h,
m,
s
} = this.formatTime(timeLeft)
if (h !== '00') {
timeStrArr.push(h)
}
timeStrArr.push(m)
timeStrArr.push(s)
return timeStrArr.join(":")
},
clearTimter() {
clearTimeout(timter)
}
}
})

@ -0,0 +1,7 @@
<view class="count-time_cont">
<block wx:if="{{hour!=='00'}}">
<view>{{hour}}</view>:
</block>
<view>{{minute}}</view>:
<view>{{secondsec}}</view>
</view>

@ -0,0 +1,66 @@
// components/dhbfh.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})

@ -0,0 +1,2 @@
<!--components/dhbfh.wxml-->
<text>components/dhbfh.wxml</text>

@ -0,0 +1,42 @@
const app = getApp();
Component({
options: {
addGlobalClass: true,
},
properties: {
show: {
type: Boolean,
value: false
},
text: {
type: String,
value: '暂无数据'
},
subText: {
type: String,
value: ''
}
},
data: {},
methods: {
onLoad(options) {
console.log(options);
},
onShow() {
console.log('onShow');
},
onReady() {
console.log('onReady');
},
},
lifetimes: {
attached: function () { },
moved: function () { },
detached: function () { },
},
pageLifetimes: {
show: function () { },
hide: function () { },
resize: function () { },
},
});

@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

@ -0,0 +1,5 @@
<view class="no-data" hidden="{{!show}}">
<image class="image" src="./empty_tip.png" />
<view class="text">{{text}}</view>
<view class="sub-text">{{subText}}</view>
</view>

@ -0,0 +1 @@
.no-data{padding:270rpx 0 60rpx;text-align:center}.no-data .image{width:400rpx;height:325rpx;margin-bottom:60rpx}.no-data .text{margin-bottom:30rpx;font-size:32rpx;color:#333;font-weight:bold}.no-data .subtitle{font-size:28rpx;color:#a2a2a2;letter-spacing:4rpx}

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

@ -0,0 +1,23 @@
Component({
options: {
addGlobalClass: true
},
properties: {
info: {
type: Object
},
show: Boolean
},
data: {
},
methods: {
close: function () {
this.triggerEvent('close')
}
}
})

@ -0,0 +1,19 @@
<wxs src="../../util/comm.wxs" module="comm" />
<view class="fadeIn" wx:if="{{show}}">
<view class="weui-mask" bindtap="close"></view>
<view class="weui-dialog">
<view class="title">{{info.name}}</view>
<view class="body">
<view class="weui-dialog__bd text">
<text class="header">
❀描述:
</text>{{info.explain}}
<view class ="type">同类型的还有:</view>{{info.contain}}
<view class ="tip">投放技巧:</view>{{info.tip}}
</view>
</view>
<view class="weui-dialog__ft">
<a class="weui-dialog__btn weui-dialog__btn_primary qd" bindtap="close">确定</a>
</view>
</view>
</view>

@ -0,0 +1,52 @@
view.weui-mask {
background-color: rgba(66, 66, 66, 0.4);
}
.title {
font-size: 40rpx;
line-height: 90rpx;
margin-top: 20rpx;
}
.img {
width: 200rpx;
display: flex;
justify-content: center;
margin: auto;
}
.text {
/* margin-top: 40rpx; */
text-align: left;
font-size: 30rpx;
}
.type{
color:brown;
font-size: 35rpx;
}
.tip{
color:rgb(27, 228, 111);
font-size: 35rpx;
}
.header {
color: var(--indexL);
}
.qd {
color: var(--indexL);
font-weight: normal;
}
view.weui-dialog__ft {
line-height: 50px;
min-height: 50px;
}
view.weui-dialog {
min-height: 700rpx;
justify-content: flex-start;
width: 80%;
}
.body {
flex: 1;
}

@ -0,0 +1,23 @@
Component({
options: {
addGlobalClass: true
},
properties: {
info: {
type: Object
},
show: Boolean
},
data: {
},
methods: {
close: function () {
this.triggerEvent('close')
}
}
})

@ -0,0 +1,16 @@
<wxs src="../../util/comm.wxs" module="comm" />
<view class="fadeIn" wx:if="{{show}}">
<view class="weui-mask" bindtap="close"></view>
<view class="weui-dialog">
<view class="title">{{info.name}}</view>
<view class="body">
<!-- <view class="img">
<image wx:if="{{comm.textToImg(info.contain)}}" src="../../static/image/{{comm.textToImg(info.cate_name)}}" mode="widthFix"></image>
</view> -->
<view class ="type">详细介绍:</view>{{info.lajitip}}
</view>
<view class="weui-dialog__ft">
<a class="weui-dialog__btn weui-dialog__btn_primary qd" bindtap="close">确定</a>
</view>
</view>
</view>

@ -0,0 +1,49 @@
view.weui-mask {
background-color: rgba(66, 66, 66, 0.4);
}
.title {
font-size: 40rpx;
line-height: 90rpx;
margin-top: 20rpx;
}
.img {
width: 200rpx;
display: flex;
justify-content: center;
margin: auto;
}
.text {
/* margin-top: 40rpx; */
text-align: left;
font-size: 30rpx;
}
.type{
color:brown;
font-size: 35rpx;
}
.header {
color: var(--indexL);
}
.qd {
color: var(--indexL);
font-weight: normal;
}
view.weui-dialog__ft {
line-height: 50px;
min-height: 50px;
}
view.weui-dialog {
min-height: 700rpx;
justify-content: flex-start;
width: 80%;
}
.body {
flex: 1;
}

@ -0,0 +1,28 @@
Component({
properties: {
list: {
type: Array,
value: []
}
},
data: {
swiper: {
margin: "150rpx"
},
currentIndex: 0
},
methods: {
swiperChange: function (e) {
this.setData({
currentIndex: e.detail.current
})
},
cardClick(e) {
this.triggerEvent('cardClick', {
type:e.currentTarget.dataset.type
})
}
}
})

@ -0,0 +1,18 @@
<view class="helang-cardSwiper">
<view class="top-swiper">
<view class="bg">
<view class="image">
<image src="{{list[currentIndex].src}}" mode="aspectFill"></image>
</view>
</view>
<view class="box">
<view style="height: 44px;"></view>
<swiper class="swiper" previous-margin="{{swiper.margin}}" next-margin='{{swiper.margin}}' circular="{{true}}"
bindchange="swiperChange">
<swiper-item wx:for="{{list}}" wx:key="index" bindtap="cardClick" data-type="{{item.type}}">
<image src='{{item.src}}' class="{{['le-img',(currentIndex==index)?'le-active':'']}}"></image>
</swiper-item>
</swiper>
</view>
</view>
</view>

@ -0,0 +1,77 @@
.top-swiper {
margin-bottom: 30rpx;
}
.top-swiper .bg {
padding-top: 25px;
box-sizing: content-box;
width: 100%;
position: relative;
}
.top-swiper .bg .image {
box-sizing: content-box;
z-index: 1;
overflow: hidden;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
}
.top-swiper .bg .image::after {
content: "";
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
bottom: 0;
left: 0;
height: 65%;
background-image: linear-gradient(to bottom, transparent, #FFF);
}
.top-swiper .bg .image>image {
position: absolute;
box-sizing: content-box;
padding: 60px;
top: 0;
left: 0;
width: 100%;
height: 80%;
top: -60px;
left: -60px;
filter: blur(50px);
}
.top-swiper .box {
padding-top: 25px;
box-sizing: content-box;
position: absolute;
z-index: 5;
top: 0;
left: 0;
width: 100%;
height: auto;
}
.top-swiper .swiper {
height: 600rpx;
margin: 0 20rpx;
}
.top-swiper .swiper .le-img {
width: 100%;
height: 100%;
display: block;
transform: scale(0.9);
transition: transform 0.3s ease-in-out 0s;
border-radius: 4px;
}
.top-swiper .swiper .le-img.le-active {
transform: scale(1);
}

@ -0,0 +1,14 @@
Component({
externalClasses: ['i-class'],
properties: {
loading: {
type: Boolean,
value: true
},
tip: {
type: String,
value: ''
}
},
});

@ -0,0 +1,8 @@
<view class="i-class i-load-more {{ loading ? '' : 'i-load-more-line' }}">
<view class="i-load-more-loading" wx:if="{{ loading }}"></view>
<view class="i-load-more-tip">
<view wx:if="{{ tip !== '' }}">{{ tip }}</view>
<view wx:elif="{{ tip === '' && loading }}">正在加载</view>
<view class="i-load-more-empty" wx:else></view>
</view>
</view>

@ -0,0 +1 @@
.i-load-more{width:65%;margin:1.5em auto;line-height:1.6em;font-size:14px;text-align:center}.i-load-more-loading{display:inline-block;margin-right:12px;vertical-align:middle;width:14px;height:14px;background:0 0;border-radius:50%;border:2px solid #e9eaec;border-color:#e9eaec #e9eaec #e9eaec #2d8cf0;animation:btn-spin .6s linear;animation-iteration-count:infinite}.i-load-more-tip{display:inline-block;vertical-align:middle;color:#495060}.i-load-more-line{border-top:1px solid #dddee1;display:flex;border-top:0}.i-load-more-line::before{position:relative;top:-1px;-webkit-box-flex:1;-webkit-flex:1;flex:1;content:'';border-top:1px solid #dddee1}.i-load-more-line::after{position:relative;top:-1px;-webkit-box-flex:1;-webkit-flex:1;flex:1;content:'';border-top:1px solid #dddee1}.i-load-more-line .i-load-more-tip{position:relative;top:-.9em;padding:0 .55em}.i-load-more-empty{width:4px;height:4px;border-radius:50%;background-color:#e5e5e5;display:inline-block;position:relative;vertical-align:0;top:-.16em}@keyframes btn-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}

@ -0,0 +1,42 @@
let app = getApp()
Component({
options: {
addGlobalClass: true,
},
data: {
elements: [{
title: '搜索垃圾',
name: 'search',
color: 'green',
icon: 'search',
login: true
},
{
title: '拍照识别',
name: 'photo',
color: 'olive',
icon: 'album',
login: true
}
]
},
methods: {
goMenu(e) {
let {
login
} = e.currentTarget.dataset.item
if (login) {
if (!app.globalData.isLogin) {
app.$util.errorToShow("请先登录", () => {
app.$util.switchTabTo("/pages/user/user")
})
return
}
}
let url = e.currentTarget.dataset.url
wx.navigateTo({
url: url
})
}
}
})

@ -0,0 +1,12 @@
<scroll-view scroll-y class="scrollPage">
<view class='nav-list'>
<view bindtap="goMenu" hover-class='none' data-url="/pages/{{item.name}}/{{item.name}}"
data-item="{{item}}"
class="nav-li bg-{{item.color}}"
wx:for="{{elements}}" wx:key>
<view class="nav-title">{{item.title}}</view>
<view class="nav-name">{{item.name}}</view>
<text class='cuIcon-{{item.icon}}'></text>
</view>
</view>
</scroll-view>

@ -0,0 +1,101 @@
.nav-list {
display: flex;
flex-wrap: wrap;
padding: 0px 40rpx 0px;
justify-content: space-between;
}
.nav-li {
padding: 30rpx;
border-radius: 12rpx;
width: 45%;
margin: 0 2.5% 40rpx;
background-size: cover;
background-position: center;
position: relative;
z-index: 1;
}
.nav-li::after {
content: "";
position: absolute;
z-index: -1;
background-color: inherit;
width: 100%;
height: 100%;
left: 0;
bottom: -10%;
border-radius: 10rpx;
opacity: 0.2;
transform: scale(0.9, 0.9);
}
.nav-li.cur {
color: #fff;
background: rgb(94, 185, 94);
box-shadow: 4rpx 4rpx 6rpx rgba(94, 185, 94, 0.4);
}
.nav-title {
font-size: 32rpx;
font-weight: 300;
}
.nav-title::first-letter {
font-size: 40rpx;
margin-right: 4rpx;
}
.nav-name {
font-size: 28rpx;
text-transform: Capitalize;
margin-top: 20rpx;
position: relative;
}
.nav-name::before {
content: "";
position: absolute;
display: block;
width: 40rpx;
height: 6rpx;
background: #fff;
bottom: 0;
right: 0;
opacity: 0.5;
}
.nav-name::after {
content: "";
position: absolute;
display: block;
width: 100rpx;
height: 1px;
background: #fff;
bottom: 0;
right: 40rpx;
opacity: 0.3;
}
.nav-name::first-letter {
font-weight: bold;
font-size: 36rpx;
margin-right: 1px;
}
.nav-li text {
position: absolute;
right: 30rpx;
top: 30rpx;
font-size: 52rpx;
width: 60rpx;
height: 60rpx;
text-align: center;
line-height: 60rpx;
}
.text-light {
font-weight: 300;
}

@ -0,0 +1,128 @@
Component({
options: {
addGlobalClass: true,
multipleSlots: true
},
properties: {
rowKey: {
type: String,
value: 'id'
},
columns: {
type: Array,
value: []
},
item: {
type: Object,
value: {}
},
index: {
type: Number,
},
select: {
type: Boolean,
value: false
},
scrollX: {
type: Boolean,
value: false
},
checked: {
type: Boolean,
value: false
},
isExpand: {
type: Boolean,
value: false
},
expandValueKey: {
type: String,
},
initExpandValue: {
type: String,
value: '暂无信息'
},
expandStyle: {
type: String,
},
dynamicValue: {
type: Object,
optionalTypes: [Array, String, Number, Boolean, null]
},
},
data: {
expandAimation: null,
expandAimationData: null,
expanded: false
},
methods: {
handleClickListItem(e) {
const { index } = e.currentTarget.dataset;
this.setExpand();
this.triggerEvent('clicklistitem', {
value: {
index,
item: e.currentTarget.dataset.item
}
});
},
handleClickAction(e) {
this.triggerEvent('clickaction', {
value: e.detail.value
});
},
handleClickExpand(e) {
this.triggerEvent('clickexpand', {
value: e.detail.value
});
},
handleClickCheck(e) {
const { item } = e.currentTarget.dataset;
const { index } = this.data;
this.triggerEvent('checkkey', {
value: {
item,
index
}
});
},
setExpand() {
const { isExpand, expanded, expandAimation } = this.data;
if (isExpand && expandAimation) {
if (expanded) {
expandAimation.opacity(0).height(0).step();
}
else {
expandAimation.opacity(1).height('auto').step();
}
this.setData({
expandAimationData: expandAimation.export(),
expanded: !expanded
});
}
},
initAnimate() {
const { isExpand } = this.data;
if (!isExpand)
return;
const expandAimation = wx.createAnimation({
duration: 500,
timingFunction: 'ease',
});
this.data.expandAimation = expandAimation;
},
},
lifetimes: {
attached: function () { },
ready: function () {
this.initAnimate();
},
moved: function () { },
detached: function () { },
},
pageLifetimes: {
show: function () { },
hide: function () { },
resize: function () { },
},
});

@ -0,0 +1,8 @@
{
"component": true,
"usingComponents": {},
"componentGenerics": {
"action-td": true,
"expand-component": true
}
}

@ -0,0 +1,42 @@
<wxs src="../../table.wxs" module="table" />
<!-- 标识符字符串是传进来的 -->
<view class="table-line">
<view class="tr" bindtap="handleClickListItem" data-item="{{item}}" data-index="{{index}}">
<view class="td select" wx:if="{{select}}">
<checkbox checked="{{checked}}" catchtap="handleClickCheck" data-item="{{item}}" data-index="{{index}}" />
</view>
<block wx:for="{{columns}}" wx:for-index="cIndex" wx:for-item="cItem" wx:key="key">
<view class="action-td"
style="width:{{table.computedTdWidth(columns,select)}};{{cIndex===columns.length-1?'flex-grow:1;flex-shrink:1':''}}"
wx:if="{{cItem.type=='action'}}">
<action-td item="{{item}}" index="{{index}}" columns="{{cItem}}" dynamicValue="{{dynamicValue}}"
bindclickaction="handleClickAction" slot="action-td"></action-td>
</view>
<view class="td img"
style="width:{{table.computedTdWidth(columns,cItem,select,scrollX)}};{{cIndex===columns.length-1?'flex-grow:1;flex-shrink:1':''}}"
data-key="{{cItem.key}}" data-index="{{index}}" wx:elif="{{cItem.type=='img'}}">
<image src="{{item[cItem.key]}}" mode="scaleToFill"
style="width: {{cItem.imgWidth||'80%'}};height: {{cItem.imgHeight||'auto'}};">
</image>
</view>
<view class="td"
style="width:{{table.computedTdWidth(columns,cItem,select,scrollX)}};{{cIndex===columns.length-1?'flex-grow:1;flex-shrink:1':''}}"
data-key="{{cItem.key}}" data-index="{{index}}" wx:else>
{{item[cItem.key]}}
</view>
</block>
</view>
<view class="expand" style="{{expandStyle}}" wx:if="{{isExpand}}" animation="{{expandAimationData}}">
<view class="expand-box" wx:if="{{expandValueKey}}">
{{item[expandValueKey]||initExpandValue}}
</view>
<view wx:else>
<expand-component item="{{item}}" index="{{index}}" dynamicValue="{{dynamicValue}}"
bindclickexpand="handleClickExpand"></expand-component>
</view>
</view>
</view>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save