├── miniprogram
├── pages
│ ├── doctor
│ │ ├── doctor.json
│ │ ├── consulting
│ │ │ ├── consulting.json
│ │ │ ├── consulting.wxss
│ │ │ ├── consulting.wxml
│ │ │ └── consulting.js
│ │ ├── doctor.js
│ │ ├── doctor.wxml
│ │ └── doctor.wxss
│ ├── index
│ │ ├── index.json
│ │ ├── index.wxss
│ │ ├── index.js
│ │ └── index.wxml
│ ├── search
│ │ ├── search.json
│ │ ├── search.wxml
│ │ ├── search.wxss
│ │ └── search.js
│ ├── account
│ │ ├── account.json
│ │ ├── family
│ │ │ ├── family.json
│ │ │ ├── family.wxml
│ │ │ ├── family.js
│ │ │ └── family.wxss
│ │ ├── login
│ │ │ ├── login.json
│ │ │ ├── login.wxml
│ │ │ ├── login.js
│ │ │ └── login.wxss
│ │ ├── register
│ │ │ ├── register.json
│ │ │ ├── register.wxss
│ │ │ ├── register.js
│ │ │ └── register.wxml
│ │ ├── answer
│ │ │ ├── answer.json
│ │ │ ├── answer.wxml
│ │ │ ├── answer.wxss
│ │ │ └── answer.js
│ │ ├── askList
│ │ │ ├── askList.json
│ │ │ ├── askList.wxml
│ │ │ ├── askList.js
│ │ │ └── askList.wxss
│ │ ├── account.wxss
│ │ ├── account.wxml
│ │ └── account.js
│ └── upload
│ │ ├── page
│ │ ├── page.json
│ │ ├── page.wxml
│ │ ├── page.wxss
│ │ └── page.js
│ │ └── idCard
│ │ ├── idcard.json
│ │ ├── idcard.wxss
│ │ ├── idcard.wxml
│ │ └── idcard.js
├── component
│ └── Toast
│ │ ├── Toast.json
│ │ ├── Toast.wxml
│ │ ├── Toast.wxss
│ │ └── Toast.js
├── images
│ ├── yn.jpg
│ ├── beta.jpg
│ ├── logo.png
│ ├── logo2.jpg
│ ├── avatar_0.jpg
│ ├── avatar_1.jpg
│ ├── account_bg.png
│ ├── home_home.png
│ ├── tagbar
│ │ ├── me.png
│ │ ├── me_on.png
│ │ ├── consulting.png
│ │ └── consulting_on.png
│ └── avatar_user_0.png
├── app.json
├── app.wxss
└── app.js
├── text.txt
├── cloud
└── getOpenId
│ ├── index.js
│ └── package.json
├── png
├── dc.jpg
├── msg.jpg
├── card.jpg
├── home.jpg
├── msg2.jpg
├── msg3.jpg
├── user.jpg
└── register.jpg
├── project.config.json
└── README.md
/miniprogram/pages/doctor/doctor.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/miniprogram/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/miniprogram/pages/search/search.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/miniprogram/pages/account/account.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/miniprogram/pages/upload/page/page.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/miniprogram/pages/account/family/family.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/miniprogram/pages/account/login/login.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/miniprogram/pages/upload/idCard/idcard.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/miniprogram/pages/account/register/register.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/miniprogram/pages/doctor/consulting/consulting.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/miniprogram/pages/upload/page/page.wxml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/text.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/text.txt
--------------------------------------------------------------------------------
/cloud/getOpenId/index.js:
--------------------------------------------------------------------------------
1 | exports.main = async (event, context) => event.userInfo;
--------------------------------------------------------------------------------
/miniprogram/pages/account/answer/answer.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/account/askList/askList.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/png/dc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/png/dc.jpg
--------------------------------------------------------------------------------
/png/msg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/png/msg.jpg
--------------------------------------------------------------------------------
/miniprogram/pages/upload/page/page.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/upload/page/page.wxss */
--------------------------------------------------------------------------------
/png/card.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/png/card.jpg
--------------------------------------------------------------------------------
/png/home.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/png/home.jpg
--------------------------------------------------------------------------------
/png/msg2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/png/msg2.jpg
--------------------------------------------------------------------------------
/png/msg3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/png/msg3.jpg
--------------------------------------------------------------------------------
/png/user.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/png/user.jpg
--------------------------------------------------------------------------------
/png/register.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/png/register.jpg
--------------------------------------------------------------------------------
/miniprogram/component/Toast/Toast.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/miniprogram/pages/doctor/consulting/consulting.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/doctor/consulting/consulting.wxss */
--------------------------------------------------------------------------------
/miniprogram/images/yn.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/yn.jpg
--------------------------------------------------------------------------------
/miniprogram/images/beta.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/beta.jpg
--------------------------------------------------------------------------------
/miniprogram/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/logo.png
--------------------------------------------------------------------------------
/miniprogram/images/logo2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/logo2.jpg
--------------------------------------------------------------------------------
/miniprogram/images/avatar_0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/avatar_0.jpg
--------------------------------------------------------------------------------
/miniprogram/images/avatar_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/avatar_1.jpg
--------------------------------------------------------------------------------
/miniprogram/images/account_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/account_bg.png
--------------------------------------------------------------------------------
/miniprogram/images/home_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/home_home.png
--------------------------------------------------------------------------------
/miniprogram/images/tagbar/me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/tagbar/me.png
--------------------------------------------------------------------------------
/miniprogram/images/avatar_user_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/avatar_user_0.png
--------------------------------------------------------------------------------
/miniprogram/images/tagbar/me_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/tagbar/me_on.png
--------------------------------------------------------------------------------
/miniprogram/images/tagbar/consulting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/tagbar/consulting.png
--------------------------------------------------------------------------------
/miniprogram/images/tagbar/consulting_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shi-lai-mu/hospital-wxapp/HEAD/miniprogram/images/tagbar/consulting_on.png
--------------------------------------------------------------------------------
/miniprogram/pages/doctor/consulting/consulting.wxml:
--------------------------------------------------------------------------------
1 |
2 | miniprogram/pages/doctor/consulting/consulting.wxml
3 |
--------------------------------------------------------------------------------
/miniprogram/pages/upload/page/page.js:
--------------------------------------------------------------------------------
1 | const app = getApp();
2 |
3 | Page({
4 |
5 | data: {
6 |
7 | },
8 |
9 | onLoad: function (options) {
10 |
11 | app.bar({
12 | title: "空页面",
13 | bgColor: "#b5cfff"
14 | });
15 |
16 | },
17 |
18 | })
--------------------------------------------------------------------------------
/cloud/getOpenId/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "getOpenId",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
--------------------------------------------------------------------------------
/miniprogram/component/Toast/Toast.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{msg._text}}{{msg.icon?'iconfont icon-'+msg.icon:''}}
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/miniprogram/pages/account/askList/askList.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ doctor ? item.patient_name : item.doctor_name }}
6 | {{ item.status == 1 ? '会话已结束' : item.status == -1 ? '待医生回复' : '医生已回复' }}
7 | {{ item.content }}
8 | {{ item.create_day }}
9 |
10 |
11 |
12 | 暂无任何咨询消息!
13 |
--------------------------------------------------------------------------------
/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件",
3 | "miniprogramRoot": "miniprogram/",
4 | "cloudfunctionRoot": "cloud/",
5 | "packOptions": {
6 | "ignore": []
7 | },
8 | "setting": {
9 | "urlCheck": false,
10 | "es6": true,
11 | "postcss": true,
12 | "minified": true,
13 | "newFeature": true,
14 | "uglifyFileName": false
15 | },
16 | "compileType": "miniprogram",
17 | "libVersion": "2.4.2",
18 | "appid": "wx5db8bb3e34cd9234",
19 | "projectname": "%E7%94%A8%E8%83%BD%E5%85%AC%E5%8F%B8",
20 | "debugOptions": {
21 | "hidedInDevtools": []
22 | },
23 | "isGameTourist": false,
24 | "condition": {
25 | "search": {
26 | "current": -1,
27 | "list": []
28 | },
29 | "conversation": {
30 | "current": -1,
31 | "list": []
32 | },
33 | "game": {
34 | "currentL": -1,
35 | "list": []
36 | },
37 | "miniprogram": {
38 | "current": -1,
39 | "list": []
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/miniprogram/pages/doctor/consulting/consulting.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/doctor/consulting/consulting.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 |
9 | },
10 |
11 | /**
12 | * 生命周期函数--监听页面加载
13 | */
14 | onLoad: function (options) {
15 |
16 | },
17 |
18 | /**
19 | * 生命周期函数--监听页面初次渲染完成
20 | */
21 | onReady: function () {
22 |
23 | },
24 |
25 | /**
26 | * 生命周期函数--监听页面显示
27 | */
28 | onShow: function () {
29 |
30 | },
31 |
32 | /**
33 | * 生命周期函数--监听页面隐藏
34 | */
35 | onHide: function () {
36 |
37 | },
38 |
39 | /**
40 | * 生命周期函数--监听页面卸载
41 | */
42 | onUnload: function () {
43 |
44 | },
45 |
46 | /**
47 | * 页面相关事件处理函数--监听用户下拉动作
48 | */
49 | onPullDownRefresh: function () {
50 |
51 | },
52 |
53 | /**
54 | * 页面上拉触底事件的处理函数
55 | */
56 | onReachBottom: function () {
57 |
58 | },
59 |
60 | /**
61 | * 用户点击右上角分享
62 | */
63 | onShareAppMessage: function () {
64 |
65 | }
66 | })
--------------------------------------------------------------------------------
/miniprogram/pages/account/family/family.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 家庭成员 ( 5 / {{familyList.length}} )
6 |
7 |
8 |
9 | 获取中...
10 |
11 |
12 |
13 |
14 | 姓名:
15 | {{item.patientname}}
16 |
17 |
18 | 出生:
19 | {{item.csrq}}
20 |
21 |
22 | 手机号:
23 | {{item.phone}}
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/miniprogram/pages/account/family/family.js:
--------------------------------------------------------------------------------
1 | const app = getApp();
2 | Page({
3 |
4 | data: {
5 | familyList: []
6 | },
7 |
8 | onShow: function() {
9 | app.bar("title", "家庭成员");
10 | // 读取家庭成员列表
11 | app.request(`token=${app.globalData.userInfo.token}`, "getFamilyList", res => {
12 | if (res.data.length) this.setData({
13 | familyList: res.data
14 | });
15 | });
16 | },
17 |
18 | /**
19 | * 刪除家庭成员
20 | */
21 | click: function(e) {
22 | let target = e.target.dataset;
23 | if (target.no) {
24 | app.request(`${target.no}?token=${app.globalData.userInfo.token}`, 'deleteFamilyUser', res => {
25 | // 删除后重新获取
26 | app.request(`token=${app.globalData.userInfo.token}`, "getFamilyList", res => {
27 | if (res.data.length) this.setData({
28 | familyList: res.data
29 | });
30 | });
31 | });
32 | }
33 | },
34 |
35 | /**
36 | * 添加家庭成员
37 | */
38 | addFamily: function(e) {
39 | wx.navigateTo({
40 | url: '../../upload/idCard/idcard?addFamily=1',
41 | });
42 | }
43 | })
--------------------------------------------------------------------------------
/miniprogram/pages/account/login/login.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
37 |
38 |
--------------------------------------------------------------------------------
/miniprogram/pages/account/askList/askList.js:
--------------------------------------------------------------------------------
1 | const app = getApp();
2 | Page({
3 | data: {
4 | doctor: false,
5 | empty: !1
6 | },
7 | onLoad: function(e) {
8 |
9 | app.bar({
10 | title: "我的咨询",
11 | bgColor: "#B5CFFF"
12 | });
13 |
14 | this.setData({
15 | doctor: app.globalData.doctor
16 | });
17 |
18 | // 按页面参数 进行请求
19 | e.type && app.request(app.globalData.userInfo.token, `getDocAskListBy${e.type}`, res => {
20 | console.log(res.data)
21 | if (res.data.length) {
22 |
23 | //排序 已回复 > 待回复 > 已结束
24 | let sorting = [
25 | [],// 已回复
26 | [],// 待回复
27 | [] // 已结束
28 | ];
29 | res.data.forEach(value => {
30 | if (value.status == 1) {
31 | sorting[2].push(value);
32 | } else if (value.status == -1) {
33 | sorting[1].push(value);
34 | } else sorting[0].push(value);
35 | });
36 | let newArr = []
37 | newArr.push(...sorting[0], ...sorting[1], ...sorting[2]);
38 |
39 | this.setData({
40 | list: newArr
41 | });
42 | } else {
43 | this.setData({
44 | empty: !0
45 | });
46 | }
47 | });
48 |
49 | },
50 |
51 | })
--------------------------------------------------------------------------------
/miniprogram/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/account/account",
4 | "pages/account/askList/askList",
5 | "pages/index/index",
6 | "pages/doctor/doctor",
7 | "pages/account/register/register",
8 | "pages/account/login/login",
9 | "pages/search/search",
10 | "pages/account/family/family",
11 | "pages/upload/page/page",
12 | "pages/doctor/consulting/consulting"
13 | ],
14 | "window": {
15 | "backgroundTextStyle": "light",
16 | "navigationBarBackgroundColor": "#fff",
17 | "navigationBarTitleText": "康达互联网医院",
18 | "navigationBarTextStyle": "black"
19 | },
20 | "tabBar": {
21 | "color": "#a9b7b7",
22 | "selectedColor": "#11cd6e",
23 | "borderStyle": "black",
24 | "list": [
25 | {
26 | "text": "咨询",
27 | "pagePath": "pages/index/index",
28 | "iconPath": "images/tagbar/consulting.png",
29 | "selectedIconPath": "images/tagbar/consulting_on.png"
30 | },
31 | {
32 | "text": "我的",
33 | "pagePath": "pages/account/account",
34 | "iconPath": "images/tagbar/me.png",
35 | "selectedIconPath": "images/tagbar/me_on.png"
36 | }
37 | ]
38 | },
39 | "usingComponents": {
40 | "msg": "/component/Toast/Toast"
41 | }
42 | }
--------------------------------------------------------------------------------
/miniprogram/pages/account/register/register.wxss:
--------------------------------------------------------------------------------
1 | @import "../login/login.wxss";
2 | form {
3 | margin-top: 180rpx;
4 | }
5 | scroll-view,
6 | swiper {
7 | height: 100vh;
8 | }
9 | radio-group {
10 | display: flex;
11 | justify-content: space-around;
12 | }
13 | .select-user {
14 | display: block;
15 | width: 50vw;
16 | margin: 0 auto;
17 | margin-top: 200rpx;
18 | padding: 10rpx;
19 | background-color: white;
20 | border-radius: 100rpx;
21 | box-shadow: -10rpx -5rpx 20rpx rgba(0, 0, 0, .3);
22 | }
23 | .select-user-type {
24 | display: inline-block;
25 | width: 100%;
26 | padding: 10rpx 0;
27 | text-align: center;
28 | color: #333;
29 | }
30 | .select-user-type.on,.onL ,.onR {
31 | color: white;
32 | border-radius: 100rpx;
33 | background-image: linear-gradient(90deg,#00c6fb, #005bea);
34 | box-shadow: 3px 2px 5px rgba(0, 0, 0, .3);
35 | }
36 |
37 | .onL {
38 | transform: translateX(-100%);
39 | animation: onAnL .5s;
40 | animation-fill-mode: forwards;
41 | }
42 | @keyframes onAnL {
43 | to {
44 | transform: translateX(0);
45 | }
46 | }
47 |
48 | .onR {
49 | transform: translateX(100%);
50 | animation: onAnR .5s;
51 | animation-fill-mode: forwards;
52 | }
53 | @keyframes onAnR {
54 | to {
55 | transform: translateX(0);
56 | }
57 | }
--------------------------------------------------------------------------------
/miniprogram/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | page {
2 | margin-bottom: 30rpx;
3 | }
4 |
5 | .inputFocus {
6 | position: fixed;
7 | transform: translateY(-100px);
8 | border-radius: 50px;
9 | box-shadow: 2px 2px 5px 1600px rgba(0, 0, 0, .2);
10 | }
11 | .search-list {
12 | display: none;
13 | }
14 | .inputFocus .search-list {
15 | position: absolute;
16 | display: block;
17 | width: 100%;
18 | margin-top: 3px;
19 | color: #555;
20 | background-color: white;
21 | border-radius: 5px;
22 | box-shadow: 2px 2px 5px rgba(0, 0, 0, .3);
23 | }
24 | .inputFocus .search-list > view {
25 | margin: 0 20rpx;
26 | padding: 10rpx;
27 | border-bottom: 1px solid #eee;
28 | }
29 | .inputFocus .search-list > view text {
30 | color: red;
31 | }
32 | .consulting-type {
33 | margin-top: 400rpx;
34 | padding: 20rpx 0;
35 | }
36 | .consulting-type>view {
37 | float: left;
38 | width: 50%;
39 | padding: 0 20px;
40 | text-align: center;
41 | line-height: 60rpx;
42 | color: #555;
43 | box-sizing: border-box;
44 | font-size: 40rpx;
45 | text-shadow: 1px 2px 1px var(--shadow-color);
46 | transition: 0.5s;
47 | }
48 |
49 | .consulting-type>view icon {
50 | margin-right: 15rpx;
51 | }
52 |
53 | .consulting-type>view:nth-child(2) {
54 | border-left: 1px solid #eee;
55 | }
56 |
57 | .consulting-type>view:active {
58 | color: #474747;
59 | text-shadow: 0 0 1px #a9b7b7;
60 | }
61 |
--------------------------------------------------------------------------------
/miniprogram/pages/account/account.wxss:
--------------------------------------------------------------------------------
1 | .account {
2 | position: relative;
3 | margin-top: 20px;
4 | padding: 20rpx 0;
5 | }
6 |
7 | .notPage, .notPage icon {
8 | color: #ddd !important;
9 | }
10 |
11 | .account image {
12 | width: 120rpx;
13 | height: 120rpx;
14 | margin: 0 30rpx;
15 | vertical-align: middle;
16 | border-radius: 60rpx;
17 | box-shadow: 2px 2px 10px var(--shadow-color);
18 | }
19 |
20 | .account>view {
21 | display: flex;
22 | flex-wrap: wrap;
23 | flex-direction: row;
24 | align-items: center;
25 | float: right;
26 | width: calc(100% - 180rpx);
27 | height: 120rpx;
28 | }
29 |
30 | .account>view text {
31 | width: 100%;
32 | color: #888;
33 | }
34 |
35 | .account .nickName {
36 | color: #333;
37 | font-size: 1.2rem;
38 | text-shadow: 1px 2px 2px var(--shadow-color);
39 | }
40 |
41 | .row-box:nth-child(1) {
42 | margin-bottom: 50rpx;
43 | }
44 |
45 | .row-box:nth-child(n+2) {
46 | margin-top: 20rpx;
47 | }
48 |
49 | .get-user-info, .get-user-info::after {
50 | position: absolute;
51 | top: 0;
52 | left: 0;
53 | width: 100%;
54 | height: 100%;
55 | border: none;
56 | color: transparent;
57 | background-color: transparent;
58 | }
59 | .icon-shenfenzhengzheng {
60 | font-size: 1em;
61 | margin-top: -10px;
62 | }
63 | .account-error {
64 | font-size: .8rem;
65 | }
66 | .padding-empty {
67 | min-height:0;
68 | padding: 0;
69 | }
70 | .padding-empty > view {
71 | padding: 10rpx;
72 | }
--------------------------------------------------------------------------------
/miniprogram/pages/account/askList/askList.wxss:
--------------------------------------------------------------------------------
1 | .row-box {
2 | position: relative;
3 | overflow: hidden;
4 | padding: 10rpx 30rpx;
5 | margin: 20rpx auto;
6 | box-sizing: border-box;
7 | }
8 | .user-icon {
9 | position: absolute;
10 | top: 0;
11 | bottom: 0;
12 | margin: auto;
13 | margin-right: 20rpx;
14 | height: 110rpx;
15 | width: 110rpx;
16 | border-radius: 50%;
17 | }
18 | text {
19 | display: inline-block;
20 | width: calc(50% - 75rpx);
21 | }
22 |
23 | .docName,
24 | .descript {
25 | margin-left: 130rpx;
26 | }
27 | .state,
28 | .createTime {
29 | float: right;
30 | font-size: .8rem;
31 | text-align: right;
32 | color: #999;
33 | }
34 |
35 | .createTime {
36 | font-size: .7rem;
37 | color: #ccc;
38 | }
39 | .docName {
40 | font-size: 1.2rem;
41 | }
42 | .descript {
43 | overflow: hidden;
44 | width: calc(100% - 130rpx);
45 | text-overflow: ellipsis;
46 | text-indent: 1rem;
47 | white-space: nowrap;
48 | color: #888;
49 | }
50 |
51 | .nick::after,
52 | .waiting::after {
53 | content: "";
54 | position: absolute;
55 | top: 0;
56 | right: 0;
57 | width: 70rpx;
58 | height: 30rpx;
59 | background-color: rgba(0, 95, 0, .6);
60 | transform: rotateZ(45deg) translateY(-20rpx) translateX(10rpx)
61 | }
62 | .waiting::after {
63 | background-color: rgba(214, 86, 0, 0.6);
64 | }
65 |
66 | .end::after {
67 | content: "";
68 | position: absolute;
69 | top: 0;
70 | left: 0;
71 | height: 100%;
72 | background-color: rgba(0, 0, 0, .05);
73 | }
74 | .not-content {
75 | display: flex;
76 | justify-content: center;
77 | align-items: center;
78 | height: 100vh;
79 | color: #888;
80 | }
81 | .not-content text {
82 | width: 100%;
83 | text-align: center;
84 | }
--------------------------------------------------------------------------------
/miniprogram/pages/upload/idCard/idcard.wxss:
--------------------------------------------------------------------------------
1 | @import "../../account/login/login.wxss";
2 |
3 | .row-box {
4 | margin-top: 30rpx;
5 | padding: 10rpx;
6 | }
7 |
8 | .mar-top {
9 | margin-top: 50rpx;
10 | }
11 |
12 | .tag {
13 | display: block;
14 | font-weight: bold;
15 | }
16 |
17 | .upload-box {
18 | display: flex;
19 | flex-direction: row;
20 | justify-content: center;
21 | align-items: center;
22 | float: left;
23 | overflow: hidden;
24 | position: relative;
25 | width: calc(100% - 20rpx);
26 | height: 50vw;
27 | margin: 10rpx;
28 | padding: 20rpx;
29 | border-radius: 20rpx;
30 | border: 3px dashed #ccc;
31 | box-sizing: border-box;
32 | }
33 |
34 | .upload-box image {
35 | position: absolute;
36 | margin-top: -30rpx;
37 | width: 100%;
38 | }
39 |
40 | .icon-tianjia {
41 | position: relative;
42 | display: block;
43 | color: #999;
44 | text-align: center;
45 | font-size: 3em;
46 | }
47 |
48 | .icon-shenfenzhengfan, .icon-shenfenzhengzheng {
49 | position: absolute;
50 | transform: translateY(-35rpx);
51 | color: #eee;
52 | font-size: 25vw;
53 | z-index: 0;
54 | }
55 |
56 | .upload-tag {
57 | position: absolute;
58 | bottom: 0;
59 | width: 100%;
60 | padding: 5rpx 0;
61 | text-align: center;
62 | color: #fff;
63 | background-color: #437ff9;
64 | }
65 | .content {
66 | text-indent: 2em;
67 | color: #888;
68 | font-size: .8em;
69 | }
70 | .content text {
71 | color: #e64340;
72 | }
73 |
74 | .button-blue {
75 | position: absolute;
76 | bottom: 150rpx;
77 | width: 90vw;
78 | margin-left: 5vw;
79 | color: #fff;
80 | background-color: #437ff9;
81 | box-shadow: 4rpx 6rpx 9rpx rgba(0, 0, 0, .3);
82 | }
83 |
84 | form {
85 | margin: 170rpx auto 0;
86 | }
--------------------------------------------------------------------------------
/miniprogram/pages/upload/idCard/idcard.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 拍摄正面
10 |
11 |
12 |
13 |
14 | 拍摄身份证要求:
15 | 拍摄时确保身份证
16 | 边框完整,字体清晰,亮度均匀,无涂抹遮盖
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/miniprogram/pages/index/index.js:
--------------------------------------------------------------------------------
1 | var a = getApp(),
2 | change = null;
3 |
4 | Page({
5 | data: {
6 | searchClass: "",
7 | department: [{
8 | tag: "皮肤科",
9 | icon: "pifuke color1"
10 | }, {
11 | tag: "推拿",
12 | icon: "tuina color2"
13 | }, {
14 | tag: "骨科",
15 | icon: "guke color3"
16 | }, {
17 | tag: "耳鼻咽喉",
18 | icon: "erbihouke color4"
19 | }, {
20 | tag: "检验",
21 | icon: "jianyan color5"
22 | }, {
23 | tag: "B超",
24 | icon: "Bchaoyuyue-K color6"
25 | }, {
26 | tag: "科室7",
27 | icon: "wrong color7"
28 | }, {
29 | tag: "科室8",
30 | icon: "wrong color8"
31 | }],
32 | searchDoctor: []
33 | },
34 | /**
35 | * 搜索栏聚焦
36 | */
37 | searchFocus: function() {
38 | this.setData({
39 | searchClass: "inputFocus"
40 | });
41 | },
42 | /**
43 | * 搜索栏失焦
44 | */
45 | searchBlur: function() {
46 | this.setData({
47 | searchClass: ""
48 | })
49 | },
50 | /**
51 | * 搜索关键词
52 | */
53 | searchKey: function(e) {
54 |
55 | // 节流算法
56 | change && clearTimeout(change);
57 |
58 | change = setTimeout(() => {
59 | change = null;
60 | let val = e.detail.value;
61 | val && a.request({
62 | "doc_name": val,
63 | "depId": -1,
64 | "subdepId": -1
65 | }, "searchDoctor", data => {
66 | data = data.data;
67 | if (typeof data == "object") {
68 | data.map && data.map(res => {
69 | res.split = res.name.split(val);
70 | res.key = val;
71 | return res;
72 | });
73 | this.setData({
74 | searchDoctor: data
75 | });
76 | }
77 | });
78 | }, 500);
79 | }
80 | });
--------------------------------------------------------------------------------
/miniprogram/pages/search/search.wxml:
--------------------------------------------------------------------------------
1 |
14 | 按照科室查找
15 |
16 |
17 | 查找结果({{ results.length }})
18 |
19 |
20 |
21 |
22 |
29 |
30 | {{item.tag}}
31 |
32 |
33 |
34 |
35 |
36 | {{item.name}}
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
52 |
53 | {{item.name}}
54 | {{item.tag}}
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/miniprogram/component/Toast/Toast.wxss:
--------------------------------------------------------------------------------
1 | @import "../../app.wxss";
2 |
3 | .toast {
4 | position: fixed;
5 | bottom: 5vh;
6 | right: 0;
7 | padding-right: 10px;
8 | min-width: 50vw;
9 | line-height: 10vw;
10 | background-color: white;
11 | box-shadow: 5px 10px 5px -5px rgba(0, 0, 0, 0.3);
12 | border-radius: 5px 0 0 5px;
13 | transition: 1s;
14 | transform: translateX(100%);
15 | }
16 |
17 | .select {
18 | animation: 0.5s 1s marTop;
19 | animation-fill-mode: forwards;
20 | }
21 |
22 | @keyframes marTop {
23 | to {
24 | bottom: calc(10vh + 30rpx);
25 | }
26 | }
27 |
28 | .toast-show {
29 | transform: translateX(0);
30 | }
31 |
32 | .toast.error {
33 | background-color: #ffa7a1;
34 | color: red;
35 | }
36 |
37 | .toast.success {
38 | background-color: #a7ffab;
39 | color: #00b12c;
40 | }
41 |
42 | .toast.warning {
43 | background-color: #ffcb9a;
44 | color: #cc7400;
45 | }
46 |
47 | .toast.zhiwen, .saoma {
48 | background-color: #aafff4;
49 | color: #0087b1;
50 | }
51 |
52 | .toast.loading {
53 | background-color: #aeadff;
54 | color: #0003a8;
55 | }
56 |
57 | .toast icon {
58 | margin: 0 10px;
59 | vertical-align: middle;
60 | font-size: 25px;
61 | }
62 |
63 | .toast text {
64 | vertical-align: middle;
65 | font-size: 15px;
66 | }
67 |
68 | .select + .toast {
69 | display: flex;
70 | flex-wrap: wrap;
71 | flex-direction: row;
72 | align-items: center;
73 | justify-content: center;
74 | overflow: hidden;
75 | height: 10vw;
76 | min-width: 50vw;
77 | max-height: 0;
78 | padding: 0 10rpx;
79 | animation: 0.5s 1s maxH;
80 | animation-fill-mode: forwards;
81 | }
82 |
83 | @keyframes maxH {
84 | to {
85 | transform: translateX(0);
86 | max-height: 10vw;
87 | }
88 | }
89 |
90 | .toast button {
91 | display: inline-block;
92 | padding: 5rpx 10rpx;
93 | line-height: 5vh;
94 | color: white;
95 | }
96 |
97 | .toast button.green {
98 | background-color: #00b100;
99 | }
100 |
101 | .toast button.red {
102 | background-color: #f11c1c;
103 | }
104 |
105 | .toast button {
106 | background-color: #999;
107 | }
108 |
--------------------------------------------------------------------------------
/miniprogram/pages/account/family/family.wxss:
--------------------------------------------------------------------------------
1 | page {
2 | background-color: #aeba4e !important;
3 | }
4 |
5 | .background {
6 | position: relative;
7 | }
8 |
9 | .family.row-box {
10 | padding: 0;
11 | margin-bottom: 20rpx;
12 | background-color: #c8e6c9;
13 | box-shadow: 0 0 7px rgba(0, 0, 0, 0.4);
14 | border-radius: 5px;
15 | }
16 |
17 | .title {
18 | display: block;
19 | width: 100%;
20 | padding: 20rpx;
21 | color: white;
22 | background-color: #43a047;
23 | border-radius: 5px 5px 0 0;
24 | box-sizing: border-box;
25 | }
26 |
27 | .tag {
28 | float: left;
29 | font-weight: bold;
30 | font-size: 1.2em;
31 | text-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
32 | }
33 |
34 | .tag + icon {
35 | float: right;
36 | vertical-align: middle;
37 | }
38 |
39 | .row-box > view:nth-child(1n+2) {
40 | position: relative;
41 | padding: 10px;
42 | border-bottom: 2px solid rgba(255, 255, 255, .3);
43 | box-sizing: border-box;
44 | }
45 | .row-box > view:last-child {
46 | border-bottom: none;
47 | }
48 | .row-box image {
49 | float: left;
50 | width: 100rpx;
51 | height: 100rpx;
52 | margin: 10rpx;
53 | margin-right: 15px;
54 | border-radius: 10px;
55 | }
56 | .row-box .button-list {
57 | position: absolute;
58 | display: flex;
59 | flex-direction: row;
60 | flex-wrap: wrap;
61 | justify-content: center;
62 | align-items: center;
63 | top: 0;
64 | right: 0;
65 | width: 15%;
66 | height: 100%;
67 | padding: 0 10rpx;
68 | }
69 | .row-box .button-list button {
70 | display: block;
71 | padding: 10rpx 0;
72 | width: 90%;
73 | line-height: 100%;
74 | height: auto;
75 | color: white;
76 | background-color: #ef5350;
77 | box-shadow: 0 8px 5px -5px rgba(0, 0, 0, .3);
78 | transition: .1s;
79 | }
80 | .row-box .button-list button:active {
81 | color: #ddd;
82 | background-color: #f14744;
83 | box-shadow: 0 1px 4px 0 rgba(206, 57, 54, 0.8);
84 | }
85 | .row-box > view:nth-child(1n+2) text:nth-child(1) {
86 | display: inline-block;
87 | min-width: 90rpx;
88 | }
89 | .row-box > view:nth-child(1n+2) text:nth-child(2) {
90 | margin-left: 10rpx;
91 | color: #555;
92 | }
93 | .loading {
94 | width: 100%;
95 | text-align: center;
96 | color: #555;
97 | }
--------------------------------------------------------------------------------
/miniprogram/pages/account/answer/answer.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ doctor ? detail.patient_name : detail.doctor_name}}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | {{ detail.patient_name + " " + detail.l_sex + " " + detail.age }}
16 | 咨询原因:{{ detail.content }}
17 |
18 |
19 |
20 | {{ item.addDate }}
21 |
22 |
23 | {{ item.l_content }}
24 | {{ item.error }}
25 |
26 |
27 |
28 | 以上是历史消息
29 |
30 |
31 |
32 |
33 | 刷新中...
34 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
46 |
47 | 申请开药
48 | 申请开检验检查单
49 | 我已经知道
50 |
51 |
52 |
--------------------------------------------------------------------------------
/miniprogram/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | {{item.split[0]}}
13 | {{item.key}}{{item.split[1]}}
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 | {{item.tag}}
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 |
--------------------------------------------------------------------------------
/miniprogram/pages/doctor/doctor.js:
--------------------------------------------------------------------------------
1 | const app = getApp();
2 | let token = app.globalData.userInfo.token;
3 | Page({
4 | data: {
5 |
6 | // 显示简介
7 | introduce: true,
8 |
9 | // 菜单标签
10 | tag: {
11 | consulting: {
12 | page1: true
13 | }
14 | },
15 |
16 | // 家庭列表
17 | family: [],
18 | focusFamily: 0,
19 | familyList: [{
20 | patientname: '--',
21 | sex: '--',
22 | age: '--',
23 | }]
24 | },
25 | onLoad: function (options) {
26 | options && this.setData(options);
27 | },
28 | onShow: function() {
29 | app.bar({
30 | title: '医生信息',
31 | bgColor: '#B5CFFF'
32 | });
33 |
34 | app.request(`token=${token}`, "getFamilyList", res => {
35 | let data = [];
36 | for (let obj of res.data) data.push(`${obj.patientname} ${obj.sex} ${obj.age}`);
37 | (res.data.length < 5) && data.push(`+ 添加家庭成员`);
38 | this.setData({
39 | family: data,
40 | familyList: res.data
41 | });
42 | });
43 |
44 | // 默认选中 咨询
45 | this.showContent('consulting');
46 | },
47 |
48 | /**
49 | * 菜单点击后显示
50 | */
51 | showContent: function(e) {
52 | let tag = e.target ? e.target.dataset.tag : e;
53 | if (this.data.tag[tag]) return;
54 | this.setData({
55 | tag: {
56 | [tag]: {}
57 | },
58 | introduce: true
59 | });
60 | },
61 |
62 | /**
63 | * 切換内页
64 | */
65 | switchPage: function(e) {
66 | this.setData({
67 | [e.target.dataset.page]: true,
68 | introduce: false
69 | });
70 | },
71 |
72 | /**
73 | * 姓名选择
74 | */
75 | con_picker: function(e) {
76 | if (e.detail.value == this.data.family.length - 1) {
77 | wx.navigateTo({
78 | url: '../account/family/family',
79 | })
80 | return;
81 | }
82 | this.setData({
83 | focusFamily: e.detail.value
84 | });
85 | },
86 |
87 | /**
88 | * 咨询提交
89 | */
90 | consulting: function(e) {
91 | if (e.detail.value.content.length < 4) {
92 | this.setData({
93 | toast: {
94 | text: "请至少输入4个字符!",
95 | icon: "error"
96 | }
97 | })
98 | return;
99 | }
100 |
101 | let data = this.data;
102 | app.request({
103 | patient_id: data.familyList[data.focusFamily].id,
104 | doctor_id: data.id,
105 | content: e.detail.value.content
106 | }, "addDoctorAsk", res => {
107 | console.log(res.data)
108 | if (res.data.ask_id) {
109 | wx.navigateTo({
110 | url: '../account/answer/answer?id=' + res.data.ask_id,
111 | });
112 | } else this.setData({
113 | toast: {
114 | text: res.data.error,
115 | icon: 'error'
116 | }
117 | });
118 | }, token);
119 |
120 | },
121 | })
--------------------------------------------------------------------------------
/miniprogram/pages/search/search.wxss:
--------------------------------------------------------------------------------
1 | .search-box {
2 | top: 25rpx;
3 | }
4 | .type-list-tag {
5 | position: relative;
6 | display: inline-block;
7 | width: 90vw;
8 | margin: 110rpx 0 0 5vw;
9 | padding: 10rpx 20rpx;
10 | text-align: center;
11 | color: #6d6d6d;
12 | vertical-align: middle;
13 | background-color: #f8f8f8;
14 | border-radius: 5px 5px 0 0;
15 | box-sizing: border-box;
16 | }
17 | .icon-sousuo button {
18 | position: absolute;
19 | top: 0;
20 | right: 0;
21 | height: 100%;
22 | opacity: 0;
23 | }
24 | .type-list {
25 | position: relative;
26 | overflow: hidden;
27 | height: calc(100vh - 190rpx);
28 | background-color: white;
29 | border-radius: 5px;
30 | }
31 | .type-list-left {
32 | overflow-x: hidden;
33 | width: 35%;
34 | height: 100%;
35 | font-size: 1em;
36 | }
37 | .type-list-left text {
38 | pointer-events: none;
39 | }
40 | .type-list-left icon {
41 | margin: -10rpx 10rpx 0 0;
42 | font-size: 1em;
43 | color: #555;
44 | }
45 | .type-list-right {
46 | overflow-x: hidden;
47 | right: 0;
48 | width: 65%;
49 | height: 100%;
50 | }
51 | .type-list-left, .type-list-right {
52 | position: absolute;
53 | }
54 | .type-list-left > view,
55 | .type-list-right > view {
56 | padding: 10rpx;
57 | line-height: 40rpx;
58 | border-bottom: 1px solid #d8d8d8;
59 | }
60 | .type-list-right > view:active {
61 | background-color: #eee;
62 | transition: .2s;
63 | }
64 | .type-list-right > view {
65 | border-bottom: 1px solid #eee;
66 | }
67 | view.select {
68 | margin-top: -1px;
69 | color: #444;
70 | background-color: white;
71 | border-top: 1px solid #fff;
72 | border-bottom: none;
73 | }
74 | .select::before {
75 | content: '';
76 | position: absolute;
77 | left: 0;
78 | width: 100%;
79 | height: 100%;
80 | margin-top: 50rpx;
81 | background-color: rgba(0, 0, 0, .1);
82 | border-top-right-radius: 8px;
83 | pointer-events: none;
84 | }
85 | .select::after {
86 | content: '';
87 | position: absolute;
88 | left: 0;
89 | width: 100%;
90 | height: 100%;
91 | margin-top: -10rpx;
92 | background-color: rgba(0, 0, 0, .1);
93 | border-bottom-right-radius: 8px;
94 | transform: translateY(-100%);
95 | pointer-events: none;
96 | }
97 | /* 搜索结果医生 */
98 | .doctor-scroll {
99 | height: 100%;
100 | }
101 | .doctor {
102 | width: 90%;
103 | padding: 2%;
104 | margin: 10rpx auto;
105 | background-color: #eee;
106 | border-radius: 5px;
107 | }
108 | .user-icon {
109 | display: inline-block;
110 | margin-right: 2%;
111 | vertical-align: middle;
112 | pointer-events: none;
113 | }
114 | .doctor-name {
115 | display: inline-block;
116 | width: 40%;
117 | text-indent: .5em;
118 | font-weight: 500;
119 | pointer-events: none;
120 | }
121 | .doctor-tag {
122 | color: #888;
123 | pointer-events: none;
124 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 微信小程序-前端 [开发版]
2 | > `文档更新: 2018-12-23`
3 | > `体验版本: v0.7.0 [Alpha]`
4 | > `本来是公司的项目,但因某些原因项目终止,所以才可以开源`
5 | ### 内部原创组件说明
6 | >`Toast` 组件: [查看 说明/源码](https://gitee.com/slm47888/wechat_applet__component_toast)
7 | ### 部分截图预览:
8 |
9 |

10 |

11 |

12 |

13 |

14 |

15 |

16 |

17 |
18 |
19 | ### 修改接口[开源设定]:
20 | 修改 [app.js](https://github.com/shi-lai-mu/hospital-wxapp/blob/master/miniprogram/app.js) 文件内的URL即可,接口传回数据参考下方的后端文档
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 | >>- openId登录
55 | >>- openId注册
56 | >>- openId绑定
57 | >>- 身份证识别
58 | >>- 主账号注册[用户]
59 | >##### `咨询机制:`
60 | >>- 全部咨询进行权重排序 已回复 > 待回复 > 已结束
61 | >>- 历史消息无动画,发消息包含动态
62 | >>- 底部工具栏
63 |
64 | ### 本地存储调用说明:
65 | ##### `主要起到提高体验度、减轻服务器压力`
66 | | 数据 | 调用页 | 函数名 | 存储条件 | 有效时间 |
67 | | :--------| :-------- | :-------- | :--------| :------: |
68 | | 用户数据[账号/token/主账号] | account | settingAccount | 无数据/数据过期 | 3天 |
69 | | 部门信息[主部门/子部门/科室] | app | onLaunch | 无数据/数据过期 | 1小时 |
70 | | 专家列表[专家信息] | search | onLoad | 专家咨询 | 1小时 |
71 |
72 |
73 | ```javascript
74 | // 以下为小程序页面目录注释[方便快速查找]
75 | /*
76 | +---cloud [云函数]
77 | | \---getOpenId [获取openId]
78 | |
79 | +---miniprogram [主目录]
80 | | +---component [组件]
81 | | | \---Toast [Toast 消息组件]
82 | | |
83 | | +---images [图片库]
84 | | | \---tagbar [底部选项卡]
85 | | |
86 | | \---pages [页面]
87 | | +---account [账号]
88 | | | +---family [我的家庭]
89 | | | +---answer [咨询界面]
90 | | | +---docAskList [咨询历史]
91 | | | +---login [登录]
92 | | | \---register [注册]
93 | | |
94 | | +---doctor [医生]
95 | | | \---consulting [待定]
96 | | |
97 | | +---index [首页]
98 | | +---search [搜索]
99 | | \---upload [上传]
100 | | +---idCard [身份证]
101 | | \---page [空白页]
102 |
103 | */
104 | ```
105 |
106 |
--------------------------------------------------------------------------------
/miniprogram/pages/account/login/login.js:
--------------------------------------------------------------------------------
1 | const app = getApp();
2 | // 手机号返回的mssion_id
3 | let mssion_id = null,
4 | outInter = null,
5 | outTime = 0;
6 | Page({
7 | data: {
8 | sendState: "发送",
9 | },
10 | onReady: function() {
11 | app.bar({
12 | title: '绑定账号',
13 | bgColor: '#3285FF'
14 | });
15 | },
16 |
17 | /**
18 | * 聚焦事件
19 | */
20 | inputFocus: function(t) {
21 | var a = {};
22 | a[t.target.dataset.id] = "changed", this.setData(a);
23 | },
24 |
25 | /**
26 | * 失焦事件
27 | */
28 | inputBlur: function(t) {
29 | var a = {};
30 | a[t.target.dataset.id] = t.detail.value ? "nick" : "", this.setData(a);
31 | },
32 |
33 | /**
34 | * 绑定账号事件
35 | */
36 | bind: function (e) {
37 | let value = e.detail.value;
38 |
39 | // 获取token
40 | let token = wx.getStorageSync('login');
41 | if (!token) return;
42 |
43 | // 判断 手机号和验证码 是否输入
44 | if (value.phone) {
45 | if (value.codes) {
46 | // 判断是否存在验证码
47 | if (!mssion_id) return this.setData({
48 | toast: {
49 | text: "未找到验证信息!",
50 | icon: "error"
51 | }
52 | });
53 |
54 | // 请求验证码是否正确 销毁mssion_id
55 | app.request(`${mssion_id}/${value.codes}/?token=${token.data.data.token}`, "finishBind", res => {
56 | if (res.error) {
57 | this.setData({
58 | toast: {
59 | text: "验证码错误!",
60 | icon: "error"
61 | }
62 | });
63 | } else {
64 | wx.switchTab({
65 | url: '../account?reload'
66 | });
67 | }
68 | });
69 | mssion_id = null;
70 | } else {
71 | // 检测冷却
72 | if (outTime) return;
73 |
74 | // 如果未输入验证码 则 发送验证码
75 | app.request(`${value.phone}/?token=${token.data.data.token}`, "existAccount", res => {
76 | if (!isNaN(res)) {
77 | outTime = (res / 1000).toFixed(0);
78 | this.countDown(outTime);
79 | return
80 | }
81 | if (res.data.mssion_id) {
82 | mssion_id = res.data.mssion_id;
83 | this.setData({
84 | toast: {
85 | text: "验证码已发送!请输入...",
86 | icon: "success",
87 | hideTime: 3000
88 | }
89 | });
90 | this.countDown(60);
91 | } else this.setData({
92 | toast: {
93 | text: "验证码发送失败:" + res.data.error,
94 | icon: "error"
95 | }
96 | });
97 |
98 | }, false, 60);
99 | }
100 | } else return this.setData({
101 | toast: {
102 | text: "手机信息为空!",
103 | icon: "error"
104 | }
105 | });
106 | },
107 |
108 | /**
109 | * 倒计时
110 | */
111 | countDown: function(outTime) {
112 | outInter = setInterval(() => {
113 | if (!outTime) {
114 | clearInterval(outInter);
115 | outTime = "发送";
116 | }
117 | this.setData({
118 | sendState: outTime
119 | });
120 | outTime--;
121 | }, 1000);
122 | }
123 | });
--------------------------------------------------------------------------------
/miniprogram/pages/account/login/login.wxss:
--------------------------------------------------------------------------------
1 | page {
2 | overflow: hidden;
3 | }
4 |
5 | .bgColor {
6 | position: absolute;
7 | z-index: -1;
8 | height: 100vh;
9 | width: 100vw;
10 | background-image: linear-gradient(180deg, #fff 80%, #ccc);
11 | }
12 |
13 | .flex {
14 | display: flex;
15 | justify-content: center;
16 | flex-direction: row;
17 | align-items: center;
18 | flex-wrap: wrap;
19 | height: calc(80vh - 400rpx);
20 | margin-top: 250rpx;
21 | }
22 |
23 | form {
24 | display: block;
25 | width: 80vw;
26 | margin: 300rpx auto 0;
27 | }
28 |
29 | form view, form radio-group {
30 | position: relative;
31 | padding: 40rpx 0;
32 | }
33 |
34 | input {
35 | width: calc(80vw - 3em);
36 | padding: 0 0 10rpx 3em;
37 | margin: 0 auto;
38 | color: var(--main-icon-color);
39 | border-bottom: 2px solid #eee;
40 | vertical-align: middle;
41 | transition: 0.5s linear;
42 | }
43 |
44 | input+.iconfont {
45 | position: absolute;
46 | top: 25rpx;
47 | color: var(--main-icon-color);
48 | transition: 0.5s linear;
49 | }
50 |
51 | input~label {
52 | position: absolute;
53 | top: 35rpx;
54 | left: 3em;
55 | color: #ccc;
56 | transition: 0.5s linear;
57 | pointer-events: none;
58 | }
59 |
60 | .placeholder {
61 | color: #ccc;
62 | }
63 |
64 | .changed input {
65 | color: var(--main-icon-color);
66 | border-bottom: 2px solid var(--main-icon-color);
67 | }
68 |
69 | .changed .iconfont {
70 | opacity: 0;
71 | transform: translateX(-100%);
72 | }
73 |
74 | .changed>label {
75 | color: var(--main-icon-color);
76 | transform: translateX(calc(-100% - 10rpx));
77 | }
78 |
79 | .changed>label::after {
80 | content: ':';
81 | }
82 |
83 | .nick input {
84 | border-bottom: 2px solid transparent;
85 | }
86 |
87 | .nick label {
88 | opacity: 0;
89 | }
90 |
91 | button {
92 | width: 80vw;
93 | color: white;
94 | font-weight: bold;
95 | background-color: #2b6efb;
96 | box-shadow: 0 3px 5px rgba(0, 0, 0, 0.5);
97 | }
98 |
99 | button:active {
100 | box-shadow: 0 5px 15px 2px rgba(0, 0, 0, 0.4);
101 | }
102 |
103 | .form-input-left {
104 | float: left;
105 | width: calc(50vw - 3em);
106 | transition: 0.1s;
107 | }
108 |
109 | .form-input-left ~ icon {
110 | left: 0;
111 | }
112 |
113 | .form-input-right {
114 | float: right;
115 | width: calc(20vw - 20px);
116 | padding: 0 20px;
117 | margin-top: -2px;
118 | box-sizing: content-box;
119 | }
120 | .clearfix button {
121 | background-color: #fff;
122 | }
123 | .form-button-right {
124 | position: absolute;
125 | right: 0;
126 | width: 20vw;
127 | margin-top: -30rpx;
128 | color: #555;
129 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
130 | box-sizing: content-box;
131 | opacity: 1;
132 | transition: .7s;
133 | }
134 |
135 | .row-two {
136 | display: flex;
137 | }
138 | .row-two button {
139 | margin: 0 30rpx;
140 | }
141 |
142 | .none {
143 | position: absolute;
144 | right: 0;
145 | width: 20vw;
146 | opacity: 0;
147 | }
148 |
149 | .right-navigator {
150 | display: block;
151 | width: 80vw;
152 | margin-top: 20rpx;
153 | text-align: right;
154 | }
155 |
156 | .code-cooling {
157 | color: #ccc;
158 | }
159 |
--------------------------------------------------------------------------------
/miniprogram/pages/doctor/doctor.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{name}}
8 |
9 | {{tags}}主任医师
10 |
11 |
12 |
13 | 简介:
14 | {{name}}医生是我院{{tags}}的主任医师,其技术精湛,深受广大患者信赖!
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 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | 欢迎使用预约服务,此服务将节省您排队挂号时间!
79 | 预约
80 |
81 |
82 |
83 | 预约界面
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/miniprogram/component/Toast/Toast.js:
--------------------------------------------------------------------------------
1 | // component/Toast.js
2 | // 组件作者: 郑余国 https://gitee.com/slm47888/wechat_applet__component_toast
3 |
4 | // 任务列表
5 | let Task = [], show = null, self = null, hide = null, fn = [];
6 |
7 | Component({
8 | properties: {
9 | // 传入参数
10 | data: {
11 | type: Object,
12 | value: {}
13 | }
14 | },
15 |
16 | data: {
17 | // icon图标
18 | error: "wrong",
19 | success: "chenggong",
20 | warning: "jinggao",
21 | loading: "loading",
22 | zhiwen: "zhiwen",
23 | saoma: "saoma",
24 | },
25 | methods: {
26 | selectClick: function (e) {
27 | // 点击按钮时执行函数
28 | let Id = e.target.dataset.fn;
29 | fn[Id - 1] && fn[Id - 1]();
30 | }
31 | },
32 | ready: function () {
33 | // 监听 data 数据变化
34 | Object.defineProperty(this.data, "data", {
35 | // 当数据被改变时 被设置
36 | set: function (data) {
37 | let Toast = new Message(data);
38 | // 如果 没有正在显示的Toast则 显示 否则 如果是无限期显示的Toast则隐藏后显示
39 | !show ? Toast.send() : !show.data.hide && show.hide();
40 | }
41 | });
42 | },
43 | pageLifetimes: {
44 | // 修复切换页面的BUG
45 | hide: function () {
46 | show && (Task = [], show = null, clearTimeout(hide), this.setData({
47 | msg: {}
48 | }));
49 | },
50 | show: function () {
51 | self = this;
52 | },
53 | }
54 | });
55 |
56 | function Message(data) {
57 | if (typeof data !== "object") throw Error("data 必须为 Object!");
58 | // 隐藏时间或持续显示 否则 1500ms 后消失
59 | data.hideTime = (data.hideTime || data.hideTime === false) ? data.hideTime : 2500;
60 | // 修复耦合度 短时间内最多重复两条相同消息
61 | if (Task.length) {
62 | let t = Task[Task.length - 1];
63 | if (t.text == data.text && t.icon == self.data[data.icon]) return;
64 | }
65 | // 加入任务列队
66 | Task.push({
67 | text: data.text,
68 | icon: self.data[data.icon] || "",
69 | back: data.icon,
70 | hide: data.hideTime,
71 | callback: data.callback,
72 | select: data.select || false
73 | });
74 | }
75 |
76 | Message.prototype = {
77 | data: {},
78 | // 显示Toast
79 | send: function () {
80 | let after = Task[0];
81 | if (after && !show) {
82 | // 记录触发函数
83 | for (let key in after["select"]) {
84 | let val = after["select"][key];
85 | after["select"][key]._fn = val.click ? fn.push(val.click) : false
86 | }
87 | // 触发驱动
88 | self.setData({
89 | msg: {
90 | _text: after["text"],
91 | _type: after["back"],
92 | _icon: after["icon"],
93 | select: after["select"]
94 | }
95 | });
96 | // 如果Toast不是false则有消失时间
97 | after["hide"] && (hide = setTimeout(this.hide, after["hide"]));
98 | this.data = after;
99 | show = this;
100 | Task.shift();
101 | }
102 | },
103 |
104 | // 隐藏Toast
105 | hide: function () {
106 | show.data.callback && show.data.callback();
107 | // 清空显示
108 | show = null;
109 | self.setData({
110 | msg: {
111 | _text: "",
112 | _type: "",
113 | _icon: ""
114 | }
115 | });
116 | // 400毫秒后检测列队
117 | setTimeout(Message.check, 400);
118 | }
119 | };
120 |
121 | Message.check = function () {
122 | if (Task[0]) !show ? Message.prototype.send() : !show.data.hide && show.hide();
123 | }
--------------------------------------------------------------------------------
/miniprogram/pages/doctor/doctor.wxss:
--------------------------------------------------------------------------------
1 | .doctor-info {
2 | margin-top: 50rpx;
3 | padding: 30rpx 0;
4 | }
5 | .doctor-img {
6 | width: 120rpx;
7 | height: 120rpx;
8 | margin: 0 30rpx;
9 | vertical-align: middle;
10 | border-radius: 60rpx;
11 | box-shadow: 2px 2px 10px var(--shadow-color);
12 | }
13 | .doctor-info .img-right {
14 | display: flex;
15 | flex-wrap: wrap;
16 | flex-direction: row;
17 | align-items: center;
18 | float: right;
19 | width: calc(100% - 180rpx);
20 | height: 120rpx;
21 | }
22 | .doctor-info text {
23 | width: 100%;
24 | color: #888;
25 | }
26 | text.doctor-name {
27 | font-size: 1.2em;
28 | color: #222;
29 | }
30 | text.doctor-tag {
31 | margin-top: -10rpx;
32 | font-size: .9em;
33 | }
34 | .doctor-introduce {
35 | overflow: hidden;
36 | max-height: 0;
37 | padding: 20rpx;
38 | padding-bottom: 0;
39 | margin: 30rpx;
40 | margin-bottom: 0;
41 | border-top: 1px solid transparent;
42 | transition: .8s;
43 | }
44 | .doctor-introduce.focus {
45 | border-top: 1px solid #eee;
46 | max-height: 100vh;
47 | }
48 | text.introduce-tag {
49 | display: block;
50 | color: #333;
51 | }
52 | text.introduce-content {
53 | padding-left: 2em;
54 | font-size: .8em;
55 | }
56 | .doctor-name .iconfont {
57 | margin-left: 20rpx;
58 | color: #ccc;
59 | font-size: .9em;
60 | }
61 |
62 | .muen {
63 | position: relative;
64 | overflow: hidden;
65 | margin-top: 30rpx;
66 | }
67 | .muen-list {
68 | display: flex;
69 | }
70 | .muen-list text {
71 | position: relative;
72 | width: 100%;
73 | padding: 5px;
74 | z-index: 5;
75 | color: #fff;
76 | text-align: center;
77 | box-sizing: border-box;
78 | }
79 | .muen-list .focus {
80 | z-index: 1;
81 | color: #333;
82 | }
83 | .muen-list .focus::after,
84 | .muen-list .focus::before {
85 | content: '';
86 | position: absolute;
87 | top: 0;
88 | width: 100vw;
89 | height: 100%;
90 | background-color: rgba(181, 207, 255, .6);
91 | border-radius: 0 0 20rpx 20rpx;
92 | box-shadow: 0 -2px 2px rgba(0, 0, 0, .05) inset;
93 | pointer-events: none;
94 | }
95 | .muen-list .focus::after {
96 | left: 0;
97 | margin-left: 100%;
98 | }
99 | .muen-list .focus::before {
100 | right: 0;
101 | margin-right: 100%;
102 | }
103 | .muen-content {
104 | padding: 20rpx 10rpx;
105 | }
106 | .muen-content .page > view {
107 | overflow: hidden;
108 | max-height: 0;
109 | transition: .8s;
110 | }
111 | .muen-content .page .focus {
112 | max-height: 100vh;
113 | }
114 | .center-text {
115 | display: block;
116 | margin: 10rpx 0;
117 | font-size: .85rem;
118 | text-align: center;
119 | color: #888;
120 | }
121 | .button {
122 | display: block;
123 | width: 40vw;
124 | padding: 5rpx 20rpx;
125 | margin: 25rpx auto;
126 | color: #75a5ff;
127 | font-size: 1rem;
128 | line-height: 50rpx;
129 | text-align: center;
130 | border: 2rpx solid;
131 | border-radius: 20px;
132 | }
133 | .button:active {
134 | color: #fff;
135 | background-color: #75a5ff;
136 | }
137 |
138 | .qrcode {
139 | display: block;
140 | width: 50vw;
141 | height: 50vw;
142 | margin: 0 auto;
143 | }
144 |
145 | /* 咨询 */
146 | .con-list {
147 | width: 95%;
148 | padding: 10rpx 0;
149 | margin: 0 auto;
150 | font-size: 1.1rem;
151 | color: #777;
152 | border-bottom: 1px solid #eee;
153 | }
154 | .con-list text {
155 | color: #222;
156 | font-weight: 500;
157 | }
158 | .con-list .con-right {
159 | float: right;
160 | text-align: right;
161 | min-width: 50%;
162 | }
163 | .icon-fangxiangyou {
164 | float: right;
165 | margin-top: -1.5rpx;
166 | font-size: 1rem;
167 | color: #ccc;
168 | }
169 | .con-list textarea {
170 | width: 100%;
171 | min-height: 6rem;
172 | padding-bottom: 1rem;
173 | font-size: .95rem;
174 | }
175 | text.ps4 {
176 | position: absolute;
177 | right: 4%;
178 | color: #ccc;
179 | font-size: .8rem;
180 | transform: translateY(-100%)
181 | }
182 | .ps {
183 | color: #bbb;
184 | font-size: .7rem;
185 | }
186 | button {
187 | width: 60vw;
188 | margin: 20rpx auto 10rpx;
189 | font-weight: bold;
190 | color: #fff;
191 | text-shadow: 0 0 1rpx #777;
192 | background-color: #D3E2FF;
193 | }
--------------------------------------------------------------------------------
/miniprogram/pages/search/search.js:
--------------------------------------------------------------------------------
1 | const app = getApp();
2 |
3 | Page({
4 |
5 | /**
6 | * 页面的初始数据
7 | */
8 | data: {
9 | listSelect: 0,
10 | results: [],
11 | tag: ''
12 | },
13 | onLoad: function(e) {
14 |
15 | app.bar({
16 | title: "查找",
17 | bcColor: "#F7F7F7,000"
18 | });
19 |
20 | // 选中 指定的部门
21 | e.tag && this.setData(e);
22 |
23 | // 搜索 指定的医生
24 | e.name && this.search({}, e);
25 |
26 | // 显示 专家列表
27 | e.expertDoc && app.request("", "getExpertDoc", res => {
28 |
29 | // 判断部门标签是否注明 否则写入
30 | let dept = app.globalData.dept;
31 | console.log(res.data)
32 | if (!res.data[0].tag && dept[1]) {
33 | let deptList = {};
34 |
35 | // 写入医生信息
36 | for (let index in res.data) {
37 | let info = res.data[index],
38 | tag = `${info.dept_id}.${info.sub_dept_id}`;
39 |
40 | if (tag in app.globalData.deptList) {
41 | res.data[index].tag = app.globalData.deptList[tag];
42 | } else res.data[index].tag = 'not dept';
43 | }
44 | }
45 | this.setData({
46 | results: res.data
47 | });
48 | }, 3600);
49 | },
50 |
51 | onShow: function() {
52 |
53 | // 整理部门
54 | let all = [],
55 | icon = {
56 | '疼痛科': 'tengtongke',
57 | '其他': "qitake",
58 | "皮肤科": "pifuke",
59 | "内科": "neike",
60 | "口腔科": "kouqiangke",
61 | "骨科": "guke",
62 | "妇产科": "fuchanke",
63 | "耳鼻咽喉科": "erbihouke",
64 | "儿科": "erke",
65 | },
66 | tag = this.data.tag,
67 | i = 0;
68 |
69 | let dept = app.globalData.dept;
70 | // 主部门
71 | for (let id in dept) {
72 | let name = dept[id].name;
73 |
74 | // 外面图标点入时 自动选中部门
75 | (name == tag) && this.setData({
76 | listSelect: i
77 | });
78 |
79 | let value = {
80 | tag: name,
81 | icon: icon[name] || 'wrong',
82 | list: []
83 | };
84 | // 子部门
85 | let subDrpt = dept[id].subDept;
86 | for (let subId in subDrpt) {
87 | value.list.push({
88 | name: subDrpt[subId].name,
89 | id: subDrpt[subId].id
90 | });
91 | }
92 | all.push(value);
93 | i++;
94 | }
95 | this.setData({
96 | all
97 | });
98 | },
99 |
100 | // 大类选择
101 | unSelect: function(e) {
102 | if (e.target.dataset.i !== undefined) {
103 | this.setData({
104 | listSelect: e.target.dataset.i
105 | });
106 | }
107 | },
108 |
109 | // 搜索子部门医生
110 | search: function(e, data = {}) {
111 |
112 | // 兼容非事件
113 | let tar = e.target ? e.target.dataset : {};
114 |
115 | // 不允许全局[无条件]搜索
116 | if (!Object.keys(tar).length && !Object.keys(data).length) return;
117 |
118 | // 搜索请求
119 | app.request({
120 | "doc_name": data.name || tar.name || "",
121 | "depId": data.depId || tar.depid || -1,
122 | "subdepId": data.subdepId || tar.subdepid || -1
123 | }, 'searchDoctor', res => {
124 |
125 | let data = res.data,
126 | dept = app.globalData.dept;
127 |
128 | if (data.error) return this.setData({
129 | toast: {
130 | text: "未找到属于此部门的医生...",
131 | icon: "error"
132 | }
133 | });
134 |
135 | // 写入 子部门ID
136 | let results = data.map(value => {
137 | let sub = dept[value.dept_id].subDept;
138 | for (let subId in sub) {
139 | if (sub[subId].id == value.sub_dept_id) {
140 | value.tag = sub[subId].name;
141 | break;
142 | }
143 | }
144 | return value;
145 | });
146 | this.setData({
147 | results
148 | });
149 | console.log(results)
150 | });
151 | },
152 |
153 | /**
154 | * 【返回】清空搜索结果
155 | */
156 | clearResults: function() {
157 | this.setData({
158 | results: []
159 | });
160 | },
161 |
162 | /**
163 | * 按 医生名字 搜索
164 | */
165 | searchName: function(e) {
166 | let val = e.detail.value;
167 |
168 | // 兼容 键盘按下搜索
169 | (typeof val == 'string') && (val = {
170 | name: val
171 | });
172 | this.search({}, val);
173 | },
174 |
175 | /**
176 | * 打开医生信息页
177 | */
178 | doctorPage: function(e) {
179 | if(!app.isLogin()) return this.setData({
180 | toast: {
181 | text: app.getMessage("not login"),
182 | icon: "error"
183 | }
184 | });
185 | let doctor = e.target.dataset.doctor;
186 | doctor && wx.navigateTo({
187 | url: '../doctor/doctor?' + doctor,
188 | });
189 | },
190 | })
--------------------------------------------------------------------------------
/miniprogram/pages/account/account.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{
9 | userInfo.bind_account.patientname ?
10 | userInfo.bind_account.patientname :
11 | userInfo.bind_account.name ?
12 | userInfo.bind_account.name :
13 | userInfo.nickName ?
14 | userInfo.nickName :
15 | '点击授权'
16 | }}
17 | 医生代码: {{ userInfo.bind_account.ysdm }}
18 |
19 | 病号: {{ userInfo.bind_account.zxyy_id }}
20 | {{
21 | userInfo.bind_account.patientname ? '未上传身份证' : '点击绑定主账号'
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 |
120 | 检查单
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | 药店分组
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | 诊断分组
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | 版本号: {{version}}
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/miniprogram/pages/account/register/register.js:
--------------------------------------------------------------------------------
1 | const app = getApp();
2 | let sendState = null,
3 | colling = 0,
4 | mssion = 0;
5 | Page({
6 | data: {
7 | // 【0: 用户/1:医生】
8 | userType: 0,
9 | // 部门列表
10 | bmArray: [],
11 | // 部门选择器 [已选择]
12 | bmIndex: [-1, 0],
13 | // 部门选择器 [对象]
14 | bmObject: [],
15 | // 验证码冷却时间
16 | sendState: '发送'
17 | },
18 |
19 | onShow: function() {
20 | // 设置标题
21 | app.bar({
22 | title: '注册',
23 | bgColor: '#3285FF'
24 | });
25 |
26 | // 整理部门数据
27 | let dept = app.globalData.dept,
28 | bmArray = [[], []],
29 | bmObject = [];
30 |
31 | if (dept[1]) {
32 | for (let id in dept) {
33 | // 存入主部门ID
34 | dept[id].uid = id;
35 | bmObject.push(dept[id]);
36 | bmArray[0].push(dept[id].name);
37 | }
38 | // 写入第一个部门的子部门
39 | for (let id in dept[1].subDept) {
40 | bmArray[1].push(dept[1].subDept[id].name);
41 | }
42 | this.setData({
43 | bmArray,
44 | bmObject
45 | });
46 | }
47 |
48 | },
49 |
50 | /**
51 | * 选择结束
52 | */
53 | select: function(e) {
54 | this.setData({
55 | [e.target.dataset.key]: e.detail.value
56 | });
57 | this.inputBlur(e);
58 | },
59 |
60 | /**
61 | * 更新选择内容
62 | */
63 | updateSelect: function(e) {
64 | // 滑动子部门 不更新
65 | if (e.detail.column) return;
66 |
67 | let dept = this.data.bmObject[e.detail.value]
68 | if (dept) {
69 | let arr = [];
70 | for (let id in dept.subDept) arr.push(dept.subDept[id].name);
71 | this.setData({
72 | bmArray: [this.data.bmArray[0], arr]
73 | })
74 | }
75 | },
76 |
77 | /**
78 | * 聚焦函数
79 | */
80 | inputFocus: function(t) {
81 | this.setData({
82 | [t.target.dataset.id]: "changed"
83 | });
84 | },
85 |
86 | /**
87 | * 失焦函数
88 | */
89 | inputBlur: function (t) {
90 | this.setData({
91 | [t.target.dataset.id]: t.detail.value.length ? "nick" : ""
92 | });
93 | },
94 |
95 | /**
96 | * 用户提交注册事件
97 | */
98 | register: function(e) {
99 | let error = "";
100 | let val = e.detail.value;
101 |
102 | // 倒序检查!!!
103 |
104 | // 医生注册
105 | if ('ysdm' in val) {
106 | !val.ysbm && (error = "所在部门 不能为空!");
107 | !val.ysdm && (error = "医生代码 不能为空!");
108 | }
109 | // 条件判断
110 | if (!val.csrq || !(/^(\d){4}-(\d){1,2}-(\d){1,2}$/g).test(val.csrq))
111 | error = "出生日期 格式错误: 1999-01-01!"
112 | if (!val.phone || !(/^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}$/g).test(val.phone))
113 | error = "手机号 格式错误!";
114 | if (!val.name || !(/^[\u4E00-\u9FA5\uf900-\ufa2d]{2,4}$/g).test(val.name))
115 | error = "姓名 格式错误!";
116 |
117 | if (error) return this.setData({
118 | toast: {
119 | text: error,
120 | icon: "error"
121 | }
122 | });
123 |
124 | // 都没问题开始注册
125 | let api = 'userRegister';
126 | if ('ysdm' in val) {
127 | let dept = this.data.bmObject[this.data.bmIndex[0]];
128 | val.hospital_id = "";
129 | val.dept_id = dept.uid;
130 | val.sub_dept_id = dept.subDept[this.data.bmIndex[1]].id;
131 | val.ksdm = dept.ksdm;
132 | delete val.ysbm;
133 | api = 'doctorRegister';
134 | }
135 |
136 | app.request(val, api, res => {
137 | console.log(res)
138 | if (res.data.mssion_id) {
139 | this.setData({
140 | showCode: 1
141 | });
142 | mssion = res.data.mssion_id;
143 | } else this.setData({
144 | toast: {
145 | text: res.data.error,
146 | icon: "error"
147 | }
148 | });
149 | }, app.globalData.token);
150 |
151 | console.log(val)
152 | },
153 |
154 | /**
155 | * 发送验证码
156 | */
157 | sendCode: function(e) {
158 | let code = e.detail.value.codes;
159 | if(!code) return this.setData({
160 | toast: {
161 | text: '验证码不能为空!',
162 | icon: "error"
163 | }
164 | });
165 | app.request(`${mssion}/${code}?token=${app.globalData.token}`, "finishBindAndRegMssion", res => {
166 | console.log(res)
167 | if (res.data.status) {
168 | wx.navigateBack({
169 | delta: 3
170 | });
171 | } this.setData({
172 | toast: {
173 | text: res.data.error,
174 | icon: "error"
175 | }
176 | });
177 | });
178 | },
179 |
180 | /**
181 | * 隐藏验证码界面
182 | */
183 | hideCode: function() {
184 | this.setData({
185 | showCode: 0
186 | });
187 | },
188 |
189 | /**
190 | * 选择用户类型事件
191 | */
192 | selectUserType: function(e) {
193 | e.target.dataset.i && this.setData({
194 | userType: e.target.dataset.i
195 | });
196 | },
197 |
198 | /**
199 | * 页面滑动事件
200 | */
201 | pageChange: function(e) {
202 | this.setData({
203 | userType: e.detail.current
204 | });
205 | },
206 | })
--------------------------------------------------------------------------------
/miniprogram/pages/account/account.js:
--------------------------------------------------------------------------------
1 | var app = getApp();
2 | let register = false;
3 |
4 | Page({
5 | data: {
6 |
7 | // 小程序版本
8 | version: "1.0.0",
9 |
10 | // 用户信息
11 | userInfo: {
12 | avatarUrl: "/images/avatar_user_0.png",
13 | bind_account: {
14 | zxyy_id: "------"
15 | },
16 | doctor: false
17 | }
18 | },
19 |
20 | onShow: function() {
21 | if (!Boolean(app.globalData.userInfo + []) ||
22 | !app.globalData.userInfo.bind_account) {
23 | wx.getSetting({
24 | success: setting => {
25 | if (setting.authSetting["scope.userInfo"]) {
26 | wx.getUserInfo({
27 | success: res => {
28 | this.settingAccount(res, true);
29 | }
30 | });
31 | }
32 | }
33 | })
34 | } else {
35 | this.setData({
36 | userInfo: app.globalData.userInfo,
37 | doctor: !!app.globalData.userInfo.bind_account.ysdm
38 | });
39 | }
40 |
41 | },
42 |
43 | onLoad: function(a) {
44 | app.bar({
45 | title: "我的",
46 | bgColor: "#b5cfff"
47 | });
48 |
49 | // 初始化版本
50 | this.setData({
51 | version: app.globalData.version
52 | });
53 |
54 | // 监听数据 同步全局
55 | Object.defineProperty(this.data, "userInfo", {
56 | set: data => {
57 | app.globalData.userInfo = data;
58 | }
59 | });
60 | },
61 |
62 | // 提示版本
63 | printVersion: function() {
64 | this.setData({
65 | toast: {
66 | text: "VERSION " + this.data.version,
67 | icon: "loading",
68 | hideTime: 4e3
69 | }
70 | });
71 | },
72 |
73 | // 设置账号
74 | settingAccount: function (res, load) {
75 | // if (this.__viewData__.userInfo.xcxid) return;
76 |
77 | // 兼容事件处理
78 | res.detail && (res = res.detail);
79 |
80 | // 检测授权
81 | if (res.userInfo) {
82 | this.setData({
83 | userInfo: res.userInfo
84 | });
85 |
86 | // 如果本地已存储数据且没过期则用本地的
87 | // let storage = wx.getStorageSync("userInfo");
88 | // if (storage && storage.bind_account && storage.endTime > Date.now() / 1000) return this.setData({
89 | // userInfo: storage,
90 | // doctor: storage.bind_account ? !!storage.bind_account.ysdm : false
91 | // });
92 |
93 | // 获取openid
94 | wx.cloud.callFunction({
95 | name: "getOpenId",
96 | complete: data => {
97 |
98 | // 拉取主系统数据
99 | let getLoginData = e => {
100 | data.result.openId = 'o-PgA5R0PU-6L-JS_XN0jHGDp-3w';
101 | app.request(data.result.openId, "login", login => {
102 | // 用户是否注册
103 | if (login.data.token) {
104 |
105 | app.globalData.token = login.data.token;
106 | // 获取账号数据
107 | app.request(login.data.token, "accountData", info => {
108 | let user = Object.assign(res.userInfo, login.data, info.data);
109 | // 判断绑定
110 | if (user.bind_account) {
111 | res.userInfo.endTime = user.token.split("-")[2] || Date.now() + 259200;
112 | this.setData({
113 | userInfo: user,
114 | doctor: user.bind_account ? !!user.bind_account.ysdm : false
115 | });
116 | wx.setStorage({
117 | key: "userInfo",
118 | data: user
119 | });
120 |
121 | } else {
122 | !load && wx.navigateTo({
123 | url: "login/login?token=" + login.data.token
124 | });
125 | }
126 | });
127 | } else if (!register) {
128 |
129 | // 注册账号
130 | register = true;
131 | app.request(data.result.openId, "register", getLoginData, false, 20);
132 | }
133 | }, 5);
134 | };
135 |
136 | // 主动执行一次
137 | getLoginData();
138 |
139 | }
140 | });
141 | } else {
142 | this.setData({
143 | toast: {
144 | text: "获取授权失败!请允许授权...",
145 | icon: "error",
146 | hideTime: 2000
147 | }
148 | });
149 | }
150 | },
151 |
152 | /**
153 | * 权限检测
154 | */
155 | navgiate: function(e) {
156 |
157 | let data = e.currentTarget.dataset;
158 | if (data.page) {
159 | if (data.pro) {
160 | let error = false;
161 | console.log(app.globalData.doctor)
162 | if (data.pro == 'put' && !app.globalData.userInfo.nickName) {
163 | error = '请先登录!';
164 | } else if (data.pro == 'doc' && !app.globalData.doctor) {
165 | error = '非医生不能进行此操作!';
166 | } else if (data.pro == 'card' && !app.globalData.userInfo.bind_account.patientname) {
167 | error = '此操作必须在实名后!';
168 | }
169 | if (error) return this.setData({
170 | toast: {
171 | text: error,
172 | icon: 'error'
173 | }
174 | });
175 | }
176 | wx.navigateTo({
177 | url: data.page,
178 | });
179 | }
180 | console.log(e, data)
181 | if (!app.globalData.userInfo.nickName) {}
182 | },
183 |
184 | });
--------------------------------------------------------------------------------
/miniprogram/pages/upload/idCard/idcard.js:
--------------------------------------------------------------------------------
1 | const app = getApp();
2 | let outInter = null,
3 | mssion_id = 0;
4 |
5 | Page({
6 |
7 | data: {
8 | isId: "",
9 | sendState: "发送",
10 | res: {}
11 | },
12 |
13 | onLoad: function(e) {
14 | e && this.setData(e);
15 | },
16 |
17 | onShow: function() {
18 | app.bar({
19 | title: "身份认证",
20 | bgColor: "#b5cfff"
21 | });
22 | },
23 |
24 | /**
25 | * 聚焦函数
26 | */
27 | inputFocus: function(t) {
28 | this.setData({
29 | [t.target.dataset.id]: "changed"
30 | });
31 | },
32 |
33 | /**
34 | * 失焦函数
35 | */
36 | inputBlur: function(t) {
37 | this.setData({
38 | [t.target.dataset.id]: t.detail.value.length ? "nick" : ""
39 | });
40 | },
41 |
42 | /**
43 | * 选择图片
44 | */
45 | camera: function(e) {
46 | let self = this;
47 | wx.chooseImage({
48 | count: 1,
49 | success: function(res) {
50 | self.setData({
51 | isId: res.tempFilePaths[0]
52 | });
53 | }
54 | });
55 | },
56 |
57 | /**
58 | * 身份证上传
59 | */
60 | upload: function() {
61 |
62 | if (!this.data.isId) return this.setData({
63 | toast: {
64 | text: '请拍摄或者选择一张身份证正面照片!',
65 | icon: 'error'
66 | }
67 | });
68 |
69 | // 如果为上传家庭成员身份证
70 | if (this.data.addFamily) return this.addFamily();
71 |
72 | this.uploadFile(res => {
73 | if (res.status) {
74 | app.globalData.userInfo = [];
75 | wx.removeStorageSync('userInfo');
76 | wx.switchTab({
77 | url: '../../account/account'
78 | });
79 | }
80 | });
81 | },
82 |
83 | /**
84 | * 上传家庭成员身份证
85 | */
86 | addFamily: function() {
87 | this.uploadFile(res => {
88 |
89 | this.setData({
90 | code: true,
91 | res
92 | });
93 | });
94 |
95 | },
96 |
97 | /**
98 | * 返回按钮
99 | */
100 | hideCode: function() {
101 | this.setData({
102 | code: false
103 | });
104 | },
105 |
106 | /**
107 | * 发送验证码
108 | */
109 | sendCode: function (e) {
110 | e = e.detail.value;
111 | if (e.codes) {
112 | // 验证 验证码是否正确
113 | app.request(`${mssion_id}/${e.codes}?token=${app.globalData.userInfo.token}`, 'addFamilySendCode', res => {
114 | if (res.data.status) {
115 | wx.navigateBack({
116 | delta: 1
117 | });
118 | } else this.setData({
119 | toast: {
120 | text: "身份证验证失败:" + res.data.error,
121 | icon: "error"
122 | }
123 | });
124 | });
125 | } else if (e.phone) {
126 | let res = this.data.res;
127 | app.request(`${res.mssion_id}/${res.code}/${e.phone}?token=${app.globalData.userInfo.token}`, 'addFamilyGetCode', res => {
128 |
129 | // 冷却
130 | if (!isNaN(res)) return this.countDown((res / 1000).toFixed(0));
131 |
132 | // 如果存在mssion_id
133 | if (res.data.mssion_id) {
134 |
135 | mssion_id = res.data.mssion_id;
136 | this.setData({
137 | toast: {
138 | text: "验证码已发送!请输入...",
139 | icon: "success",
140 | hideTime: 3000
141 | }
142 | });
143 | // 冷却倒计时
144 | this.countDown(60);
145 | } else this.setData({
146 | toast: {
147 | text: "验证码发送失败:" + res.data.error,
148 | icon: "error"
149 | }
150 | });
151 | }, false, 60);
152 | }
153 | },
154 |
155 | /**
156 | * 身份证错误信息翻译
157 | */
158 | idCardError: function(error) {
159 | let err = error;
160 | switch (error) {
161 | case "not a patient account":
162 | err = "不是病人的账号!";
163 | break;
164 | case "Unbound main system account":
165 | err = "未绑定的主系统账号!";
166 | break;
167 | case "no image file upload":
168 | err = "图片上传程序错误!";
169 | break;
170 | case "recognize error":
171 | err = "图片无法识别,请按要求拍摄!";
172 | break;
173 | case "Image type error":
174 | err = "图片类型错误,无法识别为身份证!";
175 | break;
176 | case "please upload face side":
177 | err = "请上传身份证正面的照片!";
178 | break;
179 | case "card number is empty":
180 | err = "卡号为空!";
181 | break;
182 | }
183 | return err;
184 | },
185 |
186 | uploadFile: function(callback) {
187 |
188 | let self = this,
189 | url = !this.data.addFamily ?
190 | app.globalData.ip + "api/SetIDCard?token=" + app.globalData.userInfo.token :
191 | app.globalData.ip + "api/addFamilyUserStep1?token=" + app.globalData.userInfo.token;
192 |
193 | wx.uploadFile({
194 | url,
195 | filePath: this.data.isId,
196 | name: "idcard",
197 | success: function(res) {
198 |
199 | let data = JSON.parse(res.data);
200 | if (data.error) {
201 | let err = self.idCardError(data.error);
202 | return self.setData({
203 | toast: {
204 | text: err,
205 | icon: 'error',
206 | hideTime: 4000
207 | }
208 | });
209 | } else callback(data);
210 | },
211 | fail: console.error
212 | });
213 | },
214 |
215 | /**
216 | * 倒计时
217 | */
218 | countDown: function (outTime) {
219 | outInter = setInterval(() => {
220 | if (!outTime) {
221 | clearInterval(outInter);
222 | outTime = "发送";
223 | }
224 | this.setData({
225 | sendState: outTime
226 | });
227 | outTime--;
228 | }, 1000);
229 | }
230 | })
--------------------------------------------------------------------------------
/miniprogram/pages/account/register/register.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 用户
7 |
8 |
9 |
10 |
11 |
12 |
45 |
46 |
57 |
58 |
59 |
60 |
61 |
62 |
134 |
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/miniprogram/pages/account/answer/answer.wxss:
--------------------------------------------------------------------------------
1 | page {
2 | max-height: 100vh;
3 | overflow: hidden;
4 | }
5 | .row-box {
6 | width: 100vw;
7 | height: 100rpx;
8 | padding: 20rpx 0;
9 | }
10 | .row-box .user-icon {
11 | float: left;
12 | margin: 0 20rpx;
13 | }
14 | .doc-name {
15 | font-size: 1.2rem;
16 | color: #333;
17 | }
18 | .doc-type {
19 | margin-left: 20rpx;
20 | font-size: .8rem;
21 | color: #ccc;
22 | }
23 | .doc-department {
24 | display: block;
25 | width: clac(100% - 150rpx);
26 | font-size: .9rem;
27 | color: #777;
28 | }
29 |
30 |
31 | .msg-box {
32 | height: calc(100vh - 225rpx);
33 | transition: .5s;
34 | }
35 | .msg-show {
36 | height: calc(100vh - 300rpx);
37 | }
38 | .put-info {
39 | width: 90vw;
40 | margin: 30rpx auto;
41 | padding: 20rpx;
42 | color: #555;
43 | background-color: #eee;
44 | border: 10rpx dashed #ddd;
45 | border-radius: 20rpx;
46 | box-sizing: border-box;
47 | }
48 | .descript {
49 | display: block;
50 | text-indent: 2rem;
51 | color: #888;
52 | }
53 | .put-box,
54 | .doc-box {
55 | width: 100vw;
56 | margin: 10rpx 0;
57 | display: flex;
58 | flex-direction: row;
59 | flex-wrap: wrap;
60 | align-items: center;
61 | justify-content: flex-end;
62 | }
63 | .doc-box {
64 | flex-direction: row-reverse;
65 | }
66 | /* 医生 */
67 | .doctor .doc-box {
68 | flex-direction: inherit;
69 | }
70 | .doctor .doc-box .doc {
71 | margin-right: 30rpx;
72 | }
73 | .doctor .put-box {
74 | flex-direction: row-reverse;
75 | }
76 | .doctor .put-box .put {
77 | margin-left: 30rpx;
78 | }
79 | .doctor .doc-box .doc::after {
80 | right: -27rpx;
81 | left: auto;
82 | border-color: transparent transparent transparent #53DB95;
83 | }
84 | .doctor .put-box .put::after {
85 | right: auto;
86 | left: -27rpx;
87 | border-color: transparent #29CCC1 transparent transparent;
88 | }
89 | /* 公用对话 */
90 | .msg-box .put,
91 | .doc-box .doc {
92 | float: left;
93 | position: relative;
94 | max-width: 60vw;
95 | padding: 20rpx;
96 | margin-right: 30rpx;
97 | color: #fff;
98 | line-height: 1.75;
99 | word-wrap: break-word;
100 | background-image: linear-gradient(90deg, #29CCC1, #53DB95);
101 | border-radius: 20rpx;
102 | }
103 | .nick .put,
104 | .nick .doc {
105 | transform-origin: right;
106 | animation: 1s .5s msg;
107 | animation-fill-mode: forwards;
108 | transform: rotateY(90deg);
109 | }
110 | @keyframes msg {
111 | to {
112 | transform: rotateY(0deg);
113 | }
114 | }
115 | .msg-box .put::after,
116 | .doc-box .doc::after {
117 | content: "";
118 | position: absolute;
119 | right: -27rpx;
120 | top: 0;
121 | bottom: 0;
122 | height: 0;
123 | margin: auto;
124 | border-style: solid;
125 | border-width: 15rpx;
126 | border-color: transparent transparent transparent #53DB95;
127 | transform: translateY(50%);
128 | }
129 | .put text,
130 | .doc text {
131 | font-size: .7rem;
132 | color: #888;
133 | }
134 |
135 | .doc-box .doc {
136 | margin-right: 0;
137 | margin-left: 30rpx;
138 | }
139 | .doc-box .doc::after {
140 | right: auto;
141 | left: -27rpx;
142 | border-color: transparent #29CCC1 transparent transparent;
143 | }
144 | .msg-box image {
145 | float: right;
146 | width: 100rpx;
147 | height: 100rpx;
148 | margin: 10rpx;
149 | border: 1rpx dashed #ccc;
150 | border-radius: 10rpx;
151 | }
152 | .nick image {
153 | animation: .5s icon;
154 | }
155 | @keyframes icon {
156 | from {
157 | transform: translateY(50%);
158 | opacity: 0;
159 | }
160 | to {
161 | transform: translateY(0);
162 | }
163 | }
164 | .fix {
165 | height: 100rpx;
166 | }
167 |
168 |
169 | .input-box {
170 | width: 100%;
171 | /* background-color: #eee; */
172 | border-top: 1px solid #ddd;
173 | }
174 | .input-box .icon-fangxiangshang {
175 | float: left;
176 | width: calc(10% - 2rpx);
177 | height: 10%;
178 | margin: 15rpx 0;
179 | text-align: center;
180 | color: #999;
181 | background-color: #ddd;
182 | border: 1px solid #ccc;
183 | border-radius: 100px;
184 | transition: .5s;
185 | }
186 | .deg {
187 | transform: rotate(180deg)
188 | }
189 | .input-box input {
190 | float: left;
191 | width: 60%;
192 | height: 60rpx;
193 | padding: 0 .5rem;
194 | margin: 15rpx 10rpx;
195 | font-size: 1rem;
196 | color: #444;
197 | border: 1px solid #ddd;
198 | background-color: #fff;
199 | border-radius: 100px;
200 | box-sizing: border-box;
201 | }
202 | .input-box button {
203 | float: left;
204 | width: calc(30% - 40rpx);
205 | height: 60rpx;
206 | margin: 15rpx 10rpx;
207 | line-height: initial;
208 | white-space: nowrap;
209 | color: #666;
210 | background-color: #ddd;
211 | border-radius: 100px;
212 | border: 1px solid #ccc;
213 | outline: 0;
214 | }
215 | .tool-box {
216 | max-height: 0;
217 | width: 100vw;
218 | transition: 1s;
219 | }
220 | .show {
221 | max-height: 10vh;
222 | }
223 | .tool {
224 | min-height: 2.5rem;
225 | white-space: nowrap;
226 | }
227 | .tool icon,
228 | .tool text {
229 | padding: 0 20rpx;
230 | margin: 0 10rpx;
231 | vertical-align: middle;
232 | color: #666;
233 | background-color: #ddd;
234 | border-radius: 100px;
235 | border: 1px solid #ccc;
236 | }
237 |
238 | .loading {
239 | display: flex;
240 | flex-direction: row;
241 | justify-content: center;
242 | align-items: center;
243 | font-size: .8rem;
244 | color: #ccc;
245 | }
246 | .loading icon {
247 | margin: -10rpx 10rpx 0;
248 | font-size: 1rem;
249 | vertical-align: middle;
250 | }
251 | .date {
252 | display: block;
253 | font-size: .8rem;
254 | text-align: center;
255 | color: #ccc;
256 | }
257 | .old {
258 | display: block;
259 | padding: 10rpx 0 30rpx;
260 | text-align: center;
261 | color: #999;
262 | font-size: .8rem;
263 | }
264 | .old::after,
265 | .old::before {
266 | content: '';
267 | display: inline-block;
268 | margin: 0 5vw .3rem;
269 | width: calc(40vw - 2.8rem);
270 | height: 2rpx;
271 | background-color: currentColor;
272 | }
--------------------------------------------------------------------------------
/miniprogram/pages/account/answer/answer.js:
--------------------------------------------------------------------------------
1 | const app = getApp();
2 | const timeC = 60 * 1000;
3 | let msgBox = {},
4 | token = false,
5 | last = 0,
6 | scroll = null;
7 |
8 | let unRead = null;
9 |
10 | Page({
11 |
12 | data: {
13 | msg: [],
14 | end: 0,
15 | inputValue: '',
16 | scrollTop: 0,
17 | loading: true
18 | },
19 |
20 | onLoad: function(option) {
21 |
22 | option.id = 659;
23 | this.setData({
24 | user: app.globalData.userInfo,
25 | id: option.id,
26 | doctor: app.globalData.doctor
27 | });
28 | app.bar({
29 | title: "咨询医生",
30 | bgColor: "#B5CFFF"
31 | });
32 | token = app.globalData.userInfo.token;
33 | let value = `${option.id}?token=${token}`;
34 |
35 | // 未读读内容获取[权重 高]
36 | app.request(value, "getUnreadQA", res => {
37 |
38 | setTimeout(() => {
39 | this.setData({
40 | loading: false
41 | });
42 | }, 5000);
43 |
44 | if (!res.data.length) return;
45 |
46 | // 计算时差
47 | let list = this.unDate(res.data);
48 |
49 | // 如果 未读先得到则合并 但是 已读一定得在未读后面
50 | if (this.data.msg.length) {
51 | this.data.msg.push(...res.data);
52 | list = this.data.msg;
53 | }
54 |
55 | this.setData({
56 | msg: list,
57 | end: list.length - 1,
58 | loading: false
59 | });
60 |
61 | });
62 | // 咨询消息读取[权重 中]
63 | app.request(value, "getAskDoctorDetail", res => {
64 | if (res.data) {
65 | this.setData({
66 | detail: res.data
67 | });
68 | } else this.setData({
69 | toast: {
70 | text: "咨询数据读取错误,不存在或无权限!",
71 | icon: "error"
72 | }
73 | });
74 | });
75 |
76 |
77 | // 已读内容获取[权重 低]
78 | app.request(value, "getHistoryQA", res => {
79 | if (!res.data.length) return;
80 |
81 | // 计算时差
82 | let list = this.unDate(res.data);
83 |
84 | // 未读位置
85 | last = list.length;
86 |
87 | // 最后一条消息后面显示历史消息
88 | // (list.length > 0) && (list[list.length - 1].old = true);
89 | let listLast = list.length;
90 | // 如果 未读先得到则合并 但是 已读一定得在未读后面
91 | this.data.msg.length && list.push(...this.data.msg);
92 |
93 | if (listLast) {
94 | if (!this.data.doctor) {
95 | // 最后一条消息后面显示历史消息 但如果已读的前几条为病人的消息 则往下直到医生
96 | while (list[listLast] && list[listLast].is_question) {
97 | listLast++;
98 | }
99 | } else {
100 | // 与上条相反 直到病人
101 | while (list[listLast] && !list[listLast].is_question) {
102 | listLast++;
103 | }
104 | }
105 | list[listLast - 1].old = true
106 | }
107 |
108 | this.setData({
109 | msg: list,
110 | end: list.length - 1,
111 | loading: false
112 | });
113 |
114 | this.update();
115 | // 滑动到历史位置[测试]
116 | let query = wx.createSelectorQuery();
117 | query.select('.old').boundingClientRect();
118 | query.exec(res => {
119 | (res[0].top && msgBox.box) && this.setData({
120 | scrollTop: res[0].top + msgBox.box.height + 'rpx'
121 | });
122 | });
123 |
124 | });
125 |
126 | unRead = setInterval(() => {
127 |
128 | app.request(value, "getUnreadQA", res => {
129 |
130 | if (!this.data.msg.length && !res.data.length) return;
131 |
132 | // 计算时差
133 | let list = this.unDate(res.data);
134 | // 过滤出自己的消息
135 | for (let i = 0, l = res.data.length - 1; i < l; i++) {
136 | if (this.data.doctor) {
137 | if (!res.data[i].is_question) res.data.splice(i, 1)
138 | } else {
139 | if (res.data[i].is_question) res.data.splice(i, 1)
140 | }
141 | }
142 | if (res.data.length) {
143 | this.data.msg.push(...res.data);
144 | this.setData({
145 | msg: this.data.msg
146 | });
147 | let oldLast = last;
148 | // 根据 得到消息进行判断
149 | for (let i = last, l = this.data.msg.length; i < l; i ++) {
150 | if (!this.data.doctor && !this.data.msg[i].is_question) last = i;
151 | if (this.data.doctor && this.data.msg[i].is_question) last = i;
152 | }
153 | if (oldLast < last) {
154 | app.request(`${this.data.id}/${res.data[res.data.length - 1].id}?token=${token}`, "qaMarkAsRead");
155 | }
156 |
157 | this.update();
158 | // 滑动到历史位置[测试]
159 | let query = wx.createSelectorQuery();
160 | query.select('.msg-box').boundingClientRect();
161 | query.exec(res => {
162 | (res[0].top && msgBox.box) && this.setData({
163 | scrollTop: (last * 150) + 'rpx'
164 | });
165 | });
166 | }
167 |
168 | });
169 | }, 5000)
170 | },
171 |
172 |
173 | onUnload: function () {
174 | clearInterval(unRead);
175 | },
176 |
177 | /**
178 | * 视图大小更新
179 | */
180 | update: function() {
181 | let query = wx.createSelectorQuery();
182 | // 得到聊天视图大小
183 | query.select('.msg-box').boundingClientRect();
184 | query.exec(res => {
185 | msgBox.box = res[0];
186 | let child = wx.createSelectorQuery();
187 | child.selectAll('.in-box').boundingClientRect();
188 | child.selectViewport()
189 |
190 | child.exec(res => {
191 | msgBox.child = res[0];
192 | });
193 | });
194 | },
195 |
196 | onShow: function() {
197 |
198 | },
199 |
200 | /**
201 | * 发送咨询消息
202 | */
203 | sendInput: function(e) {
204 | let con = e.detail.value.content || e.detail.value;
205 | if (con && typeof con == 'string') {
206 | let msg = this.data.msg;
207 | // 时差计算
208 | let time = app.getDate("yyyy-MM-dd HH:mm:ss");
209 | let index = msg.push({
210 | l_content: con,
211 | is_question: this.data.doctor ? 0 : 1,
212 | create_time: time,
213 | addDate: msg[msg.length - 1] ? (new Date(time) - new Date(msg[msg.length - 1].create_time) > timeC) ? time : false : time
214 | });
215 |
216 | // 写入数据 并 滚动至底部
217 | this.setData({
218 | msg,
219 | inputValue: '',
220 | scrollTop: msg.length * 100 + 'px'
221 | });
222 |
223 | // 向服务器发送消息
224 | app.request({
225 | ask_id: this.data.id,
226 | content: con
227 | }, this.data.doctor ? "docAddAnswer" : "patAddAnswer", res => {
228 | if (!res.data.status) {
229 | this.data.msg[index - 1].error = ' [发送失败]';
230 | this.setData({
231 | msg: this.data.msg
232 | });
233 | }
234 | }, token);
235 | }
236 | },
237 |
238 | /**
239 | * 切换工具栏
240 | */
241 | toggleTool: function() {
242 | this.setData({
243 | tool: !!!this.data.tool
244 | });
245 | },
246 |
247 | /**
248 | * 直接发送内容
249 | */
250 | addContent: function(e) {
251 | if (e._relatedInfo) {
252 | this.sendInput({
253 | detail: {
254 | value: e._relatedInfo.anchorTargetText
255 | }
256 | });
257 | }
258 | },
259 |
260 | /**
261 | * 滚动时节流算法触发 [已读算法]
262 | */
263 | lower: function(e) {
264 | // 节流
265 | clearTimeout(scroll);
266 | scroll = setTimeout(() => {
267 | this.update();
268 | let height = msgBox.box ? msgBox.box.height : 0;
269 | // 计算可视角大小
270 | let top = e.detail.scrollTop + height,
271 | newVl = last;
272 |
273 | // 从最后一条开始往下遍历 防止多余的遍历
274 | for (let i = last, l = msgBox.child.length; i < l; i++) {
275 | (msgBox.child[i].top <= top &&
276 | (
277 | // 标记医生消息
278 | (!this.data.doctor && !this.data.msg[i].is_question) ||
279 | // 标记用户消息
280 | (this.data.doctor && this.data.msg[i].is_question)
281 | )
282 | ) && (last = i);
283 | }
284 |
285 | // 得到屏幕最后一条可见消息 标记已读
286 | if (newVl < last) {
287 | app.request(`${this.data.id}/${this.data.msg[last].id}?token=${token}`,"qaMarkAsRead");
288 | }
289 | }, 1000);
290 | },
291 |
292 | /**
293 | * 时差计算
294 | */
295 | unDate: function(date) {
296 | // 计算时间差
297 | return date.map((val, ind, arr) => {
298 | let date = new Date(val.create_time),
299 | date2 = arr[ind - 1] ? new Date(arr[ind - 1].create_time) : 0;
300 |
301 | val.addDate = date2 - date < -timeC ? val.create_time : false;
302 | return val;
303 | });
304 | },
305 | })
--------------------------------------------------------------------------------
/miniprogram/app.wxss:
--------------------------------------------------------------------------------
1 | page {
2 | --shadow-color: rgba(0, 0, 0, .15);
3 | --main-icon-color: #4684f7;
4 | --main-font-color: #11cd6e;
5 | --main-fontSelect-color: #a9b7b7;
6 | background-color: #f7f7f7;
7 | }
8 |
9 |
10 | /* 背景 */
11 | .background {
12 | position: absolute;
13 | top: 0;
14 | left: 0;
15 | width: 750rpx;
16 | z-index: -1;
17 | }
18 |
19 | .backgroundColor {
20 | position: absolute;
21 | z-index: -1;
22 | top: 0;
23 | left: 0;
24 | width: 100vw;
25 | height: 120rpx;
26 | background-color: #b5cfff;
27 | }
28 |
29 |
30 | /* LOGO */
31 | .logo {
32 | display: block;
33 | width: 180rpx;
34 | height: 180rpx;
35 | margin: 50rpx auto;
36 | border-radius: 90rpx;
37 | box-shadow: 0 0 100rpx #1831c2;
38 | border: 5rpx solid rgba(255, 255, 255, 0.3);
39 | }
40 |
41 | /* 修复浮动 */
42 | .clearfix::after {
43 | content: '';
44 | display: block;
45 | width: 100%;
46 | height: 100%;
47 | clear: both;
48 | }
49 |
50 |
51 | /* 主盒子 */
52 | .row-box {
53 | width: 94vw;
54 | min-height: 30rpx;
55 | margin: 0 auto;
56 | background-color: white;
57 | border-radius: 10rpx;
58 | box-shadow: 0 2px 5px var(--shadow-color);
59 | }
60 |
61 |
62 | /* 四列列表 */
63 | .four-list {
64 | margin-top: 25rpx;
65 | padding: 0;
66 | font-size: 30rpx;
67 | }
68 | .four-list-tag {
69 | display: flex;
70 | justify-content: space-between;
71 | align-items: center;
72 | width: 95%;
73 | margin: 0 2.5%;
74 | padding: 20rpx 10rpx;
75 | text-align: left;
76 | color: #888;
77 | font-weight: bold;
78 | border-bottom: 1px solid #eee;
79 | }
80 |
81 | .four-list .four-list-tag > view > text:active,
82 | .four-list .four-list-tag > view > text:active + icon {
83 | color: #666;
84 | }
85 |
86 | .four-list-all .icon-fangxiangyou {
87 | font-size: 15px;
88 | margin: -17rpx 0 0 10rpx;
89 | }
90 |
91 | .four-list-all {
92 | color: #ccc;
93 | font-weight: normal;
94 | text-shadow: none;
95 | font-size: 15px;
96 | }
97 |
98 | .four-list-icon > view {
99 | float: left;
100 | width: 25%;
101 | padding: 15rpx 10rpx;
102 | box-sizing: border-box;
103 | text-align: center;
104 | color: #777;
105 | }
106 |
107 | .four-list-icon icon:nth-child(1),
108 | .four-list-icon image,
109 | .user-icon {
110 | display: block;
111 | width: 50rpx;
112 | height: 50rpx;
113 | margin: 0 auto 10rpx;
114 | padding: 20rpx;
115 | color: rgba(255, 255, 255, .8);
116 | font-size: 50rpx;
117 | text-align: center;
118 | background-color: #149be7;
119 | border-radius: 50rpx;
120 | box-shadow: 0 2px 3px var(--shadow-color);
121 | text-shadow: 1px 1px 2px rgba(0, 0, 0, .3);
122 | transition: .1s;
123 | }
124 |
125 | .four-list > view icon:nth-child(1):active {
126 | text-shadow: .5px .5px 1px rgba(0, 0, 0, .6);
127 | box-shadow: 0 3px 10px rgba(0, 0, 0, .3)
128 | }
129 |
130 | .four-list > view image,
131 | .user-icon {
132 | padding: 0;
133 | width: 90rpx;
134 | height: 90rpx;
135 | background-color: #fff;
136 | border: 1px solid #eee;
137 | }
138 |
139 |
140 | /* 图标颜色 */
141 | .four-list-icon .color1 { background-image: linear-gradient(135deg, #FFA7E7, #EA6362) }
142 | .four-list-icon .color2 { background-image: linear-gradient(135deg, #17EAD9, #6078EA) }
143 | .four-list-icon .color3 { background-image: linear-gradient(135deg, #45E994, #23BCBB) }
144 | .four-list-icon .color4 { background-image: linear-gradient(135deg, #FFDEA7, #EA6362) }
145 | .four-list-icon .color5 { background-image: linear-gradient(135deg, #fa71cd, #c471f5) }
146 | .four-list-icon .color6 { background-image: linear-gradient(135deg, #7C4DFF, #7B1FA2) }
147 | .four-list-icon .color7 { background-image: linear-gradient(135deg, #00c6fb, #005bea) }
148 | .four-list-icon .color8 { background-image: linear-gradient(135deg, #F57C00, #CF360C) }
149 |
150 | /* 搜索栏 */
151 | .search-box {
152 | position: absolute;
153 | top: 270rpx;
154 | width: 90vw;
155 | margin: 0 5vw;
156 | padding: 0;
157 | background-color: white;
158 | transition: .25s;
159 | }
160 | .search-box input {
161 | height: 70rpx;
162 | padding: 0 40px 0 .5em;
163 | color: #555;
164 | }
165 | .search-box .icon-sousuo {
166 | position: absolute;
167 | top: 0;
168 | right: 0;
169 | padding: 0 25rpx;
170 | line-height: 70rpx;
171 | font-size: 40rpx;
172 | color: #888;
173 | }
174 | .search-placeholder {
175 | color: #ddd;
176 | }
177 |
178 |
179 | /* 横轴列表 */
180 | .row-list {
181 | margin-top: 20px;
182 | padding: 5rpx 0;
183 | color: #777;
184 | font-size: 30rpx;
185 | }
186 | .row-list > view {
187 | margin: 0 10rpx;
188 | padding: 10rpx;
189 | border-bottom: 1px solid #eee;
190 | }
191 | .row-list > view icon {
192 | margin-right: 10rpx;
193 | color: var(--main-icon-color);
194 | vertical-align: middle;
195 | }
196 | .row-list > view text {
197 | vertical-align: middle;
198 | }
199 | .row-list > view:last-child {
200 | border-bottom: none;
201 | }
202 | .row-list .icon-fangxiangyou {
203 | float: right;
204 | color: #ccc;
205 | font-size: 30rpx;
206 | }
207 | .navigator-hover {
208 | background: transparent;
209 | }
210 |
211 |
212 | /* 字体图标 */
213 | @font-face {
214 | font-family: 'iconfont'; /* project id 906741 */
215 | src: url('//at.alicdn.com/t/font_906741_fjs57q4lyma.eot');
216 | src: url('//at.alicdn.com/t/font_906741_fjs57q4lyma.eot?#iefix') format('embedded-opentype'),
217 | url('//at.alicdn.com/t/font_906741_fjs57q4lyma.woff') format('woff'),
218 | url('//at.alicdn.com/t/font_906741_fjs57q4lyma.ttf') format('truetype'),
219 | url('//at.alicdn.com/t/font_906741_fjs57q4lyma.svg#iconfont') format('svg');
220 | }
221 | .iconfont {
222 | font-family: "iconfont" !important;
223 | font-size: 50rpx;
224 | font-style: normal;
225 | color: currentColor;
226 | vertical-align: middle;
227 | -webkit-font-smoothing: antialiased;
228 | -moz-osx-font-smoothing: grayscale;
229 | }
230 |
231 | .icon-tupianpx-:before { content: "\e644"; }
232 | .icon-nvyisheng-mian:before { content: "\e7da"; }
233 | .icon-nanyisheng-mian:before { content: "\e7db"; }
234 | .icon-tianjia:before { content: "\e60a"; }
235 | .icon-shenfenzhengzheng:before { content: "\e60f"; }
236 | .icon-shenfenzhengfan:before { content: "\e611"; }
237 | .icon-shangchuan:before { content: "\e6b7"; }
238 | .icon-qiyejianchadan:before { content: "\e8d6"; }
239 | .icon-chufang:before { content: "\e651"; }
240 | .icon-bumen:before { content: "\e7d4"; }
241 | .icon-code:before { content: "\e616"; }
242 | .icon-qianbao:before { content: "\e637"; }
243 | .icon-yaodian:before { content: "\e668"; }
244 | .icon-aixin-copy:before { content: "\e60e"; }
245 | .icon-neike:before { content: "\e677"; }
246 | .icon-fuchanke:before { content: "\e61e"; }
247 | .icon-fangxiangxia:before { content: "\e684"; }
248 | .icon-fangxiangshang:before { content: "\e685"; }
249 | .icon-idcard:before { content: "\e6f1"; }
250 | .icon-pifuke:before { content: "\e6bb"; }
251 | .icon-guanjiaowangtubiao59:before { content: "\e64d"; }
252 | .icon-trun:before { content: "\e605"; }
253 | .icon-kouqiangke:before { content: "\e659"; }
254 | .icon-qitake:before { content: "\e8b0"; }
255 | .icon-chengyuan:before { content: "\e65c"; }
256 | .icon-xiaoxi:before { content: "\e600"; }
257 | .icon-tuina:before { content: "\e749"; }
258 | .icon-yinhangqia:before { content: "\e64b"; }
259 | .icon-xingbie:before { content: "\e650"; }
260 | .icon-shouji:before { content: "\e634"; }
261 | .icon-guke:before { content: "\e628"; }
262 | .icon-anquan:before { content: "\e610"; }
263 | .icon-chusheng:before { content: "\e624"; }
264 | .icon-chenggong:before { content: "\e609"; }
265 | .icon-wrong:before { content: "\e615"; }
266 | .icon-tengtongke:before { content: "\e635"; }
267 | .icon-jinggao:before { content: "\e604"; }
268 | .icon-erbihouke:before { content: "\e990"; }
269 | .icon-xiugai:before { content: "\e84d"; }
270 | .icon-fangxiang-zuo:before { content: "\e6a6"; }
271 | .icon-yanzhengma:before { content: "\e8a0"; }
272 | .icon-erke:before { content: "\e636"; }
273 | .icon-fangxiang:before { content: "\e606"; }
274 | .icon-zongjie:before { content: "\e603"; }
275 | .icon-zhuanjia:before { content: "\e6a5"; }
276 | .icon-fangxiangyou:before { content: "\e608"; }
277 | .icon-zhiwen:before { content: "\e60b"; }
278 | .icon-jianyan:before { content: "\e814"; }
279 | .icon-loading:before { content: "\e6dc"; }
280 | .icon-duanxin:before { content: "\e63f"; }
281 | .icon-suo:before { content: "\e6a9"; }
282 | .icon-banben:before { content: "\e607"; }
283 | .icon-Bchaoyuyue-K:before { content: "\e7b8"; }
284 | .icon-add:before { content: "\e60c"; }
285 | .icon-yichu:before { content: "\e623"; }
286 | .icon-Micon-zixun:before { content: "\e7e2"; }
287 | .icon-location:before { content: "\e601"; }
288 | .icon-wode:before { content: "\e72a"; }
289 | .icon-sousuo:before { content: "\e602"; }
--------------------------------------------------------------------------------
/miniprogram/app.js:
--------------------------------------------------------------------------------
1 | let loading = null;
2 | App({
3 | /**
4 | * 公共数据
5 | */
6 | globalData: {
7 | version: "0.8.0 [Alpha]",
8 | title: "康达互联网医院",
9 |
10 | // 域名
11 | ip: "http://127.0.0.1/",
12 | // 全部部门列表
13 | dept: [],
14 |
15 | // 接口
16 | url: {
17 | // 小程序登录
18 | login: "login/",
19 | // 小程序注册
20 | register: "register/",
21 |
22 | // 获取用户信息
23 | accountData: "getUserDetail/?token=",
24 | // 绑定到主系统[第一步]
25 | existAccount: "bindExistAccount/",
26 | // 绑定到主系统[第二步]
27 | finishBind: "finishBind/",
28 |
29 | // 搜索医生
30 | searchDoctor: "searchDoctor",
31 | // 获取所有部门列表
32 | getAllDept: "getAllDept",
33 | // 获取 专家列表
34 | getExpertDoc: "getExpertDoc",
35 |
36 | // 医生注册
37 | doctorRegister: "bindAndRegMainSysAccountDoc/?token=",
38 | // 用户注册
39 | userRegister: "bindAndRegMainSysAccountPat/?token=",
40 | // 注册 [验证 验证码]
41 | finishBindAndRegMssion: "finishBindAndRegMssion/",
42 |
43 | // 获取 家庭成员列表
44 | getFamilyList: "getFamilyList?",
45 | // 添加 家庭成员[发送验证码]
46 | addFamilyGetCode: "addFamilyUserStep2/",
47 | // 添加 家庭成员[验证码验证]
48 | addFamilySendCode: "addFamilyUserStep3/",
49 | // 删除 家庭成员
50 | deleteFamilyUser: "deleteFamilyUser/",
51 |
52 | // 添加医生咨询
53 | addDoctorAsk: "addDoctorAsk?token=",
54 | // 医生发送聊天:回复
55 | docAddAnswer: "docAddAnswer?token=",
56 | // 病人发送聊天:咨询
57 | patAddAnswer: "patAddAnswer?token=",
58 | // 获取咨询信息
59 | getAskDoctorDetail: "getAskDoctorDetail/",
60 | // 获取未读的聊天信息
61 | getUnreadQA: "getUnreadQA/",
62 | // 设置 标记聊天消息已读
63 | qaMarkAsRead: "QAMarkAsRead/",
64 | // 获取 历史聊天记录
65 | getHistoryQA: "getHistoryQA/",
66 | // 获取 [病人]活跃的咨询列表
67 | getDocAskListByPatAlive: "getDocAskListByPatAlive?token=",
68 | // 获取 [病人]活跃的咨询列表
69 | getDocAskListByPatClose: "getDocAskListByPatClose?token=",
70 | // 获取 [医生]活跃的咨询列表
71 | getDocAskListByDocAlive: "getDocAskListByDocAlive?token=",
72 | // 获取 [医生]关闭的咨询列表
73 | getDocAskListByDocClose: "getDocAskListByDocClose?token=",
74 | },
75 | userInfo: {},
76 | doctor: false
77 | },
78 |
79 |
80 |
81 | onLaunch: function() {
82 | wx.cloud.init();
83 |
84 | let storage = wx.getStorageSync("userInfo");
85 | if (storage && storage.bind_account && storage.endTime > Date.now() / 1000) {
86 | this.globalData.userInfo = storage;
87 | this.globalData.doctor = this.isDoctor();
88 | }
89 |
90 | /////////////////
91 |
92 | // 初始化本地缓存
93 | !wx.getStorageSync('colling') && wx.setStorage({
94 | key: 'colling',
95 | data: {},
96 | });
97 |
98 |
99 | // 获取全部部门列表 [读取本地,超过一小时则重新获取]
100 |
101 | this.request("", "getAllDept", res => {
102 |
103 | let deptList = [];
104 | // 主部门
105 | for (let id in res.data) {
106 | // 子部门
107 | let subDrpt = res.data[id].subDept;
108 | for (let subId of subDrpt) {
109 | // 格式 主部门ID.子部门ID = 子部门名字
110 | deptList[`${id}.${subId.id}`] = subId.name;
111 | }
112 | }
113 |
114 | this.globalData.dept = res.data;
115 | this.globalData.deptList = deptList;
116 | }, 3600);
117 | },
118 |
119 |
120 |
121 | /**
122 | * 判断是否登录
123 | */
124 | isLogin: function() {
125 | return this.globalData.userInfo.bind_account ? this.globalData.userInfo : false;
126 | },
127 |
128 |
129 |
130 | /**
131 | * 判断是否上传身份证
132 | */
133 | isCard: function() {
134 | return this.isLogin() ? this.globalData.userInfo.bind_account.patientname : false;
135 | },
136 |
137 |
138 |
139 | /**
140 | * 判断是否为医生
141 | */
142 | isDoctor: function() {
143 | return this.isLogin() ? !!this.globalData.userInfo.bind_account.ysdm : false;
144 | },
145 |
146 |
147 | /**
148 | * 获取公共信息
149 | */
150 | getMessage: function(tag) {
151 |
152 | let msg = {
153 | 'not login': '请先登录!'
154 | }
155 |
156 | if (tag in msg) return msg[tag];
157 |
158 | return 'error msg!';
159 | },
160 |
161 |
162 |
163 | /**
164 | * 请求函数封装:
165 | * @param {string} data get请求
166 | * {object} data post 请求
167 | * @param {string} api 调用设定好的url接口,如果不存在则会被当成url
168 | * @param {function} callback 当得到请求内容时的回调
169 | * @param {string} note 当为post请求时,url需要额外添加的参数
170 | * {number} note 缓存过期时间/下次在过期时间内读取直接返回缓存数据
171 | */
172 | request: function(data, api, callback, note, colling) {
173 |
174 | let post = (typeof data == "string"),
175 |
176 | url = this.globalData.ip +
177 | (this.globalData.url[api] ? "api/" + this.globalData.url[api] : api) +
178 | (post ? data : "") +
179 | (note && isNaN(note) ? note : "");
180 |
181 | let storage_coll = wx.getStorageSync('colling');
182 |
183 | // 查看是否存在缓存,有则直接返回[GET]
184 | if (post && note) {
185 | let storage = wx.getStorageSync(api);
186 |
187 | // 存在数据 && url相等 && 数据未过期
188 | if (storage &&
189 | storage.url == url &&
190 | storage.end >= Date.now()
191 | ) {
192 | // 添加缓存识别
193 | storage.data.storage = true;
194 | return callback(storage.data);
195 | }
196 | } else if (colling) {
197 | // 非缓存数据 才有冷却
198 | if (api in storage_coll) {
199 | if (storage_coll[api] > Date.now()) {
200 | return callback(storage_coll[api] - Date.now());
201 | }
202 | }
203 | }
204 |
205 | // 设定过久显示互动
206 | let showToast = false;
207 | // 禁止显示toast api列表
208 | let notLoading = {
209 | getHistoryQA : 1,
210 | patAddAnswer : 1,
211 | qaMarkAsRead : 1,
212 | docAddAnswer : 1,
213 | getUnreadQA: 1
214 | };
215 | // 如果不在不显示toast列表内
216 | if (!(api in notLoading)) {
217 | loading = setTimeout(() => {
218 | wx.showToast({
219 | title: '加载中...',
220 | icon: 'loading',
221 | mask: true,
222 | duration: 10000
223 | });
224 | showToast = true;
225 | }, 1500);
226 | }
227 |
228 | let req = wx.request({
229 | url,
230 | method: post ? "GET" : "POST",
231 | data: post ? false : data,
232 | success: res => {
233 | // 是否有计数器 有则 清除
234 | if (loading) {
235 | clearTimeout(loading);
236 | loading = null;
237 |
238 | // 判断是否正在显示图标
239 | if (showToast) {
240 | wx.hideToast();
241 | showToast = false;
242 | }
243 | }
244 |
245 | if (res.statusCode == 200 || res.statusCode == 304) {
246 | callback && (!res.error ? callback(res) : callback(false));
247 |
248 | // 设置了缓存过期时间 [只缓存GET|且正常请求]
249 | // ps: 过期请求会被直接覆盖
250 | if (post && !res.error) {
251 | if (!isNaN(note) && note) {
252 | res.header && delete res.header;
253 | wx.setStorage({
254 | key: api,
255 | data: {
256 | url,
257 | end: Date.now() + note * 1000,
258 | data: res
259 | },
260 | });
261 | }
262 | if (colling) {
263 | storage_coll[api] = Date.now() + colling * 1000;
264 | wx.setStorage({
265 | key: 'colling',
266 | data: storage_coll,
267 | });
268 | }
269 | }
270 | } else {
271 | wx.showToast({
272 | title: `内部服务器出现问题!请稍后再试[ERROR: ${api}]`,
273 | icon: "none",
274 | mask: true,
275 | duration: 2000
276 | });
277 | }
278 | },
279 | fail: err => {
280 | console.log('请求调用出错: ', err);
281 | }
282 | });
283 | //console.log("发送请求 <" + (new Date().toTimeString()) + ">: " + url + (post ? data : "") + (note ? note : ""));
284 | },
285 |
286 |
287 |
288 | /**
289 | * 设置顶部封装
290 | * @param {string/object} data 传入string为单项属性设置 反之 多项设定
291 | * @param {string} value 单项设定时调用,当包含","文字将会是黑色反之白色[格式 "#ffffff,000"]
292 | */
293 | bar: function(json, value) {
294 |
295 | let setBar = (key, val) => {
296 | key == 'title' ?
297 | wx.setNavigationBarTitle({
298 | title: `${this.globalData.title} - ${val}`
299 | }) :
300 | wx.setNavigationBarColor({
301 | frontColor: val.indexOf(',') == -1 ? "#ffffff" : "#000000",
302 | backgroundColor: val.split(',')[0],
303 | });
304 | }
305 |
306 | value ? setBar(json, value) : Object.keys(json).forEach((val, key) =>
307 | setBar(val, json[val])
308 | );
309 | },
310 |
311 |
312 |
313 | /**
314 | * 返回格式的时间
315 | * 对Date的扩展,将 Date 转化为指定格式的String
316 | * 月(M)、日(d)、12小时(h)、24小时(H)、分(m)、秒(s)、周(E)、季度(q) 可以用 1-2 个占位符
317 | * 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
318 | * eg:
319 | * "yyyy-MM-dd hh:mm:ss.S" ==> 2006-07-02 08:09:04.423
320 | * "yyyy-MM-dd E HH:mm:ss" ==> 2009-03-10 二 20:09:04
321 | * "yyyy-MM-dd EE hh:mm:ss" ==> 2009-03-10 周二 08:09:04
322 | * "yyyy-MM-dd EEE hh:mm:ss" ==> 2009-03-10 星期二 08:09:04
323 | * "yyyy-M-d h:m:s.S" ==> 2006-7-2 8:9:4.18
324 | */
325 | getDate: function(fmt) {
326 | let date = new Date();
327 | let o = {
328 | "M+": date.getMonth() + 1,
329 | "d+": date.getDate(),
330 | "h+": date.getHours() % 12 == 0 ? 12 : date.getHours() % 12,
331 | "H+": date.getHours(),
332 | "m+": date.getMinutes(),
333 | "s+": date.getSeconds(),
334 | "q+": Math.floor((date.getMonth() + 3) / 3),
335 | "S": date.getMilliseconds()
336 | };
337 | let week = {
338 | "0": "日",
339 | "1": "一",
340 | "2": "二",
341 | "3": "三",
342 | "4": "四",
343 | "5": "五",
344 | "6": "六"
345 | };
346 | if (/(y+)/.test(fmt)) {
347 | fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
348 | }
349 | if (/(E+)/.test(fmt)) {
350 | fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "星期" : "周") : "") + week[date.getDay() + ""]);
351 | }
352 | for (let k in o) {
353 | if (new RegExp("(" + k + ")").test(fmt)) {
354 | fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
355 | }
356 | }
357 | return fmt;
358 | }
359 |
360 | });
--------------------------------------------------------------------------------