├── LICENSE
├── README.md
├── images
├── 个人信息.png
├── 体质分析.png
├── 体质记录.png
├── 使用说明.png
├── 症状匹配.png
├── 膳食推荐.png
└── 首页.jpg
└── mini-program
├── backend
└── ai_tongue
│ ├── 3597134_www.aitongue.tech.crt
│ ├── 3597134_www.aitongue.tech.key
│ ├── RecWholeModel_5.pt
│ ├── __pycache__
│ ├── app.cpython-36.pyc
│ ├── app.cpython-37.pyc
│ ├── constant.cpython-36.pyc
│ ├── constant.cpython-37.pyc
│ ├── picSegment.cpython-36.pyc
│ ├── runModel.cpython-37.pyc
│ ├── runModel2.cpython-36.pyc
│ ├── runModel2.cpython-37.pyc
│ └── runModel3.cpython-36.pyc
│ ├── app.py
│ ├── app.pyc
│ ├── cert.pem
│ ├── constant.py
│ ├── information.csv
│ ├── key.pem
│ ├── nohup.out
│ ├── picSegment.py
│ ├── runModel.py
│ ├── runModel2.py
│ ├── runModel3.py
│ └── upload_picture
│ ├── 58957275.jpg
│ └── __pycache__
│ ├── api.cpython-37.pyc
│ ├── craws_proxy_ip.cpython-37.pyc
│ ├── douban.cpython-37.pyc
│ └── task.cpython-37.pyc
├── crawler
└── 爬取百度贴吧指定吧图片.py
└── frontend
├── .gitignore
├── app.js
├── app.json
├── app.wxss
├── colorUI
└── icon.wxss
├── image-cropper
├── image-cropper.js
├── image-cropper.json
├── image-cropper.wxml
└── image-cropper.wxss
├── images
├── ac_down.png
├── ac_icon.png
├── ac_up.png
├── air.png
├── bg_image.png
├── camera.png
├── cameraIcon.png
├── card.png
├── damp.png
├── diet.png
├── drink.png
├── eye.png
├── food-and-restaurant.png
├── food.png
├── food_rec.png
├── ganmao.png
├── help.png
├── icon_component_1.png
├── icon_component_2.png
├── icon_component_3.png
├── icon_component_4.png
├── info.png
├── info_card.png
├── like.png
├── next.png
├── risk.png
├── scan.png
├── shop.png
├── shopp.png
├── solar.png
├── solar_text.png
├── spit_rec.png
├── sym.png
├── tongue.png
├── tongue2.png
└── ziwai.png
├── package.json
├── pages
├── crop
│ ├── crop.js
│ ├── crop.json
│ ├── crop.wxml
│ └── crop.wxss
├── detail
│ ├── detail.js
│ ├── detail.json
│ ├── detail.wxml
│ └── detail.wxss
├── drinks
│ ├── drinks.js
│ ├── drinks.json
│ ├── drinks.wxml
│ └── drinks.wxss
├── help
│ ├── help.js
│ ├── help.json
│ ├── help.wxml
│ └── help.wxss
├── index
│ ├── index.js
│ ├── index.json
│ ├── index.wxml
│ └── index.wxss
├── logs
│ ├── logs.js
│ ├── logs.json
│ ├── logs.wxml
│ └── logs.wxss
├── optional
│ ├── optional.js
│ ├── optional.json
│ ├── optional.wxml
│ └── optional.wxss
└── result
│ ├── result.js
│ ├── result.json
│ ├── result.wxml
│ └── result.wxss
├── project.config.json
├── sitemap.json
└── utils
└── util.js
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 charfole
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 多模态信息融合主导的体质分析与膳食推荐小程序
2 |
3 | 本项目基于多模态信息融合的思想,打造了一款具有症状分析、智能舌诊功能的体质分析与膳食推荐微信小程序。
4 |
5 | ## 项目结构
6 | 项目的开发主要分为以下四个模块:
7 |
8 | - **数据获取与预处理模块**
9 |
10 | 主要用到的技术是网络爬虫,使用Python对网上的舌象图片爬取并下载到本地,之后删除掉一些冗余的图片,建立起初步的数据集并做好每张图片的数据标注。
11 |
12 | - **算法开发模块**
13 |
14 | 利用OpenCV进行图片分割、去除噪声,并且利用imgaug进行数据增广扩充数据集。舌象分类采用PyTorch框架进行开发,选择ResNet50构建模型。
15 |
16 | - **后端部署模块**
17 |
18 | 使用Gunicorn+Flask+阿里云服务器部署,将舌象分类模型与症状匹配模块信息融合后综合部署。
19 |
20 | - **微信小程序模块**
21 |
22 | 依托WXML、WXSS、JavaScript和众多开源的微信小程序组件,构建并提供一个界面精美,交互友好的小程序给用户。
23 |
24 | ## 小程序截图
25 |
26 | ### 1. 首页
27 |
28 |

29 |
30 | ### 2. 使用说明
31 |
32 | 
33 |
34 | ### 3. 症状匹配
35 |
36 | 
37 |
38 | ### 4. 体质分析
39 |
40 | 
41 |
42 | ### 5. 个人信息
43 |
44 | 
45 |
46 | ### 6. 膳食推荐
47 |
48 | 
49 |
50 | ### 7. 体质记录
51 |
52 | 
53 |
54 | ## License
55 |
56 | [MIT License](https://github.com/charfole/HeyConstitution/blob/master/LICENSE).
--------------------------------------------------------------------------------
/images/个人信息.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/images/个人信息.png
--------------------------------------------------------------------------------
/images/体质分析.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/images/体质分析.png
--------------------------------------------------------------------------------
/images/体质记录.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/images/体质记录.png
--------------------------------------------------------------------------------
/images/使用说明.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/images/使用说明.png
--------------------------------------------------------------------------------
/images/症状匹配.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/images/症状匹配.png
--------------------------------------------------------------------------------
/images/膳食推荐.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/images/膳食推荐.png
--------------------------------------------------------------------------------
/images/首页.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/images/首页.jpg
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/3597134_www.aitongue.tech.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIFnDCCBISgAwIBAgIQDEqw8CI+bV1UL2Xmr5EpKTANBgkqhkiG9w0BAQsFADBu
3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4 | d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
5 | RFYgVExTIENBIC0gRzEwHhcNMjAwMzEzMDAwMDAwWhcNMjEwMzE0MTIwMDAwWjAc
6 | MRowGAYDVQQDExF3d3cuYWl0b25ndWUudGVjaDCCASIwDQYJKoZIhvcNAQEBBQAD
7 | ggEPADCCAQoCggEBAMN/2z3aTAWj7KG41/7VJiwr6lG3cFoZAy05amD5Lx4X5Wju
8 | fc4SG83sUkqDMdyaCceMzBxwP2ePZn3XiegRDbPPukuUYfYv06+iJesLN4hsl0pI
9 | QVE+c1cG5UQiNEyz46a6k0WP+A6FutspKc6uK1cyhhB6GQvQzyHFAt/jEhA/ebm9
10 | 5s6aXnsI6q5EgJAf0aUds8bOU7Due7C2Fi668AlAvOPC/NhC+tW9Yl5hLxMlxm/j
11 | oOhk/Xh5ut9sBXeI0uSYiObcWh5pJr4F7Y2/fIsSrdz0feVqVFWrtiPQ4XhlPcVV
12 | g5Wui+H04wXOHxeQzS4VvcZbSFlMVicJQO5hlTcCAwEAAaOCAoYwggKCMB8GA1Ud
13 | IwQYMBaAFFV0T7JyT/VgulDR1+ZRXJoBhxrXMB0GA1UdDgQWBBRmKpZ+BdPtG06G
14 | ooKESgstRWucxTArBgNVHREEJDAighF3d3cuYWl0b25ndWUudGVjaIINYWl0b25n
15 | dWUudGVjaDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
16 | AQUFBwMCMEwGA1UdIARFMEMwNwYJYIZIAYb9bAECMCowKAYIKwYBBQUHAgEWHGh0
17 | dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQIBMIGABggrBgEFBQcB
18 | AQR0MHIwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBKBggr
19 | BgEFBQcwAoY+aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0VuY3J5cHRpb25F
20 | dmVyeXdoZXJlRFZUTFNDQS1HMS5jcnQwCQYDVR0TBAIwADCCAQYGCisGAQQB1nkC
21 | BAIEgfcEgfQA8gB3ALvZ37wfinG1k5Qjl6qSe0c4V5UKq1LoGpCWZDaOHtGFAAAB
22 | cNTXLBEAAAQDAEgwRgIhALuZe6ABSmbJKu2EVbSEuLQ+jvAqCk2d4jN/9BxUPH5Q
23 | AiEA8+gABTOHj209eH5jFOP0O36S0SEj+nXezedbKFRwU6MAdwBc3EOS/uarRUSx
24 | XprUVuYQN/vV+kfcoXOUsl7m9scOygAAAXDU1yxBAAAEAwBIMEYCIQDD86Iw3jlh
25 | ocdyuLxIR8LoEeHxjjzBL5geppBFX2iEbQIhAJbnPQWrVNjcuedX1XS9qKXILMwX
26 | PXXUF8L0fgKkti8bMA0GCSqGSIb3DQEBCwUAA4IBAQAtZxDFmgnzt83K20oZ0/vs
27 | uDThJEzEw6WGKoyburs3qxeHaPmWNhERiBlmHAJkFPikE3QWwnSLPaKBpMpSheXG
28 | ANQ9taupwkkXG5YLu2LuML3gY7eRxxPJfmIITf2YyZEp2NQ7ZhphNOO9Hxmf2UNj
29 | 0fyhYTeAGcEjKw3D+W/S1NyE66D89uu8JXparHs5tce/Jyv1S6JwT++RWlPHZpkp
30 | oddA8JYv8OcuS0cqt4qNpCuyfKS6GNBPPzrWcbmALuZNGRr7Oo3AJMQmEza7YNIr
31 | 2r5+75+5k+UQmy4lipr5jqnfoCuavn1b1mJuv9hHikIEMrP+d+TBv4LJr6EvgSh2
32 | -----END CERTIFICATE-----
33 | -----BEGIN CERTIFICATE-----
34 | MIIEqjCCA5KgAwIBAgIQAnmsRYvBskWr+YBTzSybsTANBgkqhkiG9w0BAQsFADBh
35 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
36 | d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
37 | QTAeFw0xNzExMjcxMjQ2MTBaFw0yNzExMjcxMjQ2MTBaMG4xCzAJBgNVBAYTAlVT
38 | MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
39 | b20xLTArBgNVBAMTJEVuY3J5cHRpb24gRXZlcnl3aGVyZSBEViBUTFMgQ0EgLSBH
40 | MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALPeP6wkab41dyQh6mKc
41 | oHqt3jRIxW5MDvf9QyiOR7VfFwK656es0UFiIb74N9pRntzF1UgYzDGu3ppZVMdo
42 | lbxhm6dWS9OK/lFehKNT0OYI9aqk6F+U7cA6jxSC+iDBPXwdF4rs3KRyp3aQn6pj
43 | pp1yr7IB6Y4zv72Ee/PlZ/6rK6InC6WpK0nPVOYR7n9iDuPe1E4IxUMBH/T33+3h
44 | yuH3dvfgiWUOUkjdpMbyxX+XNle5uEIiyBsi4IvbcTCh8ruifCIi5mDXkZrnMT8n
45 | wfYCV6v6kDdXkbgGRLKsR4pucbJtbKqIkUGxuZI2t7pfewKRc5nWecvDBZf3+p1M
46 | pA8CAwEAAaOCAU8wggFLMB0GA1UdDgQWBBRVdE+yck/1YLpQ0dfmUVyaAYca1zAf
47 | BgNVHSMEGDAWgBQD3lA1VtFMu2bwo+IbG8OXsj3RVTAOBgNVHQ8BAf8EBAMCAYYw
48 | HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
49 | AQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
50 | Y2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQu
51 | Y29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG
52 | /WwBAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
53 | MAgGBmeBDAECATANBgkqhkiG9w0BAQsFAAOCAQEAK3Gp6/aGq7aBZsxf/oQ+TD/B
54 | SwW3AU4ETK+GQf2kFzYZkby5SFrHdPomunx2HBzViUchGoofGgg7gHW0W3MlQAXW
55 | M0r5LUvStcr82QDWYNPaUy4taCQmyaJ+VB+6wxHstSigOlSNF2a6vg4rgexixeiV
56 | 4YSB03Yqp2t3TeZHM9ESfkus74nQyW7pRGezj+TC44xCagCQQOzzNmzEAP2SnCrJ
57 | sNE2DpRVMnL8J6xBRdjmOsC3N6cQuKuRXbzByVBjCqAA8t1L0I+9wXJerLPyErjy
58 | rMKWaBFLmfK/AHNF4ZihwPGOc7w6UHczBZXH5RFzJNnww+WnKuTPI0HfnVH8lg==
59 | -----END CERTIFICATE-----
60 |
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/3597134_www.aitongue.tech.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEowIBAAKCAQEAw3/bPdpMBaPsobjX/tUmLCvqUbdwWhkDLTlqYPkvHhflaO59
3 | zhIbzexSSoMx3JoJx4zMHHA/Z49mfdeJ6BENs8+6S5Rh9i/Tr6Il6ws3iGyXSkhB
4 | UT5zVwblRCI0TLPjprqTRY/4DoW62ykpzq4rVzKGEHoZC9DPIcUC3+MSED95ub3m
5 | zppeewjqrkSAkB/RpR2zxs5TsO57sLYWLrrwCUC848L82EL61b1iXmEvEyXGb+Og
6 | 6GT9eHm632wFd4jS5JiI5txaHmkmvgXtjb98ixKt3PR95WpUVau2I9DheGU9xVWD
7 | la6L4fTjBc4fF5DNLhW9xltIWUxWJwlA7mGVNwIDAQABAoIBAED/WEgHNPFHH9xg
8 | 1Uc/XJKhAyWqBGugF0NI7IpTLowly7sIV8FUmfPr1yw41DIQ8KFsuUvXMe1faub5
9 | 6zrBuLmIndqU+cDdA9dH5K1xrEPqPp6OyVCWn8hWXZE6ggLiaBS9wUsGY6WIZqiI
10 | 1gKGO5ihDpuZzIv2H3eNxbfkCdRmgNsjoYSR6myIAuZA/F4uISuLBR1A5OYn4OrT
11 | jD33ElusRibi73lbc2Uwp2S9ws9tY4MJxO4SEmHc+U2TvK1ITWKg4Zzsoflt5udq
12 | S3TpseCAwYv0p6HhN+o9/k+lln8Spka58Fijbb7qkBdnpcG7ZtMP7r9LxMwKuGcj
13 | 8d8a2akCgYEA9JmACdCvNGlz6katihG+Hh0FxP+y/N5BEKW4UaTxD0msWd7gHuSY
14 | 05FR/z1rPAy0Is7RigBYsI3ZfQGvD0ze+E44Fj0vjnCiFu2BgSwy7YVSYTQ6gyvV
15 | 2RCeoI+9JBleVjVRCGTG7xM29z17ITUMNliXoDbdVekLe1to7+a6ATsCgYEAzJyB
16 | b6EemgspdR3Xn1BUzvgwXO8Bp2i6JDkf09FWK2SfcdgxGYQbu/2tigx39TJQAJsr
17 | Wa2btzwB5dX4ttnOic1A4BiAOI53w3cp1vdJ9K9FT1FYsLwhnQ34/6ivpd2G+hAa
18 | ZHAnCocjufeI8QPiI+w93Lb/eqvBlXFCniNovDUCgYEAh04GWueak7alzXnNc6v+
19 | 7C+HyoLb4y+a9HeHr3o7cwaBFbHJbq1rsNUZc8To9e3dE8gud1VbukatgY4V5bPT
20 | P64dLogoL3Y049P8KJVnkqaGfIjkuTzdbdbYuN7qdPanja6upaMBvKx3YmsbGrJ6
21 | j/GP5quS4nwowtM9CEAsspMCgYBvUH3Cgz8owwXM521VCNj6uF9nT8fwkbMi3ckI
22 | 7YwZk2aDAwDDRvHntjzhK6NfS/3mNoTBBwf+CbFmnp/uqlQI+BdhUzL+kdNqDbw/
23 | bM1ZRrlIS5Mao18OGHnsbJMSg5BZHsWc+r7ipV60X4yqwlgW/wEwwIYA8MwiRznc
24 | 2pqyOQKBgDuVTqY6QUhNduIh+0SHb+TXuHCgNSfBDlaLMTDQ1NdLPTagFgNCOL5t
25 | v1h/b0miku9nNIZGf6KhArxz/Sx7xBIkpz7U4oR72RiLmrrFFvkZlr50CruJMmb+
26 | lNU5BDgazorRMZQqK3DZr2u8k8YXRU7PvDYozzFdLhq4g3epDkk+
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/RecWholeModel_5.pt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/RecWholeModel_5.pt
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/__pycache__/app.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/__pycache__/app.cpython-36.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/__pycache__/app.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/__pycache__/app.cpython-37.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/__pycache__/constant.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/__pycache__/constant.cpython-36.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/__pycache__/constant.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/__pycache__/constant.cpython-37.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/__pycache__/picSegment.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/__pycache__/picSegment.cpython-36.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/__pycache__/runModel.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/__pycache__/runModel.cpython-37.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/__pycache__/runModel2.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/__pycache__/runModel2.cpython-36.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/__pycache__/runModel2.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/__pycache__/runModel2.cpython-37.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/__pycache__/runModel3.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/__pycache__/runModel3.cpython-36.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/app.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 |
3 | # author:Tang Gaozhi
4 |
5 | import os
6 | import random
7 | from flask import Flask, request, url_for, send_from_directory,jsonify
8 |
9 | # from werkzeug import secure_filename
10 | from werkzeug.utils import secure_filename
11 |
12 |
13 | # import runModel
14 | # import runModel2
15 | import runModel3
16 | import picSegment
17 |
18 | from constant import value2Dict, type2Dict, weights2Dict
19 | from constant import imgUrl
20 |
21 | import time
22 |
23 | #保存信息用
24 | import csv
25 |
26 |
27 | ALLOWED_EXTENSIONS = set(['bmp','png', 'jpg', 'jpeg', 'gif'])
28 |
29 | app = Flask(__name__)
30 | app.config['UPLOAD_FOLDER'] = os.getcwd()+'/upload_picture'
31 | app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
32 |
33 |
34 | html = '''
35 |
36 | Upload File
37 | Photo Upload
38 |
42 | '''
43 |
44 |
45 | def allowed_file(filename):
46 | return '.' in filename and \
47 | filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
48 |
49 |
50 | @app.route('/uploads/')
51 | def uploaded_file(filename):
52 | return send_from_directory(app.config['UPLOAD_FOLDER'],
53 | filename)
54 |
55 |
56 | @app.route('/', methods=['GET', 'POST'])
57 | def upload_file():
58 |
59 | message = "null"
60 | isTongue = True
61 | predictedTypeRate = 0.0
62 | tags = []
63 | result = -1
64 | maxConfidence = 0.0
65 |
66 | #下面那几个变量只是为了写入信息,不需要时应该删掉
67 | writeName = "未命名"
68 | typeList = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]
69 | writePredictRate = []
70 | writeTotalRate = {}
71 | weight2Dict = {}
72 |
73 | try:
74 |
75 | if request.method == 'POST':
76 | file = request.files['file']
77 | # print(request.values.get("tags"))
78 | if file and allowed_file(file.filename):
79 | # filename = secure_filename(file.filename)
80 | fileTime = time.strftime("%Y-%m-%d", time.localtime())+"-"+time.strftime("%H:%M:%S", time.localtime())
81 | try:
82 | name = secure_filename(file.filename)
83 | suffix = name[name.rfind("."):]
84 | if request.values.get("name")!="null":
85 | filename = request.values.get("name")+fileTime+suffix
86 | writeName = request.values.get("name")
87 | else:
88 | filename = secure_filename(file.filename)
89 | writeName = filename
90 | except:
91 | filename = secure_filename(file.filename)
92 | writeName = filename
93 |
94 | file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
95 | file_url = url_for('uploaded_file', filename=filename)
96 |
97 | isTongue = picSegment.pictureProcess(os.path.join(app.config['UPLOAD_FOLDER'], filename))
98 |
99 | try:
100 | tagsString = request.values.get("tags")
101 | # print(tagsString)
102 | if tagsString!="":
103 | tags = tagsString.split(",")
104 | except:
105 | tagsString = ""
106 | pass
107 |
108 | try:
109 |
110 | if isTongue==True:
111 | rate = runModel3.getResult(os.path.join(app.config['UPLOAD_FOLDER'], filename).replace(".", "_mask."))#这里需要注意,模型2是rec,模型3是mask
112 | # print(os.path.join(app.config['UPLOAD_FOLDER'], filename).replace(".", "_rec."))
113 | # print(rate)
114 | # rate = rate.tolist()#转为list,方便处理
115 | writePredictRate =rate
116 | # print(rate)
117 | predictedTypeRate = max(rate)#留一手,若无tags传过来,这两个就用上了
118 | maxConfidence = predictedTypeRate#看看纯预测的置信度最高的是多少
119 | result = rate.index(predictedTypeRate)
120 |
121 |
122 | if len(tags)!=0:
123 | # weight2Dict = {}
124 |
125 | for i in range(0,len(rate)):
126 | weight2Dict[i] = 0.4*rate[i]
127 | for tag in tags:
128 | # print(tags)
129 | weight2Dict[int(type2Dict[tag])-1] += weights2Dict[tag]*0.6
130 | typeList[int(type2Dict[tag])-1] += weights2Dict[tag]
131 | if tag=="身体水肿":#因为有重叠的,还要算上另一个
132 | weight2Dict[6] += weights2Dict["水肿"]*0.6
133 | if tag=="大便稀溏":
134 | weight2Dict[3] += weights2Dict["大便稀"]*0.6
135 | if tag=="胸胁疼痛":
136 | weight2Dict[2] += 0.3*0.6
137 | if tag=="乏力":
138 | weight2Dict[1] += 0.5*0.6
139 |
140 | writeTotalRate = weight2Dict
141 | typeWeight = sorted(weight2Dict.items(),key=lambda item:item[1])
142 |
143 | result = typeWeight[-1][0]#预测体质名称下标
144 | predictedTypeRate = typeWeight[-1][1]#置信度
145 | # print(predictedTypeRate)
146 |
147 | else:
148 | writeTotalRate = writePredictRate#这句干嘛来着我忘了
149 |
150 | for i in range(0,len(rate)):
151 | weight2Dict[i] = rate[i]
152 |
153 | # type = value2Dict[str(result+1)]
154 | # # print(type)
155 |
156 | # newname = filename[:filename.find(".")] + "," + tagsString +","+ type +filename[filename.find("."):]
157 |
158 | # os.chdir(os.getcwd()+'/upload_picture')
159 |
160 | # os.rename(filename,newname)
161 |
162 | else:
163 | message = "上传照片未检测到舌头,请重新上传!"
164 |
165 | except:
166 | message = "服务器异常1,请过几分钟再试!若仍不行,请联系1348040397@qq.com"
167 | pass
168 |
169 | else:
170 | message = "请求方式错误!正确请求为POST"
171 | return html
172 |
173 | except:
174 | message = "服务器异常2,请过几分钟再试!若仍不行,请联系1348040397@qq.com"
175 |
176 | # num = str(random.randint(0,9))
177 |
178 | # print(predictedTypeRate)
179 | # print(maxConfidence)
180 |
181 | # 8月10日注释掉,修改代码
182 | # if len(tags)!=0 and predictedTypeRate>0.25:
183 | # num = str(result+1)
184 | # elif len(tags)==0 and predictedTypeRate>0.50:
185 | # num = str(result+1)
186 | # # elif maxConfidence<0.40:
187 | # # num = str(0)
188 | # else:
189 | # num = str(1)
190 |
191 |
192 | num = str(0)
193 |
194 |
195 |
196 | # judgeFlag = True
197 |
198 | # for i in range(0,len(rate)-1):
199 | # if weight2Dict[i+2]>=0.5:
200 | # judgeFlag = False
201 |
202 | # print(weight2Dict)
203 |
204 | if weight2Dict=={} and isTongue==True:
205 | message = "服务器已宕机,请联系我们重启程序!"
206 |
207 | if isTongue==True and weight2Dict!={}:
208 |
209 | if weight2Dict[1]>0.5:
210 | num = str(1)
211 | elif maxConfidence<0.5:
212 | message = "未知体质,请检查上传图片是否正确!!"
213 | else:
214 | num = str(result+1)
215 |
216 | t = {'message':message,'confidence':str( round(predictedTypeRate, 3) ) ,'body':value2Dict[num],'imgUrl':imgUrl[value2Dict[num]],'year_month_day':time.strftime("%Y-%m-%d", time.localtime()),'time':time.strftime("%H:%M", time.localtime()) }
217 |
218 | path = "information.csv"
219 |
220 | with open(path,'a+',newline=None,encoding='gbk') as f:
221 | csv_write = csv.writer(f)
222 | writeTime = time.strftime("%Y-%m-%d", time.localtime())+"-"+time.strftime("%H:%M", time.localtime())
223 | data_row = [writeName,filename,writeTime,tagsString,typeList,writePredictRate,writeTotalRate,value2Dict[num]]
224 | csv_write.writerow(data_row)
225 |
226 | # t = {'body':value2Dict['0'],'imgUrl':imgUrl[value2Dict['0']],'year_month_day':time.strftime("%Y-%m-%d", time.localtime()),'time':time.strftime("%H:%M", time.localtime()) }
227 | return jsonify(t)
228 |
229 |
230 | if __name__ == '__main__':
231 | # app.run(host='0.0.0.0')
232 | app.run(host='0.0.0.0',ssl_context=('3597134_www.aitongue.tech.pem', '3597134_www.aitongue.tech.key'))
233 |
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/app.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/app.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
33 | /57P
34 | -----END CERTIFICATE-----
35 |
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/constant.py:
--------------------------------------------------------------------------------
1 | imgUrl = {"未知体质":"https://s1.ax1x.com/2020/05/06/YExgxK.png",
2 | "湿热质":"https://s1.ax1x.com/2020/05/06/YEx4VH.png",
3 | "气虚质":"https://s1.ax1x.com/2020/05/06/YExIIA.png",
4 | "血瘀质":"https://s1.ax1x.com/2020/05/06/YExLM8.png",
5 | "特禀质":"https://s1.ax1x.com/2020/05/06/YExvZQ.png",
6 | "痰湿质":"https://s1.ax1x.com/2020/05/06/YExzIs.png",
7 | "阴虚质":"https://s1.ax1x.com/2020/05/06/YEzCR0.png",
8 | "阳虚质":"https://s1.ax1x.com/2020/05/06/YEzALF.png",
9 | "平和质":"https://s1.ax1x.com/2020/05/06/YEzZdJ.png",
10 | "气郁质":"https://s1.ax1x.com/2020/05/06/YEzeo9.png",
11 | }
12 |
13 | # value2Dict ={"0":"未知体质",
14 | # "1":"湿热质",
15 | # "2":"气虚质",
16 | # "3":"血瘀质",
17 | # "4":"特禀质",
18 | # "5":"痰湿质",
19 | # "6":"阴虚质",
20 | # "7":"阳虚质",
21 | # "8":"平和质",
22 | # "9":"气郁质"}
23 |
24 | ###下面是version2版本,对应新模型,上面对应旧模型
25 |
26 | value2Dict ={"0":"未知体质",
27 | "1":"平和质",
28 | "2":"气虚质",
29 | "3":"气郁质",
30 | "4":"湿热质",
31 | "5":"痰湿质",
32 | "6":"血瘀质",
33 | "7":"阳虚质",
34 | "8":"阴虚质"}
35 |
36 | # type2Dict = {
37 | # "不易疲劳":"1",
38 | # "耐寒受热":"1",
39 | # "乏力":"2",
40 | # "自汗":"2",
41 | # "容易生气":"3",
42 | # "多愁善感":"3",
43 | # "口腔溃疡":"4",
44 | # "长痘痘":"4",
45 | # "头胀胸闷":"5",
46 | # "多痰":"5",
47 | # "面色晦暗":"6",
48 | # "胸胁疼痛":"6",
49 | # "怕冷":"7",
50 | # "乏力":"7",
51 | # "口渴":"8",
52 | # "自觉发热":"8",
53 | # }
54 |
55 | type2Dict = {
56 | "耐受寒热":"1","不易疲劳":"1",
57 | "乏力":"2","少气懒言":"2","自汗":"2","容易感冒":"2",
58 | "容易生气":"3","胸胁胀痛":"3","嗳气叹气":"3","多愁善感": "3",
59 | "消化不良":"4","大便稀":"4","易长痘痘":"4","口苦":"4","身体困重":"4","口腔溃疡":"4",
60 | "痰多":"5","身体水肿":"5","头胀胸闷":"5","关节疼痛":"5",
61 | "月经血块":"6","皮肤粗糙有瘀斑":"6","面色晦暗":"6","胸胁疼痛":"6",
62 | "畏寒肢冷":"7","大便稀溏":"7","乏力":"7","水肿":"7",
63 | "口渴":"8","自觉发热":"8","心烦":"8","失眠":"8","皮肤干燥":"8"
64 | }
65 |
66 | weights2Dict = {
67 | "耐受寒热":0.4,"不易疲劳":0.6,
68 | "乏力":0.5,"少气懒言":0.2,"自汗":0.2,"容易感冒":0.1,
69 | "容易生气":0.3,"胸胁胀痛":0.3,"嗳气叹气":0.2,"多愁善感": 0.2,
70 | "消化不良":0.1,"大便稀":0.1,"易长痘痘":0.1,"口苦":0.3,"身体困重":0.2,"口腔溃疡":0.2,
71 | "痰多":0.3,"身体水肿":0.3,"头胀胸闷":0.2,"关节疼痛":0.2,
72 | "月经血块":0.3,"皮肤粗糙有瘀斑":0.3,"面色晦暗":0.2,"胸胁疼痛":0.2,
73 | "畏寒肢冷":0.3,"大便稀溏":0.3,"乏力":0.2,"水肿":0.2,
74 | "口渴":0.3,"自觉发热":0.2,"心烦":0.2,"失眠":0.2,"皮肤干燥":0.1
75 | }
76 |
77 | # type2List = [
78 | # {"乏力":0.5,"少气懒言":0.2,"自汗":0.2,"容易感冒":0.1},
79 | # {"容易生气":0.3,"胸胁胀痛":0.3,"嗳气叹气":0.2,"多愁善感": 0.2},
80 | # {"消化不良":0.1,"大便稀":0.1,"易长痘痘":0.1,"口苦":0.3,"身体困重":0.2,"口腔溃疡":0.2},
81 | # {"痰多":0.3,"身体水肿":0.3,"头胀胸闷":0.2,"关节疼痛":0.2},
82 | # {"月经血块":0.3,"皮肤粗糙有瘀斑":0.3,"面色晦暗":0.2,"胸胁疼痛":0.2},
83 | # {"畏寒肢冷":0.3,"大便稀溏":0.3,"乏力":0.2,"水肿":0.2}
84 | # {"口渴":0.3,"自觉发热":0.2,"心烦":0.2,"失眠":0.2,"皮肤干噪":0.1 }
85 | # ]
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/information.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/information.csv
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | 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
51 | 8zXYzktr0dTPS4mj35UIxl/yeRQV02Q=
52 | -----END PRIVATE KEY-----
53 |
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/nohup.out:
--------------------------------------------------------------------------------
1 | [2020-04-21 08:31:45 -0400] [12890] [INFO] Starting gunicorn 20.0.4
2 | [2020-04-21 08:31:45 -0400] [12890] [INFO] Listening at: https://0.0.0.0:8666 (12890)
3 | [2020-04-21 08:31:45 -0400] [12890] [INFO] Using worker: sync
4 | [2020-04-21 08:31:45 -0400] [12893] [INFO] Booting worker with pid: 12893
5 | [2020-04-21 08:31:46 -0400] [12894] [INFO] Booting worker with pid: 12894
6 | [2020-04-21 08:31:46 -0400] [12896] [INFO] Booting worker with pid: 12896
7 | [2020-04-21 08:31:46 -0400] [12897] [INFO] Booting worker with pid: 12897
8 | [2020-04-21 08:31:54 -0400] [12890] [INFO] Handling signal: hup
9 | [2020-04-21 08:31:54 -0400] [12890] [INFO] Hang up: Master
10 | [2020-04-21 08:31:54 -0400] [12905] [INFO] Booting worker with pid: 12905
11 | [2020-04-21 08:31:54 -0400] [12906] [INFO] Booting worker with pid: 12906
12 | [2020-04-21 08:31:54 -0400] [12907] [INFO] Booting worker with pid: 12907
13 | [2020-04-21 08:31:54 -0400] [12908] [INFO] Booting worker with pid: 12908
14 | [2020-04-21 08:32:25 -0400] [12890] [CRITICAL] WORKER TIMEOUT (pid:12905)
15 | [2020-04-21 08:32:26 -0400] [12953] [INFO] Booting worker with pid: 12953
16 | [2020-04-25 10:40:32 -0400] [12890] [CRITICAL] WORKER TIMEOUT (pid:12906)
17 | [2020-04-25 10:40:33 -0400] [22448] [INFO] Booting worker with pid: 22448
18 | [2020-04-25 10:40:54 -0400] [12890] [CRITICAL] WORKER TIMEOUT (pid:12908)
19 | [2020-04-25 10:40:55 -0400] [22460] [INFO] Booting worker with pid: 22460
20 | [2020-04-25 10:41:03 -0400] [12890] [CRITICAL] WORKER TIMEOUT (pid:22448)
21 | [2020-04-25 10:41:04 -0400] [22472] [INFO] Booting worker with pid: 22472
22 | [2020-04-25 10:41:18 -0400] [12890] [CRITICAL] WORKER TIMEOUT (pid:12907)
23 | [2020-04-25 10:41:18 -0400] [12890] [CRITICAL] WORKER TIMEOUT (pid:12953)
24 | Using TensorFlow backend.
25 | [2020-04-25 10:41:18 -0400] [12907] [INFO] Worker exiting (pid: 12907)
26 | [2020-04-25 10:41:19 -0400] [22480] [INFO] Booting worker with pid: 22480
27 | [2020-04-25 10:41:19 -0400] [22481] [INFO] Booting worker with pid: 22481
28 | [2020-04-25 10:41:49 -0400] [12890] [CRITICAL] WORKER TIMEOUT (pid:22480)
29 | [2020-04-25 10:41:50 -0400] [22505] [INFO] Booting worker with pid: 22505
30 | [2020-04-25 10:43:42 -0400] [12890] [CRITICAL] WORKER TIMEOUT (pid:22460)
31 | [2020-04-25 10:43:43 -0400] [22583] [INFO] Booting worker with pid: 22583
32 | [2020-04-25 10:44:14 -0400] [12890] [CRITICAL] WORKER TIMEOUT (pid:22481)
33 | [2020-04-25 10:44:15 -0400] [22605] [INFO] Booting worker with pid: 22605
34 | [2020-04-25 10:44:32 -0400] [22625] [INFO] Starting gunicorn 20.0.4
35 | [2020-04-25 10:44:32 -0400] [22625] [INFO] Listening at: https://0.0.0.0:8666 (22625)
36 | [2020-04-25 10:44:32 -0400] [22625] [INFO] Using worker: sync
37 | [2020-04-25 10:44:32 -0400] [22628] [INFO] Booting worker with pid: 22628
38 | [2020-04-25 10:44:32 -0400] [22629] [INFO] Booting worker with pid: 22629
39 | [2020-04-25 10:44:32 -0400] [22630] [INFO] Booting worker with pid: 22630
40 | [2020-04-25 10:44:32 -0400] [22631] [INFO] Booting worker with pid: 22631
41 | [2020-04-25 10:45:02 -0400] [22625] [CRITICAL] WORKER TIMEOUT (pid:22628)
42 | [2020-04-25 10:45:03 -0400] [22660] [INFO] Booting worker with pid: 22660
43 | [2020-04-25 10:45:12 -0400] [22625] [CRITICAL] WORKER TIMEOUT (pid:22631)
44 | [2020-04-25 10:45:13 -0400] [22667] [INFO] Booting worker with pid: 22667
45 | [2020-04-25 10:45:34 -0400] [22625] [CRITICAL] WORKER TIMEOUT (pid:22660)
46 | [2020-04-25 10:45:35 -0400] [22687] [INFO] Booting worker with pid: 22687
47 | [2020-04-25 10:45:43 -0400] [22625] [CRITICAL] WORKER TIMEOUT (pid:22630)
48 | [2020-04-25 10:45:44 -0400] [22693] [INFO] Booting worker with pid: 22693
49 | [2020-04-25 10:52:25 -0400] [23123] [INFO] Starting gunicorn 20.0.4
50 | [2020-04-25 10:52:25 -0400] [23123] [INFO] Listening at: https://0.0.0.0:8666 (23123)
51 | [2020-04-25 10:52:25 -0400] [23123] [INFO] Using worker: sync
52 | [2020-04-25 10:52:25 -0400] [23126] [INFO] Booting worker with pid: 23126
53 | [2020-04-25 10:52:25 -0400] [23127] [INFO] Booting worker with pid: 23127
54 | [2020-04-25 10:52:25 -0400] [23128] [INFO] Booting worker with pid: 23128
55 | [2020-04-25 10:52:25 -0400] [23129] [INFO] Booting worker with pid: 23129
56 | [2020-04-25 10:52:29 -0400] [23123] [INFO] Handling signal: hup
57 | [2020-04-25 10:52:29 -0400] [23123] [INFO] Hang up: Master
58 | [2020-04-25 10:52:29 -0400] [23143] [INFO] Booting worker with pid: 23143
59 | [2020-04-25 10:52:29 -0400] [23144] [INFO] Booting worker with pid: 23144
60 | [2020-04-25 10:52:29 -0400] [23146] [INFO] Booting worker with pid: 23146
61 | [2020-04-25 10:52:29 -0400] [23145] [INFO] Booting worker with pid: 23145
62 | Using TensorFlow backend.
63 | [2020-04-26 03:20:16,440] ERROR in app: Exception on / [POST]
64 | Traceback (most recent call last):
65 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
66 | response = self.full_dispatch_request()
67 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
68 | rv = self.handle_user_exception(e)
69 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
70 | reraise(exc_type, exc_value, tb)
71 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
72 | raise value
73 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
74 | rv = self.dispatch_request()
75 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
76 | return self.view_functions[rule.endpoint](**req.view_args)
77 | File "/home1/user/jcf/root/flask/app.py", line 60, in upload_file
78 | except:
79 | File "/home1/user/jcf/anaconda3/lib/python3.7/posixpath.py", line 94, in join
80 | genericpath._check_arg_types('join', a, *p)
81 | File "/home1/user/jcf/anaconda3/lib/python3.7/genericpath.py", line 149, in _check_arg_types
82 | (funcname, s.__class__.__name__)) from None
83 | TypeError: join() argument must be str or bytes, not 'NoneType'
84 | [2020-04-26 03:20:46 -0400] [23123] [CRITICAL] WORKER TIMEOUT (pid:23146)
85 | Using TensorFlow backend.
86 | [2020-04-26 03:20:46 -0400] [23146] [INFO] Worker exiting (pid: 23146)
87 | [2020-04-26 03:20:46 -0400] [31143] [INFO] Booting worker with pid: 31143
88 | Using TensorFlow backend.
89 | [2020-04-26 03:21:09,034] ERROR in app: Exception on / [POST]
90 | Traceback (most recent call last):
91 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
92 | response = self.full_dispatch_request()
93 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
94 | rv = self.handle_user_exception(e)
95 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
96 | reraise(exc_type, exc_value, tb)
97 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
98 | raise value
99 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
100 | rv = self.dispatch_request()
101 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
102 | return self.view_functions[rule.endpoint](**req.view_args)
103 | File "/home1/user/jcf/root/flask/app.py", line 60, in upload_file
104 | except:
105 | File "/home1/user/jcf/anaconda3/lib/python3.7/posixpath.py", line 94, in join
106 | genericpath._check_arg_types('join', a, *p)
107 | File "/home1/user/jcf/anaconda3/lib/python3.7/genericpath.py", line 149, in _check_arg_types
108 | (funcname, s.__class__.__name__)) from None
109 | TypeError: join() argument must be str or bytes, not 'NoneType'
110 | [2020-04-26 03:21:19,869] ERROR in app: Exception on / [POST]
111 | Traceback (most recent call last):
112 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
113 | response = self.full_dispatch_request()
114 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
115 | rv = self.handle_user_exception(e)
116 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
117 | reraise(exc_type, exc_value, tb)
118 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
119 | raise value
120 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
121 | rv = self.dispatch_request()
122 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
123 | return self.view_functions[rule.endpoint](**req.view_args)
124 | File "/home1/user/jcf/root/flask/app.py", line 60, in upload_file
125 | except:
126 | File "/home1/user/jcf/anaconda3/lib/python3.7/posixpath.py", line 94, in join
127 | genericpath._check_arg_types('join', a, *p)
128 | File "/home1/user/jcf/anaconda3/lib/python3.7/genericpath.py", line 149, in _check_arg_types
129 | (funcname, s.__class__.__name__)) from None
130 | TypeError: join() argument must be str or bytes, not 'NoneType'
131 | [2020-04-26 03:21:59 -0400] [31195] [INFO] Starting gunicorn 20.0.4
132 | [2020-04-26 03:21:59 -0400] [31195] [INFO] Listening at: https://0.0.0.0:8666 (31195)
133 | [2020-04-26 03:21:59 -0400] [31195] [INFO] Using worker: sync
134 | [2020-04-26 03:21:59 -0400] [31198] [INFO] Booting worker with pid: 31198
135 | [2020-04-26 03:21:59 -0400] [31199] [INFO] Booting worker with pid: 31199
136 | [2020-04-26 03:21:59 -0400] [31200] [INFO] Booting worker with pid: 31200
137 | [2020-04-26 03:21:59 -0400] [31201] [INFO] Booting worker with pid: 31201
138 | [2020-04-26 03:22:30 -0400] [31195] [CRITICAL] WORKER TIMEOUT (pid:31199)
139 | [2020-04-26 03:22:31 -0400] [31228] [INFO] Booting worker with pid: 31228
140 | [2020-04-26 03:22:33 -0400] [31195] [CRITICAL] WORKER TIMEOUT (pid:31200)
141 | Using TensorFlow backend.
142 | [2020-04-26 03:22:33 -0400] [31200] [INFO] Worker exiting (pid: 31200)
143 | [2020-04-26 03:22:33 -0400] [31231] [INFO] Booting worker with pid: 31231
144 | [2020-04-26 03:23:05 -0400] [31195] [CRITICAL] WORKER TIMEOUT (pid:31231)
145 | [2020-04-26 03:23:06 -0400] [31255] [INFO] Booting worker with pid: 31255
146 | [2020-04-26 03:23:09 -0400] [31195] [CRITICAL] WORKER TIMEOUT (pid:31201)
147 | Using TensorFlow backend.
148 | [2020-04-26 03:23:09 -0400] [31201] [INFO] Worker exiting (pid: 31201)
149 | [2020-04-26 03:23:09 -0400] [31264] [INFO] Booting worker with pid: 31264
150 | [2020-04-26 03:23:39 -0400] [31195] [CRITICAL] WORKER TIMEOUT (pid:31264)
151 | [2020-04-26 03:23:40 -0400] [31287] [INFO] Booting worker with pid: 31287
152 | [2020-04-26 03:23:44 -0400] [31195] [CRITICAL] WORKER TIMEOUT (pid:31198)
153 | Using TensorFlow backend.
154 | [2020-04-26 03:23:44 -0400] [31198] [INFO] Worker exiting (pid: 31198)
155 | [2020-04-26 03:23:45 -0400] [31291] [INFO] Booting worker with pid: 31291
156 | [2020-04-26 03:28:16 -0400] [31560] [INFO] Starting gunicorn 20.0.4
157 | [2020-04-26 03:28:16 -0400] [31560] [INFO] Listening at: https://0.0.0.0:8666 (31560)
158 | [2020-04-26 03:28:16 -0400] [31560] [INFO] Using worker: sync
159 | [2020-04-26 03:28:16 -0400] [31563] [INFO] Booting worker with pid: 31563
160 | [2020-04-26 03:28:16 -0400] [31564] [INFO] Booting worker with pid: 31564
161 | [2020-04-26 03:28:16 -0400] [31565] [INFO] Booting worker with pid: 31565
162 | [2020-04-26 03:28:16 -0400] [31566] [INFO] Booting worker with pid: 31566
163 | Using TensorFlow backend.
164 | [2020-04-26 03:28:28,009] ERROR in app: Exception on / [POST]
165 | Traceback (most recent call last):
166 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
167 | response = self.full_dispatch_request()
168 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
169 | rv = self.handle_user_exception(e)
170 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
171 | reraise(exc_type, exc_value, tb)
172 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
173 | raise value
174 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
175 | rv = self.dispatch_request()
176 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
177 | return self.view_functions[rule.endpoint](**req.view_args)
178 | File "/home1/user/jcf/root/flask/app.py", line 63, in upload_file
179 | result = runModel.getResult(os.path.join(app.config['UPLOAD_FOLDER'], filename))
180 | File "/home1/user/jcf/root/flask/runModel.py", line 33, in getResult
181 | newModel = load_model('20200203.model')
182 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/keras/models.py", line 240, in load_model
183 | model = model_from_config(model_config, custom_objects=custom_objects)
184 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/keras/models.py", line 314, in model_from_config
185 | return layer_module.deserialize(config, custom_objects=custom_objects)
186 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/keras/layers/__init__.py", line 55, in deserialize
187 | printable_module_name='layer')
188 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/keras/utils/generic_utils.py", line 139, in deserialize_keras_object
189 | list(custom_objects.items())))
190 | File "/home1/user/jcf/anaconda3/lib/python3.7/site-packages/keras/models.py", line 1310, in from_config
191 | if 'class_name' not in config[0] or config[0]['class_name'] == 'Merge':
192 | KeyError: 0
193 | [2020-04-26 03:28:57 -0400] [31597] [INFO] Starting gunicorn 20.0.4
194 | [2020-04-26 03:28:57 -0400] [31597] [INFO] Listening at: https://0.0.0.0:8666 (31597)
195 | [2020-04-26 03:28:57 -0400] [31597] [INFO] Using worker: sync
196 | [2020-04-26 03:28:57 -0400] [31600] [INFO] Booting worker with pid: 31600
197 | [2020-04-26 03:28:57 -0400] [31601] [INFO] Booting worker with pid: 31601
198 | [2020-04-26 03:28:57 -0400] [31602] [INFO] Booting worker with pid: 31602
199 | [2020-04-26 03:28:57 -0400] [31603] [INFO] Booting worker with pid: 31603
200 | [2020-04-26 03:29:27 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31600)
201 | [2020-04-26 03:29:28 -0400] [31629] [INFO] Booting worker with pid: 31629
202 | [2020-04-26 03:29:45 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31602)
203 | Using TensorFlow backend.
204 | [2020-04-26 03:29:45 -0400] [31602] [INFO] Worker exiting (pid: 31602)
205 | [2020-04-26 03:29:45 -0400] [31645] [INFO] Booting worker with pid: 31645
206 | [2020-04-26 03:29:59 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31629)
207 | [2020-04-26 03:30:00 -0400] [31658] [INFO] Booting worker with pid: 31658
208 | [2020-04-26 03:30:16 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31645)
209 | [2020-04-26 03:30:17 -0400] [31674] [INFO] Booting worker with pid: 31674
210 | [2020-04-26 03:30:31 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31658)
211 | [2020-04-26 03:30:32 -0400] [31683] [INFO] Booting worker with pid: 31683
212 | [2020-04-26 03:30:47 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31674)
213 | [2020-04-26 03:30:48 -0400] [31699] [INFO] Booting worker with pid: 31699
214 | [2020-04-26 03:31:03 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31683)
215 | [2020-04-26 03:31:04 -0400] [31709] [INFO] Booting worker with pid: 31709
216 | [2020-04-26 03:31:19 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31699)
217 | [2020-04-26 03:31:20 -0400] [31725] [INFO] Booting worker with pid: 31725
218 | [2020-04-26 03:31:34 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31709)
219 | [2020-04-26 03:31:35 -0400] [31734] [INFO] Booting worker with pid: 31734
220 | [2020-04-26 03:31:51 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31725)
221 | [2020-04-26 03:31:52 -0400] [31750] [INFO] Booting worker with pid: 31750
222 | [2020-04-26 03:32:06 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31734)
223 | [2020-04-26 03:32:07 -0400] [31760] [INFO] Booting worker with pid: 31760
224 | [2020-04-26 03:32:22 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31750)
225 | [2020-04-26 03:32:23 -0400] [31776] [INFO] Booting worker with pid: 31776
226 | [2020-04-26 03:32:38 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31760)
227 | [2020-04-26 03:32:39 -0400] [31791] [INFO] Booting worker with pid: 31791
228 | [2020-04-26 03:32:54 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31776)
229 | [2020-04-26 03:32:55 -0400] [31801] [INFO] Booting worker with pid: 31801
230 | [2020-04-26 03:33:09 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31791)
231 | [2020-04-26 03:33:10 -0400] [31817] [INFO] Booting worker with pid: 31817
232 | [2020-04-26 03:33:26 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31801)
233 | [2020-04-26 03:33:27 -0400] [31827] [INFO] Booting worker with pid: 31827
234 | [2020-04-26 03:33:41 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31817)
235 | [2020-04-26 03:33:42 -0400] [31842] [INFO] Booting worker with pid: 31842
236 | [2020-04-26 03:33:57 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31827)
237 | [2020-04-26 03:33:58 -0400] [31852] [INFO] Booting worker with pid: 31852
238 | [2020-04-26 03:34:13 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31842)
239 | [2020-04-26 03:34:14 -0400] [31868] [INFO] Booting worker with pid: 31868
240 | [2020-04-26 03:34:29 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31852)
241 | [2020-04-26 03:34:30 -0400] [31878] [INFO] Booting worker with pid: 31878
242 | [2020-04-26 03:34:44 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31868)
243 | [2020-04-26 03:34:45 -0400] [31893] [INFO] Booting worker with pid: 31893
244 | [2020-04-26 03:35:00 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31878)
245 | [2020-04-26 03:35:01 -0400] [31906] [INFO] Booting worker with pid: 31906
246 | [2020-04-26 03:35:16 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31893)
247 | [2020-04-26 03:35:17 -0400] [31922] [INFO] Booting worker with pid: 31922
248 | [2020-04-26 03:35:32 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31906)
249 | [2020-04-26 03:35:33 -0400] [31932] [INFO] Booting worker with pid: 31932
250 | [2020-04-26 03:35:47 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31922)
251 | [2020-04-26 03:35:48 -0400] [31947] [INFO] Booting worker with pid: 31947
252 | [2020-04-26 03:36:04 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31932)
253 | [2020-04-26 03:36:05 -0400] [31957] [INFO] Booting worker with pid: 31957
254 | [2020-04-26 03:36:19 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31947)
255 | [2020-04-26 03:36:20 -0400] [31973] [INFO] Booting worker with pid: 31973
256 | [2020-04-26 03:36:35 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31957)
257 | [2020-04-26 03:36:36 -0400] [31983] [INFO] Booting worker with pid: 31983
258 | [2020-04-26 03:36:51 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31973)
259 | [2020-04-26 03:36:52 -0400] [31998] [INFO] Booting worker with pid: 31998
260 | [2020-04-26 03:37:07 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31983)
261 | [2020-04-26 03:37:08 -0400] [32015] [INFO] Booting worker with pid: 32015
262 | [2020-04-26 03:37:22 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:31998)
263 | [2020-04-26 03:37:23 -0400] [32025] [INFO] Booting worker with pid: 32025
264 | [2020-04-26 03:37:39 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:32015)
265 | [2020-04-26 03:37:40 -0400] [32041] [INFO] Booting worker with pid: 32041
266 | [2020-04-26 03:37:54 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:32025)
267 | [2020-04-26 03:37:55 -0400] [32050] [INFO] Booting worker with pid: 32050
268 | [2020-04-26 03:38:10 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:32041)
269 | [2020-04-26 03:38:11 -0400] [32066] [INFO] Booting worker with pid: 32066
270 | [2020-04-26 03:38:26 -0400] [31597] [CRITICAL] WORKER TIMEOUT (pid:32050)
271 | [2020-04-26 03:38:27 -0400] [32094] [INFO] Booting worker with pid: 32094
272 |
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/picSegment.py:
--------------------------------------------------------------------------------
1 | # encoding:utf-8
2 |
3 | #time:2020-8-26 17:26
4 | #task:图像分割
5 |
6 | import urllib.request
7 | import base64
8 | import json
9 | import pycocotools.mask as mask_util#先pip Cython再pip install pycocotools,好坑
10 | import cv2
11 | import numpy as np
12 | # from google.colab.patches import cv2_imshow
13 | import glob
14 | import os
15 | import requests
16 |
17 |
18 | # client_id 为官网获取的AK, client_secret 为官网获取的SK
19 | host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=udjj3x3uB16w2A5CAIUWfCy6&client_secret=IxwXNR6HQf8cKtPm2wVcBCjC4qmmTY6x'
20 | response = requests.get(host)
21 | token = "24.e02b5cdcccad55ba8599ad7168b4a127.2592000.1603329667.282335-22076750"
22 | if response:
23 | token = response.json()["access_token"]#随时更新access_token
24 |
25 |
26 | '''
27 | 图像分割函数,三个参数依次为:图片路径、矩形分割图片的命名、mask分割图片的命名
28 | '''
29 |
30 | def pictureProcess(path):
31 |
32 | # recString = path.split("/")[-1].split(".")[0] + "_rec.jpg" # 重命名矩形分割的图片,第1518张_rec.jpg
33 | recString = path.replace(".", "_rec.")
34 | maskString = path.replace(".", "_mask.")
35 | # maskString = imgPath.split("/")[-1].split(".")[0] + "_mask.jpg" # 重命名mask分割的图片,第1518张_mask.jpg
36 |
37 | # 第一部分:读图片
38 |
39 | with open(path, 'rb') as f: # 以二进制读取图片
40 | data = f.read()
41 | encodestr = base64.b64encode(data) # 得到 byte 编码的数据
42 |
43 | # 第二部分:请求分割API,获得结果参数
44 |
45 | params = {
46 | "image" : encodestr.decode('ascii'),
47 | "threshold" : 0.9 # 注意这里是图片分割置信度的阈值,百度建议的是0.4,模型只会返回大于0.4的分割结果。
48 | }
49 | params = json.dumps(params)
50 | params=bytes(params,'utf8')
51 |
52 | access_token = token # 根据上面AK和SK获取的access_token
53 | request_url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/segmentation/seg4miniProgram" # 模型API地址
54 | request_url = request_url + "?access_token=" + access_token
55 | request = urllib.request.Request(url=request_url,data=params)
56 | request.add_header('Content-Type', 'application/json')
57 | response = urllib.request.urlopen(request)
58 | content = response.read()
59 |
60 | # print(content)
61 |
62 | try:
63 |
64 | results = json.loads(content)['results']
65 |
66 | # print(results)
67 |
68 | # 获取结果,并画图
69 | try:
70 |
71 | results = json.loads(content)['results']
72 | # print(results)
73 | ori_img = cv2.imread(path).astype(np.float32) #读图片
74 | height, width = ori_img.shape[:2]
75 |
76 | if results==[]:
77 | return False
78 |
79 | for item in results:
80 | scores = float(item["score"])
81 | if scores >= 0.0:
82 | # Draw bbox
83 | x1 = int(item["location"]["left"])
84 | y1 = int(item["location"]["top"])
85 | w = int(item["location"]["width"])
86 | h = int(item["location"]["height"])
87 | x2 = x1 + w
88 | y2 = y1 + h
89 |
90 | cv2.rectangle(ori_img, (x1, y1), (x2, y2), (0,255,0), 2)
91 | cv2.putText(ori_img, "{} score: {}".format(item["name"], round(float(item["score"]),4)), (x1, y1 - 10), cv2.FONT_HERSHEY_PLAIN, 0.7, (255, 255, 255), 1)
92 |
93 | # Draw mask
94 | rle_obj = {"counts": item['mask'],
95 | "size": [height, width]}
96 | mask = mask_util.decode(rle_obj)
97 |
98 | for i in range(0,height):
99 | for j in range(0,width):
100 | if mask[i][j]==1 :
101 | mask[i][j]=2
102 | elif mask[i][j]==0:
103 | mask[i][j]=1
104 |
105 | for i in range(0,height):
106 | for j in range(0,width):
107 | if mask[i][j]==2 :
108 | mask[i][j]=0
109 |
110 | new_rle_obj = mask_util.encode(mask)
111 | idx = np.nonzero(mask)
112 |
113 | #注释时间为2020-9-22 9:35 原因:这个模型用到的是mask
114 | # # 处理矩形分割,并保存矩形分割图
115 | # cropped_rec = ori_img[y1:y2,x1:x2]
116 | # cropped_rec2 = cv2.resize(cropped_rec, (350, 350), interpolation=cv2.INTER_LANCZOS4)#图片resize:https://blog.csdn.net/C_chuxin/article/details/82817407
117 | # # cv2_imshow(cropped_rec)
118 | # recString = "" + recString
119 | # cv2.imwrite(recString, cropped_rec2)
120 | # # print(recString.split('/')[-1] + " sussessfully processed")
121 |
122 | # 处理mask分割,并保存mask分割图
123 | ori_img[idx[0], idx[1], :] = np.array([255,255,255])
124 | cropped_mask = ori_img[y1:y2,x1:x2]
125 | cropped_mask2 = cv2.resize(cropped_mask, (350, 350), interpolation=cv2.INTER_LANCZOS4)#图片resize:https://blog.csdn.net/C_chuxin/article/details/82817407
126 |
127 | # cv2_imshow(cropped_mask2)
128 | maskString = "" + maskString
129 | cv2.imwrite(maskString, cropped_mask2)
130 | # print(maskString.split('/')[-1] + " sussessfully processed")
131 |
132 | return True
133 |
134 |
135 | except ValueError:
136 | return False
137 |
138 | except Exception as e:
139 | # print(e)
140 | return False
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/runModel.py:
--------------------------------------------------------------------------------
1 | from PIL import Image
2 | from keras.models import load_model
3 | from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
4 | import numpy as np
5 |
6 | WIDTH = 100
7 | HEIGHT = 100
8 |
9 | #定义图像读取
10 | def get_image_pixel(file):
11 | img = Image.open(file)
12 | img = img.resize((WIDTH,HEIGHT))
13 | #图片灰度化-l
14 | img = img.convert("L")
15 | img_array = img_to_array(img)
16 | return img_array
17 |
18 |
19 | #获取要预测的图片的像素矩阵
20 | def get_test_image_pixel(file):
21 | X_test = []
22 | img_array = get_image_pixel(file)
23 | X_test.append(img_array)
24 | X_test = np.array(X_test)
25 | X_test = X_test.reshape(1, WIDTH, HEIGHT, 1)
26 | X_test = X_test.astype('float32')
27 | X_test /= 255 #归一化
28 | return X_test
29 |
30 | #获取上传图片对应体质结果
31 | def getResult(filePath):
32 | #根据tag输出对应的分类
33 | newModel = load_model('20200203.model')
34 | # newModel.summary()
35 |
36 | predictions_array = newModel.predict(get_test_image_pixel(filePath))
37 |
38 | predictions_list = predictions_array.tolist()[0]
39 | # print(predictions_list)
40 | #各个分类的预测列表
41 |
42 | predictions_tag = predictions_list.index(max(predictions_list))
43 | # print(predictions_tag)
44 | return predictions_tag
45 | #预测值最大的那个tag
46 |
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/runModel2.py:
--------------------------------------------------------------------------------
1 | #@title
2 | import torch
3 | from torch.autograd import Variable
4 | from torch.utils.data import Dataset, DataLoader
5 | import torch.nn as nn
6 | import torch.nn.functional as F
7 | import torch.optim as optim
8 | from torch.optim.lr_scheduler import StepLR
9 | from torchvision import datasets, transforms, models
10 | from torchvision.datasets import ImageFolder
11 | import torchvision.models as models
12 | import numpy as np
13 | import cv2
14 | from PIL import Image
15 | import os
16 |
17 | # classes = ['pinghe', 'qixu', 'qiyu', 'shire', 'tanshi', 'xueyu', 'yangxu', 'yinxu']
18 | WIDTH, HEIGHT=350,350
19 |
20 | def getResult(filePath):
21 | # 环境
22 | # use_cuda = not no_cuda and torch.cuda.is_available()
23 | use_cuda = torch.cuda.is_available()
24 | device = torch.device("cuda" if use_cuda else "cpu")
25 |
26 | normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
27 | preprocess = transforms.Compose([transforms.ToTensor(), normalize])
28 | img_pil = Image.open(filePath)
29 | img_pil = img_pil.resize((WIDTH, HEIGHT),Image.ANTIALIAS)
30 | img = preprocess(img_pil)
31 | img = img.unsqueeze(0)
32 | img = img.to(device)
33 |
34 | #读模型参数
35 | # model = models.resnet18(pretrained=True)
36 | # model.fc = nn.Linear(512,8)
37 | # model=model.to(device)
38 | # model.load_state_dict(torch.load(model_path))
39 | # model.eval()
40 |
41 | # #读整个模型
42 | model=(torch.load('RecWholeModel_5.pt'))
43 | model=model.to(device)
44 | model.eval()
45 |
46 | with torch.no_grad():
47 | py = model(img)
48 | # print(py)
49 |
50 | py = F.softmax(py,1)
51 | confidence = py.numpy()
52 |
53 | return confidence[0]#返回置信度进行加权
54 |
55 | # print(py)
56 |
57 | '''
58 | res,predicted = torch.max(py, 1) # 获取分类结果
59 | predicted = predicted.numpy()
60 | classIndex = predicted[0]
61 | res = res.numpy() #将tensor转换成numpy,再取出置信度的int
62 | rate = res[0]
63 | # print(rate,classIndex)
64 | return res,predicted
65 | '''
66 | # return rate,classIndex
67 |
68 | # print("置信度:",rate)
69 | # print("种类:",classIndex)
70 | # print('预测结果:类{} {}'.format(classIndex, class_name[classIndex]))
71 |
72 | # predict(model_path,img_path,classes)
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/runModel3.py:
--------------------------------------------------------------------------------
1 | # encoding:utf-8
2 | #time: 2020-9-22 8:36
3 | #author:Tang Gaozhi
4 | #target:新的图像分类模型
5 |
6 | import requests
7 | import urllib.request
8 | import base64
9 | import json
10 |
11 | # client_id 为官网获取的AK, client_secret 为官网获取的SK
12 | host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=2lmGPrCIikIwRlqbeRT5Eg9E&client_secret=1rhxcHAG9OtEy3AR2o3sQij7WKdzUHz2'
13 | response = requests.get(host)
14 | token = "24.fe1b146c2966d72551635a05202c370f.2592000.1603179060.282335-22710328"
15 | if response:
16 | token = response.json()["access_token"]
17 |
18 | classes = ['pinghe', 'qixu', 'qiyu', 'shire', 'tanshi', 'xueyu', 'yangxu', 'yinxu']
19 |
20 | def getResult(path):
21 | request_url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/classification/tongueClassfication"
22 |
23 | # 读入图片
24 | with open(path, 'rb') as f:
25 | base64_data = base64.b64encode(f.read())
26 | s = base64_data.decode('UTF8')
27 |
28 | params = {"image": s, "top_num": "8"} # 两个参数分别为图片的base64编码和返回的分类结果数目
29 | params = json.dumps(params)
30 | params=bytes(params,'utf8')
31 |
32 | access_token = token
33 | request_url = request_url + "?access_token=" + access_token
34 | request = urllib.request.Request(url=request_url, data=params)
35 | request.add_header('Content-Type', 'application/json')
36 | response = urllib.request.urlopen(request)
37 | content = response.read()
38 |
39 | if content:
40 | # print(content) # 结果数组
41 | results = json.loads(content)['results']
42 | results_dict = {}
43 | for result in results:
44 | results_dict[result["name"]] = result["score"]
45 | confidence = []
46 |
47 | for i in range(0,len(results_dict)):
48 | confidence.append(results_dict[classes[i]])
49 |
50 | return confidence
51 |
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/upload_picture/58957275.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/upload_picture/58957275.jpg
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/upload_picture/__pycache__/api.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/upload_picture/__pycache__/api.cpython-37.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/upload_picture/__pycache__/craws_proxy_ip.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/upload_picture/__pycache__/craws_proxy_ip.cpython-37.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/upload_picture/__pycache__/douban.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/upload_picture/__pycache__/douban.cpython-37.pyc
--------------------------------------------------------------------------------
/mini-program/backend/ai_tongue/upload_picture/__pycache__/task.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/backend/ai_tongue/upload_picture/__pycache__/task.cpython-37.pyc
--------------------------------------------------------------------------------
/mini-program/crawler/爬取百度贴吧指定吧图片.py:
--------------------------------------------------------------------------------
1 | #爬取百度贴吧指定吧图片
2 |
3 | # -*- coding: utf-8 -*-
4 | import requests
5 | import time
6 | from bs4 import BeautifulSoup
7 |
8 | import io
9 | import sys
10 | import urllib.request
11 | import re
12 |
13 |
14 | id_all=[]
15 | cnt=0
16 |
17 | class bdtbpicture:
18 | def __init__(self,baseurl,seeLZ):
19 | self.baseURL=baseurl
20 | self.seeLZ='?see_lz='+str(seeLZ)
21 | def getPage(self,pageNum):
22 | url=self.baseURL+self.seeLZ+'&pn='+str(pageNum)
23 | request=urllib.request.Request(url)
24 | response=urllib.request.urlopen(request)
25 | return response.read().decode('utf-8','ignore')
26 | def getPageNum(self,page):
27 | pattern = re.compile('我的人物设计和制作
64 |
65 | #发帖人:
66 | 新日落
67 | #发帖日期:
68 | 2016-09
69 |
70 |
71 | #回复数量:
72 |
73 | 73
74 |
75 | '''
76 | #抓取网页的通用框架,获取页面的内容
77 | def getHtml(url):
78 | try:
79 | r= requests.get(url,timeout=30)
80 | #状态码不是200就发出httpError的异常
81 | r.raise_for_status()
82 | #获取正确的编码格式
83 | # r.encoding=r.apparent_encoding
84 | r.encoding="utf-8"
85 | #打印内容
86 | return r.text
87 |
88 |
89 | except:
90 | return "wrong!"
91 |
92 |
93 |
94 | #分析网页的html文件,整理信息,保存问列表文件中
95 | def get_content(url):
96 | #初始化一个列表来保存所有的帖子信息
97 | contents=[]
98 |
99 | #获取网页的内容
100 | html=getHtml(url)
101 |
102 | #将网页内容格式化利用bs4库
103 | soup = BeautifulSoup(html, 'lxml')
104 |
105 | #获取所有的li标签属性为 j_thread_list clearfix,用列表接收
106 | liTags = soup.find_all('li', attrs={'class': ' j_thread_list clearfix'})
107 | print (len(liTags))
108 |
109 |
110 |
111 | #循环这个内容li集合
112 | for li in liTags:
113 |
114 | #将爬取到了每一条信息。保存到字典里
115 | content={}
116 |
117 | #将异样抛出,避免无数据时,停止运
118 | try:
119 | #开始筛选信息
120 | content['title']=li.find('a',attrs={"class":"j_th_tit"}).text.strip()#.strip() 翻译为中文
121 | print (li.find('a',attrs={"class":"j_th_tit"}).text.strip())
122 |
123 | #获取a标签的内部属性
124 | content['link'] ="http://tieba.baidu.com/"+li.find('a', attrs={"class": "j_th_tit"})["href"]
125 |
126 | # print("测试"+li.find('a', attrs={"class": "j_th_tit"})["href"][3:])
127 | id_all.append(li.find('a', attrs={"class": "j_th_tit"})["href"][3:])
128 |
129 | print("http://tieba.baidu.com/"+li.find('a', attrs={"class": "j_th_tit"})["href"])
130 |
131 |
132 | content['author']=li.find('span',attrs={"class":'tb_icon_author '}).text.strip()
133 | print (li.find('span',attrs={"class":'tb_icon_author '}).text.strip())
134 |
135 |
136 | content['responseNum']=li.find('span',attrs={'class': 'threadlist_rep_num center_text'}).text.strip()
137 | print(li.find(
138 | 'span', attrs={'class': 'threadlist_rep_num center_text'}).text.strip())
139 | content['creatTime']=li.find('span',attrs={"class":'pull-right is_show_create_time'}).text.strip()
140 | print (li.find(
141 | 'span', attrs={'class': 'pull-right is_show_create_time'}).text.strip())
142 | #将字典加入到列表中
143 | contents.append(content)
144 |
145 |
146 | except:
147 | print('出问题')
148 |
149 |
150 |
151 | #返回数据
152 | return contents
153 |
154 |
155 | def writeTxt(content):
156 |
157 | #这里不能写成 f=open("data.txt",'a+')否则会乱码,设置沉utf-8的格式,与getHtml(url):中的encoding一致
158 | f=open("data.txt",'a+',encoding='utf-8')
159 |
160 | for c in content:
161 | f.write('标题: {} \t 链接:{} \t 发帖人:{} \t 发帖时间:{} \t 回复数量: {} \n'.format(
162 | c['title'], c['link'], c['author'], c['creatTime'], c['responseNum']))
163 |
164 |
165 |
166 | url="https://tieba.baidu.com/f?ie=utf-8&kw=%E8%88%8C%E8%AF%8A&red_tag=z0177533255"
167 | page=14
168 |
169 |
170 | def main(url,page):
171 |
172 | url_list=[]
173 | #将所需要爬取的url放到列表中
174 | for i in range(0,page):
175 | url_list.append(url+'&pn='+str(i*50))
176 |
177 | for u in url_list:
178 | content=get_content(u)
179 | writeTxt(content)
180 |
181 | if __name__=="__main__":
182 | main(url,page)
183 | get_content("https://tieba.baidu.com/f?ie=utf-8&kw=%E8%88%8C%E8%AF%8A&red_tag=z0177533255")
184 |
185 | print("长度"+str(len(id_all)))
186 |
187 | for i in range(0,len(id_all)):
188 | print(i)
189 | baseURL = 'http://tieba.baidu.com/p/' + id_all[i]
190 | bdtb=bdtbpicture(baseURL,0)
191 | bdtb.start()
192 |
--------------------------------------------------------------------------------
/mini-program/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows
2 | [Dd]esktop.ini
3 | Thumbs.db
4 | $RECYCLE.BIN/
5 |
6 | # macOS
7 | .DS_Store
8 | .fseventsd
9 | .Spotlight-V100
10 | .TemporaryItems
11 | .Trashes
12 |
13 | # Node.js
14 | node_modules/
15 |
--------------------------------------------------------------------------------
/mini-program/frontend/app.js:
--------------------------------------------------------------------------------
1 | App({
2 |
3 | globalData:{
4 | log:[],
5 | userInfo: null,
6 | options:null,
7 | imgSrc:null,
8 | },
9 | /**
10 | * 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
11 | */
12 | onLaunch: function () {
13 | const data = wx.getStorageSync('log') || [];
14 | console.log("加载本地存储:"+data);
15 | // 登录
16 | wx.login({
17 | success: res => {
18 | // 发送 res.code 到后台换取 openId, sessionKey, unionId
19 | }
20 | })
21 | },
22 | /**
23 | * 当小程序启动,或从后台进入前台显示,会触发 onShow
24 | */
25 | onShow: function (options) {
26 |
27 | },
28 |
29 | /**
30 | * 当小程序从前台进入后台,会触发 onHide
31 | */
32 | onHide: function () {
33 |
34 | },
35 |
36 | /**
37 | * 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
38 | */
39 | onError: function (msg) {
40 |
41 | },
42 | // globalData: {
43 | // imgSrc:''
44 | // },
45 | })
46 |
--------------------------------------------------------------------------------
/mini-program/frontend/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/index/index",
4 | "pages/result/result",
5 | "pages/drinks/drinks",
6 | "pages/optional/optional",
7 | "pages/crop/crop",
8 | "pages/logs/logs",
9 | "pages/help/help",
10 | "pages/detail/detail"
11 | ],
12 | "tabBar": {
13 | "color": "#7A7E83",
14 | "selectedColor": "#3cc51f",
15 | "borderStyle": "white",
16 | "backgroundColor": "#ffffff",
17 | "list": [
18 | {
19 | "pagePath": "pages/index/index",
20 | "iconPath": "images/icon_component_3.png",
21 | "selectedIconPath": "images/icon_component_3.png",
22 | "text": "舌诊"
23 | },
24 | {
25 | "pagePath": "pages/help/help",
26 | "iconPath": "images/icon_component_1.png",
27 | "selectedIconPath": "images/icon_component_1.png",
28 | "text": "说明"
29 | },
30 | {
31 | "pagePath": "pages/result/result",
32 | "iconPath": "images/icon_component_4.png",
33 | "selectedIconPath": "images/icon_component_4.png",
34 | "text": "我的"
35 | }
36 | ]
37 | },
38 | "window": {
39 | "backgroundTextStyle": "light",
40 | "navigationBarBackgroundColor": "#729b89",
41 | "navigationBarTitleText": "智能舌诊",
42 | "navigationBarTextStyle": "white"
43 | },
44 | "style": "v2",
45 | "sitemapLocation": "sitemap.json"
46 | }
--------------------------------------------------------------------------------
/mini-program/frontend/app.wxss:
--------------------------------------------------------------------------------
1 | @import "/colorUI/icon.wxss";
--------------------------------------------------------------------------------
/mini-program/frontend/image-cropper/image-cropper.js:
--------------------------------------------------------------------------------
1 | Component({
2 | properties: {
3 | /**
4 | * 图片路径
5 | */
6 | 'imgSrc': {
7 | type: String
8 | },
9 | /**
10 | * 裁剪框高度
11 | */
12 | 'height': {
13 | type: Number,
14 | value: 200
15 | },
16 | /**
17 | * 裁剪框宽度
18 | */
19 | 'width': {
20 | type: Number,
21 | value: 200
22 | },
23 | /**
24 | * 裁剪框最小尺寸
25 | */
26 | 'min_width': {
27 | type: Number,
28 | value: 50
29 | },
30 | 'min_height': {
31 | type: Number,
32 | value: 50
33 | },
34 | /**
35 | * 裁剪框最大尺寸
36 | */
37 | 'max_width': {
38 | type: Number,
39 | value: 300
40 | },
41 | 'max_height': {
42 | type: Number,
43 | value: 300
44 | },
45 | /**
46 | * 裁剪框禁止拖动
47 | */
48 | 'disable_width': {
49 | type: Boolean,
50 | value: false
51 | },
52 | 'disable_height': {
53 | type: Boolean,
54 | value: false
55 | },
56 | /**
57 | * 锁定裁剪框比例
58 | */
59 | 'disable_ratio':{
60 | type: Boolean,
61 | value: false
62 | },
63 | /**
64 | * 生成的图片尺寸相对剪裁框的比例
65 | */
66 | 'export_scale': {
67 | type: Number,
68 | value: 3
69 | },
70 | /**
71 | * 生成的图片质量0-1
72 | */
73 | 'quality': {
74 | type: Number,
75 | value: 1
76 | },
77 | 'cut_top': {
78 | type: Number,
79 | value: null
80 | },
81 | 'cut_left': {
82 | type: Number,
83 | value: null
84 | },
85 | /**
86 | * canvas上边距(不设置默认不显示)
87 | */
88 | 'canvas_top': {
89 | type: Number,
90 | value: null
91 | },
92 | /**
93 | * canvas左边距(不设置默认不显示)
94 | */
95 | 'canvas_left': {
96 | type: Number,
97 | value: null
98 | },
99 | /**
100 | * 图片宽度
101 | */
102 | 'img_width': {
103 | type: null,
104 | value: null
105 | },
106 | /**
107 | * 图片高度
108 | */
109 | 'img_height': {
110 | type: null,
111 | value: null
112 | },
113 | /**
114 | * 图片缩放比
115 | */
116 | 'scale': {
117 | type: Number,
118 | value: 1
119 | },
120 | /**
121 | * 图片旋转角度
122 | */
123 | 'angle': {
124 | type: Number,
125 | value: 0
126 | },
127 | /**
128 | * 最小缩放比
129 | */
130 | 'min_scale': {
131 | type: Number,
132 | value: 0.5
133 | },
134 | /**
135 | * 最大缩放比
136 | */
137 | 'max_scale': {
138 | type: Number,
139 | value: 2
140 | },
141 | /**
142 | * 是否禁用旋转
143 | */
144 | 'disable_rotate': {
145 | type: Boolean,
146 | value: false
147 | },
148 | /**
149 | * 是否限制移动范围(剪裁框只能在图片内)
150 | */
151 | 'limit_move':{
152 | type: Boolean,
153 | value: false
154 | }
155 | },
156 | data: {
157 | el: 'image-cropper', //暂时无用
158 | info: wx.getSystemInfoSync(),
159 | MOVE_THROTTLE:null,//触摸移动节流settimeout
160 | MOVE_THROTTLE_FLAG: true,//节流标识
161 | INIT_IMGWIDTH: 0, //图片设置尺寸,此值不变(记录最初设定的尺寸)
162 | INIT_IMGHEIGHT: 0, //图片设置尺寸,此值不变(记录最初设定的尺寸)
163 | TIME_BG: null,//背景变暗延时函数
164 | TIME_CUT_CENTER:null,
165 | _touch_img_relative: [{
166 | x: 0,
167 | y: 0
168 | }], //鼠标和图片中心的相对位置
169 | _flag_cut_touch:false,//是否是拖动裁剪框
170 | _hypotenuse_length: 0, //双指触摸时斜边长度
171 | _flag_img_endtouch: false, //是否结束触摸
172 | _flag_bright: true, //背景是否亮
173 | _canvas_overflow:true,//canvas缩略图是否在屏幕外面
174 | _canvas_width:200,
175 | _canvas_height:200,
176 | origin_x: 0.5, //图片旋转中心
177 | origin_y: 0.5, //图片旋转中心
178 | _cut_animation: false,//是否开启图片和裁剪框过渡
179 | _img_top: wx.getSystemInfoSync().windowHeight / 2, //图片上边距
180 | _img_left: wx.getSystemInfoSync().windowWidth / 2, //图片左边距
181 | watch: {
182 | //监听截取框宽高变化
183 | width(value, that) {
184 | if (value < that.data.min_width){
185 | that.setData({
186 | width: that.data.min_width
187 | });
188 | }
189 | that._computeCutSize();
190 | },
191 | height(value, that) {
192 | if (value < that.data.min_height) {
193 | that.setData({
194 | height: that.data.min_height
195 | });
196 | }
197 | that._computeCutSize();
198 | },
199 | angle(value, that){
200 | //停止居中裁剪框,继续修改图片位置
201 | that._moveStop();
202 | if(that.data.limit_move){
203 | if (that.data.angle % 90) {
204 | that.setData({
205 | angle: Math.round(that.data.angle / 90) * 90
206 | });
207 | return;
208 | }
209 | }
210 | },
211 | _cut_animation(value, that){
212 | //开启过渡300毫秒之后自动关闭
213 | clearTimeout(that.data._cut_animation_time);
214 | if (value){
215 | that.data._cut_animation_time = setTimeout(()=>{
216 | that.setData({
217 | _cut_animation:false
218 | });
219 | },300)
220 | }
221 | },
222 | limit_move(value, that){
223 | if (value) {
224 | if (that.data.angle%90){
225 | that.setData({
226 | angle: Math.round(that.data.angle / 90)*90
227 | });
228 | }
229 | that._imgMarginDetectionScale();
230 | !that.data._canvas_overflow && that._draw();
231 | }
232 | },
233 | canvas_top(value, that){
234 | that._canvasDetectionPosition();
235 | },
236 | canvas_left(value, that){
237 | that._canvasDetectionPosition();
238 | },
239 | imgSrc(value, that){
240 | that.pushImg();
241 | },
242 | cut_top(value, that) {
243 | that._cutDetectionPosition();
244 | if (that.data.limit_move) {
245 | !that.data._canvas_overflow && that._draw();
246 | }
247 | },
248 | cut_left(value, that) {
249 | that._cutDetectionPosition();
250 | if (that.data.limit_move) {
251 | !that.data._canvas_overflow && that._draw();
252 | }
253 | }
254 | }
255 | },
256 | attached() {
257 | this.data.info = wx.getSystemInfoSync();
258 | //启用数据监听
259 | this._watcher();
260 | this.data.INIT_IMGWIDTH = this.data.img_width;
261 | this.data.INIT_IMGHEIGHT = this.data.img_height;
262 | this.setData({
263 | _canvas_height: this.data.height,
264 | _canvas_width: this.data.width,
265 | });
266 | this._initCanvas();
267 | this.data.imgSrc && (this.data.imgSrc = this.data.imgSrc);
268 | //根据开发者设置的图片目标尺寸计算实际尺寸
269 | this._initImageSize();
270 | //设置裁剪框大小>设置图片尺寸>绘制canvas
271 | this._computeCutSize();
272 | //检查裁剪框是否在范围内
273 | this._cutDetectionPosition();
274 | //检查canvas是否在范围内
275 | this._canvasDetectionPosition();
276 | //初始化完成
277 | this.triggerEvent('load', {
278 | cropper: this
279 | });
280 | },
281 | methods: {
282 | /**
283 | * 上传图片
284 | */
285 | upload() {
286 | let that = this;
287 | wx.chooseImage({
288 | count: 1,
289 | sizeType: ['original', 'compressed'],
290 | sourceType: ['album', 'camera'],
291 | success(res) {
292 | const tempFilePaths = res.tempFilePaths[0];
293 | that.pushImg(tempFilePaths);
294 | }
295 | })
296 | },
297 | /**
298 | * 返回图片信息
299 | */
300 | getImg(getCallback) {
301 | this._draw(()=>{
302 | wx.canvasToTempFilePath({
303 | width: this.data.width * this.data.export_scale,
304 | height: Math.round(this.data.height * this.data.export_scale),
305 | destWidth: this.data.width * this.data.export_scale,
306 | destHeight: Math.round(this.data.height) * this.data.export_scale,
307 | fileType: 'jpg',
308 | quality: this.data.quality,
309 | canvasId: this.data.el,
310 | success: (res) => {
311 | getCallback({
312 | url: res.tempFilePath
313 | });
314 | }
315 | }, this)
316 | });
317 | },
318 | /**
319 | * 设置图片动画
320 | * {
321 | * x:10,//图片在原有基础上向下移动10px
322 | * y:10,//图片在原有基础上向右移动10px
323 | * angle:10,//图片在原有基础上旋转10deg
324 | * scale:0.5,//图片在原有基础上增加0.5倍
325 | * }
326 | */
327 | setTransform(transform) {
328 | if (!transform) return;
329 | if (!this.data.disable_rotate){
330 | this.setData({
331 | angle: transform.angle ? this.data.angle + transform.angle : this.data.angle
332 | });
333 | }
334 | var scale = this.data.scale;
335 | if (transform.scale) {
336 | scale = this.data.scale + transform.scale;
337 | scale = scale <= this.data.min_scale ? this.data.min_scale : scale;
338 | scale = scale >= this.data.max_scale ? this.data.max_scale : scale;
339 | }
340 | this.data.scale = scale;
341 | let cutX = this.data.cut_left;
342 | let cutY = this.data.cut_top;
343 | if (transform.cutX){
344 | this.setData({
345 | cut_left: cutX + transform.cutX
346 | });
347 | this.data.watch.cut_left(null, this);
348 | }
349 | if (transform.cutY){
350 | this.setData({
351 | cut_top: cutY + transform.cutY
352 | });
353 | this.data.watch.cut_top(null, this);
354 | }
355 | this.data._img_top = transform.y ? this.data._img_top + transform.y : this.data._img_top;
356 | this.data._img_left = transform.x ? this.data._img_left + transform.x : this.data._img_left;
357 | //图像边缘检测,防止截取到空白
358 | this._imgMarginDetectionScale();
359 | //停止居中裁剪框,继续修改图片位置
360 | this._moveDuring();
361 | this.setData({
362 | scale: this.data.scale,
363 | _img_top: this.data._img_top,
364 | _img_left: this.data._img_left
365 | });
366 | !this.data._canvas_overflow && this._draw();
367 | //可以居中裁剪框了
368 | this._moveStop();//结束操作
369 | },
370 | /**
371 | * 设置剪裁框位置
372 | */
373 | setCutXY(x,y){
374 | this.setData({
375 | cut_top: y,
376 | cut_left:x
377 | });
378 | },
379 | /**
380 | * 设置剪裁框尺寸
381 | */
382 | setCutSize(w,h){
383 | this.setData({
384 | width: w,
385 | height:h
386 | });
387 | this._computeCutSize();
388 | },
389 | /**
390 | * 设置剪裁框和图片居中
391 | */
392 | setCutCenter() {
393 | let cut_top = (this.data.info.windowHeight - this.data.height) * 0.5;
394 | let cut_left = (this.data.info.windowWidth - this.data.width) * 0.5;
395 | //顺序不能变
396 | this.setData({
397 | _img_top: this.data._img_top - this.data.cut_top + cut_top,
398 | cut_top: cut_top, //截取的框上边距
399 | _img_left: this.data._img_left - this.data.cut_left + cut_left,
400 | cut_left: cut_left, //截取的框左边距
401 | });
402 | },
403 | _setCutCenter(){
404 | let cut_top = (this.data.info.windowHeight - this.data.height) * 0.5;
405 | let cut_left = (this.data.info.windowWidth - this.data.width) * 0.5;
406 | this.setData({
407 | cut_top: cut_top, //截取的框上边距
408 | cut_left: cut_left, //截取的框左边距
409 | });
410 | },
411 | /**
412 | * 设置剪裁框宽度-即将废弃
413 | */
414 | setWidth(width) {
415 | this.setData({
416 | width: width
417 | });
418 | this._computeCutSize();
419 | },
420 | /**
421 | * 设置剪裁框高度-即将废弃
422 | */
423 | setHeight(height) {
424 | this.setData({
425 | height: height
426 | });
427 | this._computeCutSize();
428 | },
429 | /**
430 | * 是否锁定旋转
431 | */
432 | setDisableRotate(value){
433 | this.data.disable_rotate = value;
434 | },
435 | /**
436 | * 是否限制移动
437 | */
438 | setLimitMove(value){
439 | this.setData({
440 | _cut_animation: true,
441 | limit_move: !!value
442 | });
443 | },
444 | /**
445 | * 初始化图片,包括位置、大小、旋转角度
446 | */
447 | imgReset() {
448 | this.setData({
449 | scale: 1,
450 | angle: 0,
451 | _img_top: wx.getSystemInfoSync().windowHeight / 2,
452 | _img_left: wx.getSystemInfoSync().windowWidth / 2,
453 | })
454 | },
455 | /**
456 | * 加载(更换)图片
457 | */
458 | pushImg(src) {
459 | if (src) {
460 | this.setData({
461 | imgSrc: src
462 | });
463 | //发现是手动赋值直接返回,交给watch处理
464 | return;
465 | }
466 |
467 | // getImageInfo接口传入 src: '' 会导致内存泄漏
468 |
469 | if (!this.data.imgSrc) return;
470 | wx.getImageInfo({
471 | src: this.data.imgSrc,
472 | success: (res) => {
473 | this.data.imageObject = res;
474 | //图片非本地路径需要换成本地路径
475 | if (this.data.imgSrc.search(/tmp/) == -1){
476 | this.setData({
477 | imgSrc: res.path
478 | });
479 | }
480 | //计算最后图片尺寸
481 | this._imgComputeSize();
482 | if (this.data.limit_move) {
483 | //限制移动,不留空白处理
484 | this._imgMarginDetectionScale();
485 | }
486 | this._draw();
487 | },
488 | fail: (err) => {
489 | this.setData({
490 | imgSrc: ''
491 | });
492 | }
493 | });
494 | },
495 | imageLoad(e){
496 | setTimeout(()=>{
497 | this.triggerEvent('imageload', this.data.imageObject);
498 |
499 | },1000)
500 | },
501 | /**
502 | * 设置图片放大缩小
503 | */
504 | setScale(scale) {
505 | if (!scale) return;
506 | this.setData({
507 | scale: scale
508 | });
509 | !this.data._canvas_overflow && this._draw();
510 | },
511 | /**
512 | * 设置图片旋转角度
513 | */
514 | setAngle(angle) {
515 | if (!angle) return;
516 | this.setData({
517 | _cut_animation: true,
518 | angle: angle
519 | });
520 | this._imgMarginDetectionScale();
521 | !this.data._canvas_overflow && this._draw();
522 | },
523 | _initCanvas() {
524 | //初始化canvas
525 | if (!this.data.ctx){
526 | this.data.ctx = wx.createCanvasContext("image-cropper", this);
527 | }
528 | },
529 | /**
530 | * 根据开发者设置的图片目标尺寸计算实际尺寸
531 | */
532 | _initImageSize(){
533 | //处理宽高特殊单位 %>px
534 | if (this.data.INIT_IMGWIDTH && typeof this.data.INIT_IMGWIDTH == "string" && this.data.INIT_IMGWIDTH.indexOf("%") != -1) {
535 | let width = this.data.INIT_IMGWIDTH.replace("%", "");
536 | this.data.INIT_IMGWIDTH = this.data.img_width = this.data.info.windowWidth / 100 * width;
537 | }
538 | if (this.data.INIT_IMGHEIGHT && typeof this.data.INIT_IMGHEIGHT == "string" && this.data.INIT_IMGHEIGHT.indexOf("%") != -1) {
539 | let height = this.data.img_height.replace("%", "");
540 | this.data.INIT_IMGHEIGHT = this.data.img_height = this.data.info.windowHeight / 100 * height;
541 | }
542 | },
543 | /**
544 | * 检测剪裁框位置是否在允许的范围内(屏幕内)
545 | */
546 | _cutDetectionPosition(){
547 | let _cutDetectionPositionTop = () => {
548 | //检测上边距是否在范围内
549 | if (this.data.cut_top < 0) {
550 | this.setData({
551 | cut_top: 0
552 | });
553 | }
554 | if (this.data.cut_top > this.data.info.windowHeight - this.data.height) {
555 | this.setData({
556 | cut_top: this.data.info.windowHeight - this.data.height
557 | });
558 | }
559 | }, _cutDetectionPositionLeft = () => {
560 | //检测左边距是否在范围内
561 | if (this.data.cut_left < 0) {
562 | this.setData({
563 | cut_left: 0
564 | });
565 | }
566 | if (this.data.cut_left > this.data.info.windowWidth - this.data.width) {
567 | this.setData({
568 | cut_left: this.data.info.windowWidth - this.data.width
569 | });
570 | }
571 | };
572 | //裁剪框坐标处理(如果只写一个参数则另一个默认为0,都不写默认居中)
573 | if (this.data.cut_top == null && this.data.cut_left == null) {
574 | this._setCutCenter();
575 | } else if (this.data.cut_top != null && this.data.cut_left != null){
576 | _cutDetectionPositionTop();
577 | _cutDetectionPositionLeft();
578 | } else if (this.data.cut_top != null && this.data.cut_left == null) {
579 | _cutDetectionPositionTop();
580 | this.setData({
581 | cut_left: (this.data.info.windowWidth - this.data.width) / 2
582 | });
583 | } else if (this.data.cut_top == null && this.data.cut_left != null) {
584 | _cutDetectionPositionLeft();
585 | this.setData({
586 | cut_top: (this.data.info.windowHeight - this.data.height) / 2
587 | });
588 | }
589 | },
590 | /**
591 | * 检测canvas位置是否在允许的范围内(屏幕内)如果在屏幕外则不开启实时渲染
592 | * 如果只写一个参数则另一个默认为0,都不写默认超出屏幕外
593 | */
594 | _canvasDetectionPosition(){
595 | if(this.data.canvas_top == null && this.data.canvas_left == null) {
596 | this.data._canvas_overflow = false;
597 | this.setData({
598 | canvas_top: -5000,
599 | canvas_left: -5000
600 | });
601 | }else if(this.data.canvas_top != null && this.data.canvas_left != null) {
602 | if (this.data.canvas_top < - this.data.height || this.data.canvas_top > this.data.info.windowHeight) {
603 | this.data._canvas_overflow = true;
604 | } else {
605 | this.data._canvas_overflow = false;
606 | }
607 | }else if(this.data.canvas_top != null && this.data.canvas_left == null) {
608 | this.setData({
609 | canvas_left: 0
610 | });
611 | } else if (this.data.canvas_top == null && this.data.canvas_left != null) {
612 | this.setData({
613 | canvas_top: 0
614 | });
615 | if (this.data.canvas_left < -this.data.width || this.data.canvas_left > this.data.info.windowWidth) {
616 | this.data._canvas_overflow = true;
617 | } else {
618 | this.data._canvas_overflow = false;
619 | }
620 | }
621 | },
622 | /**
623 | * 图片边缘检测-位置
624 | */
625 | _imgMarginDetectionPosition(scale) {
626 | if (!this.data.limit_move) return;
627 | let left = this.data._img_left;
628 | let top = this.data._img_top;
629 | var scale = scale || this.data.scale;
630 | let img_width = this.data.img_width;
631 | let img_height = this.data.img_height;
632 | if (this.data.angle / 90 % 2) {
633 | img_width = this.data.img_height;
634 | img_height = this.data.img_width;
635 | }
636 | left = this.data.cut_left + img_width * scale / 2 >= left ? left : this.data.cut_left + img_width * scale / 2;
637 | left = this.data.cut_left + this.data.width - img_width * scale / 2 <= left ? left : this.data.cut_left + this.data.width - img_width * scale / 2;
638 | top = this.data.cut_top + img_height * scale / 2 >= top ? top : this.data.cut_top + img_height * scale / 2;
639 | top = this.data.cut_top + this.data.height - img_height * scale / 2 <= top ? top : this.data.cut_top + this.data.height - img_height * scale / 2;
640 | this.setData({
641 | _img_left: left,
642 | _img_top: top,
643 | scale: scale
644 | })
645 | },
646 | /**
647 | * 图片边缘检测-缩放
648 | */
649 | _imgMarginDetectionScale(){
650 | if (!this.data.limit_move)return;
651 | let scale = this.data.scale;
652 | let img_width = this.data.img_width;
653 | let img_height = this.data.img_height;
654 | if (this.data.angle / 90 % 2) {
655 | img_width = this.data.img_height;
656 | img_height = this.data.img_width;
657 | }
658 | if (img_width * scale < this.data.width){
659 | scale = this.data.width / img_width;
660 | }
661 | if (img_height * scale < this.data.height) {
662 | scale = Math.max(scale,this.data.height / img_height);
663 | }
664 | this._imgMarginDetectionPosition(scale);
665 | },
666 | _setData(obj) {
667 | let data = {};
668 | for (var key in obj) {
669 | if (this.data[key] != obj[key]){
670 | data[key] = obj[key];
671 | }
672 | }
673 | this.setData(data);
674 | return data;
675 | },
676 | /**
677 | * 计算图片尺寸
678 | */
679 | _imgComputeSize() {
680 | let img_width = this.data.img_width,
681 | img_height = this.data.img_height;
682 | if (!this.data.INIT_IMGHEIGHT && !this.data.INIT_IMGWIDTH) {
683 | //默认按图片最小边 = 对应裁剪框尺寸
684 | img_width = this.data.imageObject.width;
685 | img_height = this.data.imageObject.height;
686 | if (img_width / img_height > this.data.width / this.data.height){
687 | img_height = this.data.height;
688 | img_width = this.data.imageObject.width / this.data.imageObject.height * img_height;
689 | }else{
690 | img_width = this.data.width;
691 | img_height = this.data.imageObject.height / this.data.imageObject.width * img_width;
692 | }
693 | } else if (this.data.INIT_IMGHEIGHT && !this.data.INIT_IMGWIDTH) {
694 | img_width = this.data.imageObject.width / this.data.imageObject.height * this.data.INIT_IMGHEIGHT;
695 | } else if (!this.data.INIT_IMGHEIGHT && this.data.INIT_IMGWIDTH) {
696 | img_height = this.data.imageObject.height / this.data.imageObject.width * this.data.INIT_IMGWIDTH;
697 | }
698 | this.setData({
699 | img_width: img_width,
700 | img_height: img_height
701 | });
702 | },
703 | //改变截取框大小
704 | _computeCutSize() {
705 | if (this.data.width > this.data.info.windowWidth) {
706 | this.setData({
707 | width: this.data.info.windowWidth,
708 | });
709 | } else if (this.data.width + this.data.cut_left > this.data.info.windowWidth){
710 | this.setData({
711 | cut_left: this.data.info.windowWidth - this.data.cut_left,
712 | });
713 | };
714 | if (this.data.height > this.data.info.windowHeight) {
715 | this.setData({
716 | height: this.data.info.windowHeight,
717 | });
718 | } else if (this.data.height + this.data.cut_top > this.data.info.windowHeight){
719 | this.setData({
720 | cut_top: this.data.info.windowHeight - this.data.cut_top,
721 | });
722 | }
723 | !this.data._canvas_overflow && this._draw();
724 | },
725 | //开始触摸
726 | _start(event) {
727 | this.data._flag_img_endtouch = false;
728 | if (event.touches.length == 1) {
729 | //单指拖动
730 | this.data._touch_img_relative[0] = {
731 | x: (event.touches[0].clientX - this.data._img_left),
732 | y: (event.touches[0].clientY - this.data._img_top)
733 | }
734 | } else {
735 | //双指放大
736 | let width = Math.abs(event.touches[0].clientX - event.touches[1].clientX);
737 | let height = Math.abs(event.touches[0].clientY - event.touches[1].clientY);
738 | this.data._touch_img_relative = [{
739 | x: (event.touches[0].clientX - this.data._img_left),
740 | y: (event.touches[0].clientY - this.data._img_top)
741 | }, {
742 | x: (event.touches[1].clientX - this.data._img_left),
743 | y: (event.touches[1].clientY - this.data._img_top)
744 | }];
745 | this.data._hypotenuse_length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
746 | }
747 | !this.data._canvas_overflow && this._draw();
748 | },
749 | _move_throttle(){
750 | //安卓需要节流
751 | if (this.data.info.platform =='android'){
752 | clearTimeout(this.data.MOVE_THROTTLE);
753 | this.data.MOVE_THROTTLE = setTimeout(() => {
754 | this.data.MOVE_THROTTLE_FLAG = true;
755 | }, 1000 / 40)
756 | return this.data.MOVE_THROTTLE_FLAG;
757 | }else{
758 | this.data.MOVE_THROTTLE_FLAG = true;
759 | }
760 | },
761 | _move(event) {
762 | if (this.data._flag_img_endtouch || !this.data.MOVE_THROTTLE_FLAG) return;
763 | this.data.MOVE_THROTTLE_FLAG = false;
764 | this._move_throttle();
765 | this._moveDuring();
766 | if (event.touches.length == 1) {
767 | //单指拖动
768 | let left = (event.touches[0].clientX - this.data._touch_img_relative[0].x),
769 | top = (event.touches[0].clientY - this.data._touch_img_relative[0].y);
770 | //图像边缘检测,防止截取到空白
771 | this.data._img_left = left;
772 | this.data._img_top = top;
773 | this._imgMarginDetectionPosition();
774 | this.setData({
775 | _img_left: this.data._img_left,
776 | _img_top: this.data._img_top
777 | });
778 | } else {
779 | //双指放大
780 | let width = (Math.abs(event.touches[0].clientX - event.touches[1].clientX)),
781 | height = (Math.abs(event.touches[0].clientY - event.touches[1].clientY)),
782 | hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),
783 | scale = this.data.scale * (hypotenuse / this.data._hypotenuse_length),
784 | current_deg = 0;
785 | scale = scale <= this.data.min_scale ? this.data.min_scale : scale;
786 | scale = scale >= this.data.max_scale ? this.data.max_scale : scale;
787 | //图像边缘检测,防止截取到空白
788 | this.data.scale = scale;
789 | this._imgMarginDetectionScale();
790 | //双指旋转(如果没禁用旋转)
791 | let _touch_img_relative = [{
792 | x: (event.touches[0].clientX - this.data._img_left),
793 | y: (event.touches[0].clientY - this.data._img_top)
794 | }, {
795 | x: (event.touches[1].clientX - this.data._img_left),
796 | y: (event.touches[1].clientY - this.data._img_top)
797 | }];
798 | if (!this.data.disable_rotate){
799 | let first_atan = 180 / Math.PI * Math.atan2(_touch_img_relative[0].y, _touch_img_relative[0].x);
800 | let first_atan_old = 180 / Math.PI * Math.atan2(this.data._touch_img_relative[0].y, this.data._touch_img_relative[0].x);
801 | let second_atan = 180 / Math.PI * Math.atan2(_touch_img_relative[1].y, _touch_img_relative[1].x);
802 | let second_atan_old = 180 / Math.PI * Math.atan2(this.data._touch_img_relative[1].y, this.data._touch_img_relative[1].x);
803 | //当前旋转的角度
804 | let first_deg = first_atan - first_atan_old,
805 | second_deg = second_atan - second_atan_old;
806 | if (first_deg != 0) {
807 | current_deg = first_deg;
808 | } else if (second_deg != 0) {
809 | current_deg = second_deg;
810 | }
811 | }
812 | this.data._touch_img_relative = _touch_img_relative;
813 | this.data._hypotenuse_length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
814 | //更新视图
815 | this.setData({
816 | angle: this.data.angle + current_deg,
817 | scale: this.data.scale
818 | });
819 | }
820 | !this.data._canvas_overflow && this._draw();
821 | },
822 | //结束操作
823 | _end(event) {
824 | this.data._flag_img_endtouch = true;
825 | this._moveStop();
826 | },
827 | //点击中间剪裁框处理
828 | _click(event) {
829 | if (!this.data.imgSrc) {
830 | //调起上传
831 | this.upload();
832 | return;
833 | }
834 | this._draw(()=>{
835 | let x = event.detail ? event.detail.x : event.touches[0].clientX;
836 | let y = event.detail ? event.detail.y : event.touches[0].clientY;
837 | if ((x >= this.data.cut_left && x <= (this.data.cut_left + this.data.width)) && (y >= this.data.cut_top && y <= (this.data.cut_top + this.data.height))) {
838 | //生成图片并回调
839 | wx.canvasToTempFilePath({
840 | width: this.data.width * this.data.export_scale,
841 | height: Math.round(this.data.height * this.data.export_scale),
842 | destWidth: this.data.width * this.data.export_scale,
843 | destHeight: Math.round(this.data.height) * this.data.export_scale,
844 | fileType: 'jpg',
845 | quality: this.data.quality,
846 | canvasId: this.data.el,
847 | success: (res) => {
848 | this.triggerEvent('tapcut', {
849 | url: res.tempFilePath,
850 | width: this.data.width * this.data.export_scale,
851 | height: this.data.height * this.data.export_scale
852 | });
853 | }
854 | }, this)
855 | }
856 | });
857 | },
858 | //渲染
859 | _draw(callback) {
860 | if (!this.data.imgSrc) return;
861 | let draw = () => {
862 | //图片实际大小
863 | let img_width = this.data.img_width * this.data.scale * this.data.export_scale;
864 | let img_height = this.data.img_height * this.data.scale * this.data.export_scale;
865 | //canvas和图片的相对距离
866 | var xpos = this.data._img_left - this.data.cut_left;
867 | var ypos = this.data._img_top - this.data.cut_top;
868 | //旋转画布
869 | this.data.ctx.translate(xpos * this.data.export_scale, ypos * this.data.export_scale);
870 | this.data.ctx.rotate(this.data.angle * Math.PI / 180);
871 | this.data.ctx.drawImage(this.data.imgSrc, -img_width / 2, -img_height / 2, img_width, img_height);
872 | this.data.ctx.draw(false, () => {
873 | callback && callback();
874 | });
875 | }
876 | if (this.data.ctx.width != this.data.width || this.data.ctx.height != this.data.height){
877 | //优化拖动裁剪框,所以必须把宽高设置放在离用户触发渲染最近的地方
878 | this.setData({
879 | _canvas_height: this.data.height,
880 | _canvas_width: this.data.width,
881 | },()=>{
882 | //延迟40毫秒防止点击过快出现拉伸或裁剪过多
883 | setTimeout(() => {
884 | draw();
885 | }, 40);
886 | });
887 | }else{
888 | draw();
889 | }
890 | },
891 | //裁剪框处理
892 | _cutTouchMove(e) {
893 | if (this.data._flag_cut_touch && this.data.MOVE_THROTTLE_FLAG) {
894 | if (this.data.disable_ratio && (this.data.disable_width || this.data.disable_height)) return;
895 | //节流
896 | this.data.MOVE_THROTTLE_FLAG = false;
897 | this._move_throttle();
898 | let width = this.data.width,
899 | height = this.data.height,
900 | cut_top = this.data.cut_top,
901 | cut_left = this.data.cut_left,
902 | size_correct = () => {
903 | width = width <= this.data.max_width ? width >= this.data.min_width ? width : this.data.min_width : this.data.max_width;
904 | height = height <= this.data.max_height ? height >= this.data.min_height ? height : this.data.min_height : this.data.max_height;
905 | },
906 | size_inspect = () => {
907 | if ((width > this.data.max_width || width < this.data.min_width || height > this.data.max_height || height < this.data.min_height) && this.data.disable_ratio) {
908 | size_correct();
909 | return false;
910 | } else {
911 | size_correct();
912 | return true;
913 | }
914 | };
915 | height = this.data.CUT_START.height + ((this.data.CUT_START.corner > 1 && this.data.CUT_START.corner < 4 ? 1 : -1) * (this.data.CUT_START.y - e.touches[0].clientY));
916 | switch (this.data.CUT_START.corner) {
917 | case 1:
918 | width = this.data.CUT_START.width + this.data.CUT_START.x - e.touches[0].clientX;
919 | if (this.data.disable_ratio) {
920 | height = width / (this.data.width / this.data.height)
921 | }
922 | if (!size_inspect()) return;
923 | cut_left = this.data.CUT_START.cut_left - (width - this.data.CUT_START.width);
924 | break
925 | case 2:
926 | width = this.data.CUT_START.width + this.data.CUT_START.x - e.touches[0].clientX;
927 | if (this.data.disable_ratio) {
928 | height = width / (this.data.width / this.data.height)
929 | }
930 | if (!size_inspect()) return;
931 | cut_top = this.data.CUT_START.cut_top - (height - this.data.CUT_START.height)
932 | cut_left = this.data.CUT_START.cut_left - (width - this.data.CUT_START.width)
933 | break
934 | case 3:
935 | width = this.data.CUT_START.width - this.data.CUT_START.x + e.touches[0].clientX;
936 | if (this.data.disable_ratio) {
937 | height = width / (this.data.width / this.data.height)
938 | }
939 | if (!size_inspect()) return;
940 | cut_top = this.data.CUT_START.cut_top - (height - this.data.CUT_START.height);
941 | break
942 | case 4:
943 | width = this.data.CUT_START.width - this.data.CUT_START.x + e.touches[0].clientX;
944 | if (this.data.disable_ratio) {
945 | height = width / (this.data.width / this.data.height)
946 | }
947 | if (!size_inspect()) return;
948 | break
949 | }
950 | if (!this.data.disable_width && !this.data.disable_height) {
951 | this.setData({
952 | width: width,
953 | cut_left: cut_left,
954 | height: height,
955 | cut_top: cut_top,
956 | })
957 | } else if (!this.data.disable_width) {
958 | this.setData({
959 | width: width,
960 | cut_left: cut_left
961 | })
962 | } else if (!this.data.disable_height) {
963 | this.setData({
964 | height: height,
965 | cut_top: cut_top
966 | })
967 | }
968 | this._imgMarginDetectionScale();
969 | }
970 | },
971 | _cutTouchStart(e) {
972 | let currentX = e.touches[0].clientX;
973 | let currentY = e.touches[0].clientY;
974 | let cutbox_top4 = this.data.cut_top + this.data.height - 30;
975 | let cutbox_bottom4 = this.data.cut_top + this.data.height + 20;
976 | let cutbox_left4 = this.data.cut_left + this.data.width - 30;
977 | let cutbox_right4 = this.data.cut_left + this.data.width + 30;
978 |
979 | let cutbox_top3 = this.data.cut_top - 30;
980 | let cutbox_bottom3 = this.data.cut_top + 30;
981 | let cutbox_left3 = this.data.cut_left + this.data.width - 30;
982 | let cutbox_right3 = this.data.cut_left + this.data.width + 30;
983 |
984 | let cutbox_top2 = this.data.cut_top - 30;
985 | let cutbox_bottom2 = this.data.cut_top + 30;
986 | let cutbox_left2 = this.data.cut_left - 30;
987 | let cutbox_right2 = this.data.cut_left + 30;
988 |
989 | let cutbox_top1 = this.data.cut_top + this.data.height - 30;
990 | let cutbox_bottom1 = this.data.cut_top + this.data.height + 30;
991 | let cutbox_left1 = this.data.cut_left - 30;
992 | let cutbox_right1 = this.data.cut_left + 30;
993 | if (currentX > cutbox_left4 && currentX < cutbox_right4 && currentY > cutbox_top4 && currentY < cutbox_bottom4) {
994 | this._moveDuring();
995 | this.data._flag_cut_touch = true;
996 | this.data._flag_img_endtouch = true;
997 | this.data.CUT_START = {
998 | width: this.data.width,
999 | height: this.data.height,
1000 | x: currentX,
1001 | y: currentY,
1002 | corner: 4
1003 | }
1004 | } else if (currentX > cutbox_left3 && currentX < cutbox_right3 && currentY > cutbox_top3 && currentY < cutbox_bottom3) {
1005 | this._moveDuring();
1006 | this.data._flag_cut_touch = true;
1007 | this.data._flag_img_endtouch = true;
1008 | this.data.CUT_START = {
1009 | width: this.data.width,
1010 | height: this.data.height,
1011 | x: currentX,
1012 | y: currentY,
1013 | cut_top: this.data.cut_top,
1014 | cut_left: this.data.cut_left,
1015 | corner: 3
1016 | }
1017 | } else if (currentX > cutbox_left2 && currentX < cutbox_right2 && currentY > cutbox_top2 && currentY < cutbox_bottom2) {
1018 | this._moveDuring();
1019 | this.data._flag_cut_touch = true;
1020 | this.data._flag_img_endtouch = true;
1021 | this.data.CUT_START = {
1022 | width: this.data.width,
1023 | height: this.data.height,
1024 | cut_top: this.data.cut_top,
1025 | cut_left: this.data.cut_left,
1026 | x: currentX,
1027 | y: currentY,
1028 | corner: 2
1029 | }
1030 | } else if (currentX > cutbox_left1 && currentX < cutbox_right1 && currentY > cutbox_top1 && currentY < cutbox_bottom1) {
1031 | this._moveDuring();
1032 | this.data._flag_cut_touch = true;
1033 | this.data._flag_img_endtouch = true;
1034 | this.data.CUT_START = {
1035 | width: this.data.width,
1036 | height: this.data.height,
1037 | cut_top: this.data.cut_top,
1038 | cut_left: this.data.cut_left,
1039 | x: currentX,
1040 | y: currentY,
1041 | corner: 1
1042 | }
1043 | }
1044 | },
1045 | _cutTouchEnd(e) {
1046 | this._moveStop();
1047 | this.data._flag_cut_touch = false;
1048 | },
1049 | //停止移动时需要做的操作
1050 | _moveStop() {
1051 | //清空之前的自动居中延迟函数并添加最新的
1052 | clearTimeout(this.data.TIME_CUT_CENTER);
1053 | this.data.TIME_CUT_CENTER = setTimeout(() => {
1054 | //动画启动
1055 | if (!this.data._cut_animation) {
1056 | this.setData({
1057 | _cut_animation: true
1058 | });
1059 | }
1060 | this.setCutCenter();
1061 | }, 1000)
1062 | //清空之前的背景变化延迟函数并添加最新的
1063 | clearTimeout(this.data.TIME_BG);
1064 | this.data.TIME_BG = setTimeout(() => {
1065 | if (this.data._flag_bright) {
1066 | this.setData({
1067 | _flag_bright: false
1068 | });
1069 | }
1070 | }, 2000)
1071 | },
1072 | //移动中
1073 | _moveDuring() {
1074 | //清空之前的自动居中延迟函数
1075 | clearTimeout(this.data.TIME_CUT_CENTER);
1076 | //清空之前的背景变化延迟函数
1077 | clearTimeout(this.data.TIME_BG);
1078 | //高亮背景
1079 | if (!this.data._flag_bright) {
1080 | this.setData({
1081 | _flag_bright: true
1082 | });
1083 | }
1084 | },
1085 | //监听器
1086 | _watcher() {
1087 | Object.keys(this.data).forEach(v => {
1088 | this._observe(this.data, v, this.data.watch[v]);
1089 | })
1090 | },
1091 | _observe(obj, key, watchFun) {
1092 | var val = obj[key];
1093 | Object.defineProperty(obj, key, {
1094 | configurable: true,
1095 | enumerable: true,
1096 | set:(value) => {
1097 | val = value;
1098 | watchFun && watchFun(val, this);
1099 | },
1100 | get() {
1101 | if (val && '_img_top|img_left||width|height|min_width|max_width|min_height|max_height|export_scale|cut_top|cut_left|canvas_top|canvas_left|img_width|img_height|scale|angle|min_scale|max_scale'.indexOf(key)!=-1){
1102 | let ret = parseFloat(parseFloat(val).toFixed(3));
1103 | if (typeof val == "string" && val.indexOf("%") != -1){
1104 | ret+='%';
1105 | }
1106 | return ret;
1107 | }
1108 | return val;
1109 | }
1110 | })
1111 | },
1112 | _preventTouchMove() {
1113 | }
1114 | }
1115 | })
1116 |
--------------------------------------------------------------------------------
/mini-program/frontend/image-cropper/image-cropper.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/mini-program/frontend/image-cropper/image-cropper.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 |
--------------------------------------------------------------------------------
/mini-program/frontend/image-cropper/image-cropper.wxss:
--------------------------------------------------------------------------------
1 | .image-cropper{
2 | background:rgba(14, 13, 13,.8);
3 | position: fixed;
4 | top:0;
5 | left:0;
6 | width:100vw;
7 | height:100vh;
8 | z-index: 1;
9 | }
10 | .main{
11 | position: absolute;
12 | width:100vw;
13 | height:100vh;
14 | overflow: hidden;
15 | }
16 | .content{
17 | z-index: 9;
18 | position: absolute;
19 | width:100vw;
20 | height:100vh;
21 | display: flex;
22 | flex-direction:column;
23 | pointer-events:none;
24 | }
25 | .bg_black{
26 | background: rgba(0, 0, 0, 0.8)!important;
27 | }
28 | .bg_gray{
29 | background: rgba(0, 0, 0, 0.45);
30 | transition-duration: .35s;
31 | }
32 | .content>.content_top{
33 | pointer-events:none;
34 | }
35 | .content>.content_middle{
36 | display: flex;
37 | height: 200px;
38 | width:100%;
39 | }
40 | .content_middle_middle{
41 | width:200px;
42 | box-sizing:border-box;
43 | position: relative;
44 | transition-duration: .3s;
45 | }
46 | .content_middle_right{
47 | flex: auto;
48 | }
49 | .content>.content_bottom{
50 | flex: auto;
51 | }
52 | .image-cropper .img{
53 | z-index: 2;
54 | top:0;
55 | left:0;
56 | position: absolute;
57 | border:none;
58 | width:100%;
59 | backface-visibility: hidden;
60 | transform-origin:center;
61 | }
62 | .image-cropper-canvas{
63 | position: fixed;
64 | background: white;
65 | width:150px;
66 | height:150px;
67 | z-index: 10;
68 | top:-200%;
69 | pointer-events:none;
70 | }
71 | .border{
72 | background: #3DB29E;
73 | pointer-events:auto;
74 | position:absolute;
75 | }
76 | .border-top-left{
77 | left:-2.5px;
78 | top:-2.5px;
79 | height:2.5px;
80 | width:33rpx;
81 | }
82 | .border-top-right{
83 | right:-2.5px;
84 | top:-2.5px;
85 | height:2.5px;
86 | width:33rpx;
87 | }
88 | .border-right-top{
89 | top:-1px;
90 | width:2.5px;
91 | height:30rpx;
92 | right:-2.5px;
93 | }
94 | .border-right-bottom{
95 | width:2.5px;
96 | height:30rpx;
97 | right:-2.5px;
98 | bottom:-1px;
99 | }
100 | .border-bottom-left{
101 | height:2.5px;
102 | width:33rpx;
103 | bottom:-2.5px;
104 | left:-2.5px;
105 | }
106 | .border-bottom-right{
107 | height:2.5px;
108 | width:33rpx;
109 | bottom:-2.5px;
110 | right:-2.5px;
111 | }
112 | .border-left-top{
113 | top:-1px;
114 | width:2.5px;
115 | height:30rpx;
116 | left:-2.5px;
117 | }
118 | .border-left-bottom{
119 | width:2.5px;
120 | height:30rpx;
121 | left:-2.5px;
122 | bottom:-1px;
123 | }
--------------------------------------------------------------------------------
/mini-program/frontend/images/ac_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/ac_down.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/ac_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/ac_icon.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/ac_up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/ac_up.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/air.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/air.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/bg_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/bg_image.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/camera.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/cameraIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/cameraIcon.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/card.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/card.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/damp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/damp.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/diet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/diet.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/drink.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/drink.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/eye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/eye.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/food-and-restaurant.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/food-and-restaurant.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/food.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/food.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/food_rec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/food_rec.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/ganmao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/ganmao.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/help.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/icon_component_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/icon_component_1.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/icon_component_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/icon_component_2.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/icon_component_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/icon_component_3.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/icon_component_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/icon_component_4.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/info.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/info_card.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/info_card.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/like.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/like.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/next.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/risk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/risk.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/scan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/scan.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/shop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/shop.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/shopp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/shopp.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/solar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/solar.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/solar_text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/solar_text.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/spit_rec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/spit_rec.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/sym.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/sym.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/tongue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/tongue.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/tongue2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/tongue2.png
--------------------------------------------------------------------------------
/mini-program/frontend/images/ziwai.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/charfole/HeyConstitution/d144bf769a94761712846eb197c9623ead46a8a9/mini-program/frontend/images/ziwai.png
--------------------------------------------------------------------------------
/mini-program/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wechatprogr",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "dependencies": {},
7 | "devDependencies": {},
8 | "scripts": {
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC"
14 | }
15 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/crop/crop.js:
--------------------------------------------------------------------------------
1 | // pages/crop/crop.js
2 | const app=getApp()
3 | Page({
4 |
5 | /**
6 | * 页面的初始数据
7 | */
8 | data: {
9 | src: '',
10 | width: 250,//宽度
11 | height: 250,//高度
12 | uploadData:[],
13 | tags:null,
14 | name:null
15 | },
16 |
17 | /**
18 | * 生命周期函数--监听页面加载
19 | */
20 | onLoad: function (options) {
21 | console.log(options.data)
22 | //获取到image-cropper实例
23 | var that=this;
24 | that.data.uploadData.push(options.data);
25 | that.data.tags=that.data.uploadData.join(",");
26 | that.data.name=options.name
27 | this.cropper = this.selectComponent("#image-cropper");
28 | //开始裁剪
29 | wx.chooseImage({
30 | success(res) {
31 | const tempFilePaths = res.tempFilePaths
32 | //console.log(tempFilePaths);
33 | that.cropper.pushImg(tempFilePaths);
34 | app.globalData.imgSrc=tempFilePaths;
35 |
36 | }
37 | })
38 |
39 | },
40 | // cropperload(e) {
41 | // console.log("cropper初始化完成");
42 | // },
43 | loadimage(e) {
44 | console.log("图片加载完成", e.detail);
45 |
46 | //重置图片角度、缩放、位置
47 | this.cropper.imgReset();
48 | },
49 | submit() {
50 | var that=this;
51 |
52 | this.cropper.getImg((obj) => {
53 | console.log(obj)
54 | wx.showLoading({
55 | title: '识别中,请稍等',
56 | mask: true
57 | })
58 | console.log(that.data.tags);
59 | console.log(typeof (that.data.tags));
60 | wx.uploadFile({
61 |
62 | url: 'http://8.129.131.241:8777/', //仅为示例,非真实的接口地址
63 | filePath: obj.url,
64 | name: 'file',
65 | formData:
66 | {
67 | 'tags': that.data.tags
68 | },
69 | timeout:12000,
70 | success(res) {
71 |
72 |
73 | console.log(res.data)
74 | //const resor =res;
75 | //const data=res.data;
76 | //console.log(data);
77 |
78 | //console.log(resor);
79 | wx.hideLoading();
80 | app.globalData.options=res.data
81 | wx.switchTab({
82 |
83 | //url: "../result/result?val=" + data + "&file=" + app.imgSrc
84 | url: "../result/result"
85 | })
86 |
87 |
88 |
89 | },
90 | fail(){
91 | console.log("超时");
92 | wx.hideLoading();
93 | wx.showModal({
94 | title: '连接错误',
95 | content: '网络超时,请稍后重试!',
96 | showCancel:false,
97 | complete(res) {
98 | wx.navigateBack();
99 | }
100 | })
101 | },
102 | })
103 | });
104 | },
105 |
106 | /**
107 | * 生命周期函数--监听页面初次渲染完成
108 | */
109 | onReady: function () {
110 |
111 | },
112 |
113 | /**
114 | * 生命周期函数--监听页面显示
115 | */
116 | onShow: function () {
117 |
118 | },
119 |
120 | /**
121 | * 生命周期函数--监听页面隐藏
122 | */
123 | onHide: function () {
124 |
125 | },
126 |
127 | /**
128 | * 生命周期函数--监听页面卸载
129 | */
130 | onUnload: function () {
131 |
132 | },
133 |
134 | /**
135 | * 页面相关事件处理函数--监听用户下拉动作
136 | */
137 | onPullDownRefresh: function () {
138 |
139 | },
140 |
141 | /**
142 | * 页面上拉触底事件的处理函数
143 | */
144 | onReachBottom: function () {
145 |
146 | },
147 |
148 | /**
149 | * 用户点击右上角分享
150 | */
151 | onShareAppMessage: function () {
152 |
153 | }
154 | })
--------------------------------------------------------------------------------
/mini-program/frontend/pages/crop/crop.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | "image-cropper": "/image-cropper/image-cropper"
4 | },
5 | "navigationBarTitleText": "裁剪图片",
6 | "disableScroll": true
7 | }
--------------------------------------------------------------------------------
/mini-program/frontend/pages/crop/crop.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 请选择舌头区域
4 |
5 |
6 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/crop/crop.wxss:
--------------------------------------------------------------------------------
1 | /* pages/crop/crop.wxss */
2 | .hint{
3 | z-index: 10;
4 | width: 100%;
5 | color: #fff;
6 | position: absolute;
7 | top: 200rpx;
8 | text-align: center;
9 | }
10 | .btn{
11 | position: absolute;
12 | width:100%;
13 | bottom:200rpx;
14 | display: flex;
15 | flex-flow:wrap;
16 | z-index: 10;
17 | justify-content:space-around;
18 | }
19 | .btn-submit{
20 | background-color:#3DB29E;
21 | color: white;
22 | border-radius: 10px;
23 |
24 | }
25 | .btn-click{
26 | opacity: 0.5;
27 | transform:scale(0.92);
28 | }
--------------------------------------------------------------------------------
/mini-program/frontend/pages/detail/detail.js:
--------------------------------------------------------------------------------
1 | // pages/result/result.js
2 | const app = getApp()
3 | Page({
4 |
5 | /**
6 | * 页面的初始数据
7 | */
8 | data: {
9 | //图片存储链接
10 | val:0,
11 | resultUrl:null,
12 | display:'none',
13 | image:null,
14 | },
15 |
16 | /**
17 | * 生命周期函数--监听页面加载
18 | */
19 | onLoad: function (options) {
20 | options=app.globalData.options
21 | console.log(options)
22 | // const data = JSON.parse(options.data);
23 | const data = JSON.parse(options);
24 | //const data=options
25 | //console.log(options)
26 | this.setData({resultUrl:data.imgUrl,
27 | image:app.globalData.imgSrc
28 | });
29 | if(data.message!="null")
30 | wx.showModal({
31 | title: '提示',
32 | content:data.message,
33 | showCancel:false
34 | })
35 |
36 | // this.setData({resultUrl:data.imgUrl,
37 | // display:'block'//展示蒙版
38 | // });
39 | var obj={
40 | body:data.body,
41 | year_month_day:data.year_month_day,
42 | time:data.time
43 | }
44 | const temp = wx.getStorageSync('log') || [];
45 | temp.unshift(obj);
46 | wx.setStorageSync('log', temp);
47 |
48 |
49 |
50 | },
51 |
52 | /**
53 | * 生命周期函数--监听页面初次渲染完成
54 | */
55 | onReady: function () {
56 |
57 | },
58 |
59 | /**
60 | * 生命周期函数--监听页面显示
61 | */
62 | onShow: function () {
63 |
64 | },
65 |
66 | /**
67 | * 生命周期函数--监听页面隐藏
68 | */
69 | onHide: function () {
70 |
71 |
72 | },
73 |
74 | /**
75 | * 生命周期函数--监听页面卸载
76 | */
77 | onUnload: function () {
78 | },
79 |
80 | /**
81 | * 页面相关事件处理函数--监听用户下拉动作
82 | */
83 | onPullDownRefresh: function () {
84 |
85 | },
86 |
87 | /**
88 | * 页面上拉触底事件的处理函数
89 | */
90 | onReachBottom: function () {
91 |
92 | },
93 |
94 |
95 | /**
96 | * 用户点击右上角分享
97 | */
98 | onShareAppMessage: function () {
99 |
100 | },
101 |
102 |
103 | hideview: function() {
104 | this.setData({
105 | display: "none"
106 | })
107 | },
108 | clickDrinks:function(){
109 | wx.navigateTo({
110 | url: '/pages/drinks/drinks',
111 | })
112 | }
113 | })
114 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/detail/detail.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/mini-program/frontend/pages/detail/detail.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 | 用户上传的照片:
17 |
18 |
19 |
20 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/detail/detail.wxss:
--------------------------------------------------------------------------------
1 | /* pages/result/result.wxss */
2 |
3 | page{
4 | background-color: rgb(247, 247, 247)
5 | }
6 | .upload_img{
7 | position: absolute;
8 | top: 50rpx;
9 | left: 50rpx;
10 | color:rgba(000, 000, 000, 0.8)
11 | }
12 | .bodyimage{
13 | height: 150rpx;
14 | width: 150rpx;
15 | margin: 0 auto;
16 | margin-bottom: 50rpx;
17 | }
18 | .bodyimage image{
19 | width: 100%;
20 | height: 100%;
21 | }
22 | .resultImage{
23 | height: 1430rpx;
24 | width: 750rpx;
25 | text-align: center;
26 | }
27 | .resultImage image{
28 | height: 95%;
29 | width: 100%;
30 | }
31 | /* .clickDrink{
32 | opacity: 0.8;
33 | position: absolute;
34 | top: 5rpx;
35 | right: 5rpx;
36 | width:230rpx;
37 | text-align: center;
38 | line-height: 60rpx;
39 | height: 60rpx;
40 | z-index: 5;
41 | border-style: solid;
42 | border: 1px;
43 | border-radius: 15px;
44 | background: #3DB29E;
45 | color: black;
46 | }
47 |
48 | .clickDrink image{
49 | width: 30rpx;
50 | height: 30rpx;
51 | margin: auto;
52 | }
53 | .click{
54 | transform:scale(0.92);
55 | opacity: 0.5
56 | } */
57 | /* .bg {
58 | height: 1430rpx;
59 | width: 750rpx;
60 | display: none;
61 | position: absolute;
62 | top: 0%;
63 | left: 0%;
64 | background-color: black;
65 | z-index: 1001;
66 | -moz-opacity: 0.7;
67 | opacity: 0.70;
68 | filter: alpha(opacity=70);
69 | }
70 | .bg_image{
71 | padding-top: 20%;
72 | height: 100%;
73 | align-content: center;
74 | text-align: center;
75 | width: 100%;
76 | margin: auto;
77 | z-index: 1002;
78 |
79 | } */
--------------------------------------------------------------------------------
/mini-program/frontend/pages/drinks/drinks.js:
--------------------------------------------------------------------------------
1 | // pages/drinks.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | drinks: {
9 | '平和质': [
10 | { '名字': '百莲耳汤', '功效': '健脾养心安神', '成分': '莲子10克、百合10克、银耳10克', '状态': '热(推荐)', '热量': '500卡路里' },
11 | { '名字': '红米粥', '功效': '健脾祛湿', '成分': '红豆10克、薏米30克、梗米20克', '状态': '热(推荐)', '热量': '500卡路里' },
12 | { '名字': '胡萝卜山药汤', '功效': '健护脾胃,益气养阴', '成分': '鲜淮山1斤、猪尾骨1块、胡萝卜1根', '状态': '热(推荐)', '热量': '500卡路里' }
13 | ],
14 | '气虚质': [
15 | { '名字': '花胶党参鸡汤', '功效': '健脾养胃,益气补血', '成分': '花胶干品20克、党参20克、生姜3片,鸡半只(2人份)', '状态': '热(推荐)', '热量': '500卡路里' },
16 | { '名字': '参山莲枣汤', '功效': '健脾养胃,养心安神', '成分': '党参10克、山药10克、大枣10克、莲子10克', '状态': '热(推荐)', '热量': '500卡路里'},
17 | { '名字': '猴头菇鸡汤汤', '功效': '健脾养胃,益气养阴', '成分': '猴头菇1包、鸡半只、红枣5-6颗、枸杞1-2把、人参3片、米酒半杯', '状态': '热(推荐)', '热量': '500卡路里'}
18 | ],
19 | '气郁质':[
20 | { '名字': '佛手猪肝汤', '功效': '调和脾胃,疏肝解郁', '成分': '佛手片10克、鲜猪肝150克、麦片10克、盐、葱适量', '状态': '热(推荐)', '热量': '500卡路里' },
21 | { '名字': '陈皮玫瑰汤', '功效': '健脾疏肝解郁', '成分': '玫瑰10克、陈皮10克', '状态': '热(推荐)', '热量': '500卡路里'},
22 | { '名字': '百芎汤', '功效': '养阴安神,活血疏肝', '成分': '川芎10克、百合10克、龙眼肉10克', '状态': '热(推荐)', '热量': '500卡路里'}
23 | ],
24 | '湿热质': [
25 | { '名字': '绿豆海带煲排骨汤', '功效': '清热解毒,行气利湿', '成分': '猪排骨400克、绿豆50克、鲜海带100克、生姜3~5片,陈皮1瓣', '状态': '热(推荐)', '热量': '500卡路里' },
26 | { '名字': '胡萝卜茅根马蹄猪骨汤', '功效': '清热祛湿,生津止渴,利尿', '成分': '猪骨500克、茅根50克、马蹄6个、胡萝卜半个、蜜枣2粒', '状态': '热(推荐)', '热量': '500卡路里'},
27 | { '名字': '地石汤', '功效': '祛湿化痰、健脾补肺', '成分': '生地10克、石斛10克', '状态': '热(推荐)', '热量': '500卡路里'}
28 | ],
29 | '痰湿质': [
30 | { '名字': '冬瓜薏米猪骨汤', '功效': '健脾祛湿,利尿消肿', '成分': '猪骨500克、冬瓜700克、薏米100克、甜玉米1根、生姜1块', '状态': '热(推荐)', '热量': '500卡路里' },
31 | { '名字': '地石汤', '功效': '祛湿化痰、健脾补肺', '成分': '生地10克、石斛10克', '状态': '热(推荐)', '热量': '500卡路里'},
32 | { '名字': '杏仁薏米汤', '功效': '祛湿化痰、健脾补肺', '成分': '杏仁10克、薏米10克', '状态': '热(推荐)', '热量': '500卡路里'}
33 | ],
34 | '血瘀质': [
35 | { '名字': '田七排骨鸡脚汤', '功效': '活血化瘀,消肿止痛', '成分': '鸡脚数只、排骨500克、田七20克、姜1片、苹果半只', '状态': '热(推荐)', '热量': '500卡路里' },
36 | { '名字': '归母汤', '功效': '活血祛瘀,调经止痛', '成分': '当归10克、益母草10克、山楂10克', '状态': '热(推荐)', '热量': '500卡路里'},
37 | { '名字': '桃红汤', '功效': '活血调经、润肠通便', '成分': '桃仁10克、红花10克、大枣10克', '状态': '热(推荐)', '热量': '500卡路里'}
38 | ],
39 | '阳虚质': [{ '名字': '参归姜枣汤', '功效': '清热解毒,利气行湿', '成分': '党参10克、当归10克、生姜6克、大枣10克', '状态': '热(推荐)', '热量': '500卡路里' },
40 | { '名字': '巴戟炖猪肚汤', '功效': '强筋骨、安五脏、补中气、温肾阳', '成分': '巴戟50克、猪肚350克、姜10克、胡椒粒5克、调味料适量', '状态': '热(推荐)', '热量': '500卡路里'},
41 | { '名字': '苁蓉汤', '功效': '温补肾阳、固精缩尿', '成分': '肉苁蓉10克、菟丝子10克、大枣10克', '状态': '热(推荐)', '热量': '500卡路里'}
42 | ],
43 | '阴虚质': [
44 | { '名字': '杞冬参汤', '功效': '养阴益气,生津止渴', '成分': '枸杞10克、麦冬10克、西洋参10克', '状态': '热(推荐)', '热量': '500卡路里' },
45 | { '名字': '麦冬淮山玉竹煲鸽汤', '功效': '养阴润肺、健脾和胃', '成分': '鸽子1只、淮山15克、玉竹15克、麦冬15克、姜1片', '状态': '热(推荐)', '热量': '500卡路里'},
46 | { '名字': '杏仁汤', '功效': '养阴润肺,通肠润便', '成分': '杏仁10克、芝麻5克', '状态': '热(推荐)', '热量': '500卡路里'}
47 | ],
48 | },
49 | body:null,
50 | name:null,
51 | use:null,
52 | form:null,
53 | tem:null,
54 | energy:null,
55 | showIndex:0,
56 | },
57 |
58 | /**
59 | * 生命周期函数--监听页面加载
60 | */
61 | onLoad: function (options)
62 | {
63 | const item=wx.getStorageSync('log') || []
64 | if(item.length!=0){
65 | const body = item[0].body
66 | this.setData({
67 | body:body,
68 | name:this.data.drinks[body][0]['名字'],
69 | use: this.data.drinks[body][0]['功效'],
70 | form: this.data.drinks[body][0]['成分'],
71 | tem: this.data.drinks[body][0]['状态'],
72 | energy: this.data.drinks[body][0]['热量']
73 | })
74 | }
75 | else{
76 | wx.showModal({
77 | title: '提示',
78 | content: '检测到您还未诊断体质,请现在开始吧!',
79 | complete(res) {
80 | wx.navigateBack();
81 | }
82 | })
83 | }
84 | },
85 | change: function (e) {
86 | if (e.currentTarget.dataset.index != this.data.showIndex) {
87 | this.setData({
88 | showIndex: e.currentTarget.dataset.index
89 | })
90 | }
91 | //console.log(this.data.showIndex)
92 | const body=this.data.body
93 | const index=this.data.showIndex
94 | //console.log(body)
95 | this.setData({
96 | name: this.data.drinks[body][index]['名字'],
97 | use: this.data.drinks[body][index]['功效'],
98 | form: this.data.drinks[body][index]['成分'],
99 | tem: this.data.drinks[body][index]['状态'],
100 | energy: this.data.drinks[body][index]['热量']
101 | })
102 | },
103 | /**
104 | * 生命周期函数--监听页面初次渲染完成
105 | */
106 | onReady: function () {
107 |
108 | },
109 |
110 | /**
111 | * 生命周期函数--监听页面显示
112 | */
113 | onShow: function () {
114 |
115 | },
116 |
117 | /**
118 | * 生命周期函数--监听页面隐藏
119 | */
120 | onHide: function () {
121 |
122 | },
123 |
124 | /**
125 | * 生命周期函数--监听页面卸载
126 | */
127 | onUnload: function () {
128 |
129 | },
130 |
131 | /**
132 | * 页面相关事件处理函数--监听用户下拉动作
133 | */
134 | onPullDownRefresh: function () {
135 |
136 | },
137 |
138 | /**
139 | * 页面上拉触底事件的处理函数
140 | */
141 | onReachBottom: function () {
142 |
143 | },
144 |
145 | /**
146 | * 用户点击右上角分享
147 | */
148 | onShareAppMessage: function () {
149 |
150 | }
151 | })
--------------------------------------------------------------------------------
/mini-program/frontend/pages/drinks/drinks.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {},
3 | "navigationBarTitleText": "药膳推荐"
4 | }
--------------------------------------------------------------------------------
/mini-program/frontend/pages/drinks/drinks.wxml:
--------------------------------------------------------------------------------
1 |
2 | 根据您最近的诊断的体质:{{body}} 推荐
3 |
4 |
5 | 1
6 | 2
7 | 3
8 |
9 |
10 |
11 | {{name}}
12 |
13 | CUSTOMIZED
14 |
15 | HEALTH DRINKS
16 |
17 |
18 |
19 |
20 | |功效| {{use}}
21 | |成分| {{form}}
22 | |状态| {{tem}}
23 | |热量| {{energy}}
24 |
25 |
26 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/drinks/drinks.wxss:
--------------------------------------------------------------------------------
1 | /* pages/drinks.wxss */
2 |
3 |
4 | .tips{
5 | color: #b3b3b3;
6 | width: 70%;
7 | margin: auto;
8 | height: 50rpx;
9 | font-size: 30rpx;
10 | padding-top: 10rpx;
11 | }
12 | .drink_image{
13 | padding-top: 2rpx;
14 | height: 600rpx;
15 | width: 95%;
16 | margin: auto;
17 |
18 | }
19 | .drink_image image{
20 | width: 100%;
21 | height: 100%;
22 | margin: auto;
23 | }
24 |
25 | .drink_name{
26 | padding-top: 40rpx;
27 | height: 180rpx;
28 | width: 70%;
29 | margin: auto;
30 | border-bottom: 1px;
31 | border-bottom-style: solid;
32 | border-bottom-color: #f4c57a;
33 | }
34 |
35 | .drink_name .name{
36 | color: #3b8686;
37 | font-weight: bold;
38 | font-size: 48rpx;
39 | }
40 |
41 | .drink_name .name2{
42 | color: #bbe8e6;
43 | font-size: 36rpx;
44 | }
45 |
46 | .drink_info{
47 | padding-top: 50rpx;
48 | height: 700rpx;
49 | width: 70%;
50 | margin: auto;
51 | }
52 |
53 | .drink_info .info{
54 | font-size: 30rpx;
55 | color: #b3b3b3;
56 | margin-bottom: 70rpx;
57 | height: 60rpx;
58 | align-content: center;
59 | }
60 |
61 | .lable{
62 | padding-top: 20rpx;
63 | margin: auto;
64 | width: 70%
65 | }
66 | .lable_item{
67 | line-height: 50rpx;
68 | text-align:center;
69 | display: inline-block;
70 | width: 70rpx;
71 | height: 50rpx;
72 | border: 1px solid #f0f0f0;
73 | color: #b3b3b3;
74 | }
75 | .lable_item_selected{
76 | background-color: #3b8686;
77 | color:black;
78 | }
--------------------------------------------------------------------------------
/mini-program/frontend/pages/help/help.js:
--------------------------------------------------------------------------------
1 | // pages/help/help.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | showIndex:1,
9 | },
10 | acTap: function (e) {
11 | if (e.currentTarget.dataset.index != this.data.showIndex) {
12 | this.setData({
13 | showIndex: e.currentTarget.dataset.index
14 | })
15 | } else {
16 | this.setData({
17 | showIndex:0
18 | })
19 | }
20 | },
21 | /**
22 | * 生命周期函数--监听页面加载
23 | */
24 | onLoad: function (options) {
25 | this.setData({showIndex:1})
26 | },
27 |
28 | /**
29 | * 生命周期函数--监听页面初次渲染完成
30 | */
31 | onReady: function () {
32 |
33 | },
34 |
35 | /**
36 | * 生命周期函数--监听页面显示
37 | */
38 | onShow: function () {
39 |
40 | },
41 |
42 | /**
43 | * 生命周期函数--监听页面隐藏
44 | */
45 | onHide: function () {
46 |
47 | },
48 |
49 | /**
50 | * 生命周期函数--监听页面卸载
51 | */
52 | onUnload: function () {
53 |
54 | },
55 |
56 | /**
57 | * 页面相关事件处理函数--监听用户下拉动作
58 | */
59 | onPullDownRefresh: function () {
60 |
61 | },
62 |
63 | /**
64 | * 页面上拉触底事件的处理函数
65 | */
66 | onReachBottom: function () {
67 |
68 | },
69 |
70 | /**
71 | * 用户点击右上角分享
72 | */
73 | onShareAppMessage: function () {
74 |
75 | },
76 |
77 |
78 | name: "tuiCollapse",
79 | props: {
80 | //collapse背景颜色
81 | bgColor: {
82 | type: String,
83 | default: 'none'
84 | },
85 | //collapse-head 背景颜色
86 | hdBgColor: {
87 | type: String,
88 | default: '#fff'
89 | },
90 | //collapse-body 背景颜色
91 | bdBgColor: {
92 | type: String,
93 | default: 'none'
94 | },
95 | //collapse-body实际高度 open时使用
96 | height: {
97 | type: String,
98 | default: 'auto'
99 | },
100 | //close时translateY ,当bd高度固定时,建议值为0
101 | translateY: {
102 | type: String,
103 | default: '-50%'
104 | },
105 | //索引
106 | index: {
107 | type: Number,
108 | default: 0
109 | },
110 | //当前索引,index==current时展开
111 | current: {
112 | type: Number,
113 | default: -1
114 | },
115 | // 是否禁用
116 | disabled: {
117 | type: [Boolean, String],
118 | default: false
119 | },
120 | //是否带箭头
121 | arrow: {
122 | type: [Boolean, String],
123 | default: true
124 | },
125 | //箭头颜色
126 | arrowColor: {
127 | type: String,
128 | default: "#333"
129 | }
130 | },
131 | watch: {
132 | current() {
133 | this.updateCurrentChange()
134 | }
135 | },
136 | created() {
137 | this.updateCurrentChange()
138 | },
139 | data() {
140 | return {
141 | isOpen: false
142 | };
143 | },
144 | methods: {
145 | updateCurrentChange() {
146 | this.isOpen = this.index == this.current
147 | },
148 | handleClick() {
149 | if (this.disabled) return;
150 | this.$emit("click", {
151 | index: Number(this.index)
152 | })
153 | }
154 | }
155 |
156 |
157 | })
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/help/help.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {},
3 | "navigationBarTitleText": "说明帮助"
4 | }
--------------------------------------------------------------------------------
/mini-program/frontend/pages/help/help.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 注意事项
7 |
8 |
9 | 请确保光照条件正常。光线的强弱与色调,对颜色的影响极大。应以白天充足而柔和的自然光线为佳,如在夜间或暗处,用日光灯为好。\n\n不宜在饭后进行舌诊。饮食及药物可使舌象发生变化,过冷过热的饮食及刺激性食物可使舌色发生改变。过食肥甘之品及服大量镇静剂,可使舌苔厚腻。\n\n上传图片时尽量裁剪到舌头区域,否则可能会造成无法识别。
10 |
11 |
12 |
13 | 舌诊的来源
14 |
15 |
16 | 舌诊是观察舌头的色泽、形态的变化来辅助诊断及鉴别的一个简单有效的方法。\n\n舌诊主要诊察舌质和舌苔的形态、色泽、润燥等,以此判断疾病的性质、病势的浅深、气血的盛衰、津液的盈亏及脏腑的虚实等。
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 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | 关于我们
53 |
54 |
55 | 本小程序是由草木多闻团队设计呈现的,团队致力于高效的诊断方案和药膳汤品推荐。
56 |
57 |
58 |
59 |
60 |
62 |
67 |
68 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/help/help.wxss:
--------------------------------------------------------------------------------
1 | /* pages/help/help.wxss */
2 |
3 | page{
4 | margin-top: 80rpx;
5 | }
6 |
7 | .accordion
8 | {
9 | height: 700rpx;
10 | }
11 | .ac_item{
12 | margin: 15rpx 10rpx;
13 | height: 90rpx;
14 | line-height: 90rpx;
15 | position: relative;
16 | border-bottom-width: 1px;
17 |
18 | border-bottom-color: rgba(61,178,158,0.1);
19 | border-bottom-style: solid;
20 | padding-bottom: 10rpx;
21 |
22 | }
23 | .ac_text{
24 | padding-left: 5rpx;
25 | height: 90rpx;
26 | float: left;
27 | font-size: 15px;
28 |
29 | }
30 |
31 | .ac_icon{
32 | padding-right: 5rpx;
33 |
34 | float: right;
35 | height: 60rpx;
36 | width: 60rpx;
37 | }
38 | .ac_icon image{
39 | width: 30rpx;
40 | height: 30rpx;
41 | margin: 0 auto;
42 | align-content: center;
43 | }
44 |
45 | .ac_detail{
46 | margin: 0 25rpx;
47 | margin-bottom: 10rpx;
48 |
49 | }
50 | .ac_detail text{
51 | font-size: 14px;
52 | color:rgba(150,151,153);
53 | }
54 | .left{
55 | float: left;
56 | margin-left:10rpx;
57 | }
58 |
59 |
60 |
61 |
62 |
63 |
64 | /* .Q{
65 | margin-top: 25rpx;
66 | margin-left:5%;
67 | font-size: 15px;
68 | margin-bottom: 3px;
69 | width: 85%
70 | }
71 | .A{
72 | margin-left:5%;
73 | font-size: 13px;
74 | margin-bottom: 10px;
75 | color: rgb(130, 197, 189);
76 | width: 85%
77 |
78 | }
79 | */
80 | .exp
81 | {
82 | margin-top: 30px;
83 |
84 | display: flex;
85 | flex-direction: row;
86 | margin-left: 20px;
87 | }
88 | .text{
89 | font-size: 15px;
90 | color:rgba(150,151,153);
91 | width: 300rpx;
92 | }
93 | .text_{
94 | color:rgba(150,151,153);
95 | font-size: 13px;
96 | width: 300rpx;
97 | margin-top: 10rpx;
98 | }
99 | .image{
100 | margin-left: 50rpx;
101 | width: 250rpx;
102 | height: 250rpx;
103 | }
104 | .image image{
105 | width: 100%;
106 | height:100%;
107 | }
108 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/index/index.js:
--------------------------------------------------------------------------------
1 | var app = getApp()
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | diet_tips:"朝朝盐水,晚晚蜜汤。\n菊黄蟹肥秋正浓。\n秋之燥,菊花茶滋阴润燥。",
9 | sprit_tips:"露寒万物,汤暖你心。\n露寒霜重,心中暖意更重。",
10 | list: [{
11 | "text": "首页",
12 | dot: true
13 | },
14 | {
15 | "text": "设置",
16 | badge: 'New'
17 | }],
18 | scanitem:['','','']
19 | },
20 | clickHelp: function(){
21 | wx.navigateTo({
22 | url: '../help/help',
23 | })
24 | },
25 | /**
26 | * 生命周期函数--监听页面加载
27 | */
28 | onLoad: function (options) {
29 |
30 | },
31 |
32 | /**
33 | * 生命周期函数--监听页面初次渲染完成
34 | */
35 | onReady: function () {
36 |
37 | },
38 |
39 | /**
40 | * 生命周期函数--监听页面显示
41 | */
42 | onShow: function () {
43 |
44 | },
45 |
46 | /**
47 | * 生命周期函数--监听页面隐藏
48 | */
49 | onHide: function () {
50 |
51 | },
52 |
53 | /**
54 | * 生命周期函数--监听页面卸载
55 | */
56 | onUnload: function () {
57 |
58 | },
59 |
60 | /**
61 | * 页面相关事件处理函数--监听用户下拉动作
62 | */
63 | onPullDownRefresh: function () {
64 |
65 | },
66 |
67 | /**
68 | * 页面上拉触底事件的处理函数
69 | */
70 | onReachBottom: function () {
71 |
72 | },
73 |
74 | /**
75 | * 用户点击右上角分享
76 | */
77 | onShareAppMessage: function () {
78 |
79 | return {
80 |
81 | title: '草木多闻',
82 | desc: '快来体验舌诊识别体质吧!',
83 | path: '/pages/index/index'
84 |
85 | }
86 |
87 | },
88 |
89 |
90 | clickToTake: function()
91 | {
92 | wx.navigateTo({
93 | url: '/pages/optional/optional',
94 | })
95 | },
96 | clickLogs: function () {
97 | wx.navigateTo({
98 | url: '/pages/logs/logs',
99 | })
100 | },
101 | clickDrinks: function () {
102 | wx.navigateTo({
103 | url: '/pages/drinks/drinks',
104 | })
105 | }
106 | })
107 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 |
4 |
5 | }
--------------------------------------------------------------------------------
/mini-program/frontend/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
29 |
41 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | 临近节气
65 |
66 | 寒露
67 | Cold Dew
68 | 八月廿二
69 | 秋日的凉冷归于寒露,秋日的温暖归于暖汤。
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | 今日健康指数
78 |
79 |
80 |
81 | 优
82 |
83 |
84 |
85 | 90%
86 |
87 |
88 |
89 | 弱
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | {{diet_tips}}
98 |
99 |
100 |
101 | {{sprit_tips}}
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/logs/logs.js:
--------------------------------------------------------------------------------
1 | //logs.js
2 | const util = require('../../utils/util.js')
3 | Page({
4 | data: {
5 | log: [],
6 | hasLog:false,
7 | },
8 | // onLoad: function () {
9 | // this.setData({
10 | // logs: (wx.getStorageSync('logs') || []).map(log => {
11 | // return util.formatTime(new Date(log))
12 | // })
13 | // })
14 | // }
15 | onLoad: function () {
16 | console.log(wx.getStorageSync('log'))
17 | this.setData({
18 | log: wx.getStorageSync('log') || []
19 | })
20 | if(this.data.log.length!=0)
21 | {
22 | this.setData({
23 | hasLog:true
24 | })
25 | }
26 |
27 | },
28 |
29 | clearStorage:function()
30 | {
31 | var that=this;
32 | wx.showModal({
33 | title: '清空所有记录',
34 | content: '您确定要清空所有记录吗?',
35 | success(res){
36 | if(res.confirm)
37 | wx.clearStorageSync();
38 | that.setData({
39 | log: wx.getStorageSync('log') || []
40 | })
41 | }
42 | })
43 | }
44 | })
45 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/logs/logs.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "体质记录",
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/mini-program/frontend/pages/logs/logs.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{item.year_month_day}}
4 |
5 |
6 | {{item.time}} 诊断为{{item.body}}
7 |
8 |
9 |
10 |
11 |
12 |
13 | 清空所有记录
14 |
15 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/logs/logs.wxss:
--------------------------------------------------------------------------------
1 |
2 | page{
3 |
4 | --black: #333333;
5 | --cyan: #1cbbb4;
6 | --ghostWhite: #f1f1f1;
7 | --white: #ffffff;
8 |
9 |
10 | font-size: 28rpx;
11 | color: var(--black);
12 | font-family: Helvetica Neue, Helvetica, sans-serif;
13 | }
14 |
15 | /* ==================
16 | 时间轴
17 | ==================== */
18 |
19 | .cu-timeline {
20 | display: block;
21 | background-color: var(--white);
22 | }
23 |
24 | .cu-timeline .cu-time {
25 | width: 180rpx;
26 | text-align: center;
27 | padding: 20rpx 0;
28 | font-size: 26rpx;
29 | color: #888;
30 | display: block;
31 | }
32 |
33 | .cu-timeline>.cu-item {
34 | padding: 30rpx 30rpx 30rpx 120rpx;
35 | position: relative;
36 | display: block;
37 | z-index: 0;
38 | }
39 |
40 | .cu-timeline>.cu-item:not([class*="text-"]) {
41 | color: #ccc;
42 | }
43 |
44 | .cu-timeline>.cu-item::after {
45 | content: "";
46 | display: block;
47 | position: absolute;
48 | width: 1rpx;
49 | background-color: #ddd;
50 | left: 60rpx;
51 | height: 100%;
52 | top: 0;
53 | z-index: 8;
54 | }
55 |
56 | .cu-timeline>.cu-item::before {
57 | font-family: "cuIcon";
58 | display: block;
59 | position: absolute;
60 | top: 36rpx;
61 | z-index: 9;
62 | background-color: var(--white);
63 | width: 50rpx;
64 | height: 50rpx;
65 | text-align: center;
66 | border: none;
67 | line-height: 50rpx;
68 | left: 36rpx;
69 | }
70 |
71 | .cu-timeline>.cu-item:not([class*="cuIcon-"])::before {
72 | content: "\e763";
73 | }
74 |
75 | .cu-timeline>.cu-item[class*="cuIcon-"]::before {
76 | background-color: var(--white);
77 | width: 50rpx;
78 | height: 50rpx;
79 | text-align: center;
80 | border: none;
81 | line-height: 50rpx;
82 | left: 36rpx;
83 | }
84 |
85 | .cu-timeline>.cu-item>.content {
86 | padding: 30rpx;
87 | border-radius: 6rpx;
88 | display: block;
89 | line-height: 1.6;
90 | }
91 |
92 | .cu-timeline>.cu-item>.content:not([class*="bg-"]) {
93 | background-color: var(--ghostWhite);
94 | color: var(--black);
95 | }
96 |
97 | .cu-timeline>.cu-item>.content+.content {
98 | margin-top: 20rpx;
99 | }
100 |
101 | .text-cyan{
102 | color: var(--cyan);
103 | }
104 |
105 | .clear{
106 | width: 100%;
107 | bottom: 10px;
108 | border-top-style:solid;
109 | border-top-width: 1px;
110 | border-top-color: rgba(61,178,158,0.2);
111 | margin: 20rpx;
112 | text-align: center
113 | }
114 | .clear_btn{
115 | width: 40%;
116 | padding-top: 10px;
117 | color:rgba(150,151,153,0.8);
118 | font-size: 28rpx;
119 | margin: auto;
120 | text-align: center
121 | }
--------------------------------------------------------------------------------
/mini-program/frontend/pages/optional/optional.js:
--------------------------------------------------------------------------------
1 | // pages/optional/optional.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | list: [
9 | { name: '乏力', checked: false },
10 | { name: '口渴', checked: false },
11 | { name: '痰多', checked: false },
12 | { name: '自汗', checked: false },
13 | { name: '心烦', checked: false },
14 | { name: '失眠', checked: false },
15 | { name: '口苦', checked: false },
16 | { name: '易长痘痘', checked: false },
17 | { name: '身体困重', checked: false },
18 | { name: '耐受寒热', checked: false },
19 | { name: '不易疲劳', checked: false },
20 | { name: '自觉发热', checked: false },
21 | { name: '多愁善感', checked: false },
22 | { name: '口腔溃疡', checked: false },
23 | { name: '头胀胸闷', checked: false },
24 | { name: '面色晦暗', checked: false },
25 | { name: '胸胁疼痛', checked: false },
26 | { name: '少气懒言', checked: false },
27 | { name: '容易生气', checked: false },
28 | { name: '容易感冒', checked: false },
29 | { name: '畏寒肢冷', checked: false },
30 | { name: '嗳气叹气', checked: false },
31 | { name: '大便稀溏', checked: false },
32 | { name: '消化不良', checked: false },
33 | { name: '关节疼痛', checked: false },
34 | { name: '皮肤干燥', checked: false },
35 | { name: '皮肤粗糙有瘀斑', checked: false },
36 | { name: '月经血块', checked: false },
37 | { name: '身体水肿', checked: false },
38 |
39 |
40 |
41 | ],
42 | max_selected: 4,
43 | cur_selected: 0,
44 | arr_selected: [],
45 | name:null
46 | },
47 |
48 |
49 |
50 |
51 | lable_click: function (e) {
52 | var that = this;
53 | console.log(e.currentTarget.dataset);
54 | var index = e.currentTarget.dataset.index;
55 | var checked = e.currentTarget.dataset.checked;
56 | var name = e.currentTarget.dataset.name;
57 | //判断是否达到可选上限
58 | console.log(checked)
59 | if (!checked) {
60 | if (that.data.cur_selected >= that.data.max_selected) {
61 | //弹出模态框
62 | wx.showModal({
63 | content: '为了使结果更准确,最多选择'+that.data.max_selected+'项主要症状',
64 | showCancel: false
65 | })
66 | return;
67 | }
68 | that.data.cur_selected++;
69 | var temp = "list[" + index + "].checked";
70 | that.setData({ [temp]: !checked });
71 | that.data.arr_selected.push(name);
72 | console.log("插入后" + that.data.arr_selected)
73 | }
74 | //取消选中
75 | else {
76 | var temp = "list[" + index + "].checked";
77 | that.setData({ [temp]: !checked })
78 | for (var i in that.data.arr_selected)
79 | if (that.data.arr_selected[i] == name)
80 | that.data.arr_selected.splice(i, 1);
81 | that.data.cur_selected--;
82 | console.log("取消后" + that.data.arr_selected);
83 | }
84 |
85 |
86 | },
87 |
88 | submit:function(){
89 | var that=this;
90 | wx.redirectTo({
91 | url: "../crop/crop?data=" + that.data.arr_selected,
92 | })
93 | },
94 |
95 | /**
96 | * 生命周期函数--监听页面加载
97 | */
98 | onLoad: function (options) {
99 |
100 | },
101 |
102 | checkbox_group_change:function(e){
103 | console.log(e.detail.value)
104 |
105 | },
106 | /**
107 | * 生命周期函数--监听页面初次渲染完成
108 | */
109 | onReady: function () {
110 |
111 | },
112 |
113 | /**
114 | * 生命周期函数--监听页面显示
115 | */
116 | onShow: function () {
117 |
118 | },
119 |
120 | /**
121 | * 生命周期函数--监听页面隐藏
122 | */
123 | onHide: function () {
124 |
125 | },
126 |
127 | /**
128 | * 生命周期函数--监听页面卸载
129 | */
130 | onUnload: function () {
131 |
132 | },
133 |
134 | /**
135 | * 页面相关事件处理函数--监听用户下拉动作
136 | */
137 | onPullDownRefresh: function () {
138 |
139 | },
140 |
141 | /**
142 | * 页面上拉触底事件的处理函数
143 | */
144 | onReachBottom: function () {
145 |
146 | },
147 |
148 | /**
149 | * 用户点击右上角分享
150 | */
151 | onShareAppMessage: function () {
152 |
153 | },
154 | })
--------------------------------------------------------------------------------
/mini-program/frontend/pages/optional/optional.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/mini-program/frontend/pages/optional/optional.wxml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | {{item.name}}
10 |
11 |
12 |
13 |
14 |
15 | 下一步
16 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/optional/optional.wxss:
--------------------------------------------------------------------------------
1 | /* pages/optional/optional.wxss */
2 |
3 | page{
4 | margin: 0;
5 | padding:0;
6 | }
7 |
8 | .lable_header{ width: 100%; background-color: #fff; padding: 50rpx 30rpx 40rpx; box-sizing: border-box;
9 | }
10 | .lable_info{ width: 100%; overflow: hidden; }
11 | .lable_info .title{ font-size: 32rpx;}
12 | .lable_info .tip{ color: #b2b2b2; font-size: 26rpx; margin-top: 25rpx; }
13 |
14 | .lable_list{
15 | padding: 10rpx 25rpx;
16 | width: 100%;
17 | height: 750rpx;
18 | }
19 |
20 | .lable{
21 | width: auto;
22 | padding: 0 20rpx;
23 | display: inline-block;
24 | text-align: center;
25 | height: 70rpx;
26 | line-height: 70rpx;
27 | border: 1px solid #f0f0f0;
28 | border-radius: 10rpx;
29 | font-size: 28rpx; color: #808080;
30 | margin: 0 23rpx 23rpx 0;
31 | }
32 | .lable_selected{
33 | color: #3DB29E;
34 | border-color: #3DB29E;
35 | }
36 |
37 |
38 | .lable_button{
39 | position:fixed;
40 | bottom:10rpx;
41 | display:flex;
42 | text-align: center;
43 | justify-content:center;
44 | width: 100%;
45 | }
46 | .lable_submit{
47 | border-radius: 149px;
48 | background-color: rgba(114,155,137,0.5);
49 | box-shadow: 5px 5px 10px #8f8f8f,
50 | -5px -5px 10px #ffffff;
51 | height: 135rpx;
52 | width: 135rpx;
53 | text-align: center;
54 | justify-content:center;
55 | line-height: 135rpx;
56 | font-size: 34rpx; color: white;
57 | }
58 |
59 | .lable_submit:hover{
60 | transform:scale(0.92);
61 | opacity: 0.5
62 | }
63 |
64 |
65 |
66 | .putname{
67 | margin-left: 25rpx;
68 | }
--------------------------------------------------------------------------------
/mini-program/frontend/pages/result/result.js:
--------------------------------------------------------------------------------
1 | // pages/result/result.js
2 | const app = getApp()
3 | Page({
4 |
5 | /**
6 | * 页面的初始数据
7 | */
8 | data: {
9 | //图片存储链接
10 | bodyIntroduce:"人体阳气化生不足,温煦作用下降生里寒。",
11 | userInfo: {},
12 | hasUserInfo: false,
13 | canIUse: wx.canIUse('button.open-type.getUserInfo'),
14 | canIUseGetUserProfile: false,
15 | canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName'), // 如需尝试获取用户信息可改为false
16 | },
17 |
18 | /**
19 | * 生命周期函数--监听页面加载
20 | */
21 | onLoad: function (options) {
22 | // const data = JSON.parse(options.data);
23 | // console.log(data);
24 | // //console.log(options)
25 | // //this.setData({image:options.file});
26 | // if(data.message!="null")
27 | // wx.showModal({
28 | // title: '提示',
29 | // content:data.message,
30 | // complete(res) {
31 | // wx.navigateBack();
32 | // }
33 | // })
34 |
35 | // this.setData({resultUrl:data.imgUrl,
36 | // display:'block'//展示蒙版
37 | // });
38 | // var obj={
39 | // body:data.body,
40 | // year_month_day:data.year_month_day,
41 | // time:data.time
42 | // }
43 | // const temp = wx.getStorageSync('log') || [];
44 | // temp.unshift(obj);
45 | // wx.setStorageSync('log', temp);
46 |
47 |
48 | //------------------------------------------------!
49 | if (wx.getUserProfile) {
50 | this.setData({
51 | canIUseGetUserProfile: true
52 | })
53 | }
54 | },
55 | getUserProfile(e) {
56 | // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
57 | wx.getUserProfile({
58 | desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
59 | success: (res) => {
60 | console.log(res)
61 | this.setData({
62 | userInfo: res.userInfo,
63 | hasUserInfo: true
64 | })
65 | }
66 | })
67 |
68 | console.log(this.data.userInfo)
69 |
70 | },
71 |
72 | /**
73 | * 生命周期函数--监听页面初次渲染完成
74 | */
75 | onReady: function () {
76 |
77 | },
78 |
79 | /**
80 | * 生命周期函数--监听页面显示
81 | */
82 | onShow: function () {
83 |
84 | },
85 |
86 | /**
87 | * 生命周期函数--监听页面隐藏
88 | */
89 | onHide: function () {
90 |
91 |
92 | },
93 |
94 | /**
95 | * 生命周期函数--监听页面卸载
96 | */
97 | onUnload: function () {
98 | },
99 |
100 | /**
101 | * 页面相关事件处理函数--监听用户下拉动作
102 | */
103 | onPullDownRefresh: function () {
104 |
105 | },
106 |
107 | /**
108 | * 页面上拉触底事件的处理函数
109 | */
110 | onReachBottom: function () {
111 |
112 | },
113 |
114 |
115 | /**
116 | * 用户点击右上角分享
117 | */
118 | onShareAppMessage: function () {
119 |
120 | },
121 |
122 |
123 | hideview: function() {
124 | this.setData({
125 | display: "none"
126 | })
127 | },
128 | clickDrinks:function(){
129 | wx.navigateTo({
130 | url: '/pages/drinks/drinks',
131 | })
132 | },
133 | clickDetail:function(){
134 | wx.navigateTo({
135 | url: '/pages/detail/detail',
136 | })
137 | }
138 | })
139 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/result/result.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {},
3 | "navigationBarTitleText": "舌诊结果"
4 | }
--------------------------------------------------------------------------------
/mini-program/frontend/pages/result/result.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
14 |
17 |
26 |
27 |
28 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | 点击获取用户信息
46 |
47 |
48 |
49 |
50 | {{userInfo.nickName}}
51 |
52 | 阳虚质
53 | {{bodyIntroduce}}
54 | 2020/10/03
55 |
56 |
57 |
58 | 更多分析结果
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
70 |
--------------------------------------------------------------------------------
/mini-program/frontend/pages/result/result.wxss:
--------------------------------------------------------------------------------
1 | /* pages/result/result.wxss */
2 |
3 | /* page{
4 | background-color: rgb(247, 247, 247)
5 | } */
6 | /* .bodyimage{
7 | height: 150rpx;
8 | width: 150rpx;
9 | margin: 0 auto;
10 | margin-bottom: 50rpx;
11 | }
12 | .bodyimage image{
13 | width: 100%;
14 | height: 100%;
15 | } */
16 | /* .resultImage{
17 | height: 1430rpx;
18 | width: 750rpx;
19 | text-align: center;
20 | }
21 | .resultImage image{
22 | height: 95%;
23 | width: 100%;
24 | }
25 | .clickDrink{
26 | opacity: 0.8;
27 | position: absolute;
28 | top: 5rpx;
29 | right: 5rpx;
30 | width:230rpx;
31 | text-align: center;
32 | line-height: 60rpx;
33 | height: 60rpx;
34 | z-index: 5;
35 | border-style: solid;
36 | border: 1px;
37 | border-radius: 15px;
38 | background: #3DB29E;
39 | color: black;
40 | }
41 |
42 | .clickDrink image{
43 | width: 30rpx;
44 | height: 30rpx;
45 | margin: auto;
46 | }
47 | .click{
48 | transform:scale(0.92);
49 | opacity: 0.5
50 | }
51 | .bg {
52 | height: 1430rpx;
53 | width: 750rpx;
54 | display: none;
55 | position: absolute;
56 | top: 0%;
57 | left: 0%;
58 | background-color: black;
59 | z-index: 1001;
60 | -moz-opacity: 0.7;
61 | opacity: 0.70;
62 | filter: alpha(opacity=70);
63 | }
64 | .bg_image{
65 | padding-top: 20%;
66 | height: 100%;
67 | align-content: center;
68 | text-align: center;
69 | width: 100%;
70 | margin: auto;
71 | z-index: 1002;
72 |
73 | } */
74 |
75 | .header{
76 | background-color: #729b89;
77 | height: 300rpx;
78 | }
79 |
80 | .header_textCN{
81 | text-align: center;
82 | font-size: 38rpx;
83 | padding-top: 80rpx;
84 | padding-bottom: 10rpx;
85 | letter-spacing:8rpx;
86 | }
87 |
88 | .header_textEN{
89 | color: #e8cc9c;
90 | text-align: center;
91 | font-size: 14rpx;
92 | }
93 |
94 | .card{
95 |
96 | background-image: url('data:image/png;base64,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');
97 | background-repeat:no-repeat;
98 | background-size:100% 100%;
99 | -moz-background-size:100% 100%;
100 | margin: auto;
101 | position: relative;
102 | top: -150rpx;
103 | height: 450rpx;
104 | width: 90%;
105 | }
106 |
107 | .card_container{
108 | height: 260rpx;
109 | }
110 |
111 | .card .avatar{
112 | position: absolute;
113 | left: 40rpx;
114 | top: 40rpx;
115 | opacity: 0.8;
116 | }
117 | .userinfo-avatar {
118 | overflow: hidden;
119 | width: 128rpx;
120 | height: 128rpx;
121 | margin: 20rpx;
122 | border-radius: 50%;
123 | }
124 | .hasNotUserInfo{
125 | position: absolute;
126 | left: 80rpx;
127 | top: 100rpx;
128 | width: 300rpx;
129 | height: 100rpx;
130 | background-color:#729b89;
131 | border-radius: 999px;
132 | color: white;
133 | text-align: center;
134 | line-height: 100rpx;
135 | opacity: 0.8;
136 | }
137 | .card .nick{
138 | position: absolute;
139 | left: 80rpx;
140 | top: 250rpx;
141 | opacity: 0.8;
142 | }
143 |
144 | .card .body{
145 | position: absolute;
146 | right: 80rpx;
147 | top: 80rpx;
148 | font-weight: bold;
149 | font-size: 40rpx;
150 | letter-spacing: 5rpx;
151 | opacity: 0.8;
152 | }
153 |
154 | .card .body_info{
155 | position: absolute;
156 | right: 40rpx;
157 | top: 150rpx;
158 | font-size: 24rpx;
159 | letter-spacing: 5rpx;
160 | opacity: 0.8;
161 | width: 200rpx;
162 | text-align: left;
163 | }
164 |
165 | .card .time{
166 | position: absolute;
167 | left: 80rpx;
168 | bottom:50rpx;
169 | font-size: 30rpx;
170 | color: #e8cc9c;
171 | }
172 |
173 | .more{
174 | color: #e8cc9c;
175 | font-size: 30rpx;
176 | margin-left: 15%;
177 | height: 50rpx;
178 | line-height: 50rpx;
179 | letter-spacing: 5rpx;
180 | margin-top: 40rpx;
181 | }
182 |
183 | .button_group{
184 | margin-top: 60rpx;
185 | }
186 |
187 | .button_line{
188 | height: 325rpx;
189 | text-align: center;
190 | }
191 |
192 | .button{
193 | width:325rpx;
194 | height: 325rpx;
195 | display: inline-block;
196 | }
197 |
198 | .button image{
199 | width:325rpx;
200 | height: 325rpx;
201 | }
202 |
203 | .click
204 | {
205 | transform:scale(0.92);
206 | opacity: 0.5
207 | }
--------------------------------------------------------------------------------
/mini-program/frontend/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件",
3 | "packOptions": {
4 | "ignore": []
5 | },
6 | "setting": {
7 | "urlCheck": false,
8 | "es6": true,
9 | "postcss": true,
10 | "minified": true,
11 | "newFeature": true,
12 | "coverView": true,
13 | "autoAudits": false,
14 | "showShadowRootInWxmlPanel": true,
15 | "scopeDataCheck": false,
16 | "checkInvalidKey": true,
17 | "checkSiteMap": true,
18 | "uploadWithSourceMap": true,
19 | "useMultiFrameRuntime": false,
20 | "useApiHook": true,
21 | "babelSetting": {
22 | "ignore": [],
23 | "disablePlugins": [],
24 | "outputPath": ""
25 | },
26 | "useIsolateContext": true,
27 | "useCompilerModule": true,
28 | "userConfirmedUseCompilerModuleSwitch": false,
29 | "packNpmManually": false,
30 | "packNpmRelationList": []
31 | },
32 | "compileType": "miniprogram",
33 | "libVersion": "2.16.0",
34 | "appid": "wx99d6524a9f5ce5d5",
35 | "projectname": "%E8%8D%89%E6%9C%A8%E5%A4%9A%E9%97%BB",
36 | "debugOptions": {
37 | "hidedInDevtools": []
38 | },
39 | "isGameTourist": false,
40 | "simulatorType": "wechat",
41 | "simulatorPluginLibVersion": {},
42 | "condition": {
43 | "search": {
44 | "current": -1,
45 | "list": []
46 | },
47 | "conversation": {
48 | "current": -1,
49 | "list": []
50 | },
51 | "game": {
52 | "currentL": -1,
53 | "list": []
54 | },
55 | "miniprogram": {
56 | "current": -1,
57 | "list": []
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/mini-program/frontend/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [{
4 | "action": "allow",
5 | "page": "*"
6 | }]
7 | }
--------------------------------------------------------------------------------
/mini-program/frontend/utils/util.js:
--------------------------------------------------------------------------------
1 | const formatTime = date => {
2 | const year = date.getFullYear()
3 | const month = date.getMonth() + 1
4 | const day = date.getDate()
5 | const hour = date.getHours()
6 | const minute = date.getMinutes()
7 | const second = date.getSeconds()
8 |
9 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
10 | }
11 |
12 | const formatNumber = n => {
13 | n = n.toString()
14 | return n[1] ? n : '0' + n
15 | }
16 |
17 | module.exports = {
18 | formatTime: formatTime
19 | }
20 |
--------------------------------------------------------------------------------