├── .DS_Store
├── .cloudbase
└── container
│ └── debug.json
├── .gitignore
├── LICENSE
├── README.md
├── cloudfunctions
├── addUser
│ ├── index.js
│ ├── package-lock.json
│ └── package.json
├── autoKoutu
│ ├── config.json
│ ├── index.js
│ └── package.json
├── baiduKoutu
│ ├── config.json
│ ├── index.js
│ ├── package-lock.json
│ └── package.json
├── batchUpload
│ ├── config.json
│ ├── index.js
│ └── package.json
├── cloudbase_auth
│ ├── config.json
│ ├── index.js
│ └── package.json
├── customerService
│ ├── config.json
│ ├── index.js
│ └── package.json
├── getClothes
│ ├── config.json
│ ├── index.js
│ └── package.json
├── getHairs
│ ├── config.json
│ ├── index.js
│ └── package.json
├── getTodayBgList
│ ├── config.json
│ ├── index.js
│ └── package.json
├── imageCompose
│ ├── config.json
│ ├── index.js
│ └── package.json
├── imagemin
│ ├── config.json
│ ├── index.js
│ └── package.json
├── imgSecCheck
│ ├── AliCloud.js
│ ├── config.json
│ ├── index.js
│ └── package.json
├── printStyle
│ ├── config.json
│ ├── index.js
│ └── package.json
├── setUserInfo
│ ├── config.json
│ ├── index.js
│ ├── package-lock.json
│ └── package.json
├── shareSuccessCallback
│ ├── config.json
│ ├── index.js
│ ├── package-lock.json
│ └── package.json
├── shareUpdate
│ ├── config.json
│ ├── index.js
│ ├── package-lock.json
│ └── package.json
├── subscribeEvent
│ ├── config.json
│ ├── index.js
│ └── package.json
├── timingDelete
│ ├── config.json
│ ├── index.js
│ └── package.json
├── timingGetImage
│ ├── config.json
│ ├── index.js
│ └── package.json
├── timingTriggerSignMessage
│ ├── config.json
│ ├── index.js
│ └── package.json
├── timingUpdateBgListIndex
│ ├── config.json
│ ├── index.js
│ └── package.json
├── triggerSubscrib
│ ├── config.json
│ ├── index.js
│ └── package.json
├── updateImageCount
│ ├── config.json
│ ├── index.js
│ └── package.json
├── useCount
│ ├── index.js
│ ├── package-lock.json
│ └── package.json
├── useVipCount
│ ├── index.js
│ ├── package-lock.json
│ └── package.json
├── vipKoutu
│ ├── config.json
│ ├── index.js
│ ├── package-lock.json
│ └── package.json
└── xiangguan
│ ├── config.json
│ ├── imgList.js
│ ├── index.js
│ └── package.json
├── miniprogram
├── .DS_Store
├── app.js
├── app.json
├── app.miniapp.json
├── app.wxss
├── colorui
│ ├── icon.wxss
│ └── main.wxss
├── components
│ ├── color-picker
│ │ ├── color-picker.js
│ │ ├── color-picker.json
│ │ ├── color-picker.wxml
│ │ ├── color-picker.wxss
│ │ └── color-picker.wxss.map
│ └── pageScrollMessage
│ │ ├── pageScrollMessage.js
│ │ ├── pageScrollMessage.json
│ │ ├── pageScrollMessage.wxml
│ │ └── pageScrollMessage.wxss
├── images
│ ├── WechatIMG199.jpeg
│ ├── index-active.png
│ ├── index.png
│ ├── me-active.png
│ ├── me.png
│ ├── shareShow.jpg
│ └── take.png
├── pages
│ ├── editPhoto
│ │ ├── complete
│ │ │ ├── complete.js
│ │ │ ├── complete.json
│ │ │ ├── complete.wxml
│ │ │ └── complete.wxss
│ │ ├── editPhotoPlus
│ │ │ ├── editPhotoPlus.js
│ │ │ ├── editPhotoPlus.json
│ │ │ ├── editPhotoPlus.wxml
│ │ │ ├── editPhotoPlus.wxss
│ │ │ ├── hex-rgb.js
│ │ │ ├── imgSecCheck.js
│ │ │ └── touch.js
│ │ ├── hair
│ │ │ ├── hair.js
│ │ │ ├── hair.json
│ │ │ ├── hair.wxml
│ │ │ └── hair.wxss
│ │ ├── imageStyle
│ │ │ ├── imageStyle.js
│ │ │ ├── imageStyle.json
│ │ │ ├── imageStyle.wxml
│ │ │ └── imageStyle.wxss
│ │ └── images
│ │ │ ├── acl8s-bu9e0-016_s.png
│ │ │ ├── ahvga-47qgd-003_s.png
│ │ │ ├── author.png
│ │ │ ├── click-white-left.png
│ │ │ ├── click-white.png
│ │ │ ├── crop.png
│ │ │ ├── look-video.png
│ │ │ ├── move-white.png
│ │ │ ├── use.png
│ │ │ └── zoom-white.png
│ ├── helpMake
│ │ ├── helpMake.js
│ │ ├── helpMake.json
│ │ ├── helpMake.wxml
│ │ └── helpMake.wxss
│ ├── imgCompose
│ │ ├── compose.js
│ │ ├── compose.json
│ │ ├── compose.wxml
│ │ └── compose.wxss
│ ├── imgZip
│ │ ├── image
│ │ │ └── choosePic.png
│ │ ├── imgZip.js
│ │ ├── imgZip.json
│ │ ├── imgZip.wxml
│ │ └── imgZip.wxss
│ ├── index
│ │ ├── .DS_Store
│ │ ├── images
│ │ │ ├── 3001677327372_.pic.jpg
│ │ │ ├── custom.png
│ │ │ ├── home_icon0.png
│ │ │ ├── home_icon1.png
│ │ │ ├── home_icon2.png
│ │ │ ├── home_icon3.png
│ │ │ ├── home_icon4.png
│ │ │ ├── home_icon5.png
│ │ │ ├── home_icon6.png
│ │ │ ├── home_icon7.png
│ │ │ ├── hot.png
│ │ │ ├── icon-more.png
│ │ │ ├── icon-size1.png
│ │ │ ├── icon-size2.png
│ │ │ ├── search-input.png
│ │ │ ├── space-img.png
│ │ │ └── 微信图片_20200712103220.jpg
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── mein
│ │ ├── images
│ │ │ └── wave.gif
│ │ ├── mein.js
│ │ ├── mein.json
│ │ ├── mein.wxml
│ │ └── mein.wxss
│ ├── preEdit
│ │ ├── preEdit.js
│ │ ├── preEdit.json
│ │ ├── preEdit.wxml
│ │ └── preEdit.wxss
│ ├── searchSize
│ │ ├── custom
│ │ │ ├── custom.js
│ │ │ ├── custom.json
│ │ │ ├── custom.wxml
│ │ │ └── custom.wxss
│ │ ├── images
│ │ │ ├── card-people.png
│ │ │ ├── custom-img.png
│ │ │ └── search-input.png
│ │ ├── searchSize.js
│ │ ├── searchSize.json
│ │ ├── searchSize.wxml
│ │ ├── searchSize.wxss
│ │ └── searchView
│ │ │ ├── searchView.js
│ │ │ ├── searchView.json
│ │ │ ├── searchView.wxml
│ │ │ └── searchView.wxss
│ ├── share
│ │ ├── share.js
│ │ ├── share.json
│ │ ├── share.wxml
│ │ └── share.wxss
│ └── zipSuccess
│ │ ├── zipSuccess.js
│ │ ├── zipSuccess.json
│ │ ├── zipSuccess.wxml
│ │ └── zipSuccess.wxss
└── sitemap.json
├── project.config.json
├── project.miniapp.json
└── project.private.config.json
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/.DS_Store
--------------------------------------------------------------------------------
/.cloudbase/container/debug.json:
--------------------------------------------------------------------------------
1 | {"containers":[]}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | **/pachong
3 | **/uploadTest
4 | **/example
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # 证件照 小程序 (原生微信小程序 + 云开发)
3 | 一个用于生成证件照的小程序
4 |
5 | ## 本项目仅供学习交流,禁止商业用途
6 |
7 | **声明:本项目禁止商用!否则后果自负。**
8 |
9 | **网络上发现了一些基于此项目的二次创作,感谢你们的二次创作。请尊重原创,辛苦二次创作以及分享的时候注明原作者原项目来源。**
10 |
11 | **不要直接问怎么配置上架。**
12 |
13 | **技术指导请先赞赏**
14 |
15 | ### 功能
16 |
17 | 用于免费快速生成证件照
18 |
19 | - 可自定义照片尺寸、背景颜色
20 | - 支持换装、换发型
21 | - 支持手势拖拽缩放编辑图片
22 |
23 |
24 | - 客服消息自动回复
25 | - 定时触发器
26 | - 云函数海报生成,图片合成
27 |
28 | -------------------------
29 |
30 | 
31 |
32 | 
33 |
34 | 
35 |
36 |
37 |
--------------------------------------------------------------------------------
/cloudfunctions/addUser/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 |
6 | const db = cloud.database()
7 |
8 | // 云函数入口函数
9 | exports.main = async (event, context) => {
10 | const wxContext = cloud.getWXContext()
11 |
12 | const openid = wxContext.OPENID
13 |
14 | const { data } = await db.collection('user').where({ openid }).get()
15 |
16 | if (data.length) return { openid }
17 |
18 | await db.collection('user').add({
19 | data: {
20 | openid,
21 | create_time: Date.now(),
22 | accumCreatePhoto: 0,
23 | count: 1,
24 | signInDate: ''
25 | }
26 | })
27 |
28 | return {
29 | openid: wxContext.OPENID,
30 | unionid: wxContext.UNIONID
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/cloudfunctions/addUser/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "getBaiduToken",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/cloudfunctions/autoKoutu/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/autoKoutu/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 |
6 | // 自动抠图,待完成
7 | const access_token = process.env.access_token
8 |
9 | // 云函数入口函数
10 | exports.main = async (event, context) => {
11 | const wxContext = cloud.getWXContext()
12 |
13 | return {
14 | event,
15 | openid: wxContext.OPENID,
16 | appid: wxContext.APPID,
17 | unionid: wxContext.UNIONID,
18 | }
19 | }
--------------------------------------------------------------------------------
/cloudfunctions/autoKoutu/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "autoKoutu",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.3.2"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/baiduKoutu/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/baiduKoutu/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 | const http = require('http')
4 | const https = require('https')
5 | const dayjs = require('dayjs')
6 | const AipBodyAnalysisClient = require("baidu-aip-sdk").bodyanalysis;
7 |
8 | // 设置APPID/AK/SK
9 | const APP_ID = process.env.APP_ID;
10 | const API_KEY = process.env.API_KEY;
11 | const SECRET_KEY = process.env.SECRET_KEY;
12 |
13 | // 新建一个对象,建议只保存一个对象调用服务接口
14 | const client = new AipBodyAnalysisClient(APP_ID, API_KEY, SECRET_KEY);
15 |
16 | cloud.init()
17 |
18 | const db = cloud.database()
19 |
20 | // 云函数入口函数
21 | exports.main = async (event, context) => {
22 | // 获取图片buffer
23 | const imgBuffer = await getHttpBuffer(event.filePath)
24 | // 图片的base64
25 | const imageBase64 = encodeURI(imgBuffer.toString('base64'))
26 | // 百度抠图结果
27 | const { foreground, error_code, error_msg } = (await client.bodySeg(imageBase64, { type: 'foreground' }))
28 | if (error_code) return { msg: error_msg }
29 | if (!foreground) return { foreground, error_code, error_msg }
30 |
31 | // 将抠图结果存储到云存储
32 | const resultFileId = await uploadBase64(foreground)
33 | db.collection('tmp-file').add({ data: { time: Date.now(), fileID: resultFileId } })
34 | const url = await getFileUrlByFileID(resultFileId)
35 |
36 | return {
37 | originFilePath: event.filePath,
38 | baiduKoutuResultFileId: resultFileId,
39 | baiduKoutuUrl: url
40 | }
41 | }
42 |
43 | // 根据http地址获取图片 buffer
44 | function getHttpBuffer (src) {
45 | const protocol = src.split('://')[0]
46 | return new Promise((resolve, reject) => {
47 | ;({ http, https }[protocol]).get(src, res => {
48 | if (res.statusCode !== 200) return reject(new Error('图片加载失败'))
49 | let rawData = ''
50 | res.setEncoding('binary')
51 | res.on('data', chunk => (rawData += chunk))
52 | res.on('end', () => resolve(Buffer.from(rawData, 'binary')))
53 | })
54 | })
55 | }
56 |
57 | // base64 转为图片,存入云存储, 返回文件id
58 | async function uploadBase64 (base64) {
59 | // base64 转为buffer
60 | const buffer = Buffer.from(base64, 'base64')
61 | // 临时文件名
62 | const temFileName = `${Date.now()}-${Math.random()}.png`
63 | // 将图片上传到云存储,并拿到文件id
64 | return await cloudUploadFile(`tmp/${dayjs().format('YYYY-MM-DD')}/${temFileName}`, buffer)
65 |
66 | }
67 |
68 | // 上传图片到云存储,返回图片id
69 | async function cloudUploadFile (cloudPath, fileContent) {
70 | return (await cloud.uploadFile({ cloudPath, fileContent })).fileID
71 | }
72 |
73 | // 获取文件的临时访问url
74 | async function getFileUrlByFileID (fileID) {
75 | return (await cloud.getTempFileURL({
76 | fileList: [fileID]
77 | })).fileList[0].tempFileURL
78 | }
--------------------------------------------------------------------------------
/cloudfunctions/baiduKoutu/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "baiduKoutu",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest",
13 | "baidu-aip-sdk": "^2.4.6",
14 | "dayjs": "^1.10.3"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/cloudfunctions/batchUpload/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/batchUpload/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "batchUpload",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/cloudbase_auth/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/cloudbase_auth/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 |
6 | // 云函数入口函数
7 | exports.main = async (event, context) => {
8 | const wxContext = cloud.getWXContext()
9 |
10 | console.log(event)
11 | console.log(wxContext)
12 | // 跨账号调用时,由此拿到来源方小程序/公众号 AppID
13 | console.log(wxContext.FROM_APPID)
14 | // 跨账号调用时,由此拿到来源方小程序/公众号的用户 OpenID
15 | console.log(wxContext.FROM_OPENID)
16 | // 跨账号调用、且满足 unionid 获取条件时,由此拿到同主体下的用户 UnionID
17 | console.log(wxContext.FROM_UNIONID)
18 |
19 | return {
20 | errCode: 0,
21 | errMsg: '',
22 | auth: JSON.stringify({})
23 | }
24 | }
--------------------------------------------------------------------------------
/cloudfunctions/cloudbase_auth/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cloudbase_auth",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/customerService/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/customerService/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 |
6 | // 云函数入口函数
7 | exports.main = async (event, context) => {
8 | const wxContext = cloud.getWXContext()
9 |
10 | if (event.Content && event.Content.indexOf('人工') > -1) {
11 | return await sendImg(wxContext)
12 | }
13 |
14 | // await sendText(wxContext)
15 |
16 | await sendLink(wxContext)
17 |
18 | await sendImg(wxContext)
19 |
20 | return {
21 | event
22 | }
23 | }
24 |
25 | // 发送文字消息
26 | function sendText (wxContext) {
27 | return cloud.openapi.customerServiceMessage.send({
28 | touser: wxContext.OPENID,
29 | msgtype: 'text',
30 | text: { content: '您好, 点击下方查看 证件照制作教程。 如有其他问题,请扫描下方二维码添加微信交流群(领次数、帮制作、人工定制等)。', },
31 | })
32 | }
33 |
34 | // 发送视频教程连接
35 | async function sendLink (wxContext) {
36 | const videoSrc = 'https://mp.weixin.qq.com/s/tUKESPrY3-LIiizw3Ho2tQ'
37 | await cloud.openapi.customerServiceMessage.send({
38 | touser: wxContext.OPENID,
39 | msgtype: 'link',
40 | link: {
41 | title: '证件照、免冠照制作教程',
42 | description: '一寸、二寸证件照、免冠照,制作教程',
43 | url: videoSrc,
44 | thumbUrl: await getFileUrlByFileID('cloud://dev-4iov0.6465-dev-4iov0-1301148496/微信图片_20210109164906.jpg')
45 | }
46 | })
47 | }
48 |
49 | // 发送图片 作者二维码
50 | async function sendImg (wxContext) {
51 |
52 | // 上传图片素材 我的二维码
53 | const { mediaId } = await cloud.openapi.customerServiceMessage.uploadTempMedia({
54 | type: 'image',
55 | media: {
56 | contentType: 'image/jpg',
57 | value: await getCloudBuffer('cloud://dev-4iov0.6465-dev-4iov0-1301148496/WechatIMG199.jpeg')
58 | }
59 | })
60 |
61 | // 发送图片消息
62 | await cloud.openapi.customerServiceMessage.send({
63 | touser: wxContext.OPENID,
64 | msgtype: 'image',
65 | image: {
66 | mediaId: mediaId
67 | }
68 | })
69 |
70 | }
71 |
72 | // 根据云存储id 获取图片buffer
73 | async function getCloudBuffer (fileID) {
74 | return (await cloud.downloadFile({ fileID: fileID })).fileContent
75 | }
76 |
77 | // 获取文件的临时访问url
78 | async function getFileUrlByFileID (fileID) {
79 | return (await cloud.getTempFileURL({
80 | fileList: [fileID]
81 | })).fileList[0].tempFileURL
82 | }
--------------------------------------------------------------------------------
/cloudfunctions/customerService/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "customerService",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.3.2"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/getClothes/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/getClothes/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 | const db = cloud.database()
6 |
7 | // 云函数入口函数,获取换装的图片地址
8 | exports.main = async (event, context) => {
9 | const wxContext = cloud.getWXContext()
10 |
11 | const clothes = {}
12 | clothes.nan = await getByTag('nan')
13 | clothes.nv = await getByTag('nv')
14 | clothes.other = await getByTag('other')
15 |
16 | return {
17 | event,
18 | clothes,
19 | openid: wxContext.OPENID,
20 | appid: wxContext.APPID,
21 | unionid: wxContext.UNIONID,
22 | }
23 | }
24 |
25 | // 查询图片地址
26 | async function getByTag (tag) {
27 | return (await db.collection('resource-images').where({
28 | type: 'clothes',
29 | tag,
30 | }).get()).data
31 | }
32 |
--------------------------------------------------------------------------------
/cloudfunctions/getClothes/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "getClothes",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.5.3"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/getHairs/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/getHairs/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 | const db = cloud.database()
6 |
7 | // 云函数入口函数
8 | exports.main = async (event, context) => {
9 | const wxContext = cloud.getWXContext()
10 |
11 | const hairs = {}
12 | hairs.nan = await getByTag('nan')
13 | hairs.nv = await getByTag('nv')
14 |
15 | return {
16 | event,
17 | hairs,
18 | openid: wxContext.OPENID,
19 | appid: wxContext.APPID,
20 | unionid: wxContext.UNIONID,
21 | }
22 | }
23 |
24 | async function getByTag (tag) {
25 | return (await db.collection('resource-images').where({
26 | type: 'hairs',
27 | tag,
28 | }).get()).data
29 | }
30 |
--------------------------------------------------------------------------------
/cloudfunctions/getHairs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "getHairs",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.5.3"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/getTodayBgList/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/getTodayBgList/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 | const db = cloud.database()
6 |
7 | // 人像抠图共享小程序用
8 |
9 | // 云函数入口函数
10 | exports.main = async (event, context) => {
11 |
12 | const bgDataInfo = await db
13 | .collection('global-config')
14 | .doc('803723f46336f9d70058cdda67e1a3d8')
15 | .get()
16 |
17 | const { data } = await db.collection('bg-images')
18 | .orderBy('create_time', 'asc')
19 | .skip(bgDataInfo.data.bgListIndex)
20 | .limit(4)
21 | .get()
22 |
23 | return {
24 | bgList: data,
25 | }
26 | }
--------------------------------------------------------------------------------
/cloudfunctions/getTodayBgList/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "getTodayBgList",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/imageCompose/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/imageCompose/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 | const http = require('http')
4 | const https = require('https')
5 | const dayjs = require('dayjs')
6 | const images = require('images')
7 |
8 | cloud.init()
9 |
10 | const db = cloud.database()
11 |
12 | // 云函数入口函数
13 | exports.main = async (event, context) => {
14 | // 需要返回的图片格式
15 | const imgType = event.imgType || 'png' || 'jpg' || 'jpeg' || 'gif' || 'bmp' || 'raw' || 'webp'
16 | // 需要返回的文件类型
17 | const dataType = event.dataType || 'fileID' || 'base64' || 'url'
18 | // 海报层叠数组
19 | const VImage = event.data || []
20 | // 合成一张图片
21 | const img = await renderImg(VImage)
22 | // 根据入参所需返回图片类型
23 | const resContent = await getContentByDataType(img, dataType, imgType)
24 |
25 | return {
26 | imgType,
27 | dataType,
28 | value: resContent
29 | }
30 |
31 | }
32 |
33 | // 渲染图片,将多个层合并成一张图片
34 | function renderImg (VImage) {
35 | return VImage.reduce(async (preRomise, curData) => {
36 |
37 | const preResult = await preRomise
38 | let { width, height, x = 0, y = 0 } = curData
39 | width = +((+width).toFixed())
40 | height = +((+height).toFixed())
41 | x = +((+x).toFixed())
42 | y = +((+y).toFixed())
43 |
44 | let image = await createImage(curData)
45 | image = imageResize(image, width, height)
46 |
47 | if (preResult) return drawImg(preResult, image, x, y, width, height)
48 | else return image
49 |
50 | }, Promise.resolve())
51 | }
52 |
53 | // 获取文件内容 base64 或 文件id 或 url
54 | async function getContentByDataType (img, dataType, imgType) {
55 | const imgName = `${Date.now()}-${Math.random()}.${imgType}`
56 | const imgBuffer = img.toBuffer(imgType)
57 | if (dataType === 'base64') return imgBuffer.toString('base64')
58 | const fileID = await cloudUploadFile(`tmp/${dayjs().format('YYYY-MM-DD')}/${imgName}`, imgBuffer)
59 | db.collection('tmp-file').add({ data: { time: Date.now(), fileID: fileID } })
60 | if (dataType === 'fileID') return fileID
61 | if (dataType === 'url') return await getFileUrlByFileID(fileID)
62 | }
63 |
64 | // 获取文件的临时访问url
65 | async function getFileUrlByFileID (fileID) {
66 | return (await cloud.getTempFileURL({
67 | fileList: [fileID]
68 | })).fileList[0].tempFileURL
69 | }
70 |
71 | // 上传图片到云存储,返回图片id
72 | async function cloudUploadFile (cloudPath, fileContent) {
73 | return (await cloud.uploadFile({ cloudPath, fileContent })).fileID
74 | }
75 |
76 | // 根据云存储id 获取图片buffer
77 | async function getCloudBuffer (fileID) {
78 | return (await cloud.downloadFile({ fileID: fileID })).fileContent
79 | }
80 |
81 | // 根据http地址获取图片 buffer
82 | function getHttpBuffer (src) {
83 | const protocol = src.split('://')[0]
84 | return new Promise((resolve, reject) => {
85 | ;({ http, https }[protocol]).get(src, res => {
86 | if (res.statusCode !== 200) return reject(new Error('图片加载失败'))
87 | const rawData = []
88 | res.setEncoding('binary')
89 | res.on('data', chunk => rawData.push(chunk))
90 | res.on('end', () => resolve(Buffer.from(rawData.join(''), 'binary')))
91 | })
92 | })
93 | }
94 |
95 | // 创建图片
96 | async function createImage (data) {
97 | if (data.bgc && data.bgc.length) return images(+data.width, +data.height).fill(...data.bgc)
98 | else if (data.imgId) return images(await getCloudBuffer(data.imgId))
99 | else if (data.src) return images(await getHttpBuffer(data.src))
100 | else return images(+data.width, +data.height)
101 | }
102 |
103 | // 图片设置宽高
104 | function imageResize (image, width, height) {
105 | if (!width && !height) return image
106 | const size = image.size()
107 | if (width === size.width && height === size.height) return image
108 | if (width && height) return image.resize(width, height)
109 | if (width) return image.width(width)
110 | if (height) return image.height(height)
111 | }
112 |
113 | // 将图片画在 一张图上
114 | function drawImg (baseImg, img, x, y, width, height) {
115 | if (x >= 0 && y >= 0) return baseImg.draw(img, x, y)
116 | img = images(img, x < 0 ? Math.abs(x) : 0, y < 0 ? Math.abs(y) : 0, width, height)
117 | return baseImg.draw(img, x > 0 ? x : 0, y > 0 ? y : 0)
118 | }
119 |
120 |
--------------------------------------------------------------------------------
/cloudfunctions/imageCompose/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "imageCompose",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest",
13 | "images": "^3.2.3",
14 | "dayjs": "^1.10.3"
15 | }
16 | }
--------------------------------------------------------------------------------
/cloudfunctions/imagemin/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/imagemin/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 | const http = require('http')
4 | const https = require('https')
5 | const images = require('images')
6 | const dayjs = require('dayjs')
7 |
8 | cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境
9 |
10 | const db = cloud.database()
11 |
12 | // 云函数入口函数
13 | exports.main = async (event, context) => {
14 | console.log(event)
15 |
16 | const checkResult = (await cloud.callFunction({
17 | name: 'imgSecCheck',
18 | data: event
19 | })).result
20 |
21 | if (!checkResult.originImgPath) {
22 | return checkResult
23 | }
24 |
25 | const { filePath, type = 'jpg' } = event
26 | const width = Number(event.width)
27 | const height = Number(event.height)
28 | const quality = Number(event.quality) || 100
29 | if (!filePath) return { errMsg: '图片地址不能为空' }
30 | if (!width && !height) return { errMsg: '图片尺寸不能为空' }
31 | const imgType = 'jpg' // 只考虑jpg格式
32 | const img = images(await getHttpBuffer(filePath))
33 | if (width) img.width(width)
34 | if (height) img.height(height)
35 | const imgBuffer = img.encode('jpg', { quality: quality })
36 | const imgName = `imagemin-${Date.now()}-${Math.random()}.${imgType}`
37 | const fileID = await cloudUploadFile(`tmp/${dayjs().format('YYYY-MM-DD')}/${imgName}`, imgBuffer)
38 | await db.collection('tmp-file').add({ data: { time: Date.now(), fileID: fileID } })
39 | return await getFileUrlByFileID(fileID)
40 | }
41 |
42 | // 根据http地址获取图片 buffer
43 | function getHttpBuffer (src) {
44 | const protocol = src.split('://')[0]
45 | return new Promise((resolve, reject) => {
46 | ;({ http, https }[protocol]).get(src, res => {
47 | if (res.statusCode !== 200) return reject(new Error('图片加载失败'))
48 | const rawData = []
49 | res.setEncoding('binary')
50 | res.on('data', chunk => rawData.push(chunk))
51 | res.on('end', () => resolve(Buffer.from(rawData.join(''), 'binary')))
52 | })
53 | })
54 | }
55 |
56 | // 获取文件的临时访问url
57 | async function getFileUrlByFileID (fileID) {
58 | return (await cloud.getTempFileURL({
59 | fileList: [fileID]
60 | })).fileList[0].tempFileURL
61 | }
62 |
63 | // 上传图片到云存储,返回图片id
64 | async function cloudUploadFile (cloudPath, fileContent) {
65 | return (await cloud.uploadFile({ cloudPath, fileContent })).fileID
66 | }
67 |
--------------------------------------------------------------------------------
/cloudfunctions/imagemin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "imagemin",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3",
13 | "images": "3.2.4",
14 | "dayjs": "^1.10.3"
15 | }
16 | }
--------------------------------------------------------------------------------
/cloudfunctions/imgSecCheck/AliCloud.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | const $imageaudit20191230 = require("@alicloud/imageaudit20191230");
3 | const imageaudit20191230 = $imageaudit20191230.default
4 | const $OpenApi = require("@alicloud/openapi-client");
5 | const $Util = require("@alicloud/tea-util");
6 | const Util = $Util.default
7 | const accessKeyId = process.env.accessKeyId;
8 | const accessKeySecret = process.env.accessKeySecret;
9 |
10 | module.exports = class Client {
11 | /**
12 | * 使用AK&SK初始化账号Client
13 | * @param accessKeyId
14 | * @param accessKeySecret
15 | * @return Client
16 | * @throws Exception
17 | */
18 | static createClient() {
19 | const config = new $OpenApi.Config({
20 | accessKeyId: accessKeyId,
21 | accessKeySecret: accessKeySecret,
22 | });
23 | // 访问的域名
24 | config.endpoint = `imageaudit.cn-shanghai.aliyuncs.com`;
25 | return new imageaudit20191230(config);
26 | }
27 |
28 | static async main(imageURL) {
29 | const client = Client.createClient();
30 | const task0 = new $imageaudit20191230.ScanImageRequestTask({
31 | imageURL: imageURL,
32 | });
33 | const scanImageRequest = new $imageaudit20191230.ScanImageRequest({
34 | task: [task0],
35 | scene: ["porn", "terrorism", "live"],
36 | });
37 | const runtime = new $Util.RuntimeOptions({});
38 | try {
39 | // 复制代码运行请自行打印 API 的返回值
40 | const aliResult = await client.scanImageWithOptions(scanImageRequest, runtime);
41 | return { status: aliResult.body.data.results[0].subResults.every(item => item.suggestion === 'pass') }
42 | } catch (error) {
43 | // 如有需要,请打印 error
44 | Util.assertAsString(error.message);
45 | return { error }
46 | }
47 | }
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/cloudfunctions/imgSecCheck/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | "security.imgSecCheck"
5 | ]
6 | }
7 | }
--------------------------------------------------------------------------------
/cloudfunctions/imgSecCheck/index.js:
--------------------------------------------------------------------------------
1 | const http = require('http')
2 | const https = require('https')
3 | const cloud = require('wx-server-sdk')
4 | const AliCloud = require('./AliCloud')
5 | cloud.init({
6 | env:cloud.DYNAMIC_CURRENT_ENV,
7 | })
8 | // 云函数入口函数
9 | exports.main = async (event, context) => {
10 | try {
11 | // 图片压缩
12 | const imgInfo = await imageMinify(event)
13 | // 图片校验
14 | return await imgSecCheck(event, imgInfo)
15 | } catch (error) {
16 | return await imgSecCheck(event, event)
17 | }
18 | }
19 |
20 | // 图片压缩
21 | async function imageMinify (imgInfo) {
22 | const { width, height, filePath, type } = imgInfo
23 | // 需要压缩,腾讯免费的图片安全接口要求的
24 | if ((width > 750 && height > 750) || width > 1334 || height > 1334) {
25 | const imgSize = getImageSize({ width, height })
26 | const { result } = await cloud.callFunction({
27 | name: 'imageCompose',
28 | data: {
29 | imgType: 'jpg',
30 | dataType: 'url',
31 | data: [{ ...imgSize, src: filePath }]
32 | }
33 | })
34 | return {
35 | width: imgSize.width,
36 | height: imgSize.height,
37 | filePath: result.value,
38 | type: result.imageType
39 | }
40 | }
41 | return imgInfo
42 | }
43 |
44 | // 计算压缩后的图片宽高
45 | function getImageSize (imgInfo) {
46 | let width = 0, height = 0
47 | if (imgInfo.width > imgInfo.height) {
48 | width = 750
49 | height = 750 * imgInfo.height / imgInfo.width
50 | } else if (imgInfo.height > imgInfo.width) {
51 | height = 750
52 | width = 750 * imgInfo.width / imgInfo.height
53 | } else {
54 | width = height = 750
55 | }
56 | return {
57 | width,
58 | height
59 | }
60 | }
61 |
62 | // 获取图片buffer
63 | function getBuffer (src) {
64 | const protocol = src.split('://')[0]
65 | return new Promise((resolve, reject) => {
66 | ;({ http, https }[protocol]).get(src, res => {
67 | if (res.statusCode !== 200) return reject(new Error('图片加载失败'))
68 | const rawData = []
69 | res.setEncoding('binary')
70 | res.on('data', chunk => rawData.push(chunk))
71 | res.on('end', () => resolve(Buffer.from(rawData.join(''), 'binary')))
72 | })
73 | })
74 | }
75 |
76 | // 腾讯免费的图片内容安全检测
77 | async function imgSecCheck (event, imgInfo) {
78 | // 获取图片buffer
79 | const buffer = await getBuffer(imgInfo.filePath)
80 | try {
81 | const imgResult = await cloud.openapi.security.imgSecCheck({
82 | media:{
83 | header: {'content-Type': 'application/octe-stream'},
84 | contentType: `image/${imgInfo.type}`,
85 | value: buffer
86 | }
87 | })
88 | imgResult.filePath = imgInfo.filePath
89 | imgResult.originImgPath = event.filePath
90 | imgResult.originImgType = event.type
91 | return imgResult
92 | } catch (error) {
93 | // 校验含有敏感信息
94 | if (error.errCode === 87014) return error
95 | // 不好用,老报错,用阿里再检测一次
96 | return aliCheck(event, imgInfo)
97 | }
98 | }
99 |
100 | // 阿里云的图片内容安全接口监测
101 | async function aliCheck (event, imgInfo) {
102 | const aliRes = await AliCloud.main(event.filePath)
103 | // 阿里接口调用错误了
104 | if (aliRes.error) return { errCode: -604102, msg: aliRes.error.message }
105 | // 检测通过
106 | else if (aliRes.status) return {
107 | errCode: 0,
108 | filePath: imgInfo.filePath,
109 | originImgPath: event.filePath,
110 | originImgType: event.type
111 | }
112 | // 检测不通过
113 | else return { errCode: 87014 }
114 | }
115 |
--------------------------------------------------------------------------------
/cloudfunctions/imgSecCheck/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "imgSecCheck",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3",
13 | "@alicloud/imageaudit20191230": "^2.0.1"
14 | }
15 | }
--------------------------------------------------------------------------------
/cloudfunctions/printStyle/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/printStyle/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 | const http = require('http')
4 | const https = require('https')
5 | const images = require('images')
6 | const dayjs = require('dayjs')
7 |
8 | cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境
9 |
10 | const db = cloud.database()
11 |
12 | // 云函数入口函数
13 | exports.main = async (event, context) => {
14 | console.log(event)
15 |
16 | const checkResult = (await cloud.callFunction({
17 | name: 'imgSecCheck',
18 | data: event
19 | })).result
20 |
21 | if (!checkResult.originImgPath) {
22 | return checkResult
23 | }
24 |
25 | const { filePath } = event
26 | const width = Number(event.width)
27 | const height = Number(event.height)
28 | const resultWidth = 1200
29 | const resultHeight = 1800
30 |
31 | if (!filePath) return { errMsg: '图片地址不能为空' }
32 | if (!width || !height) return { errMsg: '图片尺寸不能为空' }
33 | if (width > (resultWidth - 100)) return { errMsg: '图片宽度不能大于1100' }
34 | if (height > (resultHeight - 100)) return { errMsg: '图片高度不能大于1700' }
35 |
36 | const sourceImg = images(await getHttpBuffer(filePath))
37 |
38 | const resultImg = images(resultWidth, resultHeight).fill(200, 200, 200, 0)
39 |
40 | let xCount = Math.floor(resultWidth / width)
41 | let xSpaces = (resultWidth % width) / (xCount + 1)
42 |
43 | let yCount = Math.floor(resultHeight / height)
44 | let ySpaces = (resultHeight % height) / (yCount + 1)
45 |
46 | console.log('xCount', xCount, 'yCount', yCount, 'ySpaces', ySpaces, 'xSpaces', xSpaces)
47 |
48 | for (let y = 0; y < yCount; y++) {
49 | for (let x = 0; x < xCount; x++) {
50 | const offsetX = x * width + xSpaces * (x + 1)
51 | const offsetY = y * height + ySpaces * (y + 1)
52 | console.log('offsetX', offsetX, 'offsetY', offsetY)
53 | resultImg.draw(sourceImg, offsetX, offsetY)
54 | }
55 | }
56 |
57 | const imgBuffer = resultImg.encode('jpg')
58 | const imgName = `print-${Date.now()}-${Math.random()}.${'jpg'}`
59 | const fileID = await cloudUploadFile(`tmp/${dayjs().format('YYYY-MM-DD')}/${imgName}`, imgBuffer)
60 | await db.collection('tmp-file').add({ data: { time: Date.now(), fileID: fileID } })
61 | return await getFileUrlByFileID(fileID)
62 |
63 | }
64 |
65 | // 根据http地址获取图片 buffer
66 | function getHttpBuffer (src) {
67 | const protocol = src.split('://')[0]
68 | return new Promise((resolve, reject) => {
69 | ;({ http, https }[protocol]).get(src, res => {
70 | if (res.statusCode !== 200) return reject(new Error('图片加载失败'))
71 | const rawData = []
72 | res.setEncoding('binary')
73 | res.on('data', chunk => rawData.push(chunk))
74 | res.on('end', () => resolve(Buffer.from(rawData.join(''), 'binary')))
75 | })
76 | })
77 | }
78 |
79 | // 获取文件的临时访问url
80 | async function getFileUrlByFileID (fileID) {
81 | return (await cloud.getTempFileURL({
82 | fileList: [fileID]
83 | })).fileList[0].tempFileURL
84 | }
85 |
86 | // 上传图片到云存储,返回图片id
87 | async function cloudUploadFile (cloudPath, fileContent) {
88 | return (await cloud.uploadFile({ cloudPath, fileContent })).fileID
89 | }
--------------------------------------------------------------------------------
/cloudfunctions/printStyle/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "preintStyle",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3",
13 | "images": "3.2.4",
14 | "dayjs": "^1.10.3"
15 | }
16 | }
--------------------------------------------------------------------------------
/cloudfunctions/setUserInfo/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/setUserInfo/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 |
6 | // 云函数入口函数
7 | exports.main = async (event, context) => {
8 | const wxContext = cloud.getWXContext()
9 | const data = Object.assign({}, event.data)
10 | delete data._id
11 | const db = cloud.database()
12 | const res = await db.collection('user').where({
13 | openid: event.openid || wxContext.OPENID
14 | }).update({ data })
15 |
16 | return {
17 | res,
18 | event,
19 | openid: wxContext.OPENID,
20 | appid: wxContext.APPID,
21 | unionid: wxContext.UNIONID,
22 | }
23 | }
--------------------------------------------------------------------------------
/cloudfunctions/setUserInfo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "setUserInfo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.0.2"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/cloudfunctions/shareSuccessCallback/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/shareSuccessCallback/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 | const db = cloud.database()
6 |
7 | // 云函数入口函数,邀请成功,来领次数了
8 | exports.main = async (event, context) => {
9 | const wxContext = cloud.getWXContext()
10 |
11 | // 更新邀请记录
12 | const shareRes = await db.collection('share').where({
13 | _openid: wxContext.OPENID,
14 | }).update({
15 | data: { [event.openid]: true }
16 | })
17 |
18 | // 更新成功,加3次
19 | let useCountRes
20 | if (shareRes.stats.updated) {
21 | useCountRes = await cloud.callFunction({
22 | name: 'useCount',
23 | data: { inc: 1, openid: wxContext.OPENID }
24 | })
25 | }
26 |
27 | return {
28 | useCountRes,
29 | shareRes,
30 | event,
31 | openid: wxContext.OPENID,
32 | appid: wxContext.APPID,
33 | unionid: wxContext.UNIONID,
34 | }
35 | }
--------------------------------------------------------------------------------
/cloudfunctions/shareSuccessCallback/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "shareSuccessCallback",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~1.8.3"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/cloudfunctions/shareUpdate/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/shareUpdate/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 | const db = cloud.database()
6 | const _ = db.command
7 |
8 | // 云函数入口函数
9 | exports.main = async (event, context) => {
10 | const wxContext = cloud.getWXContext()
11 |
12 | // 不是自己邀请自己
13 | if (event.shareOpenid !== wxContext.OPENID) {
14 | // 触发消息推送
15 | await triggerMessage(event, wxContext.OPENID)
16 | // 添加到邀请成功列表中
17 | await addToInviteesTodayList(event, wxContext)
18 | }
19 | // 给当前用户设置他的上一级,上一级就是邀请他的人
20 | setParent(event.shareOpenid, wxContext.OPENID)
21 |
22 | return {
23 | event,
24 | openid: wxContext.OPENID,
25 | appid: wxContext.APPID,
26 | unionid: wxContext.UNIONID,
27 | }
28 | }
29 |
30 | // 将用户添加到 邀请者的 列表中
31 | function addToInviteesTodayList (event, wxContext) {
32 | return db.collection('share').where({
33 | openid: event.shareOpenid,
34 | }).update({
35 | data: {
36 | invitedList: _.addToSet(wxContext.OPENID)
37 | }
38 | })
39 | }
40 |
41 | // 触发订阅消息
42 | async function triggerMessage (event, currentOpenid) {
43 | const { data } = await db.collection('share').where({
44 | _openid: event.shareOpenid,
45 | }).field({ invitedList: true }).get()
46 | if (!data.length) return
47 | if (data[0].invitedList.some(openid => openid === currentOpenid)) return
48 | cloud.callFunction({
49 | name: 'triggerSubscrib',
50 | data: {
51 | openid: event.shareOpenid,
52 | tmplId: 'CNuffKDjmxEOU_hM44Cu0KoGqOjfdacpbk4LT1abcnE'
53 | }
54 | })
55 | }
56 |
57 | // 给用户设置邀请人
58 | async function setParent (parentId, currentId) {
59 | const { data } = await db.collection('user').where({ openid: currentId }).get()
60 | if (data.parentOpenid) return
61 | await db.collection('user').where({ openid: currentId }).update({
62 | data: {
63 | parentOpenid: parentId
64 | }
65 | })
66 | }
67 |
--------------------------------------------------------------------------------
/cloudfunctions/shareUpdate/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "shareUpdate",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~1.8.3"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/cloudfunctions/subscribeEvent/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/subscribeEvent/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 |
6 | const db = cloud.database()
7 |
8 | // 云函数入口函数
9 | exports.main = async (event, context) => {
10 | const wxContext = cloud.getWXContext()
11 |
12 | // event 数据结构
13 | // const e = {
14 | // "CreateTime": 1663989948,
15 | // "Event": "subscribe_msg_popup_event",
16 | // "FromUserName": "obRga0ZrZkNe5ZF60smAvbscTM5Y",
17 | // "List": {
18 | // "PopupScene": "0",
19 | // "SubscribeStatusString": "accept",
20 | // "TemplateId": "CNuffKDjmxEOU_hM44Cu0KoGqOjfdacpbk4LT1abcnE"
21 | // },
22 | // "MsgType": "event",
23 | // "ToUserName": "gh_82e5b8a1fccf",
24 | // "userInfo": {
25 | // "appId": "wxbe6c30a61a51b422",
26 | // "openId": "obRga0ZrZkNe5ZF60smAvbscTM5Y"
27 | // }
28 | // }
29 |
30 | if (event.List.SubscribeStatusString !== 'accept') return
31 |
32 | db.collection('subscrib-message').add({
33 | data: {
34 | openid: event.userInfo.openId,
35 | tmplId: event.List.TemplateId,
36 | time: event.CreateTime
37 | },
38 | })
39 |
40 | return {
41 | event,
42 | openid: wxContext.OPENID,
43 | appid: wxContext.APPID,
44 | unionid: wxContext.UNIONID,
45 | }
46 | }
--------------------------------------------------------------------------------
/cloudfunctions/subscribeEvent/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "subscribeEvent",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/timingDelete/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "triggers": [
3 | {
4 | "name": "timingDelete",
5 | "type": "timer",
6 | "config": "0 */30 * * * * *"
7 | }
8 | ]
9 | }
--------------------------------------------------------------------------------
/cloudfunctions/timingDelete/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 |
6 | const db = cloud.database()
7 |
8 | // 云函数入口函数, 定时删除云存储的用户生成的图片
9 | exports.main = async (event, context) => {
10 |
11 | // 一小时前的毫秒数
12 | const time = Date.now() - 1000 * 60 * 60
13 |
14 | const _ = db.command
15 | // 连接数据库
16 | const tmpFiles = db.collection('tmp-file')
17 | // 查询一小时前上传的图片
18 | const { data: list } = await tmpFiles.where({ time: _.lt(time) }).limit(50).get()
19 |
20 | // 没查到
21 | if (!list.length) return { delete: false, list }
22 | // 找出图片的 fileID
23 | const fileList = list.map(v => v.fileID)
24 | // 从云存储中删除图片
25 | const { fileList: resultList } = await cloud.deleteFile({ fileList })
26 | // 删除成功的和文件不存在的
27 | const removedFiles = resultList.filter(file => file.status === 0 || file.status === -503003).map(file => file.fileID)
28 | // 从数据库中删除记录
29 | await tmpFiles.where({
30 | fileID: _.in(removedFiles)
31 | }).remove()
32 |
33 | return { delete: true, list: resultList }
34 | }
--------------------------------------------------------------------------------
/cloudfunctions/timingDelete/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "timingDelete",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.3.2"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/timingGetImage/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | },
6 | "triggers": [
7 | {
8 | "name": "timingGetImage",
9 | "type": "timer",
10 | "config": "0 */30 * * * * *"
11 | }
12 | ]
13 | }
--------------------------------------------------------------------------------
/cloudfunctions/timingGetImage/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const request = require('request')
3 | const cloud = require('wx-server-sdk')
4 | const imgApi = process.env.IMAGE_API
5 | const meinvImgApi = process.env.MEINV_IMAGE_API
6 |
7 | cloud.init()
8 |
9 | const db = cloud.database()
10 | // 共享给人像抠图小程序用
11 | // 云函数入口函数
12 | exports.main = async (event, context) => {
13 |
14 | // 获取一张美女图片,不管成功不成功,先存起来
15 | getMeinvImgUrl()
16 |
17 | // 返回一张风景图
18 | const imgUrl = await getImgUrl()
19 |
20 | return {
21 | imgurl: imgUrl,
22 | }
23 | }
24 |
25 | function getImgUrl () {
26 | return new Promise((resolve, reject) => {
27 |
28 | request(imgApi, async function (error, response, body) {
29 |
30 | const data = JSON.parse(body)
31 | if (data.code != 200) return reject(data)
32 |
33 | try {
34 | await db.collection('images').doc(data.imgurl).get()
35 | } catch (error) {
36 | db.collection('images').add({
37 | data: {
38 | _id: data.imgurl,
39 | imgurl: data.imgurl,
40 | create_time: Date.now(),
41 | category: 'fengjing',
42 | type: 'm'
43 | }
44 | })
45 | }
46 |
47 | const { total } = await db.collection('bg-images').where({ imgurl: data.imgurl }).count()
48 |
49 | if (total > 0) return resolve(data.imgurl)
50 |
51 | db.collection('bg-images').add({
52 | data: { imgurl: data.imgurl, create_time: Date.now() }
53 | })
54 |
55 | resolve(data.imgurl)
56 | })
57 | })
58 | }
59 |
60 | // 获取一张美女图片,存在库里
61 | function getMeinvImgUrl () {
62 | request(meinvImgApi, async function (error, response, body) {
63 | const data = JSON.parse(body)
64 | if (data.code != 200) return reject(data)
65 |
66 | try {
67 | await db.collection('images').doc(data.imgurl).get()
68 | } catch (error) {
69 | db.collection('images').add({
70 | data: {
71 | _id: data.imgurl,
72 | imgurl: data.imgurl,
73 | create_time: Date.now(),
74 | category: 'meinv',
75 | type: 'm'
76 | }
77 | })
78 | }
79 |
80 | })
81 | }
--------------------------------------------------------------------------------
/cloudfunctions/timingGetImage/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "timingGetImage",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/timingTriggerSignMessage/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | },
6 | "triggers": [
7 | {
8 | "name": "timingGetImage",
9 | "type": "timer",
10 | "config": "0 30 9 * * ? *"
11 | }
12 | ]
13 | }
--------------------------------------------------------------------------------
/cloudfunctions/timingTriggerSignMessage/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 |
6 | const db = cloud.database()
7 |
8 | const tmplId = 'h_P9sODh-NfeXteA5t7h6sS9BAIjtEyppGwt-biQIQ0'
9 |
10 | // 云函数入口函数
11 | exports.main = async (event, context) => {
12 |
13 | const res = await db.collection('subscrib-message').where({ tmplId }).get()
14 |
15 | res.data.forEach(item => getSignStatus(item.openid))
16 |
17 | return res
18 | }
19 |
20 | // 获取前端状态
21 | async function getSignStatus (openid) {
22 | const { data } = await db.collection('user').where({ openid }).get()
23 | if (data[0].signInDate === new Date().toDateString()) return
24 | trigger(openid)
25 | }
26 |
27 | // 触发消息
28 | function trigger (openid) {
29 | cloud.callFunction({
30 | name: 'triggerSubscrib',
31 | data: {
32 | openid,
33 | tmplId
34 | }
35 | })
36 | }
37 |
--------------------------------------------------------------------------------
/cloudfunctions/timingTriggerSignMessage/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "timingTriggerSignMessage",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/timingUpdateBgListIndex/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | },
6 | "triggers": [
7 | {
8 | "name": "timingGetImage",
9 | "type": "timer",
10 | "config": "0 0 0 * * ? *"
11 | }
12 | ]
13 | }
--------------------------------------------------------------------------------
/cloudfunctions/timingUpdateBgListIndex/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 | const db = cloud.database()
6 |
7 | // 共享给人像抠图小程序用
8 |
9 | // 云函数入口函数
10 | exports.main = async (event, context) => {
11 |
12 | const { total } = await db.collection('bg-images').where({}).count()
13 |
14 | const { data } = await db
15 | .collection('global-config')
16 | .doc('803723f46336f9d70058cdda67e1a3d8')
17 | .get()
18 |
19 | let index = data.bgListIndex + 4
20 | if (index >= total) {
21 | index = 0
22 | }
23 |
24 | await db
25 | .collection('global-config')
26 | .doc('803723f46336f9d70058cdda67e1a3d8')
27 | .update({
28 | data: {
29 | bgListIndex: index
30 | }
31 | })
32 |
33 | return {
34 | event,
35 | }
36 | }
--------------------------------------------------------------------------------
/cloudfunctions/timingUpdateBgListIndex/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "timingUpdateBgListIndex",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/triggerSubscrib/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ],
5 | "triggers": []
6 | }
7 | }
--------------------------------------------------------------------------------
/cloudfunctions/triggerSubscrib/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 |
6 | const db = cloud.database()
7 |
8 | // 云函数入口函数
9 | exports.main = async (event, context) => {
10 | const tmplId = event.tmplId
11 | try {
12 | const result = await cloud.openapi.subscribeMessage.send({
13 | touser: event.openid,
14 | templateId: tmplId,
15 | ...getMessageData(tmplId)
16 | })
17 | // 删除订阅记录
18 | if (result.errCode === 0) {
19 | await db.collection('subscrib-message').where({
20 | openid: event.openid,
21 | tmplId: tmplId
22 | }).remove()
23 | }
24 | return {
25 | ...result,
26 | msgid: result.msgid.toString()
27 | }
28 | } catch (err) {
29 | return err
30 | }
31 | }
32 |
33 |
34 | function getMessageData (tmplId) {
35 | return {
36 | // 邀请成功
37 | 'CNuffKDjmxEOU_hM44Cu0KoGqOjfdacpbk4LT1abcnE': {
38 | page: '/pages/share/share',
39 | data: {
40 | number1: { value: 3 },
41 | number2: { value: 1 }
42 | }
43 | },
44 | // 签到提醒
45 | 'h_P9sODh-NfeXteA5t7h6sS9BAIjtEyppGwt-biQIQ0': {
46 | page: '/pages/mein/mein',
47 | data: {
48 | phrase6: {value: '今日未签到'},
49 | thing7: { value: '1次免冠照片制作' },
50 | thing5: { value: '点击立即签到' }
51 | }
52 | }
53 | }[tmplId]
54 | }
55 |
--------------------------------------------------------------------------------
/cloudfunctions/triggerSubscrib/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "triggerSubscrib",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/updateImageCount/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | },
6 |
7 | "triggers": [
8 | {
9 | "name": "timingUpdateImageCount",
10 | "type": "timer",
11 | "config": "0 */30 * * * * *"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/updateImageCount/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 | const db = cloud.database()
6 |
7 | // 数据库数据发生变化时会自动触发这个云函数
8 |
9 | // 云函数入口函数
10 | exports.main = async (event, context) => {
11 |
12 | const [m_meinv, m_fengjing, m_dongman, m_biying, pc_meinv, pc_fengjing, pc_dongman, pc_biying] = await Promise.all([
13 | getTotal('meinv', 'm'),
14 | getTotal('fengjing', 'm'),
15 | getTotal('dongman', 'm'),
16 | getTotal('biying', 'm'),
17 | getTotal('meinv', 'pc'),
18 | getTotal('fengjing', 'pc'),
19 | getTotal('dongman', 'pc'),
20 | getTotal('biying', 'pc'),
21 | ])
22 |
23 | await db.collection('global-config')
24 | .doc('e936e40c633acad300608f043f5b6ec8')
25 | .update({
26 | data: {
27 | m_meinv, m_fengjing, m_dongman, m_biying, pc_meinv, pc_fengjing, pc_dongman, pc_biying
28 | }
29 | })
30 |
31 | return {
32 | m_meinv, m_fengjing, m_dongman, m_biying, pc_meinv, pc_fengjing, pc_dongman, pc_biying
33 | }
34 | }
35 |
36 | async function getTotal (category, type) {
37 | const { total } = await db.collection('images').where({
38 | category,
39 | type
40 | }).count()
41 | return total
42 | }
43 |
--------------------------------------------------------------------------------
/cloudfunctions/updateImageCount/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "updateImageCount",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/useCount/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 | const db = cloud.database()
6 | const _ = db.command
7 |
8 | // 云函数入口函数,更新用户剩余次数
9 | exports.main = async (event, context) => {
10 | const wxContext = cloud.getWXContext()
11 | const data = {
12 | // 累计生成照片 只增不减
13 | accumCreatePhoto: _.inc(event.inc > 0 ? 0 : -(event.inc)),
14 | count: _.inc(event.isVip ? 0 : (1 * event.inc))
15 | }
16 | // 签到,更新签到时间
17 | if (event.signIn) {
18 | data.signInDate = new Date(Date.now() + 1000 * 60 * 60 * 8).toDateString().trim()
19 | }
20 | // 更新当前用户次数
21 | const res = await db.collection('user').where({
22 | openid: event.openid || wxContext.OPENID
23 | }).update({ data })
24 |
25 | return {
26 | success: res.stats.updated > 0,
27 | openid: wxContext.OPENID,
28 | appid: wxContext.APPID,
29 | unionid: wxContext.UNIONID,
30 | }
31 | }
--------------------------------------------------------------------------------
/cloudfunctions/useCount/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "savePhotoId",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/cloudfunctions/useVipCount/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 | const db = cloud.database()
6 | const _ = db.command
7 |
8 | // 云函数入口函数
9 | exports.main = async (event, context) => {
10 | const wxContext = cloud.getWXContext()
11 | const data = {
12 | vipCount: _.inc(event.lookVideo ? 1 : (1 * event.inc)),
13 | lookVideoCount: _.inc(event.lookVideo ? 1 : 0)
14 | }
15 |
16 | const res = await db.collection('user').where({
17 | openid: event.openid || wxContext.OPENID
18 | }).update({ data })
19 |
20 | return {
21 | success: res.stats.updated > 0,
22 | openid: wxContext.OPENID,
23 | appid: wxContext.APPID,
24 | unionid: wxContext.UNIONID,
25 | }
26 | }
--------------------------------------------------------------------------------
/cloudfunctions/useVipCount/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "savePhotoId",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/cloudfunctions/vipKoutu/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/vipKoutu/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 | const https = require('https')
4 | const http = require('http')
5 | const axios = require('axios')
6 |
7 | cloud.init()
8 |
9 | // 云函数入口函数
10 | exports.main = async (event, context) => {
11 | console.log(event)
12 | let type = event.imgType
13 | // 获取图片buffer
14 | let targetBuffer = await getHttpBuffer(event.imgSrc)
15 | // buffer转成base64
16 | let imageBase64 = encodeURI(targetBuffer.toString('base64'))
17 | try {
18 | // 抠图接口调用
19 | const result = await koutu(type, imageBase64)
20 | // 抠图成功
21 | if (result.status === 0) return result
22 | } catch (error) {
23 |
24 | // 没有压缩图
25 | if (!event.compressSrc) return result
26 |
27 | // 使用压缩图抠图
28 | targetBuffer = await getHttpBuffer(event.compressSrc)
29 | imageBase64 = encodeURI(targetBuffer.toString('base64'))
30 | return await koutu('jpg', imageBase64)
31 | }
32 |
33 | }
34 |
35 | async function koutu (type, imageBase64) {
36 | return (await axios.post('https://aliapi.aisegment.com/segment/matting', {
37 | type: type,
38 | photo: imageBase64
39 | }, {
40 | headers: {
41 | 'Content-Type': 'application/json; charset=UTF-8',
42 | 'Authorization': 'APPCODE ' + process.env.APPCODE
43 | }
44 | })).data
45 | }
46 |
47 |
48 | // 根据http地址获取图片 buffer
49 | function getHttpBuffer (src) {
50 | const protocol = src.split('://')[0]
51 | return new Promise((resolve, reject) => {
52 | ;({ http, https }[protocol]).get(src, res => {
53 | if (res.statusCode !== 200) return reject(new Error('图片加载失败'))
54 | let rawData = ''
55 | res.setEncoding('binary')
56 | res.on('data', chunk => (rawData += chunk))
57 | res.on('end', () => resolve(Buffer.from(rawData, 'binary')))
58 | })
59 | })
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/cloudfunctions/vipKoutu/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vipKoutu",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.3.2",
13 | "axios": "^0.21.1"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/cloudfunctions/xiangguan/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | ]
5 | }
6 | }
--------------------------------------------------------------------------------
/cloudfunctions/xiangguan/imgList.js:
--------------------------------------------------------------------------------
1 | module.exports = ["cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2sl_IaoOO.eBjSZFLXXcxmXXa_!!2456947600.jpg_430x430q90.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2FF0CagOI.eBjSszhXXbHvFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2oGXyacaK.eBjSspjXXXL.XXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2o1YGakWM.eBjSZFhXXbdWpXa_!!2456947600.jpg_430x430q90.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2YGTJaoOO.eBjSZFLXXcxmXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2KgaMarVkpuFjSspcXXbSMVXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2x8GLaq8lpuFjy0FpXXaGrpXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB27guKarJkpuFjy1zcXXa5FFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB24ZOAaJXnpuFjSZFoXXXLcpXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2dMeLaB8lpuFjy0FnXXcZyXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2JtGCaHBmpuFjSZFAXXaQ0pXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2vKuMarVkpuFjSspcXXbSMVXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2oMGzaJFopuFjSZFHXXbSlXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2j4GCaNlmpuFjSZPfXXc9iXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2q6WHawJkpuFjSszcXXXfsFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB21U9CaOBnpuFjSZFzXXaSrpXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2zn9zaItnpuFjSZFvXXbcTpXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB23ZKMaC0jpuFjy0FlXXc0bpXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2urGQawxlpuFjy0FoXXa.lXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2WNmKarJkpuFjy1zcXXa5FFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2qfmIaxXkpuFjy0FiXXbUfFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2n6WAaNhmpuFjSZFyXXcLdFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2XnaKarplpuFjSspiXXcdfFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2LMKKarJkpuFjy1zcXXa5FFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2eq4vaceJ.eBjy0FiXXXqapXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2n4nCaiGO.eBjSZFpXXb3tFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2dvnHaheK.eBjSZFlXXaywXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2pvTJaheK.eBjSZFuXXcT4FXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2brWQawxlpuFjy0FoXXa.lXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB243KJaB0kpuFjy1zdXXXuUVXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2v39JaB0kpuFjy1zdXXXuUVXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2JSuyaUdnpuFjSZPhXXbChpXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2j8CIarXlpuFjSszfXXcSGXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB24IVwamKI.eBjy1zcXXXIOpXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2KZ2FaX5N.eBjSZFKXXX_QVXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2Zzq8XLTJXuFjSspeXXapipXa_!!2456947600.jpg_430x430q90.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2qwLJalaM.eBjSZFMXXcypVXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2alPLahaK.eBjSZFAXXczFXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2HA2Bajm2.eBjSZFtXXX56VXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2_94qab5K.eBjy0FfXXbApVXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2s8Bsam1I.eBjy0FjXXabfXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2y8htab1K.eBjSszbXXcTHpXa_!!2456947600.jpg_430x430q90.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2BjKHawJkpuFjSszcXXXfsFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2KzptaheJ.eBjy1zdXXXfmFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2Y7Rsam1I.eBjy0FjXXabfXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2FbpCal9J.eBjy0FoXXXyvpXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2OTdsaa9I.eBjy0FeXXXqwFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2KCfHafSM.eBjSZFNXXbgYpXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2.1qPaCJjpuFjy0FdXXXmoFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/O1CN01H3yiph260qaKwWZnv_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/O1CN01qW6wsv260qaGc4HXp_!!2456947600.jpg_430x430q90.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/O1CN015RnPdH260qaP3D2NL_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2BugOoY0kpuFjy0FjXXcBbVXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2TmaLaq8lpuFjy0FpXXaGrpXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB25xeCaSFmpuFjSZFrXXayOXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2cwuLarRkpuFjSspmXXc.9XXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2fJWMarVkpuFjSspcXXbSMVXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2OmqxaOlnpuFjSZFgXXbi7FXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2bMiLarRkpuFjSspmXXc.9XXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2BPSzaJFopuFjSZFHXXbSlXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/O1CN015SVYFT260qaNFelFL_!!2456947600.jpg_430x430q90.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/O1CN01VVymyH260qaNNSRhR_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2edPFaXOP.eBjSZFHXXXQnpXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2IJdqab1J.eBjSszcXXbFzVXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2h8YHalyN.eBjSZFgXXXmGXXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2OHzHaduO.eBjSZFCXXXULFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB216DHamiK.eBjSZFDXXbxZVXa_!!2456947600.jpg_430x430q90.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2lKzIalyN.eBjSZFkXXb8YFXa_!!2456947600.jpg", "cloud://dev-4iov0.6465-dev-4iov0-1301148496/xiangguan/TB2Inhrag1I.eBjSszeXXc2hpXa_!!2456947600.jpg"]
--------------------------------------------------------------------------------
/cloudfunctions/xiangguan/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | const photoList = require('./imgList')
5 |
6 | // 共享给人像抠图小程序用
7 |
8 | cloud.init()
9 |
10 | // 云函数入口函数
11 | exports.main = async (event, context) => {
12 | const wxContext = cloud.getWXContext()
13 |
14 | const photoIndex = event.index || Math.floor(Math.random() * photoList.length)
15 |
16 | const imgSrc = await getFileUrlByFileID(photoList[photoIndex])
17 |
18 | return {
19 | event,
20 | result: {
21 | length: photoList.length,
22 | photoId: imgSrc,
23 | photoIndex,
24 | },
25 | openid: wxContext.OPENID,
26 | appid: wxContext.APPID,
27 | unionid: wxContext.UNIONID,
28 | }
29 | }
30 |
31 |
32 | // 获取文件的临时访问url
33 | async function getFileUrlByFileID (fileID) {
34 | return (await cloud.getTempFileURL({ fileList: [fileID] })).fileList[0].tempFileURL
35 | }
--------------------------------------------------------------------------------
/cloudfunctions/xiangguan/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "xiangguan",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "~2.6.3"
13 | }
14 | }
--------------------------------------------------------------------------------
/miniprogram/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/.DS_Store
--------------------------------------------------------------------------------
/miniprogram/app.js:
--------------------------------------------------------------------------------
1 | //app.js
2 | App({
3 | onLaunch: function () {
4 |
5 | // 版本检查
6 | this.getNewVersion()
7 | // 初始化云开发
8 | wx.cloud.init({ resourceEnv: 'dev-4iov0', traceUser: true })
9 | // 新用户入库
10 | this.addUser()
11 | },
12 |
13 | // 新用户入库,并获取基本信息
14 | addUser() {
15 | wx.cloud.callFunction({
16 | name: 'addUser',
17 | success: res => {
18 | this.globalData.openid = res.result.openid
19 | },
20 | fail(err) {
21 | wx.showToast({
22 | title: '请求失败,请重试',
23 | icon: 'none'
24 | })
25 | }
26 | })
27 | },
28 |
29 | // 下载最新版本
30 | getNewVersion() {
31 | const updateManager = wx.getUpdateManager()
32 |
33 | updateManager.onCheckForUpdate(function (res) {
34 | // 请求完新版本信息的回调
35 | console.log('有新版本:', res.hasUpdate)
36 | })
37 |
38 | updateManager.onUpdateReady(function () {
39 | updateManager.applyUpdate()
40 | })
41 | },
42 |
43 | // 初始化全局数据
44 | globalData: {
45 | openid: null,
46 | photoSizeList: [{
47 | name: '一寸',
48 | px: '295×413 px',
49 | size: '25 × 35 mm',
50 | width: 295,
51 | height: 413,
52 | discription: '教师资格证、简历、会计职称考试、健康证等。'
53 | },
54 | {
55 | name: '小一寸',
56 | px: '260×378 px',
57 | size: '22 × 32 mm',
58 | width: 260,
59 | height: 378,
60 | discription: '驾驶证、驾照、英语AB级等。'
61 | },
62 | {
63 | name: '大一寸',
64 | px: '390×567 px',
65 | size: '33 × 48 mm',
66 | width: 390,
67 | height: 567,
68 | discription: '计算机等级、中国护照、英语四六级考试等。'
69 | },
70 | {
71 | name: '二寸',
72 | px: '413×579 px',
73 | size: '35 × 49 mm',
74 | width: 413,
75 | height: 579,
76 | discription: '养老护理员、医疗、职业药师资格证等。'
77 | },
78 | {
79 | name: '小二寸',
80 | px: '413×531 px',
81 | size: '33 × 45 mm',
82 | width: 413,
83 | height: 531,
84 | discription: '国考、国家公务员、护士资格证考试、主管护师等。'
85 | },
86 | {
87 | name: '大二寸',
88 | px: '413×626 px',
89 | size: '35 × 53 mm',
90 | width: 413,
91 | height: 626,
92 | discription: ''
93 | },
94 | {
95 | name: '三寸',
96 | px: '649×991 px',
97 | size: '55 × 84 mm',
98 | width: 413,
99 | height: 626,
100 | discription: ''
101 | },
102 | {
103 | name: '四寸',
104 | px: '898×1205 px',
105 | size: '76 × 102 mm',
106 | width: 413,
107 | height: 626,
108 | discription: ''
109 | },
110 | {
111 | name: '五寸',
112 | px: '1050×1499 px',
113 | size: '89 × 127 mm',
114 | width: 413,
115 | height: 626,
116 | discription: ''
117 | },
118 | {
119 | name: '简历',
120 | px: '295×413 px',
121 | size: '25 × 35 mm',
122 | width: 295,
123 | height: 413,
124 | discription: '简历'
125 | },
126 | {
127 | name: '健康证',
128 | px: '295×413 px',
129 | size: '25 × 35 mm',
130 | width: 295,
131 | height: 413,
132 | discription: '健康证'
133 | },
134 | {
135 | name: '结婚证',
136 | px: '626x413 px',
137 | size: '53 × 35 mm',
138 | width: 626,
139 | height: 413,
140 | discription: '结婚证大二寸双人证件照。'
141 | },
142 | {
143 | name: '一寸半身照',
144 | px: '295×413 px',
145 | size: '25 × 35 mm',
146 | width: 295,
147 | height: 413,
148 | discription: ''
149 | },
150 | {
151 | name: '二寸半身照',
152 | px: '413×579 px',
153 | size: '35 × 49 mm',
154 | width: 413,
155 | height: 579,
156 | discription: ''
157 | },
158 | {
159 | name: '教师资格证',
160 | px: '295×413 px',
161 | size: '25 × 35 mm',
162 | width: 295,
163 | height: 413,
164 | discription: '教师资格证'
165 | }
166 | ]
167 | }
168 | })
--------------------------------------------------------------------------------
/miniprogram/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/index/index",
4 | "pages/share/share",
5 | "pages/mein/mein",
6 | "pages/editPhoto/imageStyle/imageStyle",
7 | "pages/editPhoto/hair/hair",
8 | "pages/searchSize/searchSize",
9 | "pages/searchSize/searchView/searchView",
10 | "pages/searchSize/custom/custom",
11 | "pages/editPhoto/complete/complete",
12 | "pages/helpMake/helpMake",
13 | "pages/preEdit/preEdit",
14 | "pages/editPhoto/editPhotoPlus/editPhotoPlus",
15 | "pages/imgZip/imgZip",
16 | "pages/zipSuccess/zipSuccess",
17 | "pages/imgCompose/compose"
18 | ],
19 | "window": {
20 | "backgroundColor": "#fff",
21 | "backgroundTextStyle": "light",
22 | "navigationBarBackgroundColor": "#3E85EE",
23 | "navigationBarTitleText": "",
24 | "navigationBarTextStyle": "white"
25 | },
26 | "sitemapLocation": "sitemap.json",
27 | "style": "v2",
28 | "tabBar": {
29 | "backgroundColor": "#fff",
30 | "color": "#333333",
31 | "selectedColor": "#3E85EE",
32 | "list": [
33 | {
34 | "pagePath": "pages/index/index",
35 | "text": "首页",
36 | "iconPath": "./images/index.png",
37 | "selectedIconPath": "./images/index-active.png"
38 | },
39 | {
40 | "pagePath": "pages/mein/mein",
41 | "text": "我的",
42 | "iconPath": "./images/me.png",
43 | "selectedIconPath": "./images/me-active.png"
44 | }
45 | ]
46 | },
47 | "lazyCodeLoading": "requiredComponents"
48 | }
--------------------------------------------------------------------------------
/miniprogram/app.miniapp.json:
--------------------------------------------------------------------------------
1 | {
2 | "adapteByMiniprogram": {
3 | "userName": "gh_82e5b8a1fccf"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/miniprogram/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 | @import "colorui/main.wxss";
3 | @import "colorui/icon.wxss";
4 | .container {
5 | display: flex;
6 | flex-direction: column;
7 | align-items: center;
8 | box-sizing: border-box;
9 | }
10 |
11 | button {
12 | background: initial;
13 | }
14 |
15 | button:focus{
16 | outline: 0;
17 | }
18 |
19 | button::after{
20 | border: none;
21 | }
22 |
23 |
24 | page {
25 | /* background: linear-gradient(to bottom, rgba(0,191,243,.2), rgba(67,142,219,.2), rgba(255,0,0,.2)); */
26 | background-color: #F5F5F5;
27 | display: flex;
28 | flex-direction: column;
29 | justify-content: flex-start;
30 | }
31 |
--------------------------------------------------------------------------------
/miniprogram/components/color-picker/color-picker.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/miniprogram/components/color-picker/color-picker.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | R:{{pickerData.red}} G:{{pickerData.green}} B:{{pickerData.blue}}
17 | HEX:{{pickerData.hex}}
18 |
19 |
20 |
--------------------------------------------------------------------------------
/miniprogram/components/color-picker/color-picker.wxss:
--------------------------------------------------------------------------------
1 | .c {
2 | color: #5f27cd;
3 | }
4 | .bg {
5 | background: #5f27cd;
6 | }
7 | .t50 {
8 | top: 50%;
9 | left: 50%;
10 | transform: translate(-50%, -50%);
11 | }
12 | .tx50 {
13 | left: 50%;
14 | transform: translateX(-50%);
15 | }
16 | .ty50 {
17 | top: 50%;
18 | transform: translateY(-50%);
19 | }
20 | .cw {
21 | color: #fff;
22 | }
23 | .bw {
24 | background: #fff;
25 | }
26 | .fl {
27 | float: left;
28 | }
29 | .fr {
30 | float: right;
31 | }
32 | .fb {
33 | font-weight: bold;
34 | }
35 | .ib {
36 | display: inline-block !important;
37 | vertical-align: middle;
38 | }
39 | .tac {
40 | text-align: center;
41 | }
42 | .tal {
43 | text-align: left;
44 | }
45 | .tar {
46 | text-align: right;
47 | }
48 | .cp {
49 | cursor: pointer;
50 | }
51 | .none {
52 | display: none !important;
53 | }
54 | .hidden {
55 | visibility: hidden;
56 | opacity: 0;
57 | }
58 | .visible {
59 | visibility: visible;
60 | opacity: 1;
61 | }
62 | .mainSection {
63 | min-height: 100vh;
64 | }
65 | .row {
66 | display: flex;
67 | align-items: center;
68 | justify-content: center;
69 | }
70 | .col {
71 | display: flex;
72 | align-items: center;
73 | flex-direction: column;
74 | justify-content: center;
75 | }
76 | .ellipsis {
77 | overflow: hidden;
78 | text-overflow: ellipsis;
79 | white-space: nowrap;
80 | }
81 | .color-picker-container {
82 | width: 600rpx;
83 | }
84 | .color-picker-container .wrapper {
85 | margin: auto;
86 | }
87 | .color-picker-container .pick-area {
88 | display: flex;
89 | justify-content: space-between;
90 | }
91 | .color-picker-container .pick-area .color-picker-map {
92 | position: relative;
93 | width: 500rpx;
94 | height: 500rpx;
95 | }
96 | .color-picker-container .pick-area .color-picker-map .color-picker-map-item {
97 | position: absolute;
98 | top: 0rpx;
99 | left: 0rpx;
100 | width: 500rpx;
101 | height: 500rpx;
102 | border: 2rpx solid transparent;
103 | }
104 | .color-picker-container .pick-area .color-picker-map .color-picker-map-item.white {
105 | z-index: 10;
106 | }
107 | .color-picker-container .pick-area .color-picker-map .color-picker-map-item.black {
108 | z-index: 11;
109 | border: 2rpx solid #666;
110 | }
111 | .color-picker-container .pick-area .color-picker-map .picker {
112 | position: absolute;
113 | z-index: 12;
114 | width: 20rpx;
115 | height: 20rpx;
116 | border: 2rpx solid #666;
117 | background: #fff;
118 | border-radius: 50%;
119 | }
120 | .color-picker-container .pick-area .color-picker-bar {
121 | position: relative;
122 | width: 60rpx;
123 | height: 500rpx;
124 | border: 2rpx solid #666;
125 | background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
126 | }
127 | .color-picker-container .pick-area .color-picker-bar .picker {
128 | position: absolute;
129 | z-index: 10;
130 | width: 110%;
131 | height: 10rpx;
132 | left: 50%;
133 | transform: translateX(-50%);
134 | background: #fff;
135 | border: 2rpx solid #666;
136 | }
137 | .color-picker-container .data-area {
138 | margin-top: 20rpx;
139 | font-size: 26rpx;
140 | display: flex;
141 | justify-content: space-between;
142 | }
143 | /*# sourceMappingURL=./color-picker.wxss.map */
--------------------------------------------------------------------------------
/miniprogram/components/color-picker/color-picker.wxss.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["e:/MyProject/some-components/miniprogram/style/style.less","color-picker.less"],"names":[],"mappings":"AAEA;EACI,cAAA;;AAGJ;EACI,mBAAA;;AAyCJ;EACI,QAAA;EACA,SAAA;EACA,WAAW,qBAAX;;AAGJ;EACI,SAAA;EACA,WAAW,gBAAX;;AAGJ;EACI,QAAA;EACA,WAAW,gBAAX;;AAGJ;EACI,WAAA;;AAGJ;EACI,gBAAA;;AAGJ;EACI,WAAA;;AAGJ;EACI,YAAA;;AAGJ;EACI,iBAAA;;AAGJ;EACI,qBAAA;EACA,sBAAA;;AAGJ;EACI,kBAAA;;AAGJ;EACI,gBAAA;;AAGJ;EACI,iBAAA;;AAGJ;EACI,eAAA;;AAGJ;EACI,wBAAA;;AAGJ;EACI,kBAAA;EACA,UAAA;;AAGJ;EACI,mBAAA;EACA,UAAA;;AAGJ;EACI,iBAAA;;AAGJ;EACI,aAAA;EACA,mBAAA;EACA,uBAAA;;AAGJ;EACI,aAAA;EACA,mBAAA;EACA,sBAAA;EACA,uBAAA;;AAGJ;EACI,gBAAA;EACA,uBAAA;EACA,mBAAA;;ACzIJ;EACE,aAAA;;AADF,uBAGE;EACE,YAAA;;AAJJ,uBAOE;EACE,aAAA;EACA,8BAAA;;AATJ,uBAOE,WAIE;EACE,kBAAA;EACA,aAAA;EACA,cAAA;;AAdN,uBAOE,WAIE,kBAKE;EACE,kBAAA;EACA,SAAA;EACA,UAAA;EACA,aAAA;EACA,cAAA;EACA,8BAAA;;AAEA,uBAjBN,WAIE,kBAKE,uBAQG;EACC,WAAA;;AAGF,uBArBN,WAIE,kBAKE,uBAYG;EACC,WAAA;EACA,uBAAA;;AA9BV,uBAOE,WAIE,kBAuBE;EACE,kBAAA;EACA,WAAA;EACA,YAAA;EACA,aAAA;EACA,uBAAA;ED4BJ,gBAAA;EA9BA,kBAAA;;ACrCJ,uBAOE,WAsCE;EACE,kBAAA;EACA,YAAA;EACA,cAAA;EACA,uBAAA;EACA,YAAY,uHAAZ;;AAlDN,uBAOE,WAsCE,kBAOE;EACE,kBAAA;EACA,WAAA;EACA,WAAA;EACA,aAAA;EDHJ,SAAA;EACA,WAAW,gBAAX;EAaA,gBAAA;ECRI,uBAAA;;AA3DR,uBAgEE;EACE,iBAAA;EACA,gBAAA;EACA,aAAA;EACA,8BAAA"}
--------------------------------------------------------------------------------
/miniprogram/components/pageScrollMessage/pageScrollMessage.js:
--------------------------------------------------------------------------------
1 | // components/pageScrollMessage.ts
2 | Component({
3 | /**
4 | * 组件的属性列表
5 | */
6 | properties: {
7 |
8 | },
9 |
10 | /**
11 | * 组件的初始数据
12 | */
13 | data: {
14 |
15 | },
16 |
17 | /**
18 | * 组件的方法列表
19 | */
20 | methods: {
21 |
22 | },
23 | lifetimes: {
24 | attached: function () {
25 | this.animate('#text', [
26 | { transform: 'translateX(100%)' },
27 | { transform: 'translateX(-100%)' }
28 | ], 5000)
29 | }
30 | }
31 | })
32 |
33 |
--------------------------------------------------------------------------------
/miniprogram/components/pageScrollMessage/pageScrollMessage.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/miniprogram/components/pageScrollMessage/pageScrollMessage.wxml:
--------------------------------------------------------------------------------
1 |
2 | 制作免冠照片/证件照所上传及生成的图片资源最多保存两小时将被删除,请及时保存结果!
3 |
4 |
--------------------------------------------------------------------------------
/miniprogram/components/pageScrollMessage/pageScrollMessage.wxss:
--------------------------------------------------------------------------------
1 | /* components/pageScrollMessage.wxss */
2 | .container {
3 | width: 100%;
4 | height: 40rpx;
5 | background-color: #DBEDFC;
6 |
7 |
8 | }
9 | .container .msg {
10 | display: block;
11 | width: max-content;
12 | line-height: 40rpx;
13 | font-size: 24rpx;
14 | color: #ee8b8d;
15 | position: relative;
16 | animation: 20s identifier linear infinite normal;
17 | -webkit-animation: 20s identifier linear infinite normal;
18 | word-break: keep-all;
19 | white-space: nowrap;
20 | }
21 |
22 | @keyframes identifier {
23 | 0% {
24 | transform: translateX(100%);
25 | }
26 | 100% {
27 | transform: translateX(-100%);
28 | }
29 | }
30 |
31 | @-webkit-keyframes identifier {
32 | 0% {
33 | -webkit-transform: translateX(100%);
34 | }
35 | 100% {
36 | -webkit-transform: translateX(-100%);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/miniprogram/images/WechatIMG199.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/images/WechatIMG199.jpeg
--------------------------------------------------------------------------------
/miniprogram/images/index-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/images/index-active.png
--------------------------------------------------------------------------------
/miniprogram/images/index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/images/index.png
--------------------------------------------------------------------------------
/miniprogram/images/me-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/images/me-active.png
--------------------------------------------------------------------------------
/miniprogram/images/me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/images/me.png
--------------------------------------------------------------------------------
/miniprogram/images/shareShow.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/images/shareShow.jpg
--------------------------------------------------------------------------------
/miniprogram/images/take.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/images/take.png
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/complete/complete.js:
--------------------------------------------------------------------------------
1 |
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | msg: '',
9 | tempFilePath: '',
10 | url: ''
11 | },
12 |
13 | // 继续制作,返回到选择照片页面
14 | contineu () {
15 | wx.navigateBack()
16 | },
17 |
18 | /**
19 | * 生命周期函数--监听页面加载
20 | */
21 | onLoad: function (options) {
22 | this.setData({
23 | msg: options.msg,
24 | tempFilePath: options.tempFilePath,
25 | url: options.url
26 | })
27 |
28 | wx.showToast({ title: '制作成功', })
29 | },
30 |
31 | // 预览制作出来的照片
32 | preView () {
33 | wx.previewImage({
34 | urls: [this.data.url],
35 | current: this.data.url
36 | })
37 | },
38 |
39 | /**
40 | * 用户点击右上角分享
41 | */
42 | onShareAppMessage: function (res) {
43 | return {
44 | title: '证件照、免冠照、一寸照片、二寸照片、自定义尺寸、证件照换背景,免费生成、下载。',
45 | path: '/pages/index/index',
46 | imageUrl: this.data.tempFilePath
47 | }
48 | }
49 | })
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/complete/complete.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/complete/complete.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{msg}}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | 请在 手机相册 查看下载结果
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/complete/complete.wxss:
--------------------------------------------------------------------------------
1 | .msg {
2 | font-size: 40rpx;
3 | text-align: center;
4 | }
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/editPhotoPlus/editPhotoPlus.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | "color-picker": "/components/color-picker/color-picker",
4 | "page-scroll-message": "/components/pageScrollMessage/pageScrollMessage"
5 | },
6 | "navigationBarTitleText": "生成免冠照",
7 | "disableScroll": true
8 | }
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/editPhotoPlus/editPhotoPlus.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | 先选右侧色系
21 | \n\n
22 | 后选左侧色值
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
41 |
42 |
43 |
53 |
54 |
55 |
65 |
66 |
67 |
68 | 移动人像可调整位置\n点击下一步
69 | 双指可调整人像大小\n点击下一步
70 | 点击右侧换装换发型\n点击下一步
71 |
72 |
73 |
74 | 我知道了
75 |
76 |
77 |
78 | {{videoLoaded ? '看视频 + 1 次' : ''}}\n\n\n\n ← 点击使用精细抠图
79 |
80 | ← 更多次数请联系作者
81 |
82 |
83 |
84 |
85 |
86 |
87 | 换装
88 |
89 |
90 |
91 | 头发
92 |
93 |
94 |
102 |
103 |
104 |
105 | 看视频
106 |
107 |
108 |
109 | 剩{{vipCount}}次
110 |
111 |
112 |
113 | 作者
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | 自定义
124 |
125 |
126 |
127 |
128 | 下载次数已用完。
129 | 点击使用后即可下载
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/editPhotoPlus/editPhotoPlus.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/editPhoto/editPhoto.wxss */
2 | page {
3 | background: linear-gradient(to bottom, rgba(0,191,243,.2), rgba(67,142,219,.2), rgba(255,0,0,.2));
4 | }
5 | .container {
6 | width: 100%;
7 | overflow: hidden;
8 | }
9 |
10 | .tabs {
11 | width: 100%;
12 | height: 100rpx;
13 | background-color: rgba(255,255,255,.2);
14 | display: flex;
15 | flex-direction: row;
16 | }
17 |
18 | .tabs .tab {
19 | width: 50%;
20 | height: 100%;
21 | text-align: center;
22 | }
23 | .tab.tab-active {
24 | color: #3E85EE;
25 | border-bottom: 3px solid #3E85EE;
26 | }
27 | .tabs .tab .name {
28 | font-size: 32rpx;
29 | line-height: 1.5;
30 | }
31 | .tabs .tab .description {
32 | font-size: 24rpx;
33 | }
34 |
35 |
36 | /* 颜色选择 */
37 | .container .colors {
38 | width: 100%;
39 | display: flex;
40 | flex-direction: row;
41 | justify-content: space-around ;
42 | margin-top: 20rpx;
43 | }
44 | .container .colors .color {
45 | width: 15%;
46 | height: 0;
47 | padding-top: 15%;
48 | border: 2px solid #000;
49 | border-radius: 50%;
50 | overflow: hidden;
51 | }
52 | .container .colors .color.active {
53 | border-color: #3E85EE;
54 | }
55 | .container .colors .color.transparent {
56 | background-color: transparent;
57 | position: relative;
58 | }
59 | .container .colors .color.transparent::before {
60 | content: '透明';
61 | position: absolute;
62 | left: 0;
63 | top: 50%;
64 | width: 100%;
65 | text-align: center;
66 | color: #333;
67 | line-height: 1;
68 | height: 1em;
69 | margin-top: -0.5em;
70 | font-size: 14px;
71 | }
72 | .blue {
73 | background-color: rgb(67,142,219);
74 | }
75 | .blue2 {
76 | background-color: rgb(0,191,243);
77 | }
78 | .red {
79 | background-color: red;
80 | }
81 | .white {
82 | background-color: white;
83 | }
84 | .container .colors .color.custom {
85 | padding-top: 0;
86 | height: max-content;
87 | }
88 | .container .colors .color.custom .text {
89 | width: 100%;
90 | padding-top: 50%;
91 | height: 0;
92 | text-align: center;
93 | }
94 | .container .colors .color.custom .text text {
95 | transform: translateY(-100%);
96 | display: block;
97 | font-size: 14px;
98 | }
99 | .container .colors .color .custom-bg {
100 | width: 100%;
101 | height: 0;
102 | padding-top: 50%;
103 | }
104 |
105 | /* color picker */
106 | .color-picker-view {
107 | position: relative;
108 | margin-top: 10px;
109 | width: 100%;
110 | height: 0;
111 | overflow: visible;
112 | z-index: 99;
113 | }
114 | .color-picker-view .color-picker-content {
115 | position: absolute;
116 | left: 0;
117 | top: 0;
118 | width: 100%;
119 | background-color: #fff;
120 | }
121 | .color-picker-view .color-picker-content.hide {
122 | display: none;
123 | }
124 | .color-picker-view .color-picker-content .tips {
125 | position: absolute;
126 | width: 4em;
127 | right: 5px;
128 | top: 30px;
129 | }
130 | .color-picker-view .color-picker-content .current-color {
131 | position: absolute;
132 | width: 4em;
133 | height: 4em;
134 | right: 5px;
135 | bottom: 80px;
136 | }
137 | .color-picker-view .color-picker-content button {
138 | position: absolute;
139 | right: 5px;
140 | bottom: 30px;
141 | }
142 |
143 | /* 尺寸 */
144 | .container .size-picker {
145 | box-sizing: border-box;
146 | width: 100%;
147 | padding: 0 5px;
148 | }
149 |
150 | /* canvas */
151 | .container .pthto-edit-content {
152 | padding: 5px;
153 | width: 100%;
154 | box-sizing: border-box;
155 | }
156 | .container .pthto-edit-content .canvas-view {
157 | position: relative;
158 | width: 100%;
159 | height: 300px;
160 | margin: 0 auto;
161 | /* border: 10rpx solid #fff; */
162 | box-sizing: content-box;
163 | overflow: hidden;
164 | /* box-shadow: 0 5rpx 5rpx 5rpx rgba(255,255,255,.5) inset; */
165 | overflow: hidden;
166 | }
167 | /* .container .pthto-edit-content .canvas-view #myCanvas {
168 | width:100%;
169 | height:100%;
170 | } */
171 | .container .pthto-edit-content .canvas-view .people-photo {
172 | position: absolute;
173 | /* left: 0;
174 | bottom: 0; */
175 | width: 100%;
176 | transform-origin: center center;
177 | }
178 |
179 | .container .pthto-edit-content .canvas-view .guide {
180 | position: absolute;
181 | z-index: 9;
182 | left: 0;
183 | top: 0;
184 | right: 0;
185 | bottom: 0;
186 | background-color: rgba(0,0,0,.5);
187 | /* pointer-events: none; */
188 | }
189 |
190 | .container .pthto-edit-content .canvas-view .guide .guide-know {
191 | position: absolute;
192 | width: 6em;
193 | line-height: 2em;
194 | height: 2em;
195 | left: 0;
196 | top: 0;
197 | right: 0;
198 | bottom: 0;
199 | margin: auto;
200 | border-radius: 5px;
201 | color: #fff;
202 | border: 1px solid #fff;
203 | text-align: center;
204 | }
205 |
206 | .container .pthto-edit-content .canvas-view .guide text {
207 | position: absolute;
208 | top: 10rpx;
209 | left: 0rpx;
210 | right: 0rpx;
211 | /* bottom: 0; */
212 | margin: auto;
213 | color: #fff;
214 | text-align: center;
215 | font-size: 40rpx;
216 | }
217 | .container .pthto-edit-content .canvas-view .guide image {
218 | position: absolute;
219 | width: 200rpx;
220 | left: 0;
221 | top: 0;
222 | right: 0;
223 | bottom: 0;
224 | margin: auto;
225 | }
226 |
227 | .gesture {
228 | width: 100%;
229 | position: relative;
230 | overflow: visible;
231 | z-index: 2;
232 | }
233 |
234 | .gesture .right {
235 | right: 10rpx;
236 | }
237 | .gesture .left {
238 | left: 10rpx;
239 | }
240 |
241 | .gesture .change-clothes {
242 | position: absolute;
243 | bottom: 20rpx;
244 | width: 100rpx;
245 | height: 100rpx;
246 | text-align: center;
247 | }
248 | .gesture .change-hair {
249 | position: absolute;
250 | bottom: 250rpx;
251 | width: 100rpx;
252 | height: 100rpx;
253 | text-align: center;
254 | }
255 | .gesture .crop-image {
256 | position: absolute;
257 | top: -250rpx;
258 | width: 100rpx;
259 | height: 100rpx;
260 | text-align: center;
261 | }
262 | .gesture .look-videw {
263 | position: absolute;
264 | top: -250rpx;
265 | width: 100rpx;
266 | height: 100rpx;
267 | text-align: center;
268 | }
269 | .gesture image {
270 | width: 100%;
271 | }
272 | .gesture text {
273 | font-size: 30rpx;
274 | /* color: #06ae56; */
275 | }
276 |
277 | .result-canvas-view {
278 | max-height: 1px;
279 | overflow: hidden;
280 | }
281 |
282 | .download-view {
283 | width: 100%;
284 | box-sizing: border-box;
285 | padding: 0 20rpx;
286 | margin-top: 50rpx;
287 | }
288 |
289 | .download-view .no-count {
290 | padding: 0 10rpx;
291 | display: flex;
292 | width: 100%;
293 | flex-direction: row;
294 | justify-content: space-around;
295 | }
296 |
297 | .download-view .no-count > button, .download-view .no-count navigator {
298 | width: 45%;
299 | margin: 0;
300 | margin-bottom: 0;
301 | box-sizing: border-box;
302 | }
303 |
304 | .download-view .no-count navigator button {
305 | box-sizing: border-box;
306 | width: 100%;
307 | margin-bottom: 0;
308 | }
309 |
310 | .download-view button {
311 | margin-bottom: 20rpx;
312 | box-shadow: 0 0 10rpx 5rpx rgba(67,142,219,.25);
313 | background-color: #3E85EE !important;
314 | color: #fff !important;
315 | font-weight: normal;
316 | height: 90rpx;
317 | padding: 0;
318 | line-height: 90rpx;
319 | width: 100% !important;
320 | border-radius: 45rpx;
321 | }
322 |
323 |
324 | .style-text {
325 | color: #333333;
326 | font-size: 24rpx !important;
327 | }
328 |
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/editPhotoPlus/hex-rgb.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const hexCharacters = 'a-f\\d';
4 | const match3or4Hex = `#?[${hexCharacters}]{3}[${hexCharacters}]?`;
5 | const match6or8Hex = `#?[${hexCharacters}]{6}([${hexCharacters}]{2})?`;
6 | const nonHexChars = new RegExp(`[^#${hexCharacters}]`, 'gi');
7 | const validHexSize = new RegExp(`^${match3or4Hex}$|^${match6or8Hex}$`, 'i');
8 |
9 | module.exports = (hex, options = {}) => {
10 | if (typeof hex !== 'string' || nonHexChars.test(hex) || !validHexSize.test(hex)) {
11 | throw new TypeError('Expected a valid hex string');
12 | }
13 |
14 | hex = hex.replace(/^#/, '');
15 | let alpha = 1;
16 |
17 | if (hex.length === 8) {
18 | alpha = Number.parseInt(hex.slice(6, 8), 16) / 255;
19 | hex = hex.slice(0, 6);
20 | }
21 |
22 | if (hex.length === 4) {
23 | alpha = Number.parseInt(hex.slice(3, 4).repeat(2), 16) / 255;
24 | hex = hex.slice(0, 3);
25 | }
26 |
27 | if (hex.length === 3) {
28 | hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
29 | }
30 |
31 | const number = Number.parseInt(hex, 16);
32 | const red = number >> 16;
33 | const green = (number >> 8) & 255;
34 | const blue = number & 255;
35 |
36 | if (options.format === 'array') {
37 | return [red, green, blue, alpha];
38 | }
39 |
40 | if (options.format === 'css') {
41 | const alphaString = alpha === 1 ? '' : ` / ${Number((alpha * 100).toFixed(2))}%`;
42 | return `rgb(${red} ${green} ${blue}${alphaString})`;
43 | }
44 |
45 | return {red, green, blue, alpha};
46 | };
47 |
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/editPhotoPlus/imgSecCheck.js:
--------------------------------------------------------------------------------
1 | module.exports = function imgSecCheck (tempFilePath) {
2 | wx.showLoading({ title: '图片安全校验', })
3 | // 获取图片信息
4 | return wx.getImageInfo({ src: tempFilePath, })
5 | // 图片安全校验
6 | .then(res => {
7 | return wx.cloud.callFunction({
8 | name: 'imgSecCheck',
9 | data: {
10 | width: res.width,
11 | height: res.height,
12 | type: res.type,
13 | // 上传图片到临时CDN,返回图片地址
14 | filePath: wx.cloud.CDN({
15 | type: 'filePath',
16 | filePath: res.path,
17 | })
18 | },
19 | })
20 | })
21 | // 图片安全检测结果处理
22 | .then((res) => {
23 | if (res.result.errCode === 0) {
24 | // Object.assign(pageData, {
25 | // originImgPath: res.result.originImgPath,
26 | // originImgType: res.result.originImgType,
27 | // })
28 | // this.baiduKoutu({
29 | // fileID: res.result.fileId,
30 | // filePath: res.result.filePath
31 | // })
32 | return Promise.resolve(res.result)
33 | } else if (res.result.errCode === 87014) {
34 | wx.showToast({ title: '内容可能潜在风险,请重新选择', icon: 'none' })
35 | } else if (res.result.errCode === -604102) {
36 | wx.showToast({ title: '超时,再试一下。或换个图试试', icon: 'none', duration: 3000 })
37 | } else {
38 | wx.showToast({ title: '又是啥问题呀,请重试' + res.result.errCode, icon: 'none' })
39 | }
40 | })
41 | // 错误处理
42 | .catch(console.error)
43 | }
44 |
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/editPhotoPlus/touch.js:
--------------------------------------------------------------------------------
1 | let canOnePointMove = false
2 | let onePoint = {
3 | x: 0,
4 | y: 0
5 | }
6 | // 双指
7 | let twoPoint = {
8 | x1: 0,
9 | y1: 0,
10 | x2: 0,
11 | y2: 0
12 | }
13 | export default {
14 | touchstart: function (e) {
15 | if (e.touches.length < 2) {
16 | canOnePointMove = true
17 | onePoint.x = e.touches[0].pageX * 2
18 | onePoint.y = e.touches[0].pageY * 2
19 | } else {
20 | twoPoint.x1 = e.touches[0].pageX * 2
21 | twoPoint.y1 = e.touches[0].pageY * 2
22 | twoPoint.x2 = e.touches[1].pageX * 2
23 | twoPoint.y2 = e.touches[1].pageY * 2
24 | }
25 | },
26 | touchmove: function (e, oldData) {
27 | if (e.touches.length < 2 && canOnePointMove) {
28 | const onePointDiffX = e.touches[0].pageX * 2 - onePoint.x
29 | const onePointDiffY = e.touches[0].pageY * 2 - onePoint.y
30 | const imgSetData = {
31 | msg: '单点移动',
32 | left: oldData.left + onePointDiffX / 2,
33 | top: oldData.top + onePointDiffY / 2
34 | }
35 | onePoint.x = e.touches[0].pageX * 2
36 | onePoint.y = e.touches[0].pageY * 2
37 | return imgSetData
38 | } else if (e.touches.length > 1) {
39 | const preTwoPoint = JSON.parse(JSON.stringify(twoPoint))
40 | twoPoint.x1 = e.touches[0].pageX * 2
41 | twoPoint.y1 = e.touches[0].pageY * 2
42 | twoPoint.x2 = e.touches[1].pageX * 2
43 | twoPoint.y2 = e.touches[1].pageY * 2
44 | // 计算角度,旋转(优先)
45 | const perAngle = Math.atan((preTwoPoint.y1 - preTwoPoint.y2) / (preTwoPoint.x1 - preTwoPoint.x2)) * 180 / Math.PI
46 | const curAngle = Math.atan((twoPoint.y1 - twoPoint.y2) / (twoPoint.x1 - twoPoint.x2)) * 180 / Math.PI
47 | if (Math.abs(perAngle - curAngle) > 1) {
48 | // 旋转
49 | } else {
50 | // 计算距离,缩放
51 | var preDistance = Math.sqrt(Math.pow((preTwoPoint.x1 - preTwoPoint.x2), 2) + Math.pow((preTwoPoint.y1 - preTwoPoint.y2), 2))
52 | var curDistance = Math.sqrt(Math.pow((twoPoint.x1 - twoPoint.x2), 2) + Math.pow((twoPoint.y1 - twoPoint.y2), 2))
53 | const imgSetData = {
54 | msg: '缩放',
55 | scale: Math.max(oldData.scale + (curDistance - preDistance) * 0.005, 0.5)
56 | }
57 | return imgSetData
58 | }
59 | }
60 | },
61 | touchend: function (e) {
62 | canOnePointMove = false
63 | },
64 | }
65 |
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/hair/hair.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/editPhoto/imageStyle/imageStyle.js
2 | // 在页面中定义激励视频广告
3 | let videoAd = null
4 | // 在页面中定义插屏广告
5 | let interstitialAd = null
6 | let imgUrl = ''
7 | const allHair = {}
8 | Page({
9 |
10 | /**
11 | * 页面的初始数据
12 | */
13 | data: {
14 | TabCur: 0,
15 | videoLoaded: false,
16 | imgList: {
17 | nan: [],
18 | nv: []
19 | }
20 | },
21 |
22 | // 切换男女
23 | tabSelect(e) {
24 | this.setData({
25 | TabCur: e.currentTarget.dataset.id,
26 | scrollLeft: (e.currentTarget.dataset.id - 1) * 60
27 | })
28 | },
29 |
30 | // 选择发型,开始看视频
31 | selectImg (e) {
32 | imgUrl = e.currentTarget.dataset.url
33 | // 用户触发广告后,显示激励视频广告
34 | if (videoAd) {
35 | videoAd.show().catch(() => {
36 | // 失败重试
37 | videoAd.load()
38 | .then(() => videoAd.show())
39 | .catch(err => {
40 | console.log('激励视频 广告显示失败')
41 | })
42 | })
43 | } else {
44 | back()
45 | }
46 | },
47 |
48 | // 返回页面,传递图片地址
49 | back () {
50 | const eventChannel = this.getOpenerEventChannel()
51 | eventChannel.emit('selectHair', {imgUrl});
52 | wx.navigateBack({})
53 | },
54 |
55 | // 获取发型列表
56 | async getData () {
57 | wx.showLoading({ title: '稍等片刻...', })
58 | const { result } = await wx.cloud.callFunction({
59 | name: 'getHairs',
60 | })
61 | Object.assign(allHair, result.hairs)
62 | this.setData({
63 | imgList: {
64 | nan: allHair.nan.slice(0, 6),
65 | nv: allHair.nv.slice(0, 6),
66 | }
67 | })
68 | wx.hideLoading()
69 | },
70 |
71 | /**
72 | * 生命周期函数--监听页面加载
73 | */
74 | onLoad: function (options) {
75 | wx.setNavigationBarTitle({ title: '免冠照发型' })
76 | this.getData()
77 |
78 | // 在页面onLoad回调事件中创建激励视频广告实例
79 | if (wx.createRewardedVideoAd) {
80 | videoAd = wx.createRewardedVideoAd({
81 | adUnitId: 'adunit-240d1c7fb731d343'
82 | })
83 | videoAd.onLoad(() => {
84 | this.setData({
85 | videoLoaded: true
86 | })
87 | })
88 | videoAd.onError((err) => {
89 | this.setData({
90 | videoLoaded: false
91 | })
92 | })
93 | videoAd.onClose((res) => {
94 | console.log(res)
95 | if (res && res.isEnded) {
96 | if(imgUrl) this.back()
97 | } else {
98 | wx.showToast({
99 | title: '看完才可以使用哦',
100 | icon: 'none'
101 | })
102 | }
103 | })
104 | }
105 |
106 | // 在页面onLoad回调事件中创建插屏广告实例
107 | if (wx.createInterstitialAd) {
108 | interstitialAd = wx.createInterstitialAd({
109 | adUnitId: 'adunit-71fe77c8c4d0e3ca'
110 | })
111 | interstitialAd.onLoad(() => {})
112 | interstitialAd.onError((err) => {})
113 | interstitialAd.onClose(() => {})
114 | }
115 | },
116 |
117 | /**
118 | * 生命周期函数--监听页面初次渲染完成
119 | */
120 | onReady: function () {
121 |
122 | },
123 |
124 | /**
125 | * 生命周期函数--监听页面显示
126 | */
127 | onShow: function () {
128 | // 在适合的场景显示插屏广告
129 | if (interstitialAd) {
130 | interstitialAd.show().catch((err) => {
131 | console.error(err)
132 | })
133 | }
134 | },
135 |
136 | // 触底加载
137 | onReachBottom() {
138 | const key = ['nv', 'nan'][this.data.TabCur]
139 | if (this.data.imgList[key].length === allHair[key].length) return
140 | this.setData({
141 | imgList: {
142 | ...this.data.imgList,
143 | [key]: allHair[key].slice(0, this.data.imgList[key].length + 6)
144 | }
145 | })
146 | }
147 | })
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/hair/hair.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/hair/hair.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{item}}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | 看视频后使用
16 |
17 |
18 |
19 |
20 |
21 | 看视频后使用
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/hair/hair.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/editPhoto/imageStyle/imageStyle.wxss */
2 | .scroll-height {
3 | padding: 10rpx;
4 | overflow: auto;
5 | -webkit-overflow-scrolling: touch;
6 | }
7 |
8 | .scroll-height .img-list {
9 | display: flex;
10 | flex-direction: row;
11 | flex-wrap: wrap;
12 | justify-content: space-between;
13 | }
14 |
15 | .scroll-height .img-view {
16 | width: 49%;
17 | padding: 24.5% 0;
18 | box-sizing: border-box;
19 | background-color: rgba(255, 255, 255, .5);
20 | margin-bottom: 2%;
21 | position: relative;
22 | /* background-size: 90%;
23 | background-repeat: no-repeat;
24 | background-position: center; */
25 | /* background-origin: center; */
26 | }
27 | .scroll-height .img-view image {
28 | position: absolute;
29 | width: 90%;
30 | height: 90%;
31 | left: 0;
32 | top: 0;
33 | right: 0;
34 | bottom: 0;
35 | margin: auto;
36 | }
37 |
38 | .scroll-height .img-view .msg {
39 | position: absolute;
40 | background-color: rgba(255, 255, 255, .8);
41 | line-height: 2;
42 | height: 2em;
43 | width: 100%;
44 | left: 0;
45 | right: 0;
46 | bottom: 0;
47 | }
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/imageStyle/imageStyle.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/editPhoto/imageStyle/imageStyle.js
2 | // 在页面中定义激励视频广告
3 | let videoAd = null
4 | // 在页面中定义插屏广告
5 | let interstitialAd = null
6 | let imgUrl = ''
7 | const allClothes = {}
8 | Page({
9 |
10 | /**
11 | * 页面的初始数据
12 | */
13 | data: {
14 | TabCur: 0,
15 | videoLoaded: false,
16 | imgList: {
17 | nan: [],
18 | nv: [],
19 | other: []
20 | }
21 | },
22 |
23 | tabSelect(e) {
24 | this.setData({
25 | TabCur: e.currentTarget.dataset.id,
26 | scrollLeft: (e.currentTarget.dataset.id-1)*60
27 | })
28 | },
29 |
30 | selectImg (e) {
31 | imgUrl = e.currentTarget.dataset.url
32 |
33 | // 用户触发广告后,显示激励视频广告
34 | if (videoAd) {
35 | videoAd.show().catch(() => {
36 | // 失败重试
37 | videoAd.load()
38 | .then(() => videoAd.show())
39 | .catch(err => {
40 | console.log('激励视频 广告显示失败')
41 | })
42 | })
43 | } else {
44 | back()
45 | }
46 |
47 | },
48 |
49 | back () {
50 | const eventChannel = this.getOpenerEventChannel()
51 | eventChannel.emit('selectClothes', {imgUrl});
52 | wx.navigateBack({})
53 | },
54 |
55 | async getData () {
56 | wx.showLoading({
57 | title: '稍等片刻...',
58 | })
59 | const { result } = await wx.cloud.callFunction({
60 | name: 'getClothes',
61 | })
62 | Object.assign(allClothes, result.clothes)
63 | this.setData({
64 | imgList: {
65 | nan: allClothes.nan.slice(0, 6),
66 | nv: allClothes.nv.slice(0, 6),
67 | other: allClothes.other.slice(0, 6)
68 | }
69 | })
70 | wx.hideLoading()
71 | },
72 |
73 | /**
74 | * 生命周期函数--监听页面加载
75 | */
76 | onLoad: function (options) {
77 | wx.setNavigationBarTitle({ title: '免冠照/证件照换装' })
78 | this.getData()
79 |
80 | // 在页面onLoad回调事件中创建激励视频广告实例
81 | if (wx.createRewardedVideoAd) {
82 | videoAd = wx.createRewardedVideoAd({
83 | adUnitId: 'adunit-240d1c7fb731d343'
84 | })
85 | videoAd.onLoad(() => {
86 | this.setData({
87 | videoLoaded: true
88 | })
89 | })
90 | videoAd.onError((err) => {
91 | this.setData({
92 | videoLoaded: false
93 | })
94 | })
95 | videoAd.onClose((res) => {
96 | console.log(res)
97 | if (res && res.isEnded) {
98 | if(imgUrl) this.back()
99 | } else {
100 | wx.showToast({
101 | title: '看完才可以使用哦',
102 | icon: 'none'
103 | })
104 | }
105 | })
106 | }
107 |
108 | // 在页面onLoad回调事件中创建插屏广告实例
109 | if (wx.createInterstitialAd) {
110 | interstitialAd = wx.createInterstitialAd({
111 | adUnitId: 'adunit-ef203d1fea23c207'
112 | })
113 | interstitialAd.onLoad(() => {})
114 | interstitialAd.onError((err) => {})
115 | interstitialAd.onClose(() => {})
116 | }
117 | },
118 |
119 | /**
120 | * 生命周期函数--监听页面初次渲染完成
121 | */
122 | onReady: function () {
123 |
124 | },
125 |
126 | /**
127 | * 生命周期函数--监听页面显示
128 | */
129 | onShow: function () {
130 |
131 | // 在适合的场景显示插屏广告
132 | if (interstitialAd) {
133 | interstitialAd.show().catch((err) => {
134 | console.error(err)
135 | })
136 | }
137 | },
138 |
139 | // 触底加载
140 | onReachBottom() {
141 | const key = ['nv', 'nan', 'other'][this.data.TabCur]
142 | if (this.data.imgList[key].length === allClothes[key].length) return
143 | this.setData({
144 | imgList: {
145 | ...this.data.imgList,
146 | [key]: allClothes[key].slice(0, this.data.imgList[key].length + 6)
147 | }
148 | })
149 | }
150 |
151 | })
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/imageStyle/imageStyle.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/imageStyle/imageStyle.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{item}}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | 看视频后使用
17 |
18 |
19 |
20 |
21 |
22 | 看视频后使用
23 |
24 |
25 |
26 |
27 |
28 | 看视频后使用
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/imageStyle/imageStyle.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/editPhoto/imageStyle/imageStyle.wxss */
2 | .scroll-height {
3 | padding: 10rpx;
4 | overflow: auto;
5 | -webkit-overflow-scrolling: touch;
6 | }
7 |
8 | .scroll-height .img-list {
9 | display: flex;
10 | flex-direction: row;
11 | flex-wrap: wrap;
12 | justify-content: space-between;
13 | }
14 |
15 | .scroll-height .img-view {
16 | width: 49%;
17 | padding: 24.5% 0;
18 | box-sizing: border-box;
19 | background-color: rgba(255, 255, 255, .5);
20 | margin-bottom: 2%;
21 | position: relative;
22 | /* background-size: 90%;
23 | background-repeat: no-repeat;
24 | background-position: center; */
25 | /* background-origin: center; */
26 | }
27 | .scroll-height .img-view image {
28 | position: absolute;
29 | width: 90%;
30 | height: 90%;
31 | left: 0;
32 | top: 0;
33 | right: 0;
34 | bottom: 0;
35 | margin: auto;
36 | }
37 |
38 | .scroll-height .img-view .msg {
39 | position: absolute;
40 | background-color: rgba(255, 255, 255, .8);
41 | line-height: 2;
42 | height: 2em;
43 | width: 100%;
44 | left: 0;
45 | right: 0;
46 | bottom: 0;
47 | }
48 |
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/images/acl8s-bu9e0-016_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/editPhoto/images/acl8s-bu9e0-016_s.png
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/images/ahvga-47qgd-003_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/editPhoto/images/ahvga-47qgd-003_s.png
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/images/author.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/editPhoto/images/author.png
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/images/click-white-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/editPhoto/images/click-white-left.png
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/images/click-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/editPhoto/images/click-white.png
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/images/crop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/editPhoto/images/crop.png
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/images/look-video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/editPhoto/images/look-video.png
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/images/move-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/editPhoto/images/move-white.png
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/images/use.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/editPhoto/images/use.png
--------------------------------------------------------------------------------
/miniprogram/pages/editPhoto/images/zoom-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/editPhoto/images/zoom-white.png
--------------------------------------------------------------------------------
/miniprogram/pages/helpMake/helpMake.js:
--------------------------------------------------------------------------------
1 | // 在页面中定义插屏广告
2 | let interstitialAd = null
3 | const app = getApp()
4 | Page({
5 |
6 | onLoad () {
7 | // 在页面onLoad回调事件中创建插屏广告实例
8 | if (wx.createInterstitialAd) {
9 | interstitialAd = wx.createInterstitialAd({
10 | adUnitId: 'adunit-7bd4afc44e5cebbd'
11 | })
12 | interstitialAd.onLoad(() => {})
13 | interstitialAd.onError((err) => {})
14 | interstitialAd.onClose(() => {})
15 | }
16 | },
17 |
18 | onShow () {
19 | // 在适合的场景显示插屏广告
20 | if (interstitialAd) {
21 | interstitialAd.show().catch((err) => {
22 | console.error(err)
23 | })
24 | }
25 | },
26 |
27 | // 主动下发客服消息
28 | sendGroupQRCode () {
29 | wx.cloud.callFunction({
30 | name: 'customerService'
31 | })
32 | },
33 |
34 | /**
35 | * 用户点击右上角分享
36 | */
37 | onShareAppMessage: function () {
38 | return {
39 | title: '点这个帮我做张免冠照片吧。谢谢!',
40 | path: '/pages/index/index',
41 | imageUrl: '/shareShow.jpg'
42 | }
43 | },
44 |
45 | onShareTimeline: function () {
46 | return {
47 | title: '谁帮我制作个免冠照?点这个,谢谢。',
48 | // path: '/pages/index/index',
49 | imageUrl: '/shareShow.jpg'
50 | }
51 | },
52 | })
--------------------------------------------------------------------------------
/miniprogram/pages/helpMake/helpMake.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "帮制作",
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/miniprogram/pages/helpMake/helpMake.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | 因微信版本、手机系统等原因,部分用户无法正常操作、无法成功下载图片。
17 |
18 |
19 |
20 |
21 |
22 | 操作繁琐,不够简易,提示不明确等。
23 |
24 |
25 |
26 |
27 |
28 | 虽然作者尽可能的解决以上问题,但作者一人之力,时间精力经费有限。
29 |
30 |
31 |
32 |
33 |
34 | 为了您能成功生成想要的免冠照/证件照,您可以选择找朋友帮忙制作,或联系客服帮制作。
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/miniprogram/pages/helpMake/helpMake.wxss:
--------------------------------------------------------------------------------
1 | image {
2 | width: 80vw;
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/imgCompose/compose.js:
--------------------------------------------------------------------------------
1 | Page({
2 |
3 | /**
4 | * 页面的初始数据
5 | */
6 | data: {
7 | imageSrc: '',
8 | },
9 |
10 | /**
11 | * 生命周期函数--监听页面加载
12 | */
13 | onLoad() {
14 |
15 | },
16 |
17 | /**
18 | * 生命周期函数--监听页面初次渲染完成
19 | */
20 | onReady() {
21 |
22 | },
23 |
24 | /**
25 | * 生命周期函数--监听页面显示
26 | */
27 | onShow() {
28 |
29 | },
30 |
31 | /**
32 | * 生命周期函数--监听页面隐藏
33 | */
34 | onHide() {
35 |
36 | },
37 |
38 | /**
39 | * 生命周期函数--监听页面卸载
40 | */
41 | onUnload() {
42 |
43 | },
44 |
45 | /**
46 | * 页面相关事件处理函数--监听用户下拉动作
47 | */
48 | onPullDownRefresh() {
49 |
50 | },
51 |
52 | /**
53 | * 页面上拉触底事件的处理函数
54 | */
55 | onReachBottom() {
56 |
57 | },
58 |
59 | /**
60 | * 用户点击右上角分享
61 | */
62 | onShareAppMessage() {
63 |
64 | },
65 | preView (event) {
66 | wx.previewImage({
67 | urls: [this.data.imageSrc],
68 | current: this.data.imageSrc
69 | })
70 | },
71 | // 下载
72 | downloadClick() {
73 | if (!this.data.imageSrc) {
74 | wx.showToast({
75 | title: '请上传图片',
76 | icon: 'none',
77 | duration: 3000
78 | })
79 | } else {
80 | console.log(this.data.imageSrc);
81 | var url = this.data.imageSrc;
82 | wx.downloadFile({
83 | url: url,
84 | success: function (res) {
85 | console.log(res);
86 | //图片保存到本地
87 | wx.saveImageToPhotosAlbum({
88 | filePath: res.tempFilePath,
89 | success: function (data) {
90 | wx.showToast({
91 | title: '保存成功',
92 | icon: 'success',
93 | duration: 3000
94 | })
95 | setTimeout(() => {
96 | wx.navigateBack();
97 | }, 3000)
98 | },
99 | fail: function (err) {
100 | console.log(err);
101 | if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
102 | console.log("当初用户拒绝,再次发起授权")
103 | wx.openSetting({
104 | success(settingdata) {
105 | console.log(settingdata)
106 | if (settingdata.authSetting['scope.writePhotosAlbum']) {
107 | console.log('获取权限成功,给出再次点击图片保存到相册的提示。')
108 | } else {
109 | console.log('获取权限失败,给出不给权限就无法正常使用的提示')
110 | }
111 | }
112 | })
113 | }
114 | },
115 | complete(res) {
116 | console.log(res);
117 | }
118 | })
119 | }
120 | })
121 | }
122 |
123 | },
124 | //选图片
125 | choosePic() {
126 | if (this.data.imageSrc) {
127 | return this.preView()
128 | }
129 | console.log('选图片')
130 | wx.chooseMedia({
131 | count: 1,
132 | mediaType: ['image'],
133 | sizeType: ['compressed'],
134 | success: (res) => {
135 | const tempFilePath = res.tempFiles[0].tempFilePath
136 | this.uploadImg(tempFilePath)
137 | },
138 | fail() {
139 | wx.showToast({
140 | title: '取消选择',
141 | icon: 'none',
142 | duration: 2000
143 | })
144 | }
145 | })
146 | },
147 | uploadImg(tempFilePath) {
148 | console.log(tempFilePath)
149 | wx.showLoading({
150 | title: '图片安全校验',
151 | })
152 | // 获取图片信息
153 | wx.getImageInfo({
154 | src: tempFilePath,
155 | })
156 | // 图片安全校验
157 | .then(res => {
158 | return wx.cloud.callFunction({
159 | name: 'printStyle',
160 | data: {
161 | width: res.width,
162 | height: res.height,
163 | type: res.type,
164 | // 上传图片到临时CDN,返回图片地址
165 | filePath: wx.cloud.CDN({
166 | type: 'filePath',
167 | filePath: res.path,
168 | })
169 | },
170 | })
171 | }).then((res) => {
172 | console.log('返回值', res)
173 | wx.hideLoading()
174 | if (!res.result.errMsg) {
175 | this.setData({
176 | imageSrc: res.result
177 | })
178 | } else {
179 | wx.showToast({
180 | title: res.result.errMsg,
181 | icon: 'none',
182 | duration: 3000
183 | })
184 | }
185 |
186 | }) // 错误处理
187 | .catch(console.error)
188 | }
189 | })
--------------------------------------------------------------------------------
/miniprogram/pages/imgCompose/compose.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "图片排版",
3 | "usingComponents": {
4 | "page-scroll-message": "/components/pageScrollMessage/pageScrollMessage"
5 | }
6 | }
--------------------------------------------------------------------------------
/miniprogram/pages/imgCompose/compose.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 上传照片
4 |
5 |
6 | 排版尺寸为常用6寸,建议原图为一寸/二寸照片
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/miniprogram/pages/imgCompose/compose.wxss:
--------------------------------------------------------------------------------
1 | /* pages/imgCompose/compose.wxss */
2 | /* pages/imgZip/imgZip.wxss */
3 | .container {
4 | width: 100%;
5 | height: 100vh;
6 | background-color: #fff;
7 | /* overflow: hidden; */
8 | }
9 | .backView{
10 | margin-top: 30rpx;
11 | width: 85%;
12 | height: 700rpx;
13 | /* background-color: #999999; */
14 | border: 1px solid #eee;
15 | border-radius: 4px;
16 | display: flex;
17 | justify-content: center;
18 | align-items: center;
19 | }
20 | .zipBtn{
21 | background-color: #3E85EE;
22 | margin-top: 20px;
23 | color: white;
24 | width: 90%;
25 | }
--------------------------------------------------------------------------------
/miniprogram/pages/imgZip/image/choosePic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/imgZip/image/choosePic.png
--------------------------------------------------------------------------------
/miniprogram/pages/imgZip/imgZip.js:
--------------------------------------------------------------------------------
1 | // pages/imgZip/imgZip.ts
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | imgType: '',
9 | realW: 0,
10 | realH: 0,
11 | size: 0,
12 | imageSrc: '',
13 | imgW: '',
14 | imgH: '',
15 | quality: ''
16 | },
17 |
18 | /**
19 | * 生命周期函数--监听页面加载
20 | */
21 | onLoad() {
22 |
23 | },
24 |
25 | /**
26 | * 生命周期函数--监听页面初次渲染完成
27 | */
28 | onReady() {
29 |
30 | },
31 |
32 | /**
33 | * 生命周期函数--监听页面显示
34 | */
35 | onShow() {
36 |
37 | },
38 |
39 | /**
40 | * 生命周期函数--监听页面隐藏
41 | */
42 | onHide() {
43 |
44 | },
45 |
46 | /**
47 | * 生命周期函数--监听页面卸载
48 | */
49 | onUnload() {
50 |
51 | },
52 |
53 | /**
54 | * 页面相关事件处理函数--监听用户下拉动作
55 | */
56 | onPullDownRefresh() {
57 |
58 | },
59 |
60 | /**
61 | * 页面上拉触底事件的处理函数
62 | */
63 | onReachBottom() {
64 |
65 | },
66 |
67 | /**
68 | * 用户点击右上角分享
69 | */
70 | onShareAppMessage() {
71 |
72 | },
73 | imgWidth: function (e) {
74 | const {
75 | imageSrc
76 | } = this.data
77 | let msg = ''
78 | if (imageSrc === '') {
79 | msg = '请上传图片'
80 | wx.showToast({
81 | title: msg,
82 | icon: 'none'
83 | })
84 | this.setData({
85 | imgW: '',
86 | })
87 | } else {
88 | const zsw = this.data.realW;
89 | const zsh = this.data.realH;
90 | const w = e.detail.value;
91 | const h = parseFloat((w * zsh / zsw * 100) / 100).toFixed(2);
92 | console.log(h, '--', zsw, '-', zsh);
93 | this.setData({
94 | imgW: w,
95 | imgH: w > 0 ? h : '',
96 | })
97 | }
98 |
99 | },
100 | imgHeight: function (e) {
101 | const {
102 | imageSrc
103 | } = this.data
104 | let msg = ''
105 | if (imageSrc === '') {
106 | msg = '请上传图片'
107 | wx.showToast({
108 | title: msg,
109 | icon: 'none'
110 | })
111 | this.setData({
112 | imgH: '',
113 | })
114 | } else {
115 | const zsw = this.data.realW;
116 | const zsh = this.data.realH;
117 | const h = e.detail.value;
118 | const w = parseFloat((h * zsw / zsh * 100) / 100).toFixed(2);
119 | console.log(h);
120 | this.setData({
121 | imgW: h > 0 ? w : '',
122 | imgH: h,
123 | })
124 | }
125 |
126 | },
127 | imgQuality: function (e) {
128 | const {
129 | imageSrc
130 | } = this.data
131 | let msg = ''
132 | if (imageSrc === '') {
133 | msg = '请上传图片'
134 | wx.showToast({
135 | title: msg,
136 | icon: 'none'
137 | })
138 | this.setData({
139 | quality: '',
140 | })
141 | } else {
142 | const q = e.detail.value;
143 | this.setData({
144 | quality: q == 0 ? '' : q
145 | })
146 | }
147 |
148 | },
149 | zipClick() {
150 | const {
151 | imgW,
152 | imgH,
153 | quality,
154 | imageSrc
155 | } = this.data
156 | let msg = ''
157 | if (imageSrc === '') {
158 | msg = '请上传图片'
159 | wx.showToast({
160 | title: msg,
161 | icon: 'none'
162 | })
163 | return
164 | }
165 | console.log('请上传图片', imageSrc)
166 | if (this.data.imgW == 0 || this.data.imgH == 0 || !this.data.imgH || !this.data.imgW) {
167 | msg = '宽度或高度不能为0'
168 | wx.showToast({
169 | title: msg,
170 | icon: 'none'
171 | })
172 | return
173 | }
174 | console.log('压缩质量', quality)
175 | if (this.data.quality > 100 || this.data.quality < 50) {
176 | msg = '压缩质量范围是50-100'
177 | wx.showToast({
178 | title: msg,
179 | icon: 'none'
180 | })
181 | return
182 | }
183 | wx.showLoading({
184 | title: '图片压缩中',
185 | })
186 | wx.cloud.callFunction({
187 | name: 'imagemin',
188 | data: {
189 | width: this.data.imgW,
190 | height: this.data.imgH,
191 | type: this.data.type,
192 | quality: this.data.quality,
193 | // 上传图片到临时CDN,返回图片地址
194 | filePath: wx.cloud.CDN({
195 | type: 'filePath',
196 | filePath: this.data.imageSrc,
197 | })
198 | },
199 | }).then((res) => {
200 | console.log('返回值', res)
201 | wx.hideLoading()
202 | if (!res.result.errMsg) {
203 | wx.navigateTo({
204 | url: '/pages/zipSuccess/zipSuccess?imgurl=' + res.result,
205 | })
206 | } else {
207 | wx.showToast({
208 | title: res.result.errMsg,
209 | icon: 'none',
210 | duration: 3000
211 | })
212 | }
213 | }) // 错误处理
214 | .catch(console.error)
215 |
216 |
217 | },
218 | choosePic() {
219 | console.log('选图片')
220 | wx.chooseMedia({
221 | count: 1,
222 | mediaType: ['image'],
223 | sizeType: ['compressed'],
224 | success: (res) => {
225 | const tempFilePath = res.tempFiles[0].tempFilePath
226 | this.setData({
227 | imageSrc: tempFilePath
228 | })
229 | console.log(this.data.imageSrc)
230 | const fs = wx.getFileSystemManager()
231 | fs.getFileInfo({
232 | filePath: tempFilePath,
233 | success: (res) => {
234 | this.setData({
235 | size: (res.size / 1024).toFixed(2)
236 | })
237 | }
238 | })
239 | // 获取图片信息
240 | wx.getImageInfo({
241 | src: tempFilePath,
242 | })
243 | // 图片安全校验
244 | .then(res => {
245 | this.setData({
246 | imgType: res.type,
247 | realW: res.width,
248 | realH: res.height,
249 | imgW: res.width,
250 | imgH: res.height
251 | })
252 | console.log(res, this.data.realW, '----', this.data.realH)
253 | })
254 | },
255 | fail() {
256 | wx.showToast({
257 | title: '取消选择',
258 | icon: 'none',
259 | duration: 2000
260 | })
261 | }
262 | })
263 | }
264 | })
--------------------------------------------------------------------------------
/miniprogram/pages/imgZip/imgZip.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "图片压缩",
3 | "usingComponents": {
4 | "page-scroll-message": "/components/pageScrollMessage/pageScrollMessage"
5 | }
6 | }
--------------------------------------------------------------------------------
/miniprogram/pages/imgZip/imgZip.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 上传图片
7 |
8 |
9 | 压缩前图片宽{{realW}}px,高{{realH}}px,占用空间{{size}}kb
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/miniprogram/pages/imgZip/imgZip.wxss:
--------------------------------------------------------------------------------
1 | /* pages/imgZip/imgZip.wxss */
2 | .container {
3 | width: 100%;
4 | height: 100vh;
5 | background-color: #fff;
6 | /* overflow: hidden; */
7 | }
8 | .backView{
9 | margin-top: 30rpx;
10 | width: 85%;
11 | height: 700rpx;
12 | /* background-color: #eee; */
13 | border: 1px solid #eee;
14 | border-radius: 4px;
15 | display: flex;
16 | justify-content: center;
17 | align-items: center;
18 | margin-bottom: 30rpx;
19 | }
20 | .backView image {
21 | width: 100%;
22 | height: 100%;
23 | max-width: 100%;
24 | max-height: 100%;
25 | }
26 |
27 | .setZipView{
28 | width: 90%;
29 | padding: 20rpx;
30 | display:flex;
31 | align-items:center;
32 | }
33 | .setZipView label {
34 | color: #999999;
35 | }
36 | input{
37 | display:inline-block;
38 | width: 60px;
39 | height: 24px;
40 | padding: 0 5px;
41 | line-height:30px;
42 | border: 1px solid #999999;
43 | border-radius: 5px;
44 | /* position: absolute;
45 | top: 50%;
46 | transform: translateY(-50%); */
47 | }
48 | .zipBtn{
49 | background-color: #3E85EE;
50 | margin-top: 20px;
51 | color: white;
52 | flex: 1;
53 | }
--------------------------------------------------------------------------------
/miniprogram/pages/index/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/.DS_Store
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/3001677327372_.pic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/3001677327372_.pic.jpg
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/custom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/custom.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/home_icon0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/home_icon0.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/home_icon1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/home_icon1.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/home_icon2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/home_icon2.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/home_icon3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/home_icon3.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/home_icon4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/home_icon4.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/home_icon5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/home_icon5.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/home_icon6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/home_icon6.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/home_icon7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/home_icon7.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/hot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/hot.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/icon-more.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/icon-more.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/icon-size1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/icon-size1.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/icon-size2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/icon-size2.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/search-input.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/search-input.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/space-img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/space-img.png
--------------------------------------------------------------------------------
/miniprogram/pages/index/images/微信图片_20200712103220.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/index/images/微信图片_20200712103220.jpg
--------------------------------------------------------------------------------
/miniprogram/pages/index/index.js:
--------------------------------------------------------------------------------
1 | const app = getApp()
2 |
3 | Page({
4 |
5 | /**
6 | * 页面的初始数据
7 | */
8 | data: {
9 | // 近期热门列表
10 | photoSizeList: app.globalData.photoSizeList
11 | },
12 |
13 | /**
14 | * 生命周期函数--监听页面加载
15 | */
16 | onLoad: function (options) {
17 | wx.setNavigationBarTitle({ title: '免冠照/证件照' })
18 | // 来自邀请,签到时使用
19 | if (options.shareOpenid) {
20 | wx.setStorage({
21 | key: "fromShare",
22 | data: options.shareOpenid
23 | })
24 | }
25 | },
26 |
27 | //跳转分类页面
28 | goClassPage(e) {
29 | wx.navigateTo({
30 | url: '/pages/searchSize/searchSize?index=' + e.currentTarget.dataset.index,
31 | })
32 | },
33 |
34 | // 去选择照片页面
35 | goNextPage (e) {
36 | wx.navigateTo({
37 | url: '/pages/preEdit/preEdit?index=' + e.currentTarget.dataset.index,
38 | })
39 | },
40 |
41 | // 页面跳转
42 | navigateTo(e) {
43 | wx.navigateTo({ url: e.currentTarget.dataset.url, })
44 | },
45 |
46 | /**
47 | * 用户点击右上角分享
48 | */
49 | onShareAppMessage: function () {
50 | return {
51 | title: '证件照、免冠照、一寸照片、二寸照片、证件照换背景,免费生成、下载。',
52 | path: '/pages/index/index',
53 | imageUrl: '/shareShow.jpg'
54 | }
55 | },
56 | onShareTimeline: function () {
57 | return {
58 | title: '证件照、免冠照、一寸照片、二寸照片、证件照换背景,免费生成、下载。',
59 | imageUrl: '/shareShow.jpg'
60 | }
61 | },
62 |
63 | })
--------------------------------------------------------------------------------
/miniprogram/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "免冠照/证件照",
3 | "usingComponents": {
4 | "page-scroll-message": "/components/pageScrollMessage/pageScrollMessage"
5 | }
6 | }
--------------------------------------------------------------------------------
/miniprogram/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 | 点击“
3 |
4 | ”添加到我的小程序我知道了
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
19 |
20 |
21 |
22 | 一键P图
23 |
24 | 背景图片随意换
25 |
26 |
27 |
28 |
29 |
30 |
37 |
38 |
39 |
40 | 下载
41 |
42 | 好看的风景、美女、手机壁纸、电脑壁纸
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | 搜索:如“一寸”
52 |
53 |
54 |
55 |
56 |
57 |
58 | 常用尺寸
59 |
60 |
61 |
62 | 职业资格
63 |
64 |
65 |
66 | 公务员
67 |
68 |
69 |
70 | 学历语言
71 |
72 |
76 |
77 |
78 |
79 |
80 |
81 | 图片压缩
82 |
83 |
84 |
85 | 自定尺寸
86 |
87 |
88 |
89 |
90 | 打印排版
91 |
92 |
93 |
94 | 更多
95 |
96 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
112 |
115 |
116 |
120 | {{ item.name }}
121 | {{ item.px }} | {{ item.size }}
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/miniprogram/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/index/index.wxss */
2 | .container {
3 | background-color: #fff;
4 | position: relative;
5 | box-sizing: border-box;
6 | width: 100vw;
7 | /* height: 100vh; */
8 | display: flex;
9 | flex-direction: column;
10 | overflow-x: hidden;
11 | }
12 |
13 | swiper {
14 | width: 100%;
15 | height: 300rpx;
16 | }
17 | swiper-item {
18 | width: 100%;
19 | height: 100%;
20 | }
21 | swiper-item .swiper-item {
22 | /* background-color: pink; */
23 | width: 100%;
24 | height: 100%;
25 | display: block;
26 | }
27 |
28 |
29 | /* 人像抠图 */
30 | .img-p {
31 | background-color: #fff;
32 | position: relative;
33 | width: 100%;
34 | height: 100%;
35 | }
36 | .img-p image {
37 | width: 100%;
38 | height: 100%;
39 | }
40 | .img-p .msg {
41 | position: absolute;
42 | left: 30rpx;
43 | bottom: 0rpx;
44 | /* color: #fff; */
45 | font-size: 40rpx;
46 | line-height: 2;
47 | }
48 | .img-p .msg .sub-title {
49 | font-size: 30rpx;
50 | }
51 |
52 | .search-view {
53 | /* box-sizing: border-box; */
54 | padding-left: 30rpx;
55 | color: #999999;
56 | margin: 30rpx;
57 | width: 90%;
58 | height: 35px;
59 | padding: 15rpx;
60 | border: 1px solid #3E85EE;
61 | border-radius: 5px
62 |
63 | }
64 | /* .search-view label {
65 | width: 100%;
66 | height: 170rpx;
67 | padding-left: 50px;
68 | } */
69 |
70 | .tip-list {
71 | padding: 0 50rpx;
72 | width: 100%;
73 | display: flex;
74 | flex-direction: row;
75 | flex-wrap: nowrap;
76 | justify-content: space-between;
77 | }
78 | .tip-list .tip-item {
79 | width: 88rpx;
80 | height: 160rpx;
81 | font-size: 22rpx;
82 | display: flex;
83 | flex-direction: column;
84 | align-items: center;
85 | }
86 |
87 | .tip-list .tip-item image {
88 | width: 60rpx;
89 | height: 60rpx;
90 | margin-bottom: 20rpx;
91 | }
92 |
93 | .make-view {
94 | box-sizing: border-box;
95 | width: 100%;
96 | padding: 30rpx 30rpx;
97 | display: flex;
98 | justify-content: space-between;
99 | }
100 |
101 | .make-view image {
102 | width: 330rpx;
103 | height: 130rpx;
104 | }
105 |
106 |
107 | .hot-view {
108 | box-sizing: border-box;
109 | width: 100%;
110 | padding: 0 40rpx;
111 | }
112 | .hot-view image {
113 | width: 184rpx;
114 | height: 50rpx;
115 | }
116 |
117 | .custom-view {
118 | box-sizing: border-box;
119 | width: 100%;
120 | padding: 20rpx 30rpx;
121 | }
122 | .custom-view image {
123 | width: 100%;
124 | height: 130rpx;
125 | }
126 |
127 |
128 | .hot-list {
129 | box-sizing: border-box;
130 | width: 100%;
131 | padding: 0rpx 30rpx;
132 | }
133 | .hot-list .hot-list-item {
134 | box-sizing: border-box;
135 | width: 100%;
136 | height: 130rpx;
137 | padding: 25rpx 40rpx;
138 | border: 1px solid #eee;
139 | border-radius: 10rpx;
140 | position: relative;
141 | margin-bottom: 20rpx;
142 | }
143 | .hot-list ad {
144 | margin-bottom: 20rpx;
145 | }
146 | .hot-list .hot-list-item .title {
147 | font-size: 26rpx;
148 | }
149 | .hot-list .hot-list-item .description {
150 | font-size: 24rpx;
151 | color: #919191;
152 | margin-top: 20rpx;
153 | }
154 | .hot-list .hot-list-item image {
155 | position: absolute;
156 | width: 60rpx;
157 | height: 60rpx;
158 | right: 40rpx;
159 | top: 36rpx;
160 | }
161 |
162 | .ad-view {
163 | width: 100%;
164 | box-sizing: border-box;
165 | padding: 0 30rpx;
166 | }
167 |
168 |
169 | .tips {
170 | height: 60rpx;
171 | line-height: 60rpx;
172 | text-align: center;
173 | color: #fff;
174 | font-size: 22rpx;
175 | padding: 0 30rpx;
176 | background: rgba(0,0,0,.6);
177 | position: fixed;
178 | top: 22rpx;
179 | right: 30rpx;
180 | z-index: 999;
181 | border-radius: 8rpx;
182 | display: flex;
183 | align-items: center;
184 | }
185 |
186 | .tips.active {
187 | display: none;
188 | }
189 |
190 | .sml_dot {
191 | width: 10rpx;
192 | height: 10rpx;
193 | border-radius: 10rpx;
194 | background: #fff;
195 | display: inline-block;
196 | }
197 |
198 | .lag_dot {
199 | width: 16rpx;
200 | height: 16rpx;
201 | border-radius: 16rpx;
202 | background: #fff;
203 | display: inline-block;
204 | margin: 0 4rpx;
205 | }
206 | .top_arrow {
207 | position: absolute;
208 | top: -35rpx;
209 | right: 100rpx;
210 | width: 0;
211 | height: 0;
212 | border: 18rpx solid transparent;
213 | border-bottom-color: rgba(0,0,0,.5);
214 | }
215 | .ok {
216 | margin-left: 30rpx;
217 | color: #f44;
218 | }
--------------------------------------------------------------------------------
/miniprogram/pages/mein/images/wave.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/mein/images/wave.gif
--------------------------------------------------------------------------------
/miniprogram/pages/mein/mein.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/mein/mein.js
2 | // 在页面中定义激励视频广告
3 | let videoAd = null
4 | const app = getApp()
5 | Page({
6 |
7 | /**
8 | * 页面的初始数据
9 | */
10 | data: {
11 | userInfo: {},
12 | authorized: false, // 用户头像昵称授权
13 | signed: false,
14 | signInLoading: false,
15 | videoLoaded: false,
16 | canIUseGetUserProfile: true,
17 | envVersion: wx.getAccountInfoSync().miniProgram.envVersion || 'release'
18 | },
19 |
20 | // 下发赞赏二维码
21 | sendAppreciateQRCode (e) {
22 | wx.cloud.callFunction({
23 | name: 'sendAppreciateQRCode'
24 | })
25 | },
26 |
27 | // 下发群二维码
28 | sendGroupQRCode () {
29 | wx.cloud.callFunction({
30 | name: 'customerService'
31 | })
32 | },
33 |
34 | // 复制GitHub地址
35 | copyGithubLink() {
36 | wx.setClipboardData({
37 | data: 'https://github.com/liuxiaojun666/ID-Photo-miniapp-wechart',
38 | success (res) {
39 | wx.showToast({
40 | title: '开源地址已复制',
41 | })
42 | }
43 | })
44 | },
45 |
46 | // 获取用户信息回调
47 | bindGetUserInfo (e) {
48 | if (e.detail.userInfo) {
49 | this.setUserInfo(e.detail.userInfo)
50 | }
51 | },
52 |
53 | // 新的获取用户信息事件回调
54 | getUserProfile(e) {
55 | if (this.data.isLatestInfo) return
56 | wx.getUserProfile({
57 | desc: '用于完善资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
58 | success: (res) => {
59 | this.setUserInfo(res.userInfo)
60 | this.setData({ isLatestInfo: true })
61 | }
62 | })
63 | },
64 |
65 | // 设置用户信息
66 | setUserInfo (userInfo) {
67 | this.setData({
68 | authorized: !!userInfo.nickName,
69 | userInfo: {
70 | ...this.data.userInfo,
71 | ...userInfo
72 | }
73 | })
74 | const openid = app.globalData.openid
75 | if (!openid) return
76 | wx.cloud.callFunction({
77 | name: 'setUserInfo',
78 | data: {openid, data: userInfo}
79 | }).then(res => {
80 | console.log(res)
81 | })
82 | },
83 |
84 | // 签到
85 | signIn () {
86 | if (this.data.signInLoading) return
87 | if (!this.data.authorized) {
88 | return wx.showToast({
89 | title: '请授权登录',
90 | icon: 'none'
91 | })
92 | }
93 | this.subscribeSign()
94 | this.setData({ signInLoading: true })
95 | wx.cloud.callFunction({
96 | name: 'useCount',
97 | data: {inc: 1, signIn: true}
98 | }).then(res => {
99 | wx.showToast({ title: '签到成功', })
100 | this.getUserInfo()
101 | this.shareSuccess()
102 | })
103 | },
104 |
105 | // 被邀请成功
106 | shareSuccess () {
107 | const fromShare = wx.getStorageSync('fromShare')
108 | if (!fromShare) return
109 | wx.cloud.callFunction({
110 | name: 'shareUpdate',
111 | data: {
112 | shareOpenid: fromShare
113 | }
114 | })
115 | },
116 |
117 | // 订阅签到
118 | subscribeSign() {
119 | const tmplIds = ["h_P9sODh-NfeXteA5t7h6sS9BAIjtEyppGwt-biQIQ0"]
120 | wx.requestSubscribeMessage({
121 | tmplIds: tmplIds,
122 | success: (res) => {
123 | if (res[tmplIds[0]] === 'accept') {
124 | wx.showToast({ title: '订阅成功', })
125 | }
126 | },
127 | fail(error) {
128 | console.log(error)
129 | }
130 | })
131 | },
132 |
133 | // 看视频
134 | lookVideo () {
135 | // 用户触发广告后,显示激励视频广告
136 | if (videoAd) {
137 | videoAd.show().catch(() => {
138 | // 失败重试
139 | videoAd.load()
140 | .then(() => videoAd.show())
141 | .catch(err => {
142 | wx.showToast({
143 | title: '视频显示失败',
144 | icon: 'loading'
145 | })
146 | })
147 | })
148 | }
149 | },
150 |
151 | // 选择视频奖励
152 | modalConfirm() {
153 | wx.showModal({
154 | title: '请选择奖励',
155 | content: '选择普通,+3次普通下载,选择升级版 +1次升级版精细抠图',
156 | showCancel: true,
157 | cancelText: '普通版',
158 | confirmText: '升级版',
159 | success: (res) => {
160 | if (res.confirm) {
161 | this.inccVipCount()
162 | } else if (res.cancel) {
163 | this.incCount()
164 | console.log('用户点击取消')
165 | }
166 | wx.showToast({ title: '奖励已下发'})
167 | },
168 | fail: (res) => {
169 | // console.log(res)
170 | this.incCount()
171 | }
172 | })
173 | },
174 |
175 | // 增加次数
176 | incCount () {
177 | wx.showLoading()
178 | wx.cloud.callFunction({
179 | name: 'useCount',
180 | data: {inc: 1}
181 | }).then(res => {
182 | wx.hideLoading({})
183 | this.timerFunc()
184 | })
185 | },
186 |
187 | // 增加vip次数
188 | inccVipCount () {
189 | wx.showLoading()
190 | wx.cloud.callFunction({
191 | name: 'useVipCount',
192 | data: {
193 | lookVideo: true
194 | }
195 | }).then(res => {
196 | wx.hideLoading({})
197 | this.timerFunc()
198 | })
199 | },
200 |
201 | /**
202 | * 生命周期函数--监听页面加载
203 | */
204 | onLoad: function (options) {
205 | if (wx.getUserProfile) {
206 | this.setData({
207 | canIUseGetUserProfile: true
208 | })
209 | }
210 |
211 | // 在页面onLoad回调事件中创建激励视频广告实例
212 | if (wx.createRewardedVideoAd) {
213 | videoAd = wx.createRewardedVideoAd({
214 | adUnitId: 'adunit-93858df72c78d43a'
215 | })
216 | videoAd.onLoad(() => {
217 | this.setData({
218 | videoLoaded: true
219 | })
220 | })
221 | videoAd.onError((err) => {
222 | this.setData({
223 | videoLoaded: false
224 | })
225 | })
226 | videoAd.onClose((res) => {
227 | if (res && res.isEnded) {
228 | // this.useCount(true, 1)
229 | // this.inccVipCount()
230 | // setTimeout(this.modalConfirm, 500)
231 | // this.modalConfirm()
232 | this.incCount()
233 | } else {
234 | wx.showToast({
235 | title: '看完才有奖励哦!',
236 | icon: 'none'
237 | })
238 | }
239 | })
240 | }
241 | },
242 |
243 | /**
244 | * 生命周期函数--监听页面初次渲染完成
245 | */
246 | onReady: function () {
247 |
248 | },
249 |
250 | // 从数据库获取用户信息,并更新用户信息
251 | getUserInfo () {
252 | const that = this
253 | const openid = app.globalData.openid
254 | if (!openid) return
255 | const db = wx.cloud.database()
256 | db.collection('user').where({ openid }).get().then(res => {
257 | this.setData({
258 | userInfo: res.data[0],
259 | signed: res.data[0].signInDate.trim() === new Date().toDateString().trim()
260 | })
261 |
262 | // 如果是新接口,就算授权也不能直接获取用户信息,结束执行并设置已有信息
263 | if (this.data.canIUseGetUserProfile) {
264 | return this.setUserInfo(res.data[0])
265 | }
266 |
267 | wx.getSetting({
268 | success (res){
269 | if (res.authSetting['scope.userInfo']) {
270 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称
271 | wx.getUserInfo({
272 | success: function(res) {
273 | that.setUserInfo(res.userInfo)
274 | }
275 | })
276 | } else {
277 | that.setData({
278 | authorized: false
279 | })
280 | }
281 | }
282 | })
283 | })
284 | },
285 |
286 | /**
287 | * 生命周期函数--监听页面显示
288 | */
289 | onShow: function () {
290 | this.timerFunc()
291 | },
292 |
293 | // 定时器,解决第一次进入页面没有openid 的问题
294 | timerFunc () {
295 | const openid = app.globalData.openid
296 | if (openid) {
297 | this.getUserInfo()
298 | } else {
299 | setTimeout(() => this.timerFunc(), 3000)
300 | }
301 | },
302 |
303 | // 作者二维码
304 | previewQRcode() {
305 | wx.previewImage({
306 | urls: ['/images/WechatIMG199.jpeg'],
307 | current: '/images/WechatIMG199.jpeg'
308 | })
309 | },
310 |
311 |
312 | onShareTimeline: function () {
313 | return {
314 | title: '证件照、免冠照、一寸照片、二寸照片、证件照换背景,免费生成、下载。',
315 | imageUrl: '/shareShow.jpg'
316 | }
317 | },
318 | })
--------------------------------------------------------------------------------
/miniprogram/pages/mein/mein.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/mein/mein.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {{userInfo.nickName}}
11 |
12 |
13 |
14 | {{userInfo.nickName}}
15 |
16 | 今日已签到
17 | 签到+1次下载>
18 | 签到中...
19 |
20 |
21 |
22 |
23 |
24 |
25 | {{userInfo.count || 0}}次
26 | 剩余下载次数
27 |
28 |
32 |
33 | {{userInfo.accumCreatePhoto || 0}}张
34 | 累计下载
35 |
36 |
37 |
38 |
39 | 我的唯一标识:{{ userInfo.openid }}
40 |
41 |
42 |
43 |
44 | 邀请好友 + 次数
45 |
46 |
47 |
48 |
49 |
50 | 看视频 + 次数
51 |
52 |
53 |
54 |
55 |
56 | 有问题找作者
57 |
58 |
59 |
60 |
64 |
65 |
66 |
67 |
68 | 项目已开源:点击复制开源地址
69 |
70 |
--------------------------------------------------------------------------------
/miniprogram/pages/mein/mein.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/mein/mein.wxss */
2 | .scrollPage {
3 | height: 100vh;
4 | }
5 | .user-info .cu-avatar {
6 | overflow: hidden;
7 | }
8 |
9 | .my-info {
10 | width: 100%;
11 | }
12 |
13 | .user-info .nickName {
14 | margin-left: 1em;
15 | text-shadow: none;
16 | display: inline-block;
17 | vertical-align: middle;
18 | }
19 |
20 | .user-info .signIn {
21 | /* height: 100%; */
22 | vertical-align: middle;
23 | line-height: 120rpx;
24 | float: right;
25 | text-shadow: none;
26 | }
27 |
28 | .UCenter-bg {
29 | background: #3E85EE;
30 | height: 280rpx;
31 | display: flex;
32 | justify-content: center;
33 | /* padding-top: 40rpx; */
34 | overflow: hidden;
35 | position: relative;
36 | flex-direction: column;
37 | align-items: center;
38 | color: #fff;
39 | font-weight: 300;
40 | text-shadow: 0 0 3px rgba(0, 0, 0, 0.3);
41 | }
42 |
43 | .UCenter-bg text {
44 | opacity: 0.8;
45 | }
46 |
47 | .UCenter-bg image {
48 | width: 200rpx;
49 | height: 200rpx;
50 | }
51 |
52 | .UCenter-bg .gif-wave{
53 | position: absolute;
54 | width: 100%;
55 | bottom: 0;
56 | left: 0;
57 | z-index: 99;
58 | mix-blend-mode: screen;
59 | height: 100rpx;
60 | }
61 |
62 | .github .text-blue{
63 | padding: 10px 0;
64 | }
--------------------------------------------------------------------------------
/miniprogram/pages/preEdit/preEdit.js:
--------------------------------------------------------------------------------
1 | const app = getApp()
2 |
3 | // 非响应式数据
4 | const pageData = {
5 | photoSizeList: app.globalData.photoSizeList,
6 | width: '',
7 | height: '',
8 | originTempFilePath: '',
9 | originImgPath: '',
10 | originImgType: '',
11 | compressImagePath: ''
12 | }
13 |
14 | Page({
15 |
16 | /**
17 | * 页面的初始数据
18 | */
19 | data: {
20 | px: '',
21 | size: '自定义',
22 | photoName: '自定义尺寸',
23 | discription: '',
24 | },
25 |
26 | /**
27 | * 生命周期函数--监听页面加载
28 | */
29 | onLoad: function (options) {
30 | const {index,width,height,data} = options
31 | if (width && height) {
32 | this.setData({px: width + ' * ' + height + '像素'});
33 | Object.assign(pageData, { width: +width, height: +height })
34 | }else if(data){
35 | let newData = JSON.parse(data);
36 | this.setData({
37 | px:newData.width_px+" * "+newData.height_px + " 像素",
38 | size:newData.width_mm+" × "+newData.height_mm + " mm",
39 | photoName: "基本信息",
40 | discription: newData.name
41 | });
42 | Object.assign(pageData, { width:+newData.width_px, height:+newData.height_px, })
43 | }else{
44 | const {width, height, px, size, name, discription} = pageData.photoSizeList[index];
45 | this.setData({ px, size, photoName: name, discription: discription });
46 | Object.assign(pageData, { width, height })
47 | }
48 | },
49 |
50 | /**
51 | * 选择照片
52 | */
53 | chooseImage (event) {
54 | // wx.showLoading({title: '选择照片'})
55 | wx.chooseMedia({
56 | count: 1,
57 | mediaType: ['image'],
58 | sizeType: ['compressed'],
59 | success: (res) => {
60 | const tempFilePath = res.tempFiles[0].tempFilePath
61 | Object.assign(pageData, {originTempFilePath: tempFilePath})
62 | this.imgSecCheck(tempFilePath)
63 | },
64 | fail () {
65 | wx.showToast({ title: '取消选择', icon: 'none', duration: 2000 })
66 | }
67 | })
68 | },
69 | // 图片敏感信息检测 获取图片宽高信息
70 | imgSecCheck (tempFilePath) {
71 | wx.showLoading({ title: '图片安全校验', })
72 | // 获取图片信息
73 | wx.getImageInfo({ src: tempFilePath, })
74 | // 图片安全校验
75 | .then(res => {
76 | return wx.cloud.callFunction({
77 | name: 'imgSecCheck',
78 | data: {
79 | width: res.width,
80 | height: res.height,
81 | type: res.type,
82 | // 上传图片到临时CDN,返回图片地址
83 | filePath: wx.cloud.CDN({
84 | type: 'filePath',
85 | filePath: res.path,
86 | })
87 | },
88 | })
89 | })
90 | // 图片安全检测结果处理
91 | .then((res) => {
92 | if (res.result.errCode === 0) {
93 | Object.assign(pageData, {
94 | originImgPath: res.result.originImgPath,
95 | originImgType: res.result.originImgType,
96 | compressImagePath: res.result.filePath
97 | })
98 | this.baiduKoutu({
99 | fileID: res.result.fileId,
100 | filePath: res.result.filePath
101 | })
102 | } else if (res.result.errCode === 87014) {
103 | wx.showToast({ title: '内容可能潜在风险,请重新选择', icon: 'none' })
104 | } else if (res.result.errCode === -604102) {
105 | wx.showToast({ title: '超时,再试一下。或换个图试试', icon: 'none', duration: 3000 })
106 | } else {
107 | wx.showToast({ title: '又是啥问题呀,请换图重试', icon: 'none', duration: 3000 })
108 | }
109 | })
110 | // 错误处理
111 | .catch(console.error)
112 | },
113 |
114 | // 使用百度抠图
115 | baiduKoutu (data) {
116 | wx.showLoading({ title: '智能人像分割', })
117 | wx.cloud.callFunction({
118 | name: 'baiduKoutu',
119 | data: data
120 | })
121 | .then(({ result }) => {
122 | this.goEditPage(result)
123 | }).catch((error) => {
124 | console.log(error)
125 | wx.showToast({ title: '失败,请重试' })
126 | })
127 | },
128 |
129 | /**
130 | * 去编辑页面
131 | */
132 | goEditPage (data) {
133 | wx.hideLoading()
134 | const { width, height, originImgPath, originImgType, originTempFilePath, compressImagePath } = pageData
135 | wx.navigateTo({
136 | url: '/pages/editPhoto/editPhotoPlus/editPhotoPlus',
137 | success: function (res) {
138 | res.eventChannel.emit('acceptDataFromOpenerPage', {
139 | ...data,
140 | originTempFilePath,
141 | originImgPath,
142 | originImgType,
143 | compressImagePath,
144 | width,
145 | height
146 | })
147 | }
148 | })
149 | },
150 |
151 | /**
152 | * 用户点击右上角分享
153 | */
154 | onShareAppMessage: function () {
155 | return {
156 | title: '证件照、免冠照、一寸照片、二寸照片、自定义尺寸、证件照换背景,免费生成、下载。',
157 | imageUrl: '/shareShow.jpg'
158 | }
159 | }
160 | })
--------------------------------------------------------------------------------
/miniprogram/pages/preEdit/preEdit.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "选择照片",
3 | "disableScroll": true,
4 | "usingComponents": {
5 | "page-scroll-message": "/components/pageScrollMessage/pageScrollMessage"
6 | }
7 | }
--------------------------------------------------------------------------------
/miniprogram/pages/preEdit/preEdit.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 照片像素:{{px}}
9 | 打印尺寸:{{size}}
10 | 照片描述:{{discription}}
11 |
12 |
13 |
14 |
15 | - 照片使用纯色背景(推荐白墙)
16 | - 避免多人出现在照片中
17 | - 露出耳朵、眉毛和下巴
18 |
19 |
20 |
21 |
22 |
23 | 开始制作
24 |
25 |
26 |
27 |
28 |
29 |
30 | 开始制作
31 |
32 |
33 |
--------------------------------------------------------------------------------
/miniprogram/pages/preEdit/preEdit.wxss:
--------------------------------------------------------------------------------
1 | page {
2 | overflow-x: hidden;
3 | }
4 |
5 | .container {
6 | height: 100vh;
7 | padding: 10rpx 30rpx;
8 | padding-bottom: 100rpx;
9 | overflow: visible;
10 | box-sizing: border-box;
11 | }
12 |
13 | .tips {
14 | width: 100%;
15 | margin-bottom: 20rpx;
16 | background-color: rgba(255,255,255,1);
17 | padding: 30rpx;
18 | line-height: 2;
19 | color: #333;
20 | border-radius: 10rpx;
21 | font-size: 28rpx;
22 | position: relative;
23 | }
24 |
25 | .tips .cu-btn {
26 | position: absolute;
27 | right: 30rpx;
28 | top: 30rpx;
29 | }
30 |
31 | .header {
32 | width: 100%;
33 | line-height: 2em;
34 | padding-left: 30rpx;
35 | font-size: 28rpx;
36 | font-weight: bold;
37 | }
38 |
39 | .tips .li {
40 | margin-right: 20rpx;
41 | }
42 |
43 | .container > .cu-btn {
44 | margin: 30rpx auto;
45 | }
46 |
47 | .help-btn {
48 | position: fixed;
49 | z-index: 9999;
50 | right: 30rpx;
51 | bottom: 150rpx;
52 | width: 100rpx;
53 | height: 100rpx;
54 | line-height: 100rpx;
55 | border-radius: 50%;
56 | background-color: rgba(0,0,0,.8);
57 | }
58 |
59 | .btn-view {
60 | position: fixed;
61 | left: 0;
62 | /* right: 0; */
63 | bottom: 0;
64 | width: 100%;
65 | height: 120rpx;
66 | background-color: #fff;
67 | padding-top: 10rpx;
68 | box-shadow: 0 -10rpx 10rpx rgba(0,0,0,.1);
69 | z-index: 9999;
70 | }
71 | .btn-view .cu-btn {
72 | width: 90%;
73 | }
74 |
75 | .result-canvas-view {
76 | position: absolute;
77 | left: 100vw;
78 | top: 100vh;
79 | }
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/custom/custom.js:
--------------------------------------------------------------------------------
1 | Page({
2 |
3 | /**
4 | * 页面的初始数据
5 | */
6 | data: {
7 | width: '',
8 | height: '',
9 | },
10 |
11 | // 跳转到下一页
12 | goNextPage (e) {
13 | const {width, height} = this.data
14 | wx.navigateTo({
15 | url: '/pages/preEdit/preEdit?width=' +width+ '&height=' + height+ '&discription='
16 | })
17 | },
18 |
19 | // 宽度改变
20 | widthChange (e) {
21 | this.setData({
22 | width: +e.detail.value
23 | })
24 | },
25 |
26 | // 高度改变
27 | heightChange (e) {
28 | this.setData({
29 | height: +e.detail.value
30 | })
31 | },
32 |
33 | // 点击确定,校验用户输入
34 | selectPhoto () {
35 | const {width, height} = this.data
36 | let msg = ''
37 | if (width < 100 || height < 100) {
38 | msg = '最小边不能小于100像素'
39 | }
40 | if (width > 2000 || height > 2000) {
41 | msg = '最大边不能大于2000像素'
42 | }
43 | if (msg) {
44 | return wx.showToast({
45 | title: msg,
46 | icon: 'none'
47 | })
48 | } else {
49 | this.goNextPage()
50 | }
51 | },
52 |
53 | onShareAppMessage () {
54 | return {
55 | title: '证件照、免冠照、一寸照片、二寸照片、自定义尺寸、证件照换背景,免费生成、下载。',
56 | path: '/pages/index/index',
57 | imageUrl: '/shareShow.jpg'
58 | }
59 | },
60 |
61 | onShareTimeline: function () {
62 | return {
63 | title: '证件照、免冠照、一寸照片、二寸照片、证件照换背景,免费生成、下载。',
64 | imageUrl: '/shareShow.jpg'
65 | }
66 | },
67 |
68 | })
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/custom/custom.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "免冠照/证件照尺寸定制",
3 | "disableScroll": true,
4 | "usingComponents": {}
5 | }
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/custom/custom.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/custom/custom.wxss:
--------------------------------------------------------------------------------
1 | .container {
2 | height: 100vh;
3 | display: flex;
4 | flex-direction: column;
5 | /* justify-content: space-between; */
6 | }
7 |
8 | form {
9 | margin-top: 50rpx;
10 | }
11 |
12 | button.btn-confirm {
13 | width: 100% !important;
14 | height: 90rpx !important;
15 | padding: 0 !important;
16 | line-height: 90rpx !important;
17 | color: #fff !important;
18 | border-radius: 45rpx !important;
19 | background-color: #0081ff !important;
20 | font-weight: normal !important;
21 | margin-top: 30rpx;
22 | }
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/images/card-people.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/searchSize/images/card-people.png
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/images/custom-img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/searchSize/images/custom-img.png
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/images/search-input.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxiaojun666/certificate-photo/b88f28dd1a73470612852237b159e0a7856b86e9/miniprogram/pages/searchSize/images/search-input.png
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/searchSize.js:
--------------------------------------------------------------------------------
1 | const hideLoadView = true
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | category:"1",
9 | page:0,
10 | currentTab:0,
11 | photoSizeList:[],
12 | allRecords:[]
13 | },
14 | //滑动切换
15 | swiperTab: function(e) {
16 | this.setData({ currentTab: e.detail.current });
17 | },
18 | //点击切换
19 | clickTab: function(e) {
20 | if (this.data.currentTab === e.target.dataset.current) return false;
21 | this.setData({
22 | category: ['1', '2', '3', '4', null][e.target.dataset.current],
23 | page:0,
24 | currentTab: e.target.dataset.current,
25 | photoSizeList:[]
26 | })
27 | this.requestdata()
28 | },
29 |
30 | // 跳转到下一页
31 | goNextPage (e) {
32 | wx.navigateTo({
33 | url: '/pages/preEdit/preEdit?index=' + e.currentTarget.dataset.index + '&data='+JSON.stringify(this.data.photoSizeList[e.currentTarget.dataset.index])
34 | })
35 | },
36 | /**
37 | * 生命周期函数--监听页面加载
38 | */
39 | onLoad: function (options) {
40 | // this.requestdata();
41 | const {index} = options;
42 | this.clickTab({ target: { dataset: { current: index || '1' } } })
43 | wx.setNavigationBarTitle({ title: '免冠照/证件照尺寸' })
44 | },
45 | // 跳转到搜索页面
46 | inputPush(){
47 | wx.navigateTo({ url: './searchView/searchView' })
48 | },
49 | //获取数据
50 | requestdata (){
51 | wx.showLoading({
52 | title: '加载中...',
53 | })
54 | const db = wx.cloud.database()
55 | const MAX_LIMIT = 20
56 | const num = this.data.page*MAX_LIMIT
57 | db.collection('photo_size').where({category_id:this.data.category})
58 | .skip(num)
59 | .limit(MAX_LIMIT)
60 | .get({
61 | success: res => {
62 | console.log(res)
63 | let arrNum = res.data.length
64 | console.log(arrNum);
65 | wx.hideLoading()
66 | this.setData({
67 | photoSizeList:this.data.photoSizeList.concat(res.data),
68 | });
69 | hideLoadView = arrNum !== 20
70 | }
71 | })
72 | },
73 | //加载更多
74 | moreclick(){
75 | // 已经全部加载出来了
76 | if (hideLoadView==true) return
77 | this.setData({ page: this.data.page+=1 })
78 | this.requestdata();
79 | },
80 |
81 | // 触底加载
82 | onReachBottom:function(){
83 | this.moreclick();
84 | },
85 | /**
86 | * 用户点击右上角分享
87 | */
88 | onShareAppMessage: function () {
89 | return {
90 | title: '证件照、免冠照、一寸照片、二寸照片、证件照换背景,免费生成、下载。',
91 | path: '/pages/index/index',
92 | imageUrl: '/shareShow.jpg'
93 | }
94 | },
95 |
96 | onShareTimeline: function () {
97 | return {
98 | title: '证件照、免冠照、一寸照片、二寸照片、证件照换背景,免费生成、下载。',
99 | // path: '/pages/index/index',
100 | imageUrl: '/shareShow.jpg'
101 | }
102 | },
103 |
104 | })
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/searchSize.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "免冠照/证件照尺寸",
3 | "enablePullDownRefresh": true ,
4 | "onReachBottomDistance":50,
5 | "usingComponents": {
6 |
7 | }
8 | }
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/searchSize.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 常用尺寸
10 | 职业资格
11 | 公务员
12 | 学历/语言
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
23 |
24 |
25 |
26 |
27 | {{ item.name }}
28 | {{item.width_px}}*{{item.height_px}} px | {{item.width_mm}}*{{item.height_mm}} mm
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/searchSize.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/index/index.wxss */
2 | page {
3 | background: #fff
4 | }
5 |
6 | .top-fixed {
7 | position: fixed;
8 | left: 0;
9 | top: 0;
10 | width: 100%;
11 | padding: 30rpx;
12 | z-index: 999;
13 | background-color: #fff;
14 | }
15 |
16 | .swiper-tab {
17 | width: 100%;
18 | border-bottom: 2rpx solid rgba(0, 0, 0, 0);
19 | text-align: center;
20 | height: 88rpx;
21 | line-height: 88rpx;
22 | display: flex;
23 | flex-flow: row;
24 | justify-content: space-between;
25 | }
26 |
27 | .swiper-tab-item {
28 | width: 30%;
29 | color: #434343;
30 | /* border:1px solid #ccc; */
31 | }
32 |
33 | .active {
34 | color: #3E85EE;
35 | border-bottom: 4rpx solid #3E85EE;
36 | }
37 |
38 | swiper {
39 | text-align: center;
40 | }
41 | swiper {
42 | text-align: center;
43 | }
44 |
45 | .container {
46 | padding: 30rpx;
47 | flex-direction: row;
48 | flex-wrap:wrap;
49 | justify-content:space-around;
50 | height: 100%;
51 | display: block;
52 | background-color: white;
53 | padding-top: 200rpx;
54 | margin-top: 15px;
55 | }
56 | ad {
57 | margin-bottom: 15rpx;
58 | }
59 | .container .chooseImage {
60 | margin-top: 50vh;
61 | transform: translateY(-100%);
62 | }
63 | .container .temp-image {
64 | width: 80vw;
65 | }
66 | .container .confirm-view {
67 | margin-top: 20px;
68 | }
69 | .container .confirm-view button {
70 | margin: 0 10px;
71 | }
72 | .card-view {
73 | display: flex;
74 | flex-direction: column;
75 | flex-wrap: nowrap;
76 | align-items: center;
77 | /* justify-content: space-between */
78 | }
79 | .card {
80 | /* border: 1px solid #06ae56; */
81 | width: 100%;
82 | padding: 30rpx;
83 | /* height: 300rpx; */
84 | margin-bottom: 15rpx;
85 | /* float: left; */
86 | border-radius: 10rpx;
87 | /* text-align: center; */
88 | font-size: 26rpx;
89 | display: flex;
90 | flex-direction:column;
91 | /* overflow: hidden; */
92 | box-sizing: border-box;
93 | /* border: 8rpx solid #fff; */
94 | background-color: #eeeeee;
95 | }
96 | .card.custom {
97 | padding: 0;
98 | }
99 | .card.custom image {
100 | width: 100%;
101 | height: 120rpx;
102 | }
103 | .card .name {
104 | font-size: 36rpx;
105 | color: #0081ff;
106 | line-height: 2;
107 | }
108 | .card .size {
109 | font-size: 26rpx;
110 | line-height: 1.5;
111 | color: #666;
112 | }
113 | .card .discription {
114 | line-height: 1.4;
115 | font-size: 24rpx;
116 | color: #666;
117 | text-align:justify;
118 | /* padding: 8rpx 15rpx !important; */
119 | }
120 |
121 |
122 | .hot-list-item {
123 | box-sizing: border-box;
124 | width: 100%;
125 | height: 130rpx;
126 | padding: 25rpx 40rpx;
127 | /* background: #DBEDFC; */
128 | border: 1px solid #DBEDFC;
129 | border-radius: 10rpx;
130 | position: relative;
131 | margin-bottom: 20rpx;
132 | }
133 | .hot-list-item .title {
134 | font-size: 26rpx;
135 | }
136 | .hot-list-item .description {
137 | font-size: 24rpx;
138 | color: #919191;
139 | margin-top: 20rpx;
140 | }
141 | .hot-list-item image {
142 | position: absolute;
143 | width: 60rpx;
144 | height: 60rpx;
145 | right: 40rpx;
146 | top: 36rpx;
147 | }
148 |
149 | .transparent {
150 | width: 100%;
151 | height: 0;
152 | overflow: hidden;
153 | opacity: 0;
154 | /* margin-top: 100rpx; */
155 | }
156 |
157 | button {
158 |
159 | box-shadow: 0 0 10rpx 5rpx rgba(67,142,219,.15);
160 | font-weight: normal !important;
161 | }
162 |
163 |
164 | .help-btn {
165 | position: fixed;
166 | z-index: 9999;
167 | right: 30rpx;
168 | bottom: 50rpx;
169 | width: 100rpx;
170 | height: 100rpx;
171 | line-height: 100rpx;
172 | border-radius: 50%;
173 | background-color: rgba(0,0,0,.8);
174 | }
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/searchView/searchView.js:
--------------------------------------------------------------------------------
1 |
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | hideLoadView:true,
9 | showMenu:false,
10 | page:0,
11 | putText:"",
12 | photoSizeList:[],
13 | allRecords:[]
14 | },
15 | //输入框值
16 | bindModel(e) {
17 | this.setData({ putText: e.detail.value });
18 | if (this.data.putText.length==0) {
19 | this.setData({
20 | photoSizeList:[],
21 | putText:"",
22 | showMenu:false,
23 | })
24 | }
25 | },
26 |
27 | // 点击搜索按钮
28 | searchClick:function () {
29 | this.setData({
30 | showMenu:true,
31 | photoSizeList:[],
32 | page:0
33 | });
34 | if (this.data.putText.length>0) {
35 | this.searchData(this.data.putText)
36 | }
37 | },
38 | // 跳转到下一个页面
39 | goNextPage (e) {
40 | wx.navigateTo({
41 | url: '/pages/preEdit/preEdit?index=' + e.currentTarget.dataset.index + '&data='+JSON.stringify(this.data.photoSizeList[e.currentTarget.dataset.index])
42 | })
43 | },
44 | /**
45 | * 生命周期函数--监听页面加载
46 | */
47 | onLoad: function (options) {
48 | wx.setNavigationBarTitle({ title: '搜索' })
49 | },
50 | // 键盘搜索事件
51 | confirm() {
52 | this.setData({
53 | photoSizeList:[],
54 | page:0
55 | });
56 | if (this.data.putText.length>0) {
57 | this.searchData(this.data.putText)
58 | }
59 |
60 | },
61 | //搜索数据
62 | searchData(e){
63 | wx.showLoading({ title: '搜索中...', })
64 | const db = wx.cloud.database()
65 | const MAX_LIMIT = 20
66 | const num = this.data.page*MAX_LIMIT
67 | db.collection('photo_size').where({
68 | name:{
69 | $regex:'.*'+ this.data.putText,
70 | $options: 'i'
71 | }
72 | })
73 | .skip(num)
74 | .limit(MAX_LIMIT)
75 | .get({
76 | success: res => {
77 | wx.hideLoading()
78 | let arrNum = res.data.length
79 | this.setData({
80 | photoSizeList:this.data.photoSizeList.concat(res.data),
81 | hideLoadView:(arrNum==20)?false:true
82 | });
83 | }
84 | })
85 | },
86 | //加载更多
87 | moreclick(){
88 | if (this.data.hideLoadView==true) {
89 | return
90 | }
91 | this.setData({
92 | page:this.data.page+=1
93 | })
94 | console.log("加载更多数据"+this.data.page+'页')
95 | this.searchData(this.data.putText);
96 |
97 | },
98 | onReachBottom:function(){
99 | this.moreclick();
100 | },
101 |
102 | /**
103 | * 用户点击右上角分享
104 | */
105 | onShareAppMessage: function () {
106 | return {
107 | title: '证件照、免冠照、一寸照片、二寸照片、证件照换背景,免费生成、下载。',
108 | path: '/pages/index/index',
109 | imageUrl: '/shareShow.jpg'
110 | }
111 | },
112 |
113 | onShareTimeline: function () {
114 | return {
115 | title: '证件照、免冠照、一寸照片、二寸照片、证件照换背景,免费生成、下载。',
116 | // path: '/pages/index/index',
117 | imageUrl: '/shareShow.jpg'
118 | }
119 | },
120 |
121 | })
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/searchView/searchView.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "搜索",
3 | "enablePullDownRefresh": true ,
4 | "usingComponents": {
5 |
6 | }
7 | }
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/searchView/searchView.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | {{ item.name }}
23 | {{item.width_px}}*{{item.height_px}} px | {{item.width_mm}}*{{item.height_mm}} mm
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/miniprogram/pages/searchSize/searchView/searchView.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/index/index.wxss */
2 |
3 | page {
4 | background: #fff
5 | }
6 | .container{
7 | padding: 30rpx;
8 | }
9 | .searchView{
10 | position: relative;
11 | margin-bottom: 20rpx;
12 | }
13 | .searchput{
14 | width: 100%;
15 | height: 70rpx;
16 | padding-left: 30rpx;
17 | background-color:#fff;
18 | border-radius: 35rpx;
19 | border: 1px solid #3E85EE;
20 | }
21 | .searchBtn{
22 | width: 70rpx;
23 | height: 70rpx;
24 | position: absolute;
25 | right: 0;
26 | top: 5rpx;
27 | z-index: 9;
28 | }
29 |
30 |
31 | .hot-list-item {
32 | box-sizing: border-box;
33 | width: 100%;
34 | height: 130rpx;
35 | padding: 25rpx 40rpx;
36 | background: #DBEDFC;
37 | border-radius: 10rpx;
38 | position: relative;
39 | margin-bottom: 20rpx;
40 | }
41 | .hot-list-item .title {
42 | font-size: 26rpx;
43 | }
44 | .hot-list-item .description {
45 | font-size: 24rpx;
46 | color: #919191;
47 | margin-top: 20rpx;
48 | }
49 | .hot-list-item image {
50 | position: absolute;
51 | width: 60rpx;
52 | height: 60rpx;
53 | right: 40rpx;
54 | top: 36rpx;
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/miniprogram/pages/share/share.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/share/share.js
2 |
3 | // 在页面中定义插屏广告
4 | let interstitialAd = null
5 | let shared = false
6 | const db = wx.cloud.database()
7 |
8 | Page({
9 |
10 | /**
11 | * 页面的初始数据
12 | */
13 | data: {
14 | allShareData: {},
15 | invitedList: [],
16 | updateCountLoading: false,
17 | successUserList: [],
18 | showSubscribeBtn: false,
19 | subscribed: false
20 | },
21 |
22 | // 邀请成功,领取次数
23 | shareSuccessUpdateCount (event) {
24 | if (this.data.updateCountLoading) return
25 | const openid = event.currentTarget.dataset.openid
26 | this.setData({ updateCountLoading: true })
27 | wx.cloud.callFunction({
28 | name: 'shareSuccessCallback',
29 | data: {openid}
30 | }).then(res => {
31 | this.setData({ updateCountLoading: false })
32 | this.getData()
33 | })
34 | },
35 |
36 | /**
37 | * 生命周期函数--监听页面加载
38 | */
39 | onLoad: function (options) {
40 | wx.setNavigationBarTitle({ title: '分享免冠照' })
41 |
42 | // 在页面onLoad回调事件中创建插屏广告实例
43 | if (wx.createInterstitialAd) {
44 | interstitialAd = wx.createInterstitialAd({
45 | adUnitId: 'adunit-7bd4afc44e5cebbd'
46 | })
47 | interstitialAd.onLoad(() => {})
48 | interstitialAd.onError((err) => {})
49 | interstitialAd.onClose(() => {})
50 | }
51 | },
52 |
53 | /**
54 | * 生命周期函数--监听页面显示
55 | */
56 | onShow: function () {
57 | this.getData()
58 | this.getSubscribeStatus()
59 |
60 | // 在适合的场景显示插屏广告
61 | if (interstitialAd) {
62 | interstitialAd.show().catch((err) => {
63 | console.error(err)
64 | })
65 | }
66 | },
67 |
68 | // 订阅邀请成功通知
69 | subscribeMessage () {
70 | const tmplIds = ["CNuffKDjmxEOU_hM44Cu0KoGqOjfdacpbk4LT1abcnE"]
71 | wx.requestSubscribeMessage({
72 | tmplIds: tmplIds,
73 | success: (res) => {
74 | if (res[tmplIds[0]] === 'accept') {
75 | wx.showToast({ title: '订阅成功', })
76 | this.setData({ subscribed: true })
77 | }
78 | },
79 | fail(error) {
80 | console.log(error)
81 | }
82 | })
83 | },
84 |
85 | // 获取订阅状态
86 | getSubscribeStatus () {
87 | db.collection('subscrib-message').where({
88 | _openid: getApp().globalData.openid,
89 | tmplId: "CNuffKDjmxEOU_hM44Cu0KoGqOjfdacpbk4LT1abcnE"
90 | }).count({
91 | success: (res)=> {
92 | this.setData({ subscribed: res.total > 0 })
93 | },
94 | fail: console.error
95 | })
96 | },
97 |
98 | // 是不是已经邀请过朋友,如果就展示邀请结果
99 | getData () {
100 | wx.showLoading({ title: '加载中', })
101 | const db = wx.cloud.database()
102 | db.collection('share').where({
103 | _openid: getApp().globalData.openid
104 | }).get().then(res => {
105 | wx.hideLoading({ complete: (res) => {}, })
106 | console.log(res)
107 | if (!res.data[0]) {
108 | shared = false
109 | } else {
110 | shared = true
111 | this.setData({
112 | allShareData: res.data[0],
113 | invitedList: res.data[0].invitedList
114 | })
115 | this.getAvatar(res.data[0].invitedList || [])
116 | }
117 | }).catch(err => {
118 | wx.showToast({
119 | title: 'err',
120 | icon: 'none'
121 | })
122 | })
123 | },
124 |
125 | // 获取被邀请者的头像
126 | getAvatar (openidList = []) {
127 | if (!openidList.length) return
128 | const db = wx.cloud.database()
129 | const _ = db.command
130 | db.collection('user').where({
131 | openid: _.or(openidList.map(v => _.eq(v))),
132 | avatarUrl: _.exists(true)
133 | })
134 | .field({
135 | avatarUrl: true,
136 | nickName: true
137 | })
138 | .get().then(res => {
139 | this.setData({
140 | successUserList: res.data
141 | })
142 | })
143 | },
144 |
145 | /**
146 | * 用户点击右上角分享
147 | */
148 | onShareAppMessage: function (res) {
149 | if (res.from === 'button') {
150 | const openid = getApp().globalData.openid
151 | if (!shared) this.share(openid)
152 | return {
153 | title: '证件照、免冠照、一寸照片、二寸照片、证件照换背景,免费生成、下载。',
154 | path: '/pages/index/index?shareOpenid=' + openid,
155 | imageUrl: '/shareShow.jpg'
156 | }
157 | }
158 | },
159 |
160 | // 创建邀请记录
161 | share (openid) {
162 | const db = wx.cloud.database()
163 | db.collection('share').add({
164 | data: {
165 | invitedList: [],
166 | openid,
167 | createAt: Date.now(),
168 | },
169 | success: () => {
170 | shared = true
171 | }
172 | })
173 | }
174 | })
--------------------------------------------------------------------------------
/miniprogram/pages/share/share.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/share/share.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 成功邀请一位朋友 +1 次免费下载免冠照
7 |
8 |
9 |
25 |
26 |
27 | 还没有成功邀请好友。
28 | 被邀请者签到即算邀请成功。
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/miniprogram/pages/share/share.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/share/share.wxss */
2 | .scroll-view {
3 | width: 100%;
4 | height: 100vh;
5 | overflow: auto;
6 | position: relative;
7 | background-color: #fff;
8 | -webkit-overflow-scrolling: touch;
9 | }
10 |
11 | ad {
12 | /* position: absolute;
13 | left: 0;
14 | bottom: 0; */
15 | margin-bottom: 50rpx;
16 | }
17 |
18 | .scroll-view .jia3ci-btn {
19 | width: 6em;
20 | }
21 |
22 | button.share-btn[type='default'] {
23 | /* margin-top: 1em; */
24 | /* background-color: transparent; */
25 | color: #fff;
26 | }
27 |
28 | .cu-item .content {
29 | display: flex;
30 | flex-direction: row;
31 | align-items: center;
32 | }
33 |
34 | .cu-item .content .cu-avatar {
35 | margin-right: 10rpx;
36 | }
37 |
38 | .bg-gradual-green {
39 | margin-top: 30rpx;
40 | }
--------------------------------------------------------------------------------
/miniprogram/pages/zipSuccess/zipSuccess.js:
--------------------------------------------------------------------------------
1 | // pages/zipSuccess/zipSuccess.ts
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | imageSrc:''
9 | },
10 |
11 | /**
12 | * 生命周期函数--监听页面加载
13 | */
14 | onLoad: async function (options) {
15 | const {imgurl} = options
16 | this.setData({ imageSrc:imgurl })
17 | const { tempFilePath, dataLength } = await this.downloadImg(imgurl)
18 | const size = (dataLength / 1024).toFixed(2)
19 | this.setData({ size: size })
20 | },
21 |
22 | // 将远端图片,下载到本地
23 | downloadImg(url) {
24 | return new Promise((resolve, reject) => {
25 | wx.downloadFile({
26 | url,
27 | success(res) {
28 | if (res.statusCode === 200) {
29 | resolve(res)
30 | } else {
31 | reject(res)
32 | }
33 | },
34 | fail(error) {
35 | reject(error)
36 | }
37 | })
38 | })
39 | },
40 | /**
41 | * 生命周期函数--监听页面初次渲染完成
42 | */
43 | onReady() {
44 |
45 | },
46 |
47 | /**
48 | * 生命周期函数--监听页面显示
49 | */
50 | onShow() {
51 |
52 | },
53 |
54 | /**
55 | * 生命周期函数--监听页面隐藏
56 | */
57 | onHide() {
58 |
59 | },
60 |
61 | /**
62 | * 生命周期函数--监听页面卸载
63 | */
64 | onUnload() {
65 |
66 | },
67 |
68 | /**
69 | * 页面相关事件处理函数--监听用户下拉动作
70 | */
71 | onPullDownRefresh() {
72 |
73 | },
74 |
75 | /**
76 | * 页面上拉触底事件的处理函数
77 | */
78 | onReachBottom() {
79 |
80 | },
81 |
82 | /**
83 | * 用户点击右上角分享
84 | */
85 | onShareAppMessage() {
86 |
87 | },
88 | preView (event) {
89 | wx.previewImage({
90 | urls: [this.data.imageSrc],
91 | current: this.data.imageSrc
92 | })
93 | },
94 | // 下载
95 | downloadClick(){
96 | if (!this.data.imageSrc) {
97 | wx.showToast({
98 | title: '请上传图片',
99 | icon: 'none',
100 | duration: 3000
101 | })
102 | }else{
103 | console.log(this.data.imageSrc);
104 | var url = this.data.imageSrc;
105 | wx.downloadFile({
106 | url: url,
107 | success: function (res) {
108 | console.log(res);
109 | //图片保存到本地
110 | wx.saveImageToPhotosAlbum({
111 | filePath: res.tempFilePath,
112 | success: function (data) {
113 | wx.showToast({
114 | title: '保存成功',
115 | icon: 'success',
116 | duration: 3000
117 | })
118 | setTimeout(() => {
119 | wx.reLaunch({
120 | url: '/pages/index/index'
121 | })
122 | }, 3000)
123 | },
124 | fail: function (err) {
125 | console.log(err);
126 | if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
127 | console.log("当初用户拒绝,再次发起授权")
128 | wx.openSetting({
129 | success(settingdata) {
130 | console.log(settingdata)
131 | if (settingdata.authSetting['scope.writePhotosAlbum']) {
132 | console.log('获取权限成功,给出再次点击图片保存到相册的提示。')
133 | } else {
134 | console.log('获取权限失败,给出不给权限就无法正常使用的提示')
135 | }
136 | }
137 | })
138 | }
139 | },
140 | complete(res){
141 | console.log(res);
142 | }
143 | })
144 | }
145 | })
146 | }
147 |
148 | }
149 | })
--------------------------------------------------------------------------------
/miniprogram/pages/zipSuccess/zipSuccess.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "图片压缩",
3 | "usingComponents": {
4 | "page-scroll-message": "/components/pageScrollMessage/pageScrollMessage"
5 | }
6 | }
--------------------------------------------------------------------------------
/miniprogram/pages/zipSuccess/zipSuccess.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 压缩后图片占用{{size}}kb
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/miniprogram/pages/zipSuccess/zipSuccess.wxss:
--------------------------------------------------------------------------------
1 | /* pages/zipSuccess/zipSuccess.wxss *//* pages/imgZip/imgZip.wxss */
2 | .container {
3 | width: 100%;
4 | height: 100%;
5 | /* overflow: hidden; */
6 | }
7 | .backView{
8 | margin-top: 30rpx;
9 | width: 85%;
10 | height: 700rpx;
11 | /* background-color: #999999; */
12 | border: 1px solid #ccc;
13 | display: flex;
14 | justify-content: center;
15 | align-items: center;
16 | }
17 | .backView image {
18 | width: 100%;
19 | height: 100%;
20 | max-width: 100%;
21 | max-height: 100%;
22 | }
23 | .downloadBtn{
24 | background-color: #3E85EE;
25 | margin-top: 20px;
26 | color: white;
27 | width: 90%;
28 | }
--------------------------------------------------------------------------------
/miniprogram/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [
4 | {
5 | "action": "allow",
6 | "page": "/pages/index/index"
7 | },
8 | {
9 | "action": "allow",
10 | "page": "/pages/searchSize/searchSize"
11 | }
12 | ]
13 | }
--------------------------------------------------------------------------------
/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "miniprogramRoot": "miniprogram/",
3 | "cloudfunctionRoot": "cloudfunctions/",
4 | "setting": {
5 | "urlCheck": false,
6 | "es6": true,
7 | "enhance": true,
8 | "postcss": true,
9 | "preloadBackgroundData": false,
10 | "minified": true,
11 | "newFeature": true,
12 | "coverView": true,
13 | "nodeModules": true,
14 | "autoAudits": false,
15 | "showShadowRootInWxmlPanel": true,
16 | "scopeDataCheck": false,
17 | "uglifyFileName": true,
18 | "checkInvalidKey": true,
19 | "checkSiteMap": true,
20 | "uploadWithSourceMap": true,
21 | "compileHotReLoad": true,
22 | "useMultiFrameRuntime": true,
23 | "useApiHook": true,
24 | "useApiHostProcess": true,
25 | "babelSetting": {
26 | "ignore": [],
27 | "disablePlugins": [],
28 | "outputPath": ""
29 | },
30 | "enableEngineNative": false,
31 | "useIsolateContext": false,
32 | "userConfirmedBundleSwitch": true,
33 | "packNpmManually": false,
34 | "packNpmRelationList": [],
35 | "minifyWXSS": true,
36 | "disableUseStrict": false,
37 | "minifyWXML": true,
38 | "showES6CompileOption": false,
39 | "useCompilerPlugins": [
40 | "typescript",
41 | "less"
42 | ],
43 | "lazyloadPlaceholderEnable": false,
44 | "useStaticServer": true,
45 | "condition": true
46 | },
47 | "appid": "wxbe6c30a61a51b422",
48 | "projectname": "证件照微信小程序",
49 | "libVersion": "2.14.1",
50 | "simulatorType": "wechat",
51 | "simulatorPluginLibVersion": {
52 | "wxext14566970e7e9f62": "2.27.3"
53 | },
54 | "compileType": "miniprogram",
55 | "srcMiniprogramRoot": "miniprogram/",
56 | "packOptions": {
57 | "ignore": [],
58 | "include": []
59 | },
60 | "editorSetting": {
61 | "tabIndent": "insertSpaces",
62 | "tabSize": 2
63 | },
64 | "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
65 | "condition": {},
66 | "projectArchitecture": "multiPlatform"
67 | }
--------------------------------------------------------------------------------
/project.miniapp.json:
--------------------------------------------------------------------------------
1 | {
2 | "miniVersion": "v2",
3 | "name": "免冠照片",
4 | "version": "0.0.1",
5 | "mini-android": {
6 | "sdkVersion": "1.0.21",
7 | "toolkitVersion": "0.10.0",
8 | "useExtendedSdk": {
9 | "media": false,
10 | "bluetooth": false,
11 | "network": false,
12 | "scanner": false,
13 | "xweb": false
14 | },
15 | "icons": {
16 | "hdpi": "",
17 | "xhdpi": "",
18 | "xxhdpi": "",
19 | "xxxhdpi": ""
20 | },
21 | "splashscreen": {
22 | "hdpi": "",
23 | "xhdpi": "",
24 | "xxhdpi": ""
25 | },
26 | "enableVConsole": "open",
27 | "privacy": {
28 | "enable": true
29 | }
30 | },
31 | "mini-ios": {
32 | "sdkVersion": "1.1.4",
33 | "toolkitVersion": "0.0.9",
34 | "useExtendedSdk": {
35 | "WeAppOpenFuns": true,
36 | "WeAppNetwork": false,
37 | "WeAppBluetooth": false,
38 | "WeAppMedia": false,
39 | "WeAppLBS": false,
40 | "WeAppOthers": false
41 | },
42 | "enableVConsole": "open",
43 | "icons": {
44 | "mainIcon120": "",
45 | "mainIcon180": "",
46 | "spotlightIcon80": "",
47 | "spotlightIcon120": "",
48 | "settingsIcon58": "",
49 | "settingsIcon87": "",
50 | "notificationIcon40": "",
51 | "notificationIcon60": "",
52 | "appStore1024": ""
53 | },
54 | "splashScreen": {
55 | "customImage": ""
56 | },
57 | "privacy": {
58 | "enable": false
59 | },
60 | "enableOpenUrlNavigate": true,
61 | "tpush": {
62 | "accessKey": "5am+m5q/ls"
63 | }
64 | },
65 | "versionCode": 100
66 | }
--------------------------------------------------------------------------------
/project.private.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "projectname": "证件照开源免费版",
3 | "setting": {
4 | "compileHotReLoad": true
5 | },
6 | "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
7 | "libVersion": "2.30.2"
8 | }
--------------------------------------------------------------------------------