├── .gitignore
├── .idea
├── inspectionProfiles
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── think.iml
├── vcs.xml
└── workspace.xml
├── .vscode
└── settings.json
├── LICENSE.md
├── README.md
├── djapi
├── djapi
│ ├── __init__.py
│ ├── settings
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── local_.py
│ │ └── settings.py
│ ├── urls.py
│ └── wsgi.py
├── gunicorn.conf.py
├── manage.py
├── passport
│ ├── __init__.py
│ ├── api.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_weixinusers_created.py
│ │ └── __init__.py
│ ├── models.py
│ └── tests.py
├── requirements.txt
├── think
│ ├── __init__.py
│ ├── api.py
│ ├── filter.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_auto_20171025_2311.py
│ │ ├── 0003_auto_20171109_1123.py
│ │ └── __init__.py
│ ├── models.py
│ ├── serializers.py
│ └── tests.py
└── tools
│ ├── auth.py
│ ├── helper.py
│ └── rest_helper.py
└── weixin
├── app.js
├── app.json
├── app.wxss
├── pages
├── detail
│ ├── detail.js
│ ├── detail.json
│ ├── detail.wxml
│ ├── detail.wxss
│ └── share
│ │ ├── share.js
│ │ ├── share.json
│ │ ├── share.wxml
│ │ └── share.wxss
├── edit
│ ├── edit.js
│ ├── edit.json
│ ├── edit.wxml
│ ├── edit.wxss
│ └── location
│ │ ├── location.js
│ │ ├── location.json
│ │ ├── location.wxml
│ │ └── location.wxss
├── index
│ ├── earth
│ │ ├── earth.js
│ │ ├── earth.json
│ │ ├── earth.wxml
│ │ └── earth.wxss
│ ├── index.js
│ ├── index.wxml
│ └── index.wxss
└── logs
│ ├── logs.js
│ ├── logs.json
│ ├── logs.wxml
│ └── logs.wxss
├── static
├── image
│ ├── add.png
│ ├── delete.png
│ ├── earth.png
│ ├── edit.png
│ ├── home.png
│ ├── home_selected.png
│ ├── index.png
│ ├── index_selected.png
│ ├── location.png
│ ├── location_selected.png
│ ├── save_pic.png
│ └── think.png
└── style
│ └── weui.wxss
└── utils
├── WxNotificationCenter.js
├── config.js
├── event-emitter.js
├── helper_business.js
├── qqmap-wx-jssdk.min.js
└── util.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 |
49 | # Translations
50 | *.mo
51 | *.pot
52 |
53 | # Django stuff:
54 | *.log
55 | local_settings.py
56 |
57 | # Flask stuff:
58 | instance/
59 | .webassets-cache
60 |
61 | # Scrapy stuff:
62 | .scrapy
63 |
64 | # Sphinx documentation
65 | docs/_build/
66 |
67 | # PyBuilder
68 | target/
69 |
70 | # Jupyter Notebook
71 | .ipynb_checkpoints
72 |
73 | # pyenv
74 | .python-version
75 |
76 | # celery beat schedule file
77 | celerybeat-schedule
78 |
79 | # SageMath parsed files
80 | *.sage.py
81 |
82 | # dotenv
83 | .env
84 |
85 | # virtualenv
86 | .venv
87 | venv/
88 | ENV/
89 |
90 | # Spyder project settings
91 | .spyderproject
92 | .spyproject
93 |
94 | # Rope project settings
95 | .ropeproject
96 |
97 | # mkdocs documentation
98 | /site
99 |
100 | # mypy
101 | .mypy_cache/
102 |
103 | local.py
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/think.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | pyc
120 | id
121 | that
122 |
123 |
124 |
125 |
126 |
127 |
128 |
141 |
142 |
143 |
144 |
145 | true
146 | DEFINITION_ORDER
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 | 1511179271814
416 |
417 |
418 | 1511179271814
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.enable": false
3 | }
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 yongxinz
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 | 欢迎关注我的微信公众号:AlwaysBeta,更多精彩内容等你来。
2 |
3 | 
4 |
5 | # think
6 |
7 | 记录位置和想法,以时间线形式来展示的微信小程序
8 |
9 | 
10 |
11 | ## 功能
12 | 目前支持功能:新加、修改想法,生成想法详情卡片并保存到相册,生成足迹卡片并保存到相册
13 |
14 | ## 环境
15 | Python 版本为 python3.6,后端使用:Django + restframework
16 | 小程序基础库版本 1.5.3
17 |
18 | ## 安装
19 | 1、新建虚拟环境
20 | >mkvirtualenv think --python=python3
21 |
22 | 2、安装依赖包
23 | >cd djapi
24 | >pip install -r requestments.txt
25 |
26 | 3、配置 APPID 和 APPsecret
27 | >cp djapi/djapi/settings/local_.py djapi/djapi/settings/local.py
28 |
29 | 然后将其中的 id 和 key 替换成你自己的
30 |
31 | >WEIXIN = {
32 | > 'url': 'https://api.weixin.qq.com',
33 | > 'id': 'your appid',
34 | > 'key': 'your appsecret'
35 | >}
36 |
37 | 4、初始化表
38 | >python manage.py migrate
39 |
40 | 5、Run,并运行小程序
41 | >python manage.py runserver 0.0.0.0:8810
42 |
43 | ## 抢先体验
44 | 
--------------------------------------------------------------------------------
/djapi/djapi/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/djapi/djapi/__init__.py
--------------------------------------------------------------------------------
/djapi/djapi/settings/__init__.py:
--------------------------------------------------------------------------------
1 | try:
2 | from .local import *
3 | except ImportError:
4 | from .base import *
5 |
--------------------------------------------------------------------------------
/djapi/djapi/settings/base.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # coding=utf-8
3 |
4 | from .settings import *
5 | from os.path import join, abspath, dirname
6 |
7 | # make root path
8 | here = lambda *x: join(abspath(dirname(__file__)), *x)
9 | PROJECT_ROOT = here("..", "..")
10 | root = lambda *x: join(abspath(PROJECT_ROOT), *x)
11 |
12 | DEBUG = False
13 |
14 | TIME_ZONE = 'Asia/Shanghai'
15 | LANGUAGE_CODE = 'zh-hans'
16 | LOGIN_URL = "/passport/login/"
17 | LOGOUT_URL = "/passport/logout/"
18 | LOGIN_REDIRECT_URL = "/passport/"
19 |
20 | ALLOWED_HOSTS = [
21 | '127.0.0.1',
22 | 'think.naturez.cn'
23 | ]
24 |
25 | INTERNAL_IPS = ['127.0.0.1', 'think.naturez.cn']
26 | INSTALLED_APPS += [
27 | 'think',
28 | 'passport'
29 | ]
30 |
31 | CAPTCHA_BACKGROUND_COLOR = "#eee"
32 | CAPTCHA_CHALLENGE_FUNCT = 'tools.helper.random_digit_challenge'
33 |
34 | REST_FRAMEWORK = {
35 | 'DEFAULT_AUTHENTICATION_CLASSES': ('tools.auth.YMAuthentication',),
36 | 'DEFAULT_PAGINATION_CLASS': 'tools.rest_helper.YMPagination',
37 | 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),
38 | }
39 |
40 | # for test
41 | TEST_RUNNER = 'test_runner.YmRunner'
42 |
--------------------------------------------------------------------------------
/djapi/djapi/settings/local_.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # coding=utf-8
3 |
4 | from .base import *
5 |
6 | DEBUG = True
7 |
8 | DATABASES = {
9 | 'default': {
10 | 'ENGINE': 'django.db.backends.postgresql_psycopg2',
11 | 'NAME': 'think',
12 | }
13 | }
14 |
15 | INSTALLED_APPS += [
16 | 'rest_framework',
17 | # 'debug_toolbar',
18 | ]
19 |
20 | WEIXIN = {
21 | 'url': 'https://api.weixin.qq.com',
22 | 'id': 'your appid',
23 | 'key': 'your appsecret',
24 | }
25 |
--------------------------------------------------------------------------------
/djapi/djapi/settings/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for djapi project.
3 |
4 | Generated by 'django-admin startproject' using Django 1.11.6.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.11/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/1.11/ref/settings/
11 | """
12 |
13 | import os
14 |
15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = 'e*e397y)u@tb7a*w$7)28@krj1a6ul^mc2n+37f^g8y^+zl*#7'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = ['192.168.1.11']
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'django.contrib.admin',
35 | 'django.contrib.auth',
36 | 'django.contrib.contenttypes',
37 | 'django.contrib.sessions',
38 | 'django.contrib.messages',
39 | 'django.contrib.staticfiles',
40 | ]
41 |
42 | MIDDLEWARE = [
43 | 'django.middleware.security.SecurityMiddleware',
44 | 'django.contrib.sessions.middleware.SessionMiddleware',
45 | 'django.middleware.common.CommonMiddleware',
46 | 'django.middleware.csrf.CsrfViewMiddleware',
47 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
48 | 'django.contrib.messages.middleware.MessageMiddleware',
49 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
50 | ]
51 |
52 | ROOT_URLCONF = 'djapi.urls'
53 |
54 | TEMPLATES = [
55 | {
56 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
57 | 'DIRS': [],
58 | 'APP_DIRS': True,
59 | 'OPTIONS': {
60 | 'context_processors': [
61 | 'django.template.context_processors.debug',
62 | 'django.template.context_processors.request',
63 | 'django.contrib.auth.context_processors.auth',
64 | 'django.contrib.messages.context_processors.messages',
65 | ],
66 | },
67 | },
68 | ]
69 |
70 | WSGI_APPLICATION = 'djapi.wsgi.application'
71 |
72 |
73 | # Database
74 | # https://docs.djangoproject.com/en/1.11/ref/settings/#databases
75 |
76 | DATABASES = {
77 | 'default': {
78 | 'ENGINE': 'django.db.backends.sqlite3',
79 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
80 | }
81 | }
82 |
83 |
84 | # Password validation
85 | # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
86 |
87 | AUTH_PASSWORD_VALIDATORS = [
88 | {
89 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
90 | },
91 | {
92 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
93 | },
94 | {
95 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
96 | },
97 | {
98 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
99 | },
100 | ]
101 |
102 |
103 | # Internationalization
104 | # https://docs.djangoproject.com/en/1.11/topics/i18n/
105 |
106 | LANGUAGE_CODE = 'en-us'
107 |
108 | TIME_ZONE = 'UTC'
109 |
110 | USE_I18N = True
111 |
112 | USE_L10N = True
113 |
114 | USE_TZ = True
115 |
116 |
117 | # Static files (CSS, JavaScript, Images)
118 | # https://docs.djangoproject.com/en/1.11/howto/static-files/
119 |
120 | STATIC_URL = '/static/'
121 |
--------------------------------------------------------------------------------
/djapi/djapi/urls.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | """djapi URL Configuration
3 |
4 | The `urlpatterns` list routes URLs to views. For more information please see:
5 | https://docs.djangoproject.com/en/1.11/topics/http/urls/
6 | Examples:
7 | Function views
8 | 1. Add an import: from my_app import views
9 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
10 | Class-based views
11 | 1. Add an import: from other_app.views import Home
12 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
13 | Including another URLconf
14 | 1. Import the include() function: from django.conf.urls import url, include
15 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
16 | """
17 | from django.conf.urls import url, include
18 | from rest_framework import routers
19 |
20 | from passport.api import WeixinUserViewSet
21 | from think.api import ThinkViewSet
22 |
23 | router = routers.DefaultRouter()
24 |
25 | # 微信登录
26 | router.register(r'passport/wx', WeixinUserViewSet, base_name='passport_weixin')
27 | router.register(r'think', ThinkViewSet, base_name='think')
28 |
29 | urlpatterns = [
30 | url(r'^api/', include(router.urls)),
31 | ]
32 |
--------------------------------------------------------------------------------
/djapi/djapi/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for djapi project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djapi.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/djapi/gunicorn.conf.py:
--------------------------------------------------------------------------------
1 | workers = 3
2 | worker_class = "gevent"
3 | bind = "127.0.0.1:8810"
4 |
--------------------------------------------------------------------------------
/djapi/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djapi.settings")
7 | try:
8 | from django.core.management import execute_from_command_line
9 | except ImportError:
10 | # The above import may fail for some other reason. Ensure that the
11 | # issue is really that Django is missing to avoid masking other
12 | # exceptions on Python 2.
13 | try:
14 | import django
15 | except ImportError:
16 | raise ImportError(
17 | "Couldn't import Django. Are you sure it's installed and "
18 | "available on your PYTHONPATH environment variable? Did you "
19 | "forget to activate a virtual environment?"
20 | )
21 | raise
22 | execute_from_command_line(sys.argv)
23 |
--------------------------------------------------------------------------------
/djapi/passport/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/djapi/passport/__init__.py
--------------------------------------------------------------------------------
/djapi/passport/api.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | import uuid
3 | import requests
4 |
5 | from django.conf import settings
6 | from rest_framework.decorators import list_route
7 | from rest_framework import viewsets
8 | from rest_framework.response import Response
9 |
10 | from passport.models import WeixinUsers
11 | from tools.helper import Dict2obj
12 |
13 |
14 | class WeixinUserViewSet(viewsets.ViewSet):
15 | @list_route(methods=['get'], authentication_classes=())
16 | def login(self, request):
17 | # 通过微信code获取用户openid
18 | conf = Dict2obj(settings.WEIXIN)
19 | url = conf.url + "/sns/jscode2session"
20 | js_code = request.query_params.get('code', '')
21 | params = dict(appid=conf.id, secret=conf.key, js_code=js_code, grant_type="authorization_code")
22 | rq = requests.get(url, params=params).json()
23 |
24 | if rq.get('errcode'):
25 | return Response(dict(status=False, msg=rq))
26 |
27 | # 更新该微信号(openid)的sid和skey
28 | wx_user, is_new = WeixinUsers.objects.update_or_create(openid=rq.get('openid'), is_del=False, defaults={
29 | 'session_key': rq.get('session_key'),
30 | 'unionid': rq.get('unionid', ''),
31 | 'sid': uuid.uuid4(),
32 | })
33 |
34 | return Response(dict(status=True, sid=wx_user.sid))
35 |
36 | @list_route(methods=['post'], authentication_classes=())
37 | def join2wx(self, request):
38 | # 检查微信登录是否成功
39 | sid = request.META.get('HTTP_AUTHORIZATION', 'whoareyou')
40 | try:
41 | wx_user = WeixinUsers.objects.get(sid=sid, is_del=False)
42 | except:
43 | return Response({'status': False, 'msg': u'微信验证失败,请重新授权'})
44 |
--------------------------------------------------------------------------------
/djapi/passport/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.6 on 2017-10-25 14:47
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import uuid
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | initial = True
12 |
13 | dependencies = [
14 | ]
15 |
16 | operations = [
17 | migrations.CreateModel(
18 | name='weixinUsers',
19 | fields=[
20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21 | ('openid', models.CharField(max_length=50, verbose_name='openid')),
22 | ('unionid', models.CharField(default='', max_length=50, verbose_name='uuid')),
23 | ('session_key', models.CharField(default='', max_length=50)),
24 | ('sid', models.UUIDField(default=uuid.uuid1)),
25 | ('is_del', models.BooleanField(default=False)),
26 | ],
27 | options={
28 | 'ordering': ['-pk'],
29 | 'get_latest_by': 'pk',
30 | },
31 | ),
32 | ]
33 |
--------------------------------------------------------------------------------
/djapi/passport/migrations/0002_weixinusers_created.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.6 on 2017-11-09 03:23
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import django.utils.timezone
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | dependencies = [
12 | ('passport', '0001_initial'),
13 | ]
14 |
15 | operations = [
16 | migrations.AddField(
17 | model_name='weixinusers',
18 | name='created',
19 | field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now, verbose_name='注册时间'),
20 | preserve_default=False,
21 | ),
22 | ]
23 |
--------------------------------------------------------------------------------
/djapi/passport/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/djapi/passport/migrations/__init__.py
--------------------------------------------------------------------------------
/djapi/passport/models.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | import uuid
3 |
4 | from django.db import models
5 |
6 |
7 | class WeixinUsers(models.Model):
8 | openid = models.CharField(u'openid', max_length=50)
9 | unionid = models.CharField(u'uuid', max_length=50, default='')
10 | session_key = models.CharField(max_length=50, default='')
11 | sid = models.UUIDField(default=uuid.uuid1)
12 | is_del = models.BooleanField(default=False)
13 | created = models.DateTimeField(u"注册时间", auto_now_add=True)
14 |
15 | class Meta:
16 | ordering = ['-pk']
17 | get_latest_by = "pk"
18 |
--------------------------------------------------------------------------------
/djapi/passport/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/djapi/requirements.txt:
--------------------------------------------------------------------------------
1 | Django==1.11.1
2 | djangorestframework==3.7.1
3 | psycopg2==2.7.3.2
4 | requests==2.18.4
5 | django-filter==1.1.0
6 | python-dateutil==2.6.1
--------------------------------------------------------------------------------
/djapi/think/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/djapi/think/__init__.py
--------------------------------------------------------------------------------
/djapi/think/api.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | import datetime
5 |
6 | from rest_framework import viewsets
7 | from rest_framework.response import Response
8 | from rest_framework.decorators import list_route
9 |
10 | from .models import Think
11 | from .serializers import ThinkSerializer
12 | from .filter import ThinkFilter
13 |
14 |
15 | class ThinkViewSet(viewsets.ModelViewSet):
16 | queryset = Think.objects.all()
17 | serializer_class = ThinkSerializer
18 | filter_class = ThinkFilter
19 |
20 | def get_queryset(self):
21 | queryset = Think.objects.filter(weixin=self.request.user)
22 |
23 | return queryset
24 |
25 | def perform_create(self, serializer):
26 | update_dict = {}
27 |
28 | update_dict['weixin'] = self.request.user
29 | update_dict['created'] = datetime.datetime.now()
30 | serializer.save(**update_dict)
31 |
32 | @list_route(methods=['get'])
33 | def earth(self, request):
34 | now = datetime.datetime.now()
35 | year = now.strftime("%Y")
36 | obj = Think.objects.filter(weixin=request.user, created__startswith=year)
37 |
38 | think_count = obj.count()
39 | nation_count = obj.exclude(nation='').distinct('nation').order_by('nation').count()
40 | city_count = obj.exclude(city='').distinct('city').order_by('city').count()
41 |
42 | return Response(
43 | data={'year': year, 'think_count': think_count, 'nation_count': nation_count, 'city_count': city_count,
44 | 'now': now.strftime("%Y-%m-%d %H:%M:%S")})
45 |
--------------------------------------------------------------------------------
/djapi/think/filter.py:
--------------------------------------------------------------------------------
1 | import django_filters
2 | from .models import Think
3 |
4 |
5 | class ThinkFilter(django_filters.rest_framework.FilterSet):
6 |
7 | class Meta:
8 | model = Think
9 | fields = ['id', ]
10 |
--------------------------------------------------------------------------------
/djapi/think/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.6 on 2017-10-25 14:47
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | initial = True
12 |
13 | dependencies = [
14 | ('passport', '0001_initial'),
15 | ]
16 |
17 | operations = [
18 | migrations.CreateModel(
19 | name='Think',
20 | fields=[
21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22 | ('think', models.TextField(max_length=1000, verbose_name='想法')),
23 | ('nation', models.CharField(blank=True, max_length=20, null=True, verbose_name='国家')),
24 | ('province', models.CharField(blank=True, max_length=20, null=True, verbose_name='省')),
25 | ('city', models.CharField(blank=True, max_length=20, null=True, verbose_name='城市')),
26 | ('address', models.CharField(blank=True, max_length=50, null=True, verbose_name='地址')),
27 | ('created', models.DateTimeField(verbose_name='创建时间')),
28 | ('weixin', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='passport.weixinUsers')),
29 | ],
30 | options={
31 | 'ordering': ['-pk'],
32 | },
33 | ),
34 | ]
35 |
--------------------------------------------------------------------------------
/djapi/think/migrations/0002_auto_20171025_2311.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.6 on 2017-10-25 15:11
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | dependencies = [
12 | ('think', '0001_initial'),
13 | ]
14 |
15 | operations = [
16 | migrations.AlterField(
17 | model_name='think',
18 | name='weixin',
19 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='passport.WeixinUsers'),
20 | ),
21 | ]
22 |
--------------------------------------------------------------------------------
/djapi/think/migrations/0003_auto_20171109_1123.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.6 on 2017-11-09 03:23
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | dependencies = [
12 | ('think', '0002_auto_20171025_2311'),
13 | ]
14 |
15 | operations = [
16 | migrations.AlterField(
17 | model_name='think',
18 | name='weixin',
19 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='passport.WeixinUsers'),
20 | ),
21 | ]
22 |
--------------------------------------------------------------------------------
/djapi/think/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/djapi/think/migrations/__init__.py
--------------------------------------------------------------------------------
/djapi/think/models.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 |
3 | from dateutil import tz
4 |
5 | from django.conf import settings
6 | from django.db import models
7 | from passport.models import WeixinUsers
8 |
9 |
10 | class Think(models.Model):
11 | """想法"""
12 | weixin = models.ForeignKey(WeixinUsers)
13 | think = models.TextField(u'想法', max_length=1000)
14 | nation = models.CharField(u"国家", max_length=20, null=True, blank=True)
15 | province = models.CharField(u"省", max_length=20, null=True, blank=True)
16 | city = models.CharField(u"城市", max_length=20, null=True, blank=True)
17 | address = models.CharField(u"地址", max_length=50, null=True, blank=True)
18 | created = models.DateTimeField(u"创建时间")
19 |
20 | def get_created(self):
21 | return self.created.astimezone(tz.gettz(settings.TIME_ZONE)).strftime('%Y-%m-%d %H:%M:%S')
22 |
23 | def get_day(self):
24 | return self.created.day
25 |
26 | def get_month(self):
27 | return self.created.month
28 |
29 | class Meta:
30 | ordering = ['-pk']
31 |
32 |
--------------------------------------------------------------------------------
/djapi/think/serializers.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | from rest_framework import serializers
3 |
4 | from .models import Think
5 |
6 |
7 | class ThinkSerializer(serializers.ModelSerializer):
8 | created_display = serializers.ReadOnlyField(source='get_created')
9 | month = serializers.ReadOnlyField(source='get_month')
10 | day = serializers.ReadOnlyField(source='get_day')
11 |
12 | class Meta:
13 | model = Think
14 | exclude = ('weixin', 'created')
15 |
--------------------------------------------------------------------------------
/djapi/think/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/djapi/tools/auth.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | from rest_framework import authentication, exceptions
3 |
4 | from passport.models import WeixinUsers
5 | from tools.helper import Dict2obj
6 |
7 |
8 | class YMAuthentication(authentication.BaseAuthentication):
9 | def authenticate(self, request):
10 | hash_key = request.META.get('HTTP_AUTHORIZATION', '123abc')
11 | try:
12 | user = WeixinUsers.objects.get(sid=hash_key, is_del=False)
13 | except:
14 | raise exceptions.AuthenticationFailed({
15 | 'status': False,
16 | 'status_code': 403010,
17 | })
18 |
19 | return user, Dict2obj({
20 | 'user': user,
21 | })
22 |
--------------------------------------------------------------------------------
/djapi/tools/helper.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 |
3 | import requests
4 | import datetime
5 | import re
6 | import random
7 | from decimal import Decimal
8 |
9 | from django.conf import settings
10 |
11 |
12 | class Helper(object):
13 | @classmethod
14 | def get_safe_now(self):
15 | try:
16 | from django.utils.timezone import utc
17 | if settings.USE_TZ:
18 | return datetime.datetime.utcnow().replace(tzinfo=utc)
19 | except:
20 | pass
21 |
22 | return datetime.datetime.now()
23 |
24 | @classmethod
25 | def mk_random(self, num=8, ram_type='str'):
26 | ram_int = '1234567890'
27 | ram_str = 'abcdefghigklmnopqrstuvwxyz1234567890'
28 |
29 | if ram_type != 'str':
30 | ram_str = ram_int
31 |
32 | return "".join(random.sample(ram_str, num))
33 |
34 | @classmethod
35 | def password_format_check(self, password):
36 | result = {"status": True}
37 | # 至少8位
38 | if len(password) < 8:
39 | result.update({"status": False, 'msg': "密码过于简单,密码至少8位"})
40 | # 至少一个数字
41 | if not re.match(r'.*[0-9]+', password):
42 | result.update({"status": False, 'msg': "密码过于简单,至少包括一个数字"})
43 | # 至少一个小写字母
44 | if not re.match(r'.*[a-zA-Z]+', password):
45 | result.update({"status": False, 'msg': "密码过于简单,至少包括一个字母"})
46 |
47 | return result
48 |
49 | @classmethod
50 | def mobile_format_check(self, mobile):
51 | result = {"status": True}
52 | # 至少11位
53 | if len(mobile) != 11:
54 | result.update({"status": False, 'msg': u"请填写11位手机号码"})
55 | # 全部数字
56 | if not re.match(r'^1[0-9]{10}', mobile):
57 | result.update({"status": False, 'msg': u"手机格式不对,请填写11位手机号码"})
58 |
59 | return result
60 |
61 |
62 | class Dict2obj(object):
63 | def __init__(self, dict_data):
64 | self.__dict__ = dict_data
65 |
66 | def __str__(self):
67 | return str(self.__dict__)
68 |
69 | def __getattr__(self, item):
70 | return self.__dict__.get(item)
71 |
72 |
73 | def random_digit_challenge():
74 | ret = u''
75 | for i in range(4):
76 | ret += str(random.randint(0, 9))
77 | return ret, ret
78 |
79 |
80 | class YMapi(object):
81 | # YMapi.get('adp', 'erp').json()
82 |
83 | @classmethod
84 | def get(self, api=' ', service='erp', params=None):
85 | host = settings.API_SRV.get(service).get('host')
86 | api = settings.API_SRV.get(service).get('api').get(api)
87 | auth = settings.API_SRV.get(service).get('authorization')
88 | key = settings.API_SRV.get(service).get('key')
89 | if auth:
90 | r = requests.get(url=host + api, headers={'AUTHORIZATION': auth}, params=params)
91 | else:
92 | r = requests.get(url=host + api + '?key=' + key, params=params)
93 | return r
94 |
95 | @classmethod
96 | def post(self, api='url', service='erp', params=None, data=None, pk=''):
97 | host = settings.API_SRV.get(service).get('host')
98 | api = settings.API_SRV.get(service).get('api').get(api)
99 | auth = settings.API_SRV.get(service).get('authorization')
100 | key = settings.API_SRV.get(service).get('key')
101 | pk = (pk + '/') if pk else ''
102 | if auth:
103 | r = requests.post(url=host + api + pk, headers={'AUTHORIZATION': auth}, params=params, json=data)
104 | else:
105 | r = requests.post(url=host + api + pk + '?key=' + key, params=params, json=data)
106 | return r
107 |
108 | @classmethod
109 | def put(self, api='url', service='erp', params=None, data=None, pk=''):
110 | host = settings.API_SRV.get(service).get('host')
111 | api = settings.API_SRV.get(service).get('api').get(api)
112 | auth = settings.API_SRV.get(service).get('authorization')
113 | key = settings.API_SRV.get(service).get('key')
114 | pk = (pk + '/') if pk else ''
115 | if auth:
116 | r = requests.put(url=host + api + pk, headers={'AUTHORIZATION': auth}, params=params, json=data)
117 | else:
118 | r = requests.put(url=host + api + pk + '?key=' + key, params=params, json=data)
119 | return r
120 |
121 | @classmethod
122 | def patch(self, api='url', service='erp', params=None, data=None, pk=''):
123 | host = settings.API_SRV.get(service).get('host')
124 | api = settings.API_SRV.get(service).get('api').get(api)
125 | auth = settings.API_SRV.get(service).get('authorization')
126 | key = settings.API_SRV.get(service).get('key')
127 | pk = (pk + '/') if pk else ''
128 | if auth:
129 | r = requests.patch(url=host + api + pk, headers={'AUTHORIZATION': auth}, params=params, json=data)
130 | else:
131 | r = requests.patch(url=host + api + pk + '?key=' + key, params=params, json=data)
132 | return r
133 |
134 | @classmethod
135 | def delete(self, api='url', service='erp', params=None, pk=''):
136 | host = settings.API_SRV.get(service).get('host')
137 | api = settings.API_SRV.get(service).get('api').get(api)
138 | auth = settings.API_SRV.get(service).get('authorization')
139 | key = settings.API_SRV.get(service).get('key')
140 | pk = (pk + '/') if pk else ''
141 | if auth:
142 | r = requests.delete(url=host + api + pk, headers={'AUTHORIZATION': auth}, params=params)
143 | else:
144 | r = requests.delete(url=host + api + pk + '?key=' + key, params=params)
145 | return r
146 |
147 |
148 | def decimal_round(value, num=2):
149 | save_num = '{:.' + str(num) + 'f}'
150 | return save_num.format(Decimal(str(value)))
151 |
--------------------------------------------------------------------------------
/djapi/tools/rest_helper.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | from rest_framework.pagination import PageNumberPagination
3 |
4 |
5 | class YMPagination(PageNumberPagination):
6 | page_size = 15
7 | page_size_query_param = 'size'
8 | max_page_size = 1000
9 |
--------------------------------------------------------------------------------
/weixin/app.js:
--------------------------------------------------------------------------------
1 | import helperB from "./utils/helper_business";
2 | import config from "./utils/config";
3 |
4 | App({
5 | helper: helperB,
6 | config: config,
7 |
8 | onLaunch: function () {
9 | // 微信登录,获取用户code
10 | helperB.wxPromisify(wx.login)().then(function (res) {
11 | // 登录后端, wx code -> dj sid
12 | helperB.getApi(config.api.login, { code: res.code }).then(function (res) {
13 | config.gData.userSid = res.data.sid;
14 | config.emitter.emit('userSid');
15 | });
16 | }).catch(function (res) {
17 | console.error(res.errMsg)
18 | });
19 | }
20 | // globalData: {
21 | // userInfo: null
22 | // }
23 | });
24 |
--------------------------------------------------------------------------------
/weixin/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/index/index",
4 | "pages/index/earth/earth",
5 | "pages/detail/detail",
6 | "pages/detail/share/share",
7 | "pages/edit/edit",
8 | "pages/edit/location/location",
9 | "pages/logs/logs"
10 | ],
11 | "window": {
12 | "backgroundTextStyle": "light",
13 | "navigationBarBackgroundColor": "#fff",
14 | "navigationBarTitleText": "灵感乍现",
15 | "navigationBarTextStyle": "black"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/weixin/app.wxss:
--------------------------------------------------------------------------------
1 | @import 'static/style/weui.wxss';
2 |
3 | page {
4 | background-color: #f0f0f0;
5 | font-size: 16px;
6 | font-family: -apple-system-font,Helvetica Neue,Helvetica,sans-serif;
7 | }
8 |
9 | .page__hd {
10 | padding: 40px;
11 | }
12 | .page__bd {
13 | padding-bottom: 40px;
14 | }
15 | .page__bd_spacing {
16 | padding-left: 15px;
17 | padding-right: 15px;
18 | }
19 |
20 | .page__ft{
21 | padding-bottom: 10px;
22 | text-align: center;
23 | }
24 |
25 | .page__title {
26 | text-align: left;
27 | font-size: 20px;
28 | font-weight: 400;
29 | }
30 |
31 | .page__desc {
32 | margin-top: 5px;
33 | color: #888888;
34 | text-align: left;
35 | font-size: 14px;
36 | }
37 |
--------------------------------------------------------------------------------
/weixin/pages/detail/detail.js:
--------------------------------------------------------------------------------
1 | const app = getApp();
2 |
3 | Page({
4 | data: {
5 | windowWidth: 0,
6 | windowHeight: 0
7 | },
8 |
9 | onLoad: function (options) {
10 | let that = this;
11 | that.setData({ options: options });
12 | wx.getSystemInfo({
13 | success: function (res) {
14 | that.setData({
15 | windowWidth: res.windowWidth,
16 | windowHeight: res.windowHeight
17 | });
18 | }
19 | });
20 | },
21 |
22 | onShow: function () {
23 | app.helper.waitUserSid(this.getApiData)
24 | },
25 |
26 | getApiData: function () {
27 | let that = this;
28 |
29 | wx.showLoading({ title: '加载中...' });
30 | app.helper.getApi(app.config.api.think, that.data.options).then(function (res) {
31 | that.setData({ id: res.data.results[0].id, think: res.data.results[0].think, address: res.data.results[0].address, created: res.data.results[0].created_display });
32 | }).then(function () {
33 | wx.hideLoading()
34 | });
35 | },
36 |
37 | thinkEdit: function(e) {
38 | let id = e.currentTarget.dataset.id;
39 | wx.navigateTo({ url: '../edit/edit?id=' + id })
40 | },
41 |
42 | thinkPic: function (e) {
43 | let id = e.currentTarget.dataset.id;
44 | wx.navigateTo({ url: './share/share?id=' + id })
45 | }
46 | });
--------------------------------------------------------------------------------
/weixin/pages/detail/detail.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "想法"
3 | }
--------------------------------------------------------------------------------
/weixin/pages/detail/detail.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ created }}
5 | {{ address }}
6 |
7 |
8 |
9 | {{ think }}
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/weixin/pages/detail/detail.wxss:
--------------------------------------------------------------------------------
1 | .section-detail{
2 | background-color: white;
3 | margin: 20px 20px 0px 20px;
4 | padding: 30px 15px 10px 15px;
5 | border-radius:10px;
6 |
7 | -webkit-box-shadow:2px 2px 5px #BFBFBF;
8 | box-shadow:2px 2px 5px #BFBFBF;
9 | }
10 |
11 | .top {
12 | border-bottom: 1px solid #eee;
13 | }
14 |
15 | .top .detail {
16 | font-size: 13px;
17 | margin-bottom: 40rpx;
18 | padding-right: 10px;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: flex-end;
22 | }
23 |
24 | .content {
25 | font-size: 16px;
26 | margin-top: 40rpx;
27 | overflow-x: scroll;
28 | }
29 |
30 | ::-webkit-scrollbar {
31 | width: 0px;
32 | height: 0px;
33 | color: transparent;
34 | }
35 |
36 | .detail-footer {
37 | height: 50px;
38 | margin-right: 25px;
39 | display: flex;
40 | align-items: center;
41 | float: right;
42 | }
43 |
44 | .detail-footer image {
45 | width: 60rpx;
46 | height: 60rpx;
47 | }
48 |
49 | .detail-footer .edit {
50 | margin-right: 10px;
51 | }
--------------------------------------------------------------------------------
/weixin/pages/detail/share/share.js:
--------------------------------------------------------------------------------
1 | import util from '../../../utils/util'
2 |
3 | const app = getApp();
4 |
5 | Page({
6 | data: {
7 | windowWidth: 0,
8 | windowHeight: 0,
9 | contentHeight: 0,
10 | thinkList: [],
11 | footer: '',
12 | offset: 0,
13 | lineHeight: 30
14 | },
15 |
16 | onLoad: function (options) {
17 | let that = this;
18 | that.setData({options: options});
19 | wx.getSystemInfo({
20 | success: function (res) {
21 | that.setData({
22 | windowWidth: res.windowWidth,
23 | windowHeight: res.windowHeight,
24 | offset: (res.windowWidth - 304) / 2
25 | });
26 | }
27 | });
28 | },
29 |
30 | onShow: function () {
31 | app.helper.waitUserSid(this.getApiData)
32 | },
33 |
34 | getApiData: function () {
35 | let that = this;
36 |
37 | wx.showLoading({ title: '加载中...' });
38 | app.helper.getApi(app.config.api.think, that.data.options).then(function (res) {
39 | that.setData({footer: res.data.results[0].created_display + ' ' + res.data.results[0].city});
40 |
41 | let i = 0;
42 | let lineNum = 1;
43 | let thinkStr = '';
44 | let thinkList = [];
45 | for (let item of res.data.results[0].think) {
46 | if (item === '\n') {
47 | thinkList.push(thinkStr);
48 | thinkList.push('a');
49 | i = 0;
50 | thinkStr = '';
51 | lineNum += 1;
52 | } else if (i === 19) {
53 | thinkList.push(thinkStr);
54 | i = 1;
55 | thinkStr = item;
56 | lineNum += 1;
57 | } else {
58 | thinkStr += item;
59 | i += 1;
60 | }
61 | }
62 | thinkList.push(thinkStr);
63 | that.setData({thinkList: thinkList});
64 | that.createNewImg(lineNum);
65 | }).then(function () {
66 | wx.hideLoading()
67 | });
68 | },
69 |
70 | drawSquare: function (ctx, height) {
71 | ctx.setFontSize(24);
72 | ctx.rect(0, 50, this.data.windowWidth, height);
73 | ctx.setFillStyle("#f5f6fd");
74 | ctx.fill()
75 | },
76 |
77 | drawFont: function (ctx, content, height) {
78 | ctx.setFontSize(16);
79 | ctx.setFillStyle("#484a3d");
80 | ctx.fillText(content, this.data.offset, height);
81 | },
82 |
83 | drawLine: function (ctx, height) {
84 | ctx.beginPath();
85 | ctx.moveTo(this.data.offset, height);
86 | ctx.lineTo(this.data.windowWidth - this.data.offset, height);
87 | ctx.stroke('#eee');
88 | ctx.closePath();
89 | },
90 |
91 | createNewImg: function (lineNum) {
92 | let that = this;
93 | let ctx = wx.createCanvasContext('myCanvas');
94 | let contentHeight = lineNum * that.data.lineHeight + 180;
95 | that.drawSquare(ctx, contentHeight);
96 | that.setData({contentHeight: contentHeight});
97 | let height = 100;
98 | for (let item of that.data.thinkList) {
99 | if (item !== 'a') {
100 | that.drawFont(ctx, item, height);
101 | height += that.data.lineHeight;
102 | }
103 | }
104 | that.drawLine(ctx, lineNum * that.data.lineHeight + 120);
105 | that.drawFont(ctx, that.data.footer, lineNum * that.data.lineHeight + 156);
106 | ctx.drawImage('../../../static/image/think.png', that.data.windowWidth - that.data.offset - 50, lineNum * that.data.lineHeight + 125, 50, 50)
107 | ctx.draw();
108 | },
109 |
110 | savePic: function () {
111 | let that = this;
112 | wx.canvasToTempFilePath({
113 | x: 0,
114 | y: 50,
115 | width: that.data.windowWidth,
116 | height: that.data.contentHeight,
117 | canvasId: 'myCanvas',
118 | success: function (res) {
119 | util.savePicToAlbum(res.tempFilePath)
120 | }
121 | });
122 | }
123 | });
--------------------------------------------------------------------------------
/weixin/pages/detail/share/share.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "想法"
3 | }
--------------------------------------------------------------------------------
/weixin/pages/detail/share/share.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/weixin/pages/detail/share/share.wxss:
--------------------------------------------------------------------------------
1 | .edit-footer {
2 | height: 60px;
3 | margin-top: 20px;
4 | padding-left: 40rpx;
5 | padding-right: 40rpx;
6 | background-color: back;
7 | display: flex;
8 | align-items: center;
9 | }
10 |
11 | .button-done {
12 | width: 100%;
13 | border-radius: 50rpx;
14 | /*background: linear-gradient(to right, red , blue);*/
15 | }
--------------------------------------------------------------------------------
/weixin/pages/edit/edit.js:
--------------------------------------------------------------------------------
1 | var WxNotificationCenter = require('../../utils/WxNotificationCenter.js');
2 | const app = getApp();
3 |
4 | Page({
5 | data: {
6 | windowWidth: 0,
7 | windowHeight: 0,
8 | address: '地点',
9 | nation: '',
10 | province: '',
11 | city: '',
12 | think: '',
13 | options: {
14 | id: ''
15 | }
16 | },
17 |
18 | onLoad: function (options) {
19 | let that = this;
20 | that.setData({ options: options });
21 | if (that.data.options.id) {
22 | app.helper.waitUserSid(that.getApiData)
23 | }
24 |
25 | wx.getSystemInfo({
26 | success: function (res) {
27 | that.setData({
28 | windowWidth: res.windowWidth,
29 | windowHeight: res.windowHeight
30 | });
31 | }
32 | });
33 |
34 | // 注册通知
35 | WxNotificationCenter.addNotification("addressSelectedNotification", that.getAddress, that);
36 | WxNotificationCenter.addNotification("nationSelectedNotification", that.getNation, that);
37 | WxNotificationCenter.addNotification("provinceSelectedNotification", that.getProvince, that);
38 | WxNotificationCenter.addNotification("citySelectedNotification", that.getCity, that);
39 | },
40 |
41 | onShow: function () {
42 | // let that = this;
43 | },
44 |
45 | getApiData: function () {
46 | let that = this;
47 | // wx.showLoading({ title: '加载中...' });
48 | app.helper.getApi(app.config.api.think, that.data.options).then(function (res) {
49 | that.setData({ id: res.data.results[0].id, think: res.data.results[0].think, address: res.data.results[0].address, created: res.data.results[0].created_display });
50 | if (res.data.results[0].address === '') {
51 | that.setData({address: '地点'})
52 | }
53 | }).then(function () {
54 | wx.hideLoading()
55 | });
56 | },
57 |
58 | keywordTyping: function (e) {
59 | this.setData({
60 | think: e.detail.value
61 | });
62 | },
63 |
64 | getAddress: function (address) {
65 | this.setData({
66 | address: address
67 | });
68 | },
69 |
70 | getNation: function (nation) {
71 | this.setData({
72 | nation: nation
73 | });
74 | },
75 |
76 | getProvince: function (province) {
77 | this.setData({
78 | province: province
79 | });
80 | },
81 |
82 | getCity: function (city) {
83 | this.setData({
84 | city: city
85 | });
86 | },
87 |
88 | thinkDone: function () {
89 | let that = this;
90 |
91 | if (that.data.think !== '') {
92 | if (that.data.address === '地点') {
93 | that.setData({address: ''})
94 | }
95 |
96 | if (that.data.options.id) {
97 | app.helper.putApi(app.config.api.think, that.data, that.data.options.id + '/').then(function (res) {
98 | let pages = getCurrentPages();
99 | let backPage = pages[pages.length - 3];
100 | let results = [];
101 | for (let item of backPage.data.apiData.results) {
102 | if (item['id'] === parseInt(that.data.options.id)) {
103 | item['think'] = that.data.think;
104 | item['nation'] = that.data.nation;
105 | item['province'] = that.data.province;
106 | item['city'] = that.data.city;
107 | item['address'] = that.data.address;
108 | }
109 | results.push(item)
110 | }
111 | backPage.setData({ 'apiData.results': results })
112 | wx.navigateBack();
113 | });
114 | } else {
115 | app.helper.postApi(app.config.api.think, that.data).then(function (res) {
116 | let pages = getCurrentPages();
117 | let backPage = pages[pages.length - 2];
118 | app.helper.getApi(app.config.api.think).then(function (res) {
119 | backPage.setData({ apiData: res.data });
120 | });
121 | wx.navigateBack();
122 | });
123 | }
124 | } else {
125 | wx.showToast({title: '嘿,写想法!', icon: 'fail', duration: 1000})
126 | }
127 | },
128 |
129 | selectLocation: function () {
130 | wx.navigateTo({ url: './location/location' })
131 | }
132 | });
--------------------------------------------------------------------------------
/weixin/pages/edit/edit.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "写想法"
3 | }
4 |
--------------------------------------------------------------------------------
/weixin/pages/edit/edit.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{address}}
8 |
9 |
10 |
13 |
--------------------------------------------------------------------------------
/weixin/pages/edit/edit.wxss:
--------------------------------------------------------------------------------
1 | .section-edit{
2 | background-color: white;
3 | margin: 10px;
4 | padding: 10px 15px;
5 | border-radius:10rpx;
6 | }
7 |
8 | .location{
9 | height: 65px;
10 | background-color: white;
11 | margin: 0px 20rpx 0px 20rpx;
12 | padding-left: 30rpx;
13 | border-radius:10rpx;
14 | display: flex;
15 | align-items: center;
16 | }
17 |
18 | .location image {
19 | width: 40rpx;
20 | height: 40rpx;
21 | }
22 |
23 | .location text {
24 | margin-left: 20rpx;
25 | }
26 |
27 | .edit-footer {
28 | height: 60px;
29 | margin-top: 20px;
30 | padding-left: 40rpx;
31 | padding-right: 40rpx;
32 | background-color: white;
33 | display: flex;
34 | align-items: center;
35 | }
36 |
37 | .button-done {
38 | width: 100%;
39 | border-radius: 50rpx;
40 | /*background: linear-gradient(to right, red , blue);*/
41 | }
--------------------------------------------------------------------------------
/weixin/pages/edit/location/location.js:
--------------------------------------------------------------------------------
1 | var QQMapWX = require('../../../utils/qqmap-wx-jssdk.min.js');
2 | var WxNotificationCenter = require('../../../utils/WxNotificationCenter.js');
3 | var qqmapsdk;
4 |
5 | Page({
6 | onLoad: function (options) {
7 | let that = this;
8 | qqmapsdk = new QQMapWX({
9 | key: 'ZRSBZ-BKL3O-L66WI-SLPTW-NSX4Z-44FZE'
10 | });
11 | that.reloadCurrent();
12 | },
13 |
14 | keywordTyping: function (e) {
15 | var keyword = e.detail.value;
16 | // 向腾讯地图接口发送请求
17 | qqmapsdk.getSuggestion({
18 | keyword: keyword,
19 | region: that.data.city,
20 | success: function (res) {
21 | that.setData({
22 | result: res.data
23 | });
24 | },
25 | fail: function (res) {
26 | console.log(res);
27 | },
28 | complete: function (res) {
29 | console.log(res);
30 | }
31 | });
32 | },
33 |
34 | addressTapped: function (e) {
35 | let that = this;
36 | let title = e.currentTarget.dataset.title;
37 |
38 | WxNotificationCenter.postNotificationName("addressSelectedNotification", title);
39 | WxNotificationCenter.postNotificationName("nationSelectedNotification", that.data.nation);
40 | WxNotificationCenter.postNotificationName("provinceSelectedNotification", that.data.province);
41 | WxNotificationCenter.postNotificationName("citySelectedNotification", that.data.city);
42 | wx.navigateBack();
43 |
44 | },
45 |
46 | geoTapped: function () {
47 | let that = this;
48 | WxNotificationCenter.postNotificationName("addressSelectedNotification", that.data.city);
49 | WxNotificationCenter.postNotificationName("nationSelectedNotification", that.data.nation);
50 | WxNotificationCenter.postNotificationName("provinceSelectedNotification", that.data.province);
51 | WxNotificationCenter.postNotificationName("citySelectedNotification", that.data.city);
52 | wx.navigateBack();
53 |
54 | },
55 |
56 | reloadCurrent: function () {
57 | let that = this;
58 | // that.setData({
59 | // address: '正在定位中...',
60 | // });
61 | // 调用接口
62 | qqmapsdk.reverseGeocoder({
63 | poi_options: 'policy=2',
64 | get_poi: 1,
65 | success: function (res) {
66 | that.setData({
67 | address: res.result.formatted_addresses.recommend,
68 | rough: res.result.formatted_addresses.rough,
69 | result: res.result.pois,
70 | nation: res.result.address_component.nation,
71 | province: res.result.address_component.province,
72 | city: res.result.address_component.city
73 | });
74 | },
75 | fail: function (res) {
76 | // console.log(res);
77 | },
78 | complete: function (res) {
79 | // console.log(res);
80 | }
81 | });
82 | }
83 | });
--------------------------------------------------------------------------------
/weixin/pages/edit/location/location.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "选择地点"
3 | }
--------------------------------------------------------------------------------
/weixin/pages/edit/location/location.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{city}}
7 |
8 |
9 |
10 |
11 |
12 | {{address}}
13 | {{rough}}
14 |
15 |
16 | {{item.title}}
17 | {{item.address}}
18 |
19 |
20 |
--------------------------------------------------------------------------------
/weixin/pages/edit/location/location.wxss:
--------------------------------------------------------------------------------
1 | .page {
2 | background-color: white;
3 | }
4 |
5 | /*搜索框*/
6 | .searcher {
7 | /* background: #009cf9; */
8 | padding: 10px;
9 | border-bottom: 1px solid #eee;
10 | }
11 |
12 | /* .searcher input {
13 | padding: 6px 8px;
14 | background: white;
15 | font-size: 14px;
16 | color: #ccc;
17 | border-radius: 5px;
18 | text-align: center;
19 | } */
20 |
21 | .placeholder-class {
22 | color: #ccc;
23 | font-size: 14px;
24 | /* padding: 10px; */
25 | /* text-align: center; */
26 | }
27 |
28 | /*标题头*/
29 | /* .header {
30 | background: #eee;
31 | font-size: 14px;
32 | padding: 10px;
33 | line-height: 24px;
34 | color: #444;
35 | } */
36 |
37 | /*当前定位*/
38 | .current {
39 | /* color: #1a80d2; */
40 | padding: 20px 20px 20px 10px;
41 | display: flex;
42 | justify-content: space-between;
43 | align-items: center;
44 | border-bottom: 1px solid #eee;
45 | }
46 |
47 | .current text {
48 | font-size: 14px;
49 | width: 100%;
50 | }
51 |
52 | .current image {
53 | width: 20px;
54 | height: 20px;
55 | }
56 |
57 | .current image:after {
58 | content: '重新定位';
59 | }
60 |
61 | /*结果行*/
62 | .item {
63 | color: #ccc;
64 | padding: 10px;
65 | display: flex;
66 | flex-direction: column;
67 | border-bottom: 1px solid #eee;
68 | }
69 |
70 | .item .title {
71 | width: 100%;
72 | font-size: 14px;
73 | line-height: 30px;
74 | color: #333;
75 | }
76 |
77 | .item .address {
78 | width: 100%;
79 | font-size: 12px;
80 | line-height: 24px;
81 | color: #666;
82 | }
--------------------------------------------------------------------------------
/weixin/pages/index/earth/earth.js:
--------------------------------------------------------------------------------
1 | import util from '../../../utils/util'
2 |
3 | const app = getApp();
4 |
5 | Page({
6 | data: {
7 | windowWidth: 0,
8 | windowHeight: 0,
9 | contentHeight: 0,
10 | thinkList: [],
11 | footer: '',
12 | offset: 0,
13 | lineHeight: 30
14 | },
15 |
16 | onLoad: function (options) {
17 | let that = this;
18 | wx.getSystemInfo({
19 | success: function (res) {
20 | that.setData({
21 | windowWidth: res.windowWidth,
22 | windowHeight: res.windowHeight,
23 | offset: (res.windowWidth - 300) / 2
24 | });
25 | }
26 | });
27 | },
28 |
29 | onShow: function () {
30 | app.helper.waitUserSid(this.getApiData)
31 | },
32 |
33 | getApiData: function () {
34 | let that = this;
35 |
36 | wx.showLoading({ title: '加载中...' });
37 | app.helper.getApi(app.config.api.earth).then(function (res) {
38 | that.setData({ footer: res.data.now});
39 |
40 | let lineNum = 3;
41 | let thinkList = [];
42 | thinkList.push(res.data.year + ' 年,我,');
43 | thinkList.push('记录了 ' + res.data.think_count + ' 条想法,');
44 | thinkList.push('去过 ' + res.data.nation_count + ' 个国家,走过 ' + res.data.city_count + ' 个城市。');
45 | that.setData({ thinkList: thinkList });
46 | that.createNewImg(lineNum);
47 | }).then(function () {
48 | wx.hideLoading()
49 | });
50 | },
51 |
52 | drawSquare: function (ctx, height) {
53 | ctx.setFontSize(24);
54 | ctx.rect(0, 50, this.data.windowWidth, height);
55 | ctx.setFillStyle("#f5f6fd");
56 | ctx.fill()
57 | },
58 |
59 | drawFont: function (ctx, content, height) {
60 | ctx.setFontSize(16);
61 | ctx.setFillStyle("#484a3d");
62 | ctx.fillText(content, this.data.offset, height);
63 | },
64 |
65 | drawLine: function (ctx, height) {
66 | ctx.beginPath();
67 | ctx.moveTo(this.data.offset, height);
68 | ctx.lineTo(this.data.windowWidth - this.data.offset, height);
69 | ctx.stroke('#eee');
70 | ctx.closePath();
71 | },
72 |
73 | createNewImg: function (lineNum) {
74 | var that = this;
75 | var ctx = wx.createCanvasContext('myCanvas');
76 | let contentHeight = lineNum * that.data.lineHeight + 180;
77 | that.drawSquare(ctx, contentHeight);
78 | that.setData({contentHeight: contentHeight});
79 | let height = 100;
80 | for (let item of that.data.thinkList) {
81 | if (item !== 'a') {
82 | that.drawFont(ctx, item, height);
83 | height += that.data.lineHeight;
84 | }
85 | }
86 | that.drawLine(ctx, lineNum * that.data.lineHeight + 120);
87 | that.drawFont(ctx, that.data.footer, lineNum * that.data.lineHeight + 156);
88 | ctx.drawImage('../../../static/image/think.png', that.data.windowWidth - that.data.offset - 50, lineNum * that.data.lineHeight + 125, 50, 50);
89 | ctx.draw();
90 | },
91 |
92 | savePic: function () {
93 | let that = this;
94 | wx.canvasToTempFilePath({
95 | x: 0,
96 | y: 50,
97 | width: that.data.windowWidth,
98 | height: that.data.contentHeight,
99 | canvasId: 'myCanvas',
100 | success: function (res) {
101 | util.savePicToAlbum(res.tempFilePath)
102 | }
103 | })
104 | }
105 | });
--------------------------------------------------------------------------------
/weixin/pages/index/earth/earth.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "足迹"
3 | }
--------------------------------------------------------------------------------
/weixin/pages/index/earth/earth.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/weixin/pages/index/earth/earth.wxss:
--------------------------------------------------------------------------------
1 | .edit-footer {
2 | height: 60px;
3 | margin-top: 20px;
4 | padding-left: 40rpx;
5 | padding-right: 40rpx;
6 | background-color: back;
7 | display: flex;
8 | align-items: center;
9 | }
10 |
11 | .button-done {
12 | width: 100%;
13 | border-radius: 50rpx!important;
14 | /*background: linear-gradient(to right, red , blue);*/
15 | }
--------------------------------------------------------------------------------
/weixin/pages/index/index.js:
--------------------------------------------------------------------------------
1 | const app = getApp();
2 |
3 | Page({
4 | data: {
5 | options: {
6 | page: 1
7 | }
8 | },
9 |
10 | onLoad: function (options) {
11 | // app.helper.waitUserSid(this.getApiData)
12 | },
13 |
14 | onShow: function () {
15 | app.helper.waitUserSid(this.getApiData)
16 | },
17 |
18 | getApiData: function () {
19 | let that = this;
20 | that.setData({
21 | 'options.page': 1
22 | });
23 |
24 | wx.showLoading({ title: '加载中...' });
25 | app.helper.getApi(app.config.api.think, that.data.options).then(function (res) {
26 | that.setData({ apiData: res.data });
27 | }).then(function () {
28 | wx.hideLoading()
29 | });
30 | },
31 |
32 | onReachBottom: function () {
33 | let that = this;
34 | if (that.data.apiData.next !== null) {
35 | let next_page = that.data.options.page + 1;
36 | that.setData({
37 | 'options.page': next_page
38 | });
39 |
40 | wx.showLoading({title: '加载中...'});
41 | app.helper.getApi(app.config.api.think, that.data.options).then(function (res) {
42 | for (let i = 0; i < res.data.results.length; i++) {
43 | that.data.apiData.results.push(res.data.results[i])
44 | }
45 | that.setData({apiData: that.data.apiData, 'apiData.next': res.data.next});
46 | }).then(function () {
47 | wx.hideLoading()
48 | });
49 | }
50 | },
51 |
52 | thinkAdd: function () {
53 | wx.navigateTo({url: '../edit/edit'})
54 | },
55 |
56 | thinkDetail: function (event) {
57 | let ds = event.currentTarget.dataset;
58 | wx.navigateTo({ url: '../detail/detail?id=' + ds.id })
59 | },
60 |
61 | earthSave: function () {
62 | wx.navigateTo({ url: './earth/earth' })
63 | },
64 |
65 | onShareAppMessage: function () {
66 | return {
67 | title: '记录位置,记录想法,记录生活。',
68 | path: '/pages/index/index'
69 | }
70 | }
71 | });
72 |
--------------------------------------------------------------------------------
/weixin/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 | 今天
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{ item.day }}{{ item.month }}月
15 |
16 | {{ item.city }}
17 |
18 | {{item.think}}
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/weixin/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | .section-index {
2 | background-color: white;
3 | margin: 20rpx;
4 | display: flex;
5 | border-radius:5px;
6 |
7 | -webkit-box-shadow:2px 2px 5px #BFBFBF;
8 | box-shadow:2px 2px 5px #BFBFBF;
9 | }
10 |
11 | .weui-flex{
12 | -webkit-box-align:center;
13 | -webkit-align-items:center;
14 | align-items:center
15 | }
16 |
17 | .weui-cells{
18 | margin-top:0;
19 | opacity:0;
20 | -webkit-transform:translateY(-50%);
21 | transform:translateY(-50%);
22 | -webkit-transition:.3s;
23 | transition:.3s
24 | }
25 |
26 | .weui-cells:after,.weui-cells:before{
27 | display:none
28 | }
29 |
30 | .weui-cells_show{
31 | opacity:1;
32 | -webkit-transform:translateY(0);
33 | transform:translateY(0)
34 | }
35 |
36 | .weui-cell:before{
37 | right:15px
38 | }
39 |
40 | .kind-list__item{
41 | margin:10px 0;
42 | background-color:#fff;
43 | border-radius:2px;
44 | overflow:hidden
45 | }
46 |
47 | .kind-list__item:first-child{
48 | margin-top:0
49 | }
50 |
51 | .kind-list__img{
52 | width:30px;
53 | height:30px
54 | }
55 |
56 | .kind-list__item-hd{
57 | padding:20px;
58 | -webkit-transition:opacity .3s;
59 | transition:opacity .3s
60 | }
61 |
62 | .kind-list__item-hd_show{
63 | opacity:.4
64 | }
65 |
66 | .kind-list__item-bd{
67 | height:0;
68 | overflow:hidden
69 | }
70 |
71 | .kind-list__item-bd_show{
72 | height:auto
73 | }
74 |
75 | /* .section-left {
76 | width: 25%;
77 | margin: 30rpx 15rpx 30rpx 10rpx;
78 | display: flex;
79 | flex-direction: column;
80 | }
81 |
82 | .section-right {
83 | width: 75%;
84 | display: flex;
85 | margin-right: 10rpx;
86 | flex-direction: column;
87 | justify-content:center;
88 | } */
89 |
90 | .day {
91 | font-size: 40rpx;
92 | }
93 |
94 | .month {
95 | font-size: 25rpx;
96 | }
97 |
98 | .location {
99 | font-size: 25rpx;
100 | color: #9e9e9e;
101 | margin-right: 5rpx;
102 | text-overflow: -o-ellipsis-lastline;
103 | overflow: hidden;
104 | text-overflow: ellipsis;
105 | display: -webkit-box;
106 | -webkit-line-clamp: 1;
107 | -webkit-box-orient: vertical;
108 | }
109 |
110 | .content{
111 | text-overflow: -o-ellipsis-lastline;
112 | overflow: hidden;
113 | text-overflow: ellipsis;
114 | display: -webkit-box;
115 | -webkit-line-clamp: 2;
116 | -webkit-box-orient: vertical;
117 | }
118 |
119 | .top-left {
120 | width: 25%;
121 | height: 120rpx;
122 | margin: 10rpx 15rpx 10rpx 10rpx;
123 | display: flex;
124 | }
125 |
126 | .today {
127 | font-size: 60rpx;
128 | margin-left: 25rpx;
129 | display: flex;
130 | align-items: center;
131 | }
132 |
133 | .image-index {
134 | width: 40px;
135 | height: 40px;
136 | }
137 |
138 | .top-index {
139 | padding: 50rpx;
140 | }
141 |
--------------------------------------------------------------------------------
/weixin/pages/logs/logs.js:
--------------------------------------------------------------------------------
1 | //logs.js
2 | const util = require('../../utils/util.js')
3 |
4 | Page({
5 | data: {
6 | logs: []
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 | })
16 |
--------------------------------------------------------------------------------
/weixin/pages/logs/logs.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "查看启动日志"
3 | }
--------------------------------------------------------------------------------
/weixin/pages/logs/logs.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{index + 1}}. {{log}}
5 |
6 |
7 |
--------------------------------------------------------------------------------
/weixin/pages/logs/logs.wxss:
--------------------------------------------------------------------------------
1 | .log-list {
2 | display: flex;
3 | flex-direction: column;
4 | padding: 40rpx;
5 | }
6 | .log-item {
7 | margin: 10rpx;
8 | }
9 |
--------------------------------------------------------------------------------
/weixin/static/image/add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/weixin/static/image/add.png
--------------------------------------------------------------------------------
/weixin/static/image/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/weixin/static/image/delete.png
--------------------------------------------------------------------------------
/weixin/static/image/earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/weixin/static/image/earth.png
--------------------------------------------------------------------------------
/weixin/static/image/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/weixin/static/image/edit.png
--------------------------------------------------------------------------------
/weixin/static/image/home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/weixin/static/image/home.png
--------------------------------------------------------------------------------
/weixin/static/image/home_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/weixin/static/image/home_selected.png
--------------------------------------------------------------------------------
/weixin/static/image/index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/weixin/static/image/index.png
--------------------------------------------------------------------------------
/weixin/static/image/index_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/weixin/static/image/index_selected.png
--------------------------------------------------------------------------------
/weixin/static/image/location.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/weixin/static/image/location.png
--------------------------------------------------------------------------------
/weixin/static/image/location_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/weixin/static/image/location_selected.png
--------------------------------------------------------------------------------
/weixin/static/image/save_pic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/weixin/static/image/save_pic.png
--------------------------------------------------------------------------------
/weixin/static/image/think.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yongxinz/think/59681c91afd808b1d6f9b85b3da2af95a9b41418/weixin/static/image/think.png
--------------------------------------------------------------------------------
/weixin/static/style/weui.wxss:
--------------------------------------------------------------------------------
1 | /*!
2 | * WeUI v1.1.1 (https://github.com/weui/weui-wxss)
3 | * Copyright 2017 Tencent, Inc.
4 | * Licensed under the MIT license
5 | */
6 | page{line-height:1.6;font-family:-apple-system-font,Helvetica Neue,sans-serif}icon{vertical-align:middle}.weui-cells{position:relative;margin-top:1.17647059em;background-color:#fff;line-height:1.41176471;font-size:17px}.weui-cells:before{top:0;border-top:1rpx solid #d9d9d9}.weui-cells:after,.weui-cells:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#d9d9d9}.weui-cells:after{bottom:0;border-bottom:1rpx solid #d9d9d9}.weui-cells__title{margin-top:.77em;margin-bottom:.3em;padding-left:15px;padding-right:15px;color:#999;font-size:14px}.weui-cells_after-title{margin-top:0}.weui-cells__tips{margin-top:.3em;color:#999;padding-left:15px;padding-right:15px;font-size:14px}.weui-cell{padding:10px 15px;position:relative;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-cell:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1rpx solid #d9d9d9;color:#d9d9d9;left:15px}.weui-cell:first-child:before{display:none}.weui-cell_active{background-color:#ececec}.weui-cell_primary{-webkit-box-align:start;-webkit-align-items:flex-start;align-items:flex-start}.weui-cell__bd{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-cell__ft{text-align:right;color:#999}.weui-cell_access{color:inherit}.weui-cell__ft_in-access{padding-right:13px;position:relative}.weui-cell__ft_in-access:after{content:" ";display:inline-block;height:6px;width:6px;border-width:2px 2px 0 0;border-color:#c8c8cd;border-style:solid;-webkit-transform:matrix(.71,.71,-.71,.71,0,0);transform:matrix(.71,.71,-.71,.71,0,0);position:relative;top:-2px;position:absolute;top:50%;margin-top:-4px;right:2px}.weui-cell_link{color:#586c94;font-size:14px}.weui-cell_link:active{background-color:#ececec}.weui-cell_link:first-child:before{display:block}.weui-icon-radio{margin-left:3.2px;margin-right:3.2px}.weui-icon-checkbox_circle,.weui-icon-checkbox_success{margin-left:4.6px;margin-right:4.6px}.weui-check__label:active{background-color:#ececec}.weui-check{position:absolute;left:-9999px}.weui-check__hd_in-checkbox{padding-right:.35em}.weui-cell__ft_in-radio{padding-left:.35em}.weui-cell_input{padding-top:0;padding-bottom:0}.weui-label{width:105px;word-wrap:break-word;word-break:break-all}.weui-input{height:2.58823529em;min-height:2.58823529em;line-height:2.58823529em}.weui-toptips{position:fixed;-webkit-transform:translateZ(0);transform:translateZ(0);top:0;left:0;right:0;padding:5px;font-size:14px;text-align:center;color:#fff;z-index:5000;word-wrap:break-word;word-break:break-all}.weui-toptips_warn{background-color:#e64340}.weui-textarea{display:block;width:100%}.weui-textarea-counter{color:#b2b2b2;text-align:right}.weui-cell_warn,.weui-textarea-counter_warn{color:#e64340}.weui-form-preview{position:relative;background-color:#fff}.weui-form-preview:before{top:0;border-top:1rpx solid #d9d9d9}.weui-form-preview:after,.weui-form-preview:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#d9d9d9}.weui-form-preview:after{bottom:0;border-bottom:1rpx solid #d9d9d9}.weui-form-preview__value{font-size:14px}.weui-form-preview__value_in-hd{font-size:26px}.weui-form-preview__hd{position:relative;padding:10px 15px;text-align:right;line-height:2.5em}.weui-form-preview__hd:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1rpx solid #d9d9d9;color:#d9d9d9;left:15px}.weui-form-preview__bd{padding:10px 15px;font-size:.9em;text-align:right;color:#999;line-height:2}.weui-form-preview__ft{position:relative;line-height:50px;display:-webkit-box;display:-webkit-flex;display:flex}.weui-form-preview__ft:after{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1rpx solid #d5d5d6;color:#d5d5d6}.weui-form-preview__item{overflow:hidden}.weui-form-preview__label{float:left;margin-right:1em;min-width:4em;color:#999;text-align:justify;text-align-last:justify}.weui-form-preview__value{display:block;overflow:hidden;word-break:normal;word-wrap:break-word}.weui-form-preview__btn{position:relative;display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;color:#3cc51f;text-align:center}.weui-form-preview__btn:after{content:" ";position:absolute;left:0;top:0;width:1px;bottom:0;border-left:1rpx solid #d5d5d6;color:#d5d5d6}.weui-form-preview__btn:first-child:after{display:none}.weui-form-preview__btn_active{background-color:#eee}.weui-form-preview__btn_default{color:#999}.weui-form-preview__btn_primary{color:#0bb20c}.weui-cell_select{padding:0}.weui-select{position:relative;padding-left:15px;padding-right:30px;height:2.58823529em;min-height:2.58823529em;line-height:2.58823529em;border-right:1rpx solid #d9d9d9}.weui-select:before{content:" ";display:inline-block;height:6px;width:6px;border-width:2px 2px 0 0;border-color:#c8c8cd;border-style:solid;-webkit-transform:matrix(.71,.71,-.71,.71,0,0);transform:matrix(.71,.71,-.71,.71,0,0);position:relative;top:-2px;position:absolute;top:50%;right:15px;margin-top:-4px}.weui-select_in-select-after{padding-left:0}.weui-cell__bd_in-select-before,.weui-cell__hd_in-select-after{padding-left:15px}.weui-cell_vcode{padding-right:0}.weui-vcode-btn,.weui-vcode-img{margin-left:5px;height:2.58823529em;vertical-align:middle}.weui-vcode-btn{display:inline-block;padding:0 .6em 0 .7em;border-left:1px solid #e5e5e5;line-height:2.58823529em;font-size:17px;color:#3cc51f;white-space:nowrap}.weui-vcode-btn:active{color:#52a341}.weui-cell_switch{padding-top:6px;padding-bottom:6px}.weui-uploader__hd{display:-webkit-box;display:-webkit-flex;display:flex;padding-bottom:10px;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-uploader__title{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-uploader__info{color:#b2b2b2}.weui-uploader__bd{margin-bottom:-4px;margin-right:-9px;overflow:hidden}.weui-uploader__file{float:left;margin-right:9px;margin-bottom:9px}.weui-uploader__img{display:block;width:79px;height:79px}.weui-uploader__file_status{position:relative}.weui-uploader__file_status:before{content:" ";position:absolute;top:0;right:0;bottom:0;left:0;background-color:rgba(0,0,0,.5)}.weui-uploader__file-content{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#fff}.weui-uploader__input-box{float:left;position:relative;margin-right:9px;margin-bottom:9px;width:77px;height:77px;border:1px solid #d9d9d9}.weui-uploader__input-box:after,.weui-uploader__input-box:before{content:" ";position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);background-color:#d9d9d9}.weui-uploader__input-box:before{width:2px;height:39.5px}.weui-uploader__input-box:after{width:39.5px;height:2px}.weui-uploader__input-box:active{border-color:#999}.weui-uploader__input-box:active:after,.weui-uploader__input-box:active:before{background-color:#999}.weui-uploader__input{position:absolute;z-index:1;top:0;left:0;width:100%;height:100%;opacity:0}.weui-article{padding:20px 15px;font-size:15px}.weui-article__section{margin-bottom:1.5em}.weui-article__h1{font-size:18px;font-weight:400;margin-bottom:.9em}.weui-article__h2{font-size:16px;font-weight:400;margin-bottom:.34em}.weui-article__h3{font-weight:400;font-size:15px;margin-bottom:.34em}.weui-article__p{margin:0 0 .8em}.weui-msg{padding-top:36px;text-align:center}.weui-msg__link{display:inline;color:#586c94}.weui-msg__icon-area{margin-bottom:30px}.weui-msg__text-area{margin-bottom:25px;padding:0 20px}.weui-msg__title{margin-bottom:5px;font-weight:400;font-size:20px}.weui-msg__desc{font-size:14px;color:#999}.weui-msg__opr-area{margin-bottom:25px}.weui-msg__extra-area{margin-bottom:15px;font-size:14px;color:#999}@media screen and (min-height:438px){.weui-msg__extra-area{position:fixed;left:0;bottom:0;width:100%;text-align:center}}.weui-flex{display:-webkit-box;display:-webkit-flex;display:flex}.weui-flex__item{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-btn{margin-top:15px}.weui-btn:first-child{margin-top:0}.weui-btn-area{margin:1.17647059em 15px .3em}.weui-agree{display:block;padding:.5em 15px;font-size:13px}.weui-agree__text{color:#999}.weui-agree__link{display:inline;color:#586c94}.weui-agree__checkbox{position:absolute;left:-9999px}.weui-agree__checkbox-icon{position:relative;top:2px;display:inline-block;border:1px solid #d1d1d1;background-color:#fff;border-radius:3px;width:11px;height:11px}.weui-agree__checkbox-icon-check{position:absolute;top:1px;left:1px}.weui-footer{color:#999;font-size:14px;text-align:center}.weui-footer_fixed-bottom{position:fixed;bottom:.52em;left:0;right:0}.weui-footer__links{font-size:0}.weui-footer__link{display:inline-block;vertical-align:top;margin:0 .62em;position:relative;font-size:14px;color:#586c94}.weui-footer__link:before{content:" ";position:absolute;left:0;top:0;width:1px;bottom:0;border-left:1rpx solid #c7c7c7;color:#c7c7c7;left:-.65em;top:.36em;bottom:.36em}.weui-footer__link:first-child:before{display:none}.weui-footer__text{padding:0 .34em;font-size:12px}.weui-grids{border-top:1rpx solid #d9d9d9;border-left:1rpx solid #d9d9d9;overflow:hidden}.weui-grid{position:relative;float:left;padding:20px 10px;width:33.33333333%;box-sizing:border-box;border-right:1rpx solid #d9d9d9;border-bottom:1rpx solid #d9d9d9}.weui-grid_active{background-color:#ececec}.weui-grid__icon{display:block;width:28px;height:28px;margin:0 auto}.weui-grid__label{margin-top:5px;display:block;text-align:center;color:#000;font-size:14px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.weui-loading{margin:0 5px;width:20px;height:20px;display:inline-block;vertical-align:middle;-webkit-animation:a 1s steps(12) infinite;animation:a 1s steps(12) infinite;background:transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat;background-size:100%}.weui-loading.weui-loading_transparent{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 100 100'%3E%3Cpath fill='none' d='M0 0h100v100H0z'/%3E%3Crect xmlns='http://www.w3.org/2000/svg' width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.56)' rx='5' ry='5' transform='translate(0 -30)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.5)' rx='5' ry='5' transform='rotate(30 105.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.43)' rx='5' ry='5' transform='rotate(60 75.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.38)' rx='5' ry='5' transform='rotate(90 65 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.32)' rx='5' ry='5' transform='rotate(120 58.66 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.28)' rx='5' ry='5' transform='rotate(150 54.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.25)' rx='5' ry='5' transform='rotate(180 50 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.2)' rx='5' ry='5' transform='rotate(-150 45.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.17)' rx='5' ry='5' transform='rotate(-120 41.34 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.14)' rx='5' ry='5' transform='rotate(-90 35 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.1)' rx='5' ry='5' transform='rotate(-60 24.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.03)' rx='5' ry='5' transform='rotate(-30 -5.98 65)'/%3E%3C/svg%3E")}@-webkit-keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.weui-badge{display:inline-block;padding:.15em .4em;min-width:8px;border-radius:18px;background-color:#e64340;color:#fff;line-height:1.2;text-align:center;font-size:12px;vertical-align:middle}.weui-badge_dot{padding:.4em;min-width:0}.weui-loadmore{width:65%;margin:1.5em auto;line-height:1.6em;font-size:14px;text-align:center}.weui-loadmore__tips{display:inline-block;vertical-align:middle}.weui-loadmore_line{border-top:1px solid #e5e5e5;margin-top:2.4em}.weui-loadmore__tips_in-line{position:relative;top:-.9em;padding:0 .55em;background-color:#fff;color:#999}.weui-loadmore__tips_in-dot{position:relative;padding:0 .16em;width:4px;height:1.6em}.weui-loadmore__tips_in-dot:before{content:" ";position:absolute;top:50%;left:50%;margin-top:-1px;margin-left:-2px;width:4px;height:4px;border-radius:50%;background-color:#e5e5e5}.weui-panel{background-color:#fff;margin-top:10px;position:relative;overflow:hidden}.weui-panel:first-child{margin-top:0}.weui-panel:before{top:0;border-top:1rpx solid #e5e5e5}.weui-panel:after,.weui-panel:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#e5e5e5}.weui-panel:after{bottom:0;border-bottom:1rpx solid #e5e5e5}.weui-panel__hd{padding:14px 15px 10px;color:#999;font-size:13px;position:relative}.weui-panel__hd:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1rpx solid #e5e5e5;color:#e5e5e5;left:15px}.weui-media-box{padding:15px;position:relative}.weui-media-box:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1rpx solid #e5e5e5;color:#e5e5e5;left:15px}.weui-media-box:first-child:before{display:none}.weui-media-box__title{font-weight:400;font-size:17px;width:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;word-wrap:break-word;word-break:break-all}.weui-media-box__desc{color:#999;font-size:13px;line-height:1.2;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.weui-media-box__info{margin-top:15px;padding-bottom:5px;font-size:13px;color:#cecece;line-height:1em;list-style:none;overflow:hidden}.weui-media-box__info__meta{float:left;padding-right:1em}.weui-media-box__info__meta_extra{padding-left:1em;border-left:1px solid #cecece}.weui-media-box__title_in-text{margin-bottom:8px}.weui-media-box_appmsg{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-media-box__thumb{width:100%;height:100%;vertical-align:top}.weui-media-box__hd_in-appmsg{margin-right:.8em;width:60px;height:60px;line-height:60px;text-align:center}.weui-media-box__bd_in-appmsg{-webkit-box-flex:1;-webkit-flex:1;flex:1;min-width:0}.weui-media-box_small-appmsg{padding:0}.weui-cells_in-small-appmsg{margin-top:0}.weui-cells_in-small-appmsg:before{display:none}.weui-progress{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-progress__bar{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-progress__opr{margin-left:15px;font-size:0}.weui-navbar{display:-webkit-box;display:-webkit-flex;display:flex;position:absolute;z-index:500;top:0;width:100%;border-bottom:1rpx solid #ccc}.weui-navbar__item{position:relative;display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;padding:13px 0;text-align:center;font-size:0}.weui-navbar__item.weui-bar__item_on{color:#1aad19}.weui-navbar__slider{position:absolute;content:" ";left:0;bottom:0;width:6em;height:3px;background-color:#1aad19;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.weui-navbar__title{display:inline-block;font-size:15px;max-width:8em;width:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal}.weui-tab{position:relative;height:100%}.weui-tab__panel{box-sizing:border-box;height:100%;padding-top:50px;overflow:auto;-webkit-overflow-scrolling:touch}.weui-search-bar{position:relative;padding:8px 10px;display:-webkit-box;display:-webkit-flex;display:flex;box-sizing:border-box;background-color:#efeff4;border-top:1rpx solid #d7d6dc;border-bottom:1rpx solid #d7d6dc}.weui-icon-search{margin-right:8px;font-size:inherit}.weui-icon-search_in-box{position:absolute;left:10px;top:7px}.weui-search-bar__text{display:inline-block;font-size:14px;vertical-align:middle}.weui-search-bar__form{position:relative;-webkit-box-flex:1;-webkit-flex:auto;flex:auto;border-radius:5px;background:#fff;border:1rpx solid #e6e6ea}.weui-search-bar__box{position:relative;padding-left:30px;padding-right:30px;width:100%;box-sizing:border-box;z-index:1}.weui-search-bar__input{height:28px;line-height:28px;font-size:14px}.weui-icon-clear{position:absolute;top:0;right:0;padding:7px 8px;font-size:0}.weui-search-bar__label{position:absolute;top:0;right:0;bottom:0;left:0;z-index:2;border-radius:3px;text-align:center;color:#9b9b9b;background:#fff;line-height:28px}.weui-search-bar__cancel-btn{margin-left:10px;line-height:28px;color:#09bb07;white-space:nowrap}
--------------------------------------------------------------------------------
/weixin/utils/WxNotificationCenter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * author: Di (微信小程序开发工程师)
3 | * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
4 | * 垂直微信小程序开发交流社区
5 | *
6 | * github地址: https://github.com/icindy/WxNotificationCenter
7 | *
8 | * for: 微信小程序通知广播模式类,降低小程序之间的耦合度
9 | * detail : http://weappdev.com/t/wxnotificationcenter/233
10 | */
11 | // 存放
12 | var __notices = [];
13 | var isDebug = true;
14 | /**
15 | * addNotification
16 | * 注册通知对象方法
17 | *
18 | * 参数:
19 | * name: 注册名,一般let在公共类中
20 | * selector: 对应的通知方法,接受到通知后进行的动作
21 | * observer: 注册对象,指Page对象
22 | */
23 | function addNotification(name, selector, observer) {
24 | if (name && selector) {
25 | if(!observer){
26 | console.log("addNotification Warning: no observer will can't remove notice");
27 | }
28 | console.log("addNotification:" + name);
29 | var newNotice = {
30 | name: name,
31 | selector: selector,
32 | observer: observer
33 | };
34 |
35 | addNotices(newNotice);
36 |
37 | } else {
38 | console.log("addNotification error: no selector or name");
39 | }
40 | }
41 |
42 | /**
43 | * 仅添加一次监听
44 | *
45 | * 参数:
46 | * name: 注册名,一般let在公共类中
47 | * selector: 对应的通知方法,接受到通知后进行的动作
48 | * observer: 注册对象,指Page对象
49 | */
50 | function addOnceNotification(name, selector, observer) {
51 | if (__notices.length > 0) {
52 | for (var i = 0; i < __notices.length; i++) {
53 | var notice = __notices[i];
54 | if (notice.name === name) {
55 | if (notice.observer === observer) {
56 | return;
57 | }
58 | }
59 | }
60 | }
61 | this.addNotification(name, selector, observer)
62 | }
63 |
64 | function addNotices(newNotice) {
65 | // if (__notices.length > 0) {
66 | // for (var i = 0; i < __notices.length; i++) {
67 | // var hisNotice = __notices[i];
68 | // //当名称一样时进行对比,如果不是同一个 则放入数组,否则跳出
69 | // if (newNotice.name === hisNotice.name) {
70 | // if (!cmp(hisNotice, newNotice)) {
71 | // __notices.push(newNotice);
72 | // }
73 | // return;
74 | // }else{
75 | // __notices.push(newNotice);
76 | // }
77 |
78 | // }
79 | // } else {
80 |
81 | // }
82 |
83 | __notices.push(newNotice);
84 | }
85 |
86 | /**
87 | * removeNotification
88 | * 移除通知方法
89 | *
90 | * 参数:
91 | * name: 已经注册了的通知
92 | * observer: 移除的通知所在的Page对象
93 | */
94 |
95 | function removeNotification(name,observer) {
96 | console.log("removeNotification:" + name);
97 | for (var i = 0; i < __notices.length; i++){
98 | var notice = __notices[i];
99 | if(notice.name === name){
100 | if(notice.observer === observer){
101 | __notices.splice(i,1);
102 | return;
103 | }
104 | }
105 | }
106 |
107 |
108 | }
109 |
110 | /**
111 | * postNotificationName
112 | * 发送通知方法
113 | *
114 | * 参数:
115 | * name: 已经注册了的通知
116 | * info: 携带的参数
117 | */
118 |
119 | function postNotificationName(name, info) {
120 | console.log("postNotificationName:" + name);
121 | if(__notices.length == 0){
122 | console.log("postNotificationName error: u hadn't add any notice.");
123 | return;
124 | }
125 |
126 | for (var i = 0; i < __notices.length; i++){
127 | var notice = __notices[i];
128 | if(notice.name === name){
129 | notice.selector(info);
130 | }
131 | }
132 |
133 | }
134 |
135 | // 用于对比两个对象是否相等
136 | function cmp(x, y) {
137 | // If both x and y are null or undefined and exactly the same
138 | if (x === y) {
139 | return true;
140 | }
141 |
142 | // If they are not strictly equal, they both need to be Objects
143 | if (! (x instanceof Object) || !(y instanceof Object)) {
144 | return false;
145 | }
146 |
147 | // They must have the exact same prototype chain, the closest we can do is
148 | // test the constructor.
149 | if (x.constructor !== y.constructor) {
150 | return false;
151 | }
152 |
153 | for (var p in x) {
154 | // Inherited properties were tested using x.constructor === y.constructor
155 | if (x.hasOwnProperty(p)) {
156 | // Allows comparing x[ p ] and y[ p ] when set to undefined
157 | if (!y.hasOwnProperty(p)) {
158 | return false;
159 | }
160 |
161 | // If they have the same strict value or identity then they are equal
162 | if (x[p] === y[p]) {
163 | continue;
164 | }
165 |
166 | // Numbers, Strings, Functions, Booleans must be strictly equal
167 | if (typeof(x[p]) !== "object") {
168 | return false;
169 | }
170 |
171 | // Objects and Arrays must be tested recursively
172 | if (!Object.equals(x[p], y[p])) {
173 | return false;
174 | }
175 | }
176 | }
177 |
178 | for (p in y) {
179 | // allows x[ p ] to be set to undefined
180 | if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) {
181 | return false;
182 | }
183 | }
184 | return true;
185 | };
186 |
187 | module.exports = {
188 | addNotification: addNotification,
189 | removeNotification: removeNotification,
190 | postNotificationName: postNotificationName,
191 | addOnceNotification: addOnceNotification
192 | }
193 |
--------------------------------------------------------------------------------
/weixin/utils/config.js:
--------------------------------------------------------------------------------
1 | import EventEmitter from "./event-emitter";
2 |
3 | let baseURL = 'https://think.naturez.cn/api';
4 |
5 | try {
6 | let res = wx.getSystemInfoSync();
7 | if (res.platform === 'devtools') {
8 | baseURL = 'http://127.0.0.1:8810/api';
9 | }
10 | } catch (e) {
11 | // Do something when catch error
12 | }
13 |
14 | module.exports.api = {
15 | passport: `${baseURL}/passport/wx/`,
16 | login: `${baseURL}/passport/wx/login/`,
17 | join: `${baseURL}/passport/wx/join/`,
18 | cancel: `${baseURL}/passport/wx/cancel/`,
19 | info: `${baseURL}/passport/wx/info/`,
20 | think: `${baseURL}/think/`,
21 | earth: `${baseURL}/think/earth/`
22 | };
23 |
24 | module.exports.emitter = new EventEmitter();
25 |
26 | module.exports.gData = {
27 | userSid: null,
28 | userInfo: null
29 | };
--------------------------------------------------------------------------------
/weixin/utils/event-emitter.js:
--------------------------------------------------------------------------------
1 | ;
2 | (function(exports) {
3 |
4 | function EventEmitter() {
5 | this.pool = {};
6 | }
7 |
8 | EventEmitter.prototype = {
9 | add: function(e, listener, bool) {
10 | listener.once = bool;
11 | this.pool[e] = this.pool[e] || [];
12 | this.pool[e].push(listener);
13 | },
14 | on: function(e, listener) {
15 | this.add(e, listener, false);
16 | },
17 | once: function(e, listener) {
18 | this.add(e, listener, true);
19 | },
20 | emit: function(e) {
21 | let _this = this;
22 | if (this.pool[e]) {
23 | this.pool[e].forEach(function(listener) {
24 | listener();
25 | if (listener.once) {
26 | _this.off(e, listener);
27 | }
28 | });
29 | }
30 | },
31 | off: function(e, listener) {
32 | let index = this.pool[e].indexOf(listener);
33 | if (index > -1) {
34 | this.pool[e].splice(index, 1);
35 | }
36 | },
37 | destory: function(e) {
38 | delete this.pool[e];
39 | }
40 | };
41 |
42 | /**
43 | * 模块导出:AMD、CommonJS、Global
44 | */
45 | if (typeof define === 'function' && define.amd) {
46 | define(function() {
47 | return EventEmitter;
48 | });
49 | } else if (typeof module === 'object' && module.exports) {
50 | module.exports = EventEmitter;
51 | } else {
52 | exports.EventEmitter = EventEmitter;
53 | }
54 | })(this || {});
--------------------------------------------------------------------------------
/weixin/utils/helper_business.js:
--------------------------------------------------------------------------------
1 | let config = require('./config');
2 |
3 | function wxPromisify(fn) {
4 | return function (obj = {}) {
5 | return new Promise((resolve, reject) => {
6 | obj.success = function (res) {
7 | resolve(res)
8 | };
9 |
10 | obj.fail = function (res) {
11 | reject(res)
12 | };
13 |
14 | fn(obj)
15 | })
16 | }
17 | }
18 |
19 | function waitSomething(fn, st) {
20 | if (config.gData[st] !== null) {
21 | fn();
22 | } else {
23 | config.emitter.on(st, fn);
24 | }
25 | }
26 |
27 |
28 | function requestApi(api_url, data, uri = '', method = 'GET') {
29 | return new Promise((resolve, reject) => {
30 | wx.request({
31 | url: api_url + uri,
32 | header: {'Authorization': config.gData.userSid},
33 | data: data,
34 | method: method,
35 | success: function (res) {
36 | // if (res.statusCode === 403 && uri !== '?is_login') {
37 | if (res.statusCode === 403) {
38 | wx.redirectTo({url: '/pages/login/index'})
39 | } else {
40 | resolve(res)
41 | }
42 | },
43 | fail: function (res) {
44 | reject(res)
45 | }
46 | })
47 | })
48 | }
49 |
50 |
51 | module.exports.waitUserSid = function (fn) {
52 | return waitSomething(fn, 'userSid')
53 | };
54 |
55 |
56 | module.exports.waitUserInfo = function (fn) {
57 | return waitSomething(fn, 'userInfo')
58 | };
59 |
60 |
61 | module.exports.getApi = function (api_name, data, uri = '') {
62 | return requestApi(api_name, data, uri, 'GET')
63 | };
64 |
65 |
66 | module.exports.postApi = function (api_name, data, uri = '') {
67 | return requestApi(api_name, data, uri, 'POST')
68 | };
69 |
70 | module.exports.putApi = function (api_name, data, uri = '') {
71 | return requestApi(api_name, data, uri, 'PUT')
72 | };
73 |
74 | module.exports.delApi = function (api_name, data, uri = '') {
75 | return requestApi(api_name, data, uri, 'DELETE')
76 | };
77 |
78 | module.exports.wxPromisify = wxPromisify;
--------------------------------------------------------------------------------
/weixin/utils/qqmap-wx-jssdk.min.js:
--------------------------------------------------------------------------------
1 | var _createClass=function(){function a(e,c){for(var b=0;b {
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 | function savePicToAlbum (tempFilePath) {
18 | wx.getSetting({
19 | success(res) {
20 | if (!res.authSetting['scope.writePhotosAlbum']) {
21 | wx.authorize({
22 | scope: 'scope.writePhotosAlbum',
23 | success(){
24 | wx.saveImageToPhotosAlbum({
25 | filePath: tempFilePath,
26 | success(res) {
27 | wx.showToast({
28 | title: '保存成功'
29 | });
30 | },
31 | fail(res) {
32 | console.log(res);
33 | }
34 | })
35 | },
36 | fail(){
37 | // 用户拒绝了授权
38 | console.log("2-授权《保存图片》权限失败");
39 | // 打开设置页面
40 | wx.openSetting({
41 | success: function (data) {
42 | console.log("openSetting: success");
43 | },
44 | fail: function (data) {
45 | console.log("openSetting: fail");
46 | }
47 | });
48 | }
49 | })
50 | } else {
51 | wx.saveImageToPhotosAlbum({
52 | filePath: tempFilePath,
53 | success(res) {
54 | wx.showToast({
55 | title: '保存成功'
56 | });
57 | },
58 | fail(res) {
59 | console.log(res);
60 | }
61 | })
62 | }
63 | },
64 | fail(res) {
65 | console.log(res);
66 | }
67 | })
68 | }
69 |
70 | module.exports = {
71 | formatTime: formatTime,
72 | savePicToAlbum: savePicToAlbum
73 | };
74 |
--------------------------------------------------------------------------------