瀏覽代碼

初始化

puyao 2 月之前
當前提交
b727a829c7
共有 100 個文件被更改,包括 11290 次插入0 次删除
  1. 17 0
      .gitignore
  2. 23 0
      .hbuilderx/launch.json
  3. 8 0
      .idea/.gitignore
  4. 12 0
      .idea/beiliyoucrm_user_app.iml
  5. 8 0
      .idea/modules.xml
  6. 7 0
      .idea/vcs.xml
  7. 208 0
      App.vue
  8. 36 0
      README.en.md
  9. 37 0
      README.md
  10. 24 0
      api/activity.js
  11. 37 0
      api/address.js
  12. 6 0
      api/adv.js
  13. 28 0
      api/article.js
  14. 35 0
      api/common.js
  15. 35 0
      api/companyOrder.js
  16. 23 0
      api/companyUser.js
  17. 29 0
      api/coupon.js
  18. 9 0
      api/department.js
  19. 16 0
      api/disease.js
  20. 45 0
      api/doc.js
  21. 11 0
      api/doctorArticle.js
  22. 47 0
      api/doctorOrder.js
  23. 78 0
      api/index.js
  24. 22 0
      api/patient.js
  25. 11 0
      api/payment.js
  26. 21 0
      api/prescribe.js
  27. 68 0
      api/product.js
  28. 8 0
      api/store.js
  29. 29 0
      api/storeAfterSales.js
  30. 92 0
      api/storeOrder.js
  31. 15 0
      api/storeProductPackage.js
  32. 24 0
      api/test.js
  33. 75 0
      api/user.js
  34. 16 0
      api/userSign.js
  35. 262 0
      assets/css/common.less
  36. 137 0
      assets/css/common.scss
  37. 141 0
      assets/css/commonTheme.css
  38. 34 0
      assets/css/theme.scss
  39. 2 0
      assets/iconfont/iconfont.css
  40. 二進制
      assets/iconfont/iconfont.ttf
  41. 80 0
      common/request.js
  42. 21 0
      components/Loading.vue
  43. 147 0
      components/Menu.vue
  44. 166 0
      components/chengpeng-audio/free-audio.vue
  45. 42 0
      components/chengpeng-audio/redme.md
  46. 二進制
      components/chengpeng-audio/static/play.png
  47. 二進制
      components/chengpeng-audio/static/stop.png
  48. 143 0
      components/evan-switch/evan-switch.vue
  49. 68 0
      components/im/base/common.js
  50. 146 0
      components/im/base/emojiMap.js
  51. 113 0
      components/im/base/message-facade.js
  52. 29 0
      components/im/tui-chat/message-elements/audio-message/index.css
  53. 67 0
      components/im/tui-chat/message-elements/audio-message/index.vue
  54. 103 0
      components/im/tui-chat/message-elements/custom-message/index.css
  55. 236 0
      components/im/tui-chat/message-elements/custom-message/index.vue
  56. 20 0
      components/im/tui-chat/message-elements/emoji/index.css
  57. 48 0
      components/im/tui-chat/message-elements/emoji/index.vue
  58. 13 0
      components/im/tui-chat/message-elements/face-message/index.css
  59. 57 0
      components/im/tui-chat/message-elements/face-message/index.vue
  60. 65 0
      components/im/tui-chat/message-elements/file-message/index.css
  61. 83 0
      components/im/tui-chat/message-elements/file-message/index.vue
  62. 13 0
      components/im/tui-chat/message-elements/image-message/index.css
  63. 54 0
      components/im/tui-chat/message-elements/image-message/index.vue
  64. 29 0
      components/im/tui-chat/message-elements/system-message/index.css
  65. 86 0
      components/im/tui-chat/message-elements/system-message/index.vue
  66. 47 0
      components/im/tui-chat/message-elements/text-message/index.css
  67. 55 0
      components/im/tui-chat/message-elements/text-message/index.vue
  68. 9 0
      components/im/tui-chat/message-elements/tip-message/index.css
  69. 46 0
      components/im/tui-chat/message-elements/tip-message/index.vue
  70. 27 0
      components/im/tui-chat/message-elements/video-message/index.css
  71. 53 0
      components/im/tui-chat/message-elements/video-message/index.vue
  72. 156 0
      components/im/tui-chat/message-input/index.css
  73. 574 0
      components/im/tui-chat/message-input/index.vue
  74. 70 0
      components/im/tui-chat/message-list/index.css
  75. 195 0
      components/im/tui-chat/message-list/index.vue
  76. 86 0
      components/im/tui-chat/message-private/common-words/index.css
  77. 85 0
      components/im/tui-chat/message-private/common-words/index.vue
  78. 178 0
      components/im/tui-chat/message-private/order-list/index.css
  79. 137 0
      components/im/tui-chat/message-private/order-list/index.vue
  80. 93 0
      components/im/tui-chat/message-private/service-evaluation/index.css
  81. 116 0
      components/im/tui-chat/message-private/service-evaluation/index.vue
  82. 208 0
      components/likeProduct.vue
  83. 315 0
      components/px-popup-bottom/px-popup-bottom.vue
  84. 94 0
      components/tabbar/tabbar.vue
  85. 210 0
      components/tuiProduct.vue
  86. 325 0
      components/z-modal/z-modal.vue
  87. 25 0
      main.js
  88. 93 0
      manifest.json
  89. 23 0
      package-lock.json
  90. 11 0
      package.json
  91. 1257 0
      pages.json
  92. 385 0
      pages/auth/login.vue
  93. 107 0
      pages/auth/wxLogin.vue
  94. 84 0
      pages/common/launch.vue
  95. 583 0
      pages/doctor/doctorDetail.vue
  96. 518 0
      pages/doctor/doctorIm.vue
  97. 434 0
      pages/doctor/doctorList.vue
  98. 319 0
      pages/doctor/doctorOrderIM.vue
  99. 490 0
      pages/doctor/index.vue
  100. 317 0
      pages/doctor/paymentOrder.vue

+ 17 - 0
.gitignore

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

+ 23 - 0
.hbuilderx/launch.json

@@ -0,0 +1,23 @@
+{
+    // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+    // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+    "version" : "0.0",
+    "configurations" : [
+        {
+            "app-plus" : {
+                "launchtype" : "local"
+            },
+            "default" : {
+                "launchtype" : "local"
+            },
+            "mp-weixin" : {
+                "launchtype" : "local"
+            },
+            "type" : "uniCloud"
+        },
+        {
+            "playground" : "standard",
+            "type" : "uni-app:app-android"
+        }
+    ]
+}

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 12 - 0
.idea/beiliyoucrm_user_app.iml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <excludeFolder url="file://$MODULE_DIR$/.tmp" />
+      <excludeFolder url="file://$MODULE_DIR$/temp" />
+      <excludeFolder url="file://$MODULE_DIR$/tmp" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/beiliyoucrm_user_app.iml" filepath="$PROJECT_DIR$/.idea/beiliyoucrm_user_app.iml" />
+    </modules>
+  </component>
+</project>

+ 7 - 0
.idea/vcs.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
+  </component>
+</project>

+ 208 - 0
App.vue

@@ -0,0 +1,208 @@
+<script>
+	import Vue from 'vue'
+	// import TIM from 'tim-wx-sdk';
+	// import COS from 'cos-wx-sdk-v5';
+	export default {
+		globalData: {
+			// confirm订单参数
+			confirmParam: [],
+			themecolor: 'beiliyou'
+		},
+		onLaunch: function() {
+			// 在这里调用 onLaunch  vuex  得 getTheme去请求接口
+			this.$store.dispatch('getTheme')
+			// console.log('App Launch')
+			// uni.hideTabBar()
+			// uni.removeStorageSync('selectedIndex');
+			// uni.$TUIKit = TIM.create({
+			// 	SDKAppID: 1400693126
+			// });
+			// uni.$TUIKit.registerPlugin({
+			// 	'cos-wx-sdk': COS
+			// });
+			// uni.$TUIKitTIM = TIM;
+			// uni.$TUIKitEvent = TIM.EVENT;
+			// uni.$TUIKitVersion = TIM.VERSION;
+			// uni.$TUIKitTypes = TIM.TYPES; // 监听系统级事件
+			// uni.$resetLoginData = this.resetLoginData();
+			// uni.$TUIKit.on(uni.$TUIKitEvent.SDK_READY, this.onSDKReady);
+			// uni.$TUIKit.on(uni.$TUIKitEvent.SDK_NOT_READY, this.onSdkNotReady);
+			// uni.$TUIKit.on(uni.$TUIKitEvent.KICKED_OUT, this.onKickedOut);
+			// uni.$TUIKit.on(uni.$TUIKitEvent.ERROR, this.onTIMError);
+			// uni.$TUIKit.on(uni.$TUIKitEvent.NET_STATE_CHANGE, this.onNetStateChange);
+			// uni.$TUIKit.on(uni.$TUIKitEvent.SDK_RELOAD, this.onSDKReload);
+			// console.log('IM')
+			// uni.$on('updateTabbar', this.updateTabbar);
+			// this.updateTabbar();
+
+		},
+		onShow: function() {
+			console.log('App Show')
+			uni.getSystemInfo({
+				success: (result) => {
+					// 获取手机系统的状态栏高度(不同手机的状态栏高度不同)
+					// console.log('当前手机的状态栏高度',result.statusBarHeight)
+					let statusBarHeight = result.statusBarHeight + 'px'
+
+					// 获取右侧胶囊的信息 单位px
+					//#ifndef H5 || APP-PLUS
+					const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
+
+					//bottom: 胶囊底部距离屏幕顶部的距离
+					//height: 胶囊高度
+					//left:   胶囊左侧距离屏幕左侧的距离
+					//right:  胶囊右侧距离屏幕左侧的距离
+					//top:    胶囊顶部距离屏幕顶部的距离
+					//width:  胶囊宽度
+					// console.log(menuButtonInfo.width, menuButtonInfo.height, menuButtonInfo.top)
+					// console.log('计算胶囊右侧距离屏幕右边距离', result.screenWidth - menuButtonInfo.right)
+					let menuWidth = menuButtonInfo.width + 'px'
+					let menuHeight = menuButtonInfo.height + 'px'
+					let menuBorderRadius = menuButtonInfo.height / 2 + 'px'
+					let menuRight = result.screenWidth - menuButtonInfo.right + 'px'
+					let menuTop = menuButtonInfo.top + 'px'
+					let contentTop = result.statusBarHeight + 44 + 'px'
+
+					let menuInfo = {
+						statusBarHeight: statusBarHeight, //状态栏高度----用来给自定义导航条页面的顶部导航条设计padding-top使用:目的留出系统的状态栏区域
+						menuWidth: menuWidth, //右侧的胶囊宽度--用来给自定义导航条页面的左侧胶囊设置使用
+						menuHeight: menuHeight, //右侧的胶囊高度--用来给自定义导航条页面的左侧胶囊设置使用
+						menuBorderRadius: menuBorderRadius, //一半的圆角--用来给自定义导航条页面的左侧胶囊设置使用
+						menuRight: menuRight, //右侧的胶囊距离右侧屏幕距离--用来给自定义导航条页面的左侧胶囊设置使用
+						menuTop: menuTop, //右侧的胶囊顶部距离屏幕顶部的距离--用来给自定义导航条页面的左侧胶囊设置使用
+						contentTop: contentTop, //内容区距离页面最上方的高度--用来给自定义导航条页面的内容区定位距离使用
+					}
+					uni.setStorageSync('menuInfo', menuInfo)
+					//#endif
+				},
+				fail: (error) => {
+					console.log(error)
+				}
+			})
+		},
+		onHide: function() {
+			console.log('App Hide')
+		},
+
+		methods: {
+			updateTabbar() {
+				// 获取当前主题
+				const theme = this.globalData.themecolor;
+				// 设置tabbar的图标
+				const tabbarList = [{
+						iconPath: `/static/images/tabbar/${theme}/home.png`,
+						selectedIconPath: `/static/images/tabbar/${theme}/home_on.png`
+					},
+					{
+						iconPath: `/static/images/tabbar/${theme}/home.png`,
+						selectedIconPath: `/static/images/tabbar/${theme}/home_on.png`
+					},
+					{
+						iconPath: `/static/images/tabbar/${theme}/home.png`,
+						selectedIconPath: `/static/images/tabbar/${theme}/home_on.png`
+					},
+					{
+						iconPath: `/static/images/tabbar/${theme}/home.png`,
+						selectedIconPath: `/static/images/tabbar/${theme}/home_on.png`
+					},
+				];
+				// 这个style不要用循环
+				uni.setTabBarStyle({
+					color: '#acafac',
+					selectedColor: '#118e4a'
+				})
+				tabbarList.forEach((item, index) => {
+					// 只能一项设置 所以循环
+					uni.setTabBarItem({
+						index,
+						...item
+					})
+				})
+			},
+			// TODO:
+			resetLoginData() {
+				// this.globalData.expiresIn = '';
+				// this.globalData.sessionID = '';
+				// this.globalData.userInfo = {
+				// 	userID: '',
+				// 	userSig: '',
+				// 	token: '',
+				// 	phone: ''
+				// };
+				// this.globalData.userProfile = null;
+				// logger.log(`| app |  resetLoginData | globalData: ${this.globalData}`);
+			},
+			onTIMError() {},
+			onSDKReady({
+				name
+			}) {
+				console.log("im注册:" + name)
+				const isSDKReady = name === uni.$TUIKitEvent.SDK_READY ? true : false
+				console.log("im注册:" + isSDKReady)
+				uni.$emit('isSDKReady', {
+					isSDKReady: true
+				});
+			},
+			onNetStateChange() {},
+			onSDKReload() {},
+			onSdkNotReady() {},
+			onKickedOut() {
+				uni.showToast({
+					title: '您被踢下线',
+					icon: 'error'
+				});
+
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	/*每个页面公共css */
+	// @import 'animate.css';
+	@import "uview-ui/index.scss";
+	@import './assets/iconfont/iconfont.css';
+	@import './assets/css/common.less';
+	@import '@/assets/css/common.scss';
+	@import '@/assets/css/commonTheme.css';
+	@import '@/assets/css/theme.scss';
+
+	page {
+		background-color: #f6f6f6;
+	}
+
+	::-webkit-scrollbar {
+		width: 0 !important;
+		height: 0 !important;
+
+	}
+</style>
+<style>
+	/*每个页面公共css */
+	/* 解决小程序和app滚动条的问题 */
+	/* #ifdef MP-WEIXIN || APP-PLUS */
+	/deep/ ::-webkit-scrollbar {
+		display: none !important;
+		width: 0 !important;
+		height: 0 !important;
+		-webkit-appearance: none;
+		background: transparent;
+		color: transparent;
+	}
+
+	/* #endif */
+
+	/* 解决H5 的问题 */
+	/* #ifdef H5 */
+	uni-scroll-view .uni-scroll-view::-webkit-scrollbar {
+		/* 隐藏滚动条,但依旧具备可以滚动的功能 */
+		display: none;
+		width: 0 !important;
+		height: 0 !important;
+		-webkit-appearance: none;
+		background: transparent;
+		color: transparent;
+	}
+
+	/* #endif */
+</style>

+ 36 - 0
README.en.md

@@ -0,0 +1,36 @@
+# WBCrm_User_Uniapp
+
+#### Description
+wbcrm_user_app
+
+#### Software Architecture
+Software architecture description
+
+#### Installation
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### Instructions
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### Contribution
+
+1.  Fork the repository
+2.  Create Feat_xxx branch
+3.  Commit your code
+4.  Create Pull Request
+
+
+#### Gitee Feature
+
+1.  You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
+2.  Gitee blog [blog.gitee.com](https://blog.gitee.com)
+3.  Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
+4.  The most valuable open source project [GVP](https://gitee.com/gvp)
+5.  The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
+6.  The most popular members  [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

+ 37 - 0
README.md

@@ -0,0 +1,37 @@
+# WBCrm_User_Uniapp
+
+#### 介绍
+wbcrm_user_app
+
+#### 软件架构
+软件架构说明
+
+
+#### 安装教程
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### 使用说明
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### 参与贡献
+
+1.  Fork 本仓库
+2.  新建 Feat_xxx 分支
+3.  提交代码
+4.  新建 Pull Request
+
+
+#### 特技
+
+1.  使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
+2.  Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
+3.  你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
+4.  [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
+5.  Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
+6.  Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

+ 24 - 0
api/activity.js

@@ -0,0 +1,24 @@
+import Request from '../common/request.js';
+let request = new Request().http
+ 
+ 
+ 
+ export function getStoreActivity(data) {
+ 	 return request('/app/activity/getStoreActivity',data,'GET');
+ }
+ export function getStoreActivityDetails(data) {
+ 	 return request('/app/activity/getStoreActivityDetails',data,'GET');
+ }
+ export function share(activityId) {
+ 	 return request('/app/activity/share?activityId='+activityId,null,'POST');
+ }
+  
+ 
+ 
+
+ 
+ 
+ 
+ 
+ 
+ 

+ 37 - 0
api/address.js

@@ -0,0 +1,37 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+ export function getCity() {
+ 	 return request('/app/address/getCity',null,'GET');
+ }
+ export function getCitys() {
+ 	 return request('/app/address/getCitys',null,'GET');
+ }
+ export function getAddressList() {
+ 	 return request('/app/address/getAddressList',null,'GET');
+ }
+
+ export function getAddressById(data) {
+ 	 return request('/app/address/getAddressById',data,'GET');
+ } 
+ 
+ export function addAddress(data) {
+ 	return request('/app/address/addAddress',data,'POST','application/json;charset=UTF-8');
+ }
+
+ export function editAddress(data) {
+ 	return request('/app/address/editAddress',data,'POST','application/json;charset=UTF-8');
+ }
+ export function delAddress(data) {
+ 	return request('/app/address/delAddress',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function parseAddress(data) {
+ 	return request('/app/address/parseAddress',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function delAllAddress(data) {
+ 	return request('/app/address/delAllAddress',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ 

+ 6 - 0
api/adv.js

@@ -0,0 +1,6 @@
+import Request from '../common/request.js';
+let request = new Request().http
+ export function getAdv(data) {
+ 	 return request('/app/adv/getAdv',data,'GET');
+ }
+ 

+ 28 - 0
api/article.js

@@ -0,0 +1,28 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+ 
+ export function getArticleCate() {
+ 	 return request('/app/article/getArticleCate',null,'GET');
+ }
+ 
+ export function getArticleList(data) {
+ 	 return request('/app/article/getArticleList',data,'GET');
+ }
+
+ export function getArticleByArticleId(data) {
+ 	 return request('/app/article/getArticleByArticleId',data,'GET');
+ } 
+ 
+ export function updateView(articleId) {
+ 	 return request('/app/article/updateView?articleId='+articleId,null,'POST');
+ } 
+ 
+ export function getArticleViewList(data) {
+ 	 return request('/app/article/getArticleViewList',data,'GET');
+ } 
+ 
+
+ 
+ 
+  

+ 35 - 0
api/common.js

@@ -0,0 +1,35 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+
+ export function uploadOSS(data) {
+ 	 return request('/app/common/uploadOSS',data,'POST');
+ }
+ export function getTlsSig(data) {
+ 	 return request('/app/common/getTlsSig',data,'GET');
+ }
+ 
+ export function getStoreConfig() {
+  	 return request('/app/common/getStoreConfig',null,'GET');
+ } 
+ 
+ export function getProductConfig() {
+  	 return request('/app/common/getProductConfig',null,'GET');
+ } 
+ 
+ export function getWeixinTemps() {
+ 	 return request('/app/common/getWeixinTemps',null,'GET');
+ }
+ export function getWeixinOrderTemps() {
+ 	 return request('/app/common/getWeixinOrderTemps',null,'GET');
+ }
+ export function getWeixinPrescribeTemps() {
+ 	 return request('/app/common/getWeixinPrescribeTemps',null,'GET');
+ }
+ 
+ 
+ export function getDictByKey(data) {
+  	 return request('/app/common/getDictByKey',data,'GET');
+ } 
+ 
+ 

+ 35 - 0
api/companyOrder.js

@@ -0,0 +1,35 @@
+import Request from '../common/request.js';
+let request = new Request().http
+ 
+ export function getSalesProducts(data) {
+ 	 return request('/app/companyOrder/getSalesProducts',data,'GET');
+ }
+ 
+ export function createSalesOrder(data) {
+ 	 return request('/app/companyOrder/createSalesOrder',data,'GET' );
+ }
+ export function updateSalseOrderMoney(data) {
+ 	 return request('/app/companyOrder/updateSalseOrderMoney',data,'GET' );
+ }
+ // 多店铺修改实付金额
+ export function updateSaleOrderMoney(data) {
+ 	 return request('/app/companyOrder/updateSaleOrderMoney',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function getSalesOrder(data) {
+ 	 return request('/app/companyOrder/getSalesOrder',data,'GET' );
+ }
+ export function getSalesOrders(data) {
+ 	 return request('/app/companyOrder/getSalesOrders',data,'GET' );
+ }
+ export function addUserCart(data) {
+ 	 return request('/app/companyOrder/addUserCart',data,'GET' );
+ }
+ 
+ export function editOrderMoney(data) {
+ 	 return request('/app/companyOrder/editOrderMoney',data,'GET' );
+ }
+ 
+  
+ 
+ 

+ 23 - 0
api/companyUser.js

@@ -0,0 +1,23 @@
+import Request from '../common/request.js';
+let request = new Request().http
+ 
+ export function login(data) {
+ 	 return request('/app/companyUser/login',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function getUserInfo(data) {
+ 	 return request('/app/companyUser/getUserInfo',data,'GET','application/json;charset=UTF-8');
+ }
+ export function getQrImg(data) {
+ 	 return request('/app/companyUser/getQrImg',data,'GET','application/json;charset=UTF-8');
+ }
+ 
+ export function getCompanyUserCard(data) {
+ 	 return request('/app/companyUser/getCompanyUserCard',data,'GET','application/json;charset=UTF-8');
+ }
+ 
+ 
+ 
+  
+ 
+ 

+ 29 - 0
api/coupon.js

@@ -0,0 +1,29 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+ export function getCouponIssueList(data) {
+ 	 return request('/app/coupon/getCouponIssueList',data,'GET');
+ }
+ export function getCompanyCouponIssueList(data) {
+ 	 return request('/app/coupon/getCompanyCouponIssueList',data,'GET');
+ }
+ export function getCouponIssueById(data) {
+ 	 return request('/app/coupon/getCouponIssueById',data,'GET');
+ }
+ 
+ 
+ 
+ export function receive(data) {
+ 	return request('/app/coupon/receive',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function getMyCouponList(data) {
+ 	 return request('/app/coupon/getMyCouponList',data,'GET');
+ }
+ export function getMyEnableCouponList(data) {
+ 	 return request('/app/coupon/getMyEnableCouponList',data,'GET');
+ }
+ 
+ 
+
+ 

+ 9 - 0
api/department.js

@@ -0,0 +1,9 @@
+import Request from '../common/request.js';
+let request = new Request().http
+ 
+ export function getDepartmentList(data) {
+ 	 return request('/app/department/getDepartmentList',data,'GET');
+ }
+ 
+  
+  

+ 16 - 0
api/disease.js

@@ -0,0 +1,16 @@
+import Request from '../common/request.js';
+let request = new Request().http
+ 
+ export function getDiseaseList(data) {
+ 	 return request('/app/disease/getDiseaseList',data,'GET');
+ }
+ export function getDiseaseById(data) {
+ 	 return request('/app/disease/getDiseaseById',data,'GET');
+ }
+ 
+ 
+ 
+ 
+  
+  
+  

+ 45 - 0
api/doc.js

@@ -0,0 +1,45 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+ 
+ export function getMyDocList(data) {
+ 	 return request('/app/doc/getMyDocList',data,'GET');
+ }
+ 
+ export function getDocDetails(data) {
+ 	 return request('/app/doc/getDocDetails',data,'GET');
+ }
+ 
+ export function addDoc(data) {
+ 	return request('/app/doc/addDoc',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function editDoc(data) {
+ 	return request('/app/doc/editDoc',data,'POST','application/json;charset=UTF-8');
+ }
+ export function delDoc(data) {
+ 	return request('/app/doc/delDoc',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function getMyDocRecordList(data) {
+ 	 return request('/app/doc/getMyDocRecordList',data,'GET');
+ }
+ 
+ export function getDocRecordReplyList(data) {
+ 	 return request('/app/doc/getDocRecordReplyList',data,'GET');
+ }
+ 
+ 
+ export function addDocRecord(data) {
+ 	return request('/app/doc/addDocRecord',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function getMyDocOrderList() {
+ 	 return request('/app/doc/getMyDocOrderList',null,'GET');
+ }
+ 
+ export function addDocOrder(data) {
+ 	return request('/app/doc/addDocOrder',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ 

+ 11 - 0
api/doctorArticle.js

@@ -0,0 +1,11 @@
+import Request from '../common/request.js';
+let request = new Request().http
+ 
+ export function getDoctorArticleList(data) {
+ 	 return request('/app/doctorArticle/getDoctorArticleList',data,'GET');
+ }
+ export function getDoctorArticleById(data) {
+ 	 return request('/app/doctorArticle/getDoctorArticleById',data,'GET');
+ }
+  
+   

+ 47 - 0
api/doctorOrder.js

@@ -0,0 +1,47 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+ 
+ 
+ 
+ export function getDepartmentList(data) {
+ 	 return request('/app/doctorOrder/getDepartmentList',data,'GET');
+ } 
+ 
+ export function getDoctorList(data) {
+ 	 return request('/app/doctorOrder/getDoctorList',data,'GET');
+ } 
+ 
+ export function getDoctorCase(data) {
+ 	 return request('/app/doctorOrder/getDoctorCase',data,'GET');
+ } 
+ 
+ 
+ export function getMyDoctorOrderList(data) {
+ 	 return request('/app/doctorOrder/getMyDoctorOrderList',data,'GET');
+ } 
+ 
+ export function getDoctorDetail(data) {
+ 	 return request('/app/doctorOrder/getDoctorDetail',data,'GET');
+ } 
+ 
+ export function getDoctorOrderDetail(data) {
+ 	 return request('/app/doctorOrder/getDoctorOrderDetail',data,'GET');
+ } 
+ export function create(data) {
+ 	 return request('/app/doctorOrder/create',data,'POST','application/json;charset=UTF-8');
+ }
+ export function pay(data) {
+ 	 return request('/app/doctorOrder/pay',data,'POST','application/json;charset=UTF-8');
+ }
+ export function cancelOrder(data) {
+ 	 return request('/app/doctorOrder/cancelOrder',data,'POST','application/json;charset=UTF-8');
+ }
+ export function pingOrder(data) {
+ 	 return request('/app/doctorOrder/pingOrder',data,'POST','application/json;charset=UTF-8');
+ }
+ export function getImOrderDetail(data) {
+ 	 return request('/app/doctorOrder/getImOrderDetail',data,'GET');
+ } 
+ 
+ 

+ 78 - 0
api/index.js

@@ -0,0 +1,78 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+export function getDicts(data) {
+ 	 return request('/app/common/getDicts',data,'GET');
+} 
+export function getCanvas() {
+ 	 return request('/app/index/getCanvas',null,'GET');
+} 
+export function getMenu() {
+ 	 return request('/app/index/getMenu',null,'GET');
+} 
+export function getIndexData(data) {
+ 	 return request('/app/index/getIndexData',data,'GET');
+} 
+export function getTuiArticle(data) {
+ 	 return request('/app/index/getTuiArticle',data,'GET');
+} 
+export function getTuiDoctor(data) {
+ 	 return request('/app/index/getTuiDoctor',data,'GET');
+} 
+
+export function getTuiDoctorOrder(data) {
+ 	 return request('/app/index/getTuiDoctorOrder',data,'GET');
+} 
+
+export function getCartCount() {
+ 	 return request('/app/index/getCartCount',null,'GET');
+} 
+
+
+ export function getFamousPrescribeList(data) {
+	 return request('/app/index/getFamousPrescribeList',data,'GET');
+ }
+ export function getFamousPrescribeById(data) {
+	 return request('/app/index/getFamousPrescribeById',data,'GET');
+ }
+ export function getQuestionsList(data) {
+ 	 return request('/app/index/getQuestionsList',data,'GET');
+ }
+ export function getQuestionsById(data) {
+ 	 return request('/app/index/getQuestionsById',data,'GET');
+ }
+ export function getMedicatedFoodList(data) {
+ 	 return request('/app/index/getMedicatedFoodList',data,'GET');
+ }
+ export function getMedicatedFoodById(data) {
+ 	 return request('/app/index/getMedicatedFoodById',data,'GET');
+ }
+ export function getVesselList(data) {
+ 	 return request('/app/index/getVesselList',data,'GET');
+ }
+ export function getVesselById(data) {
+ 	 return request('/app/index/getVesselById',data,'GET');
+ }
+ export function getChineseMedicineList(data) {
+ 	 return request('/app/index/getChineseMedicineList',data,'GET');
+ }
+ export function getChineseMedicineById(data) {
+ 	 return request('/app/index/getChineseMedicineById',data,'GET');
+ }
+ 
+ export function getMenuB(data) {
+ 	 return request('/app/index/getMenuTwo',data,'GET');
+ }
+ 
+ export function getenterprise(data) {
+ 	 return request('/app/index/getConcept',data,'GET');
+ }
+
+ export function getpro(data) {
+ 	 return request('/app/common/getConfigByKey',data,'GET');
+ } 
+ 
+ 
+
+ 
+ 

+ 22 - 0
api/patient.js

@@ -0,0 +1,22 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+ 
+ export function getPatientList() {
+ 	 return request('/app/patient/getPatientList',null,'GET');
+ }
+
+ export function getPatientById(data) {
+ 	 return request('/app/patient/getPatientById',data,'GET');
+ } 
+ 
+ export function addPatient(data) {
+ 	return request('/app/patient/addPatient',data,'POST','application/json;charset=UTF-8');
+ }
+
+ export function editPatient(data) {
+ 	return request('/app/patient/editPatient',data,'POST','application/json;charset=UTF-8');
+ }
+ export function delPatient(data) {
+ 	return request('/app/patient/delPatient',data,'POST','application/json;charset=UTF-8');
+ }

+ 11 - 0
api/payment.js

@@ -0,0 +1,11 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+  
+ export function payment(data) {
+ 	 return request('/app/payment/payment',data,'POST','application/json;charset=UTF-8');
+ }
+  
+ 
+ 
+ 

+ 21 - 0
api/prescribe.js

@@ -0,0 +1,21 @@
+import Request from '../common/request.js';
+let request = new Request().http
+ 
+ export function doPrescribe(data) {
+ 	 return request('/app/prescribe/doPrescribe',data,'POST','application/json;charset=UTF-8');
+ }
+ export function getMyPrescribeList(data) {
+ 	 return request('/app/prescribe/getMyPrescribeList',data,'GET');
+ }
+ 
+ 
+ 
+ 
+ 
+
+ 
+ 
+ 
+ 
+ 
+ 

+ 68 - 0
api/product.js

@@ -0,0 +1,68 @@
+import Request from '../common/request.js';
+let request = new Request().http
+ 
+
+ export function getProductCate(data) {
+ 	 return request('/app/product/getProductCate',data,'GET');
+ }
+ 
+ export function getProductCateByPid(data) {
+ 	 return request('/app/product/getProductCateByPid',data,'GET');
+ }
+ 
+ export function getProducts(data) {
+ 	 return request('/app/product/getProducts',data,'GET');
+ }
+ export function getProductDetails(data) {
+ 	 return request('/app/product/getProductDetails',data,'GET');
+ }
+ 
+ export function getCarts(data) {
+ 	 return request('/app/product/getCarts',data,'GET');
+ }
+ export function addCart(data) {
+ 	 return request('/app/product/addCart',data,'POST','application/json;charset=UTF-8');
+ }
+ export function delCart(data) {
+ 	 return request('/app/product/delCart',data,'POST','application/json;charset=UTF-8');
+ }
+ export function cartNum(data) {
+ 	 return request('/app/product/cartNum',data,'POST','application/json;charset=UTF-8');
+ }
+ export function getCartCount(data) {
+ 	 return request('/app/product/getCartCount',data,'GET');
+ }
+ export function getGoodsProduct() {
+ 	 return request('/app/product/getGoodsProduct',null,'GET');
+ }
+ export function getGoodsProducts(data) {
+ 	 return request('/app/product/getGoodsProducts',data,'GET');
+ }
+ export function getTuiProducts(data) {
+ 	 return request('/app/product/getTuiProducts',data,'GET');
+ }
+ export function getStoreProductAttrValueList(data) {
+ 	 return request('/app/product/getStoreProductAttrValueList',data,'GET');
+ }
+ 
+ export function getProductStoreStock(data) {
+ 	 return request('/app/product/getProductStoreStock',data,'GET');
+ }
+ 
+ 
+
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+
+ 
+ 
+ 
+ 
+ 
+ 

+ 8 - 0
api/store.js

@@ -0,0 +1,8 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+ // 获取门店详情
+ export function getStoreById(data) {
+ 	 return request('/app/store/getStoreById',data,'GET');
+ }
+ 

+ 29 - 0
api/storeAfterSales.js

@@ -0,0 +1,29 @@
+import Request from '../common/request.js';
+let request = new Request().http
+ 
+ export function getMyStoreOrderItemByOrderId(data) {
+ 	 return request('/app/storeAfterSales/getMyStoreOrderItemByOrderId',data,'GET');
+ } 
+ export function applyAfterSales(data) {
+ 	 return request('/app/storeAfterSales/applyAfterSales',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function getAfterSalesList(data) {
+ 	 return request('/app/storeAfterSales/getAfterSalesList',data,'GET');
+ } 
+ 
+ export function getAfterSalesDetails(data) {
+ 	 return request('/app/storeAfterSales/getAfterSalesDetails',data,'GET');
+ } 
+ export function revoke(data) {
+ 	 return request('/app/storeAfterSales/revoke',data,'POST','application/json;charset=UTF-8');
+ }
+ export function addDelivery(data) {
+ 	 return request('/app/storeAfterSales/addDelivery',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ 
+ 
+ 
+ 
+ 

+ 92 - 0
api/storeOrder.js

@@ -0,0 +1,92 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+ 
+ export function getMyStoreOrderList(data) {
+ 	 return request('/app/storeOrder/getMyStoreOrderList',data,'GET');
+ } 
+ export function getCompanyStoreOrderList(data) {
+ 	 return request('/app/storeOrder/getCompanyStoreOrderList',data,'GET');
+ } 
+ export function getMyStoreOrderById(data) {
+ 	 return request('/app/storeOrder/getMyStoreOrderById',data,'GET');
+ } 
+ 
+ 
+ export function getStoreOrderById(data) {
+ 	 return request('/app/storeOrder/getStoreOrderById',data,'GET');
+ } 
+ 
+ export function getStoreOrderByCombinationId(data) {
+ 	 return request('/app/storeOrder/getStoreOrderByCombinationId',data,'GET');
+ } 
+ export function otherPaymentByCombinationId(data) {
+ 	 return request('/app/storeOrder/otherPaymentByCombinationId',data,'POST','application/json;charset=UTF-8');
+ } 
+ 
+ export function confirm(data) {
+ 	 return request('/app/storeOrder/confirm',data,'POST','application/json;charset=UTF-8');
+ }
+ export function computed(data) {
+ 	 return request('/app/storeOrder/computed',data,'POST','application/json;charset=UTF-8');
+ }
+ export function create(data) {
+ 	 return request('/app/storeOrder/create',data,'POST','application/json;charset=UTF-8');
+ }
+ export function pay(data) {
+ 	 return request('/app/storeOrder/pay',data,'POST','application/json;charset=UTF-8');
+ }
+ export function payByCombinationId(data) {
+ 	 return request('/app/storeOrder/payByCombinationId',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function editPayType(data) {
+ 	 return request('/app/storeOrder/editPayType',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function editPayTypeByCombinationId(data) {
+ 	 return request('/app/storeOrder/editPayTypeByCombinationId',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function payRemain(data) {
+ 	 return request('/app/storeOrder/payRemain',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function otherPayment(data) {
+ 	 return request('/app/storeOrder/otherPayment',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function otherPaymentRemain(data) {
+ 	 return request('/app/storeOrder/otherPaymentRemain',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ 
+ export function cancelOrder(data) {
+ 	 return request('/app/storeOrder/cancelOrder',data,'POST','application/json;charset=UTF-8');
+ }
+ export function finishOrder(data) {
+ 	 return request('/app/storeOrder/finishOrder',data,'POST','application/json;charset=UTF-8');
+ }
+ export function getExpress(data) {
+ 	 return request('/app/storeOrder/getExpress',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ 
+ export function confirmPackageOrder(data) {
+ 	 return request('/app/storeOrder/confirmPackageOrder',data,'POST','application/json;charset=UTF-8');
+ }
+ export function computedPackageOrder(data) {
+ 	 return request('/app/storeOrder/computedPackageOrder',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function createPackageOrder(data) {
+ 	 return request('/app/storeOrder/createPackageOrder',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function getOrderCount() {
+ 	 return request('/app/storeOrder/getOrderCount',null,'GET');
+ } 
+ 
+ 
+ 
+ 

+ 15 - 0
api/storeProductPackage.js

@@ -0,0 +1,15 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+ export function getStoreProductPackage(data) {
+ 	 return request('/app/storeProductPackage/getStoreProductPackage',data,'GET');
+ } 
+ 
+ export function getStoreProductPackageDetails(data) {
+ 	 return request('/app/storeProductPackage/getStoreProductPackageDetails',data,'GET');
+ } 
+ 
+  
+ 
+ 
+ 

+ 24 - 0
api/test.js

@@ -0,0 +1,24 @@
+import Request from '../common/request.js';
+let request = new Request().http
+
+ export function getTestList(data) {
+ 	 return request('/app/test/getTestList',data,'GET');
+ }
+ export function getTestDetails(data) {
+ 	 return request('/app/test/getTestDetails',data,'GET');
+ }
+ 
+ export function getTestTempDetails(data) {
+ 	 return request('/app/test/getTestTempDetails',data,'GET');
+ }
+ export function getTestReport(data) {
+ 	 return request('/app/test/getTestReport',data,'GET');
+ }
+ export function getTestReportImg(data) {
+ 	 return request('/app/test/getTestReportImg',data,'GET');
+ }
+ export function doReport(data) {
+  	return request('/app/test/doReport',data,'POST','application/json;charset=UTF-8');
+ }
+  
+  

+ 75 - 0
api/user.js

@@ -0,0 +1,75 @@
+import Request from '../common/request.js';
+let request = new Request().http
+ 
+ export function loginByMiniApp(data) {
+ 	 return request('/app/wx/loginByMiniApp',data,'POST','application/json;charset=UTF-8');
+ }
+ export function loginByMp(data) {
+ 	 return request('/app/wx/loginByMp',data,'POST','application/json;charset=UTF-8');
+ }
+ export function getUserInfo() {
+ 	 return request('/app/user/getUserInfo',null,'GET');
+ }
+ 
+ export function editUser(data) {
+ 	return request('/app/user/editUser',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function getWeixinInfo(data) {
+ 	return request('/app/wx/getWeixinInfo',data,'POST','application/json;charset=UTF-8');
+ }
+ export function checkLogin() {
+ 	 return request('/app/user/checkLogin',null,'GET');
+ }
+ export function getTuiImg() {
+ 	 return request('/app/user/getTuiImg',null,'GET');
+ }
+ export function getMyTuiOrderList(data) {
+ 	 return request('/app/user/getMyTuiOrderList',data,'GET');
+ }
+ export function getTuiMoney() {
+ 	 return request('/app/user/getTuiMoney',null,'GET');
+ }
+ export function getMyTuiList(data) {
+ 	 return request('/app/user/getMyTuiList',data,'GET');
+ }
+ export function getTuiMoneyLogs(data) {
+ 	 return request('/app/user/getTuiMoneyLogs',data,'GET');
+ }
+ 
+ export function getProductFoots(data) {
+ 	 return request('/app/user/getProductFoots',data,'GET');
+ }
+ export function delProductFoots(data) {
+ 	 return request('/app/user/delProductFoots',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ export function doExtract(data) {
+ 	 return request('/app/user/doExtract',data,'POST','application/json;charset=UTF-8');
+ }
+ export function getExtractList(data) {
+ 	 return request('/app/user/getExtractList',data,'GET');
+ }
+ export function applyPromoter(data) {
+ 	 return request('/app/user/applyPromoter',data,'POST','application/json;charset=UTF-8');
+ }
+ export function bindPromoter(data) {
+ 	 return request('/app/user/bindPromoter',data,'POST','application/json;charset=UTF-8');
+ }
+ //获取图标
+ export function geticon(data) {
+ 	 return request('/app/index/getMenuUser',data,'GET','application/json;charset=UTF-8');
+ }
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 

+ 16 - 0
api/userSign.js

@@ -0,0 +1,16 @@
+import Request from '../common/request.js';
+let request = new Request().http
+ 
+ 
+ export function getUserSign() {
+ 	 return request('/app/sign/getUserSign',null,'GET');
+ }
+ 
+ export function getIntegral(data) {
+ 	 return request('/app/sign/getIntegral',data,'GET');
+ }
+ export function doSign(data) {
+ 	 return request('/app/sign/sign',data,'POST','application/json;charset=UTF-8');
+ }
+ 
+ 

+ 262 - 0
assets/css/common.less

@@ -0,0 +1,262 @@
+ 
+page {
+  background: #f5f5f5;
+  height: 100%;
+}
+.container{
+  height: 100%;
+}
+rich-text {
+  width: 100%;
+  display: block;
+  img,
+  image {
+    display: block;
+    width: 100%;
+  }
+}
+
+/*单行文本溢出省略号*/
+.one-t {
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  transition: all linear 0.2s;
+}
+
+/*多行文本溢出省略号*/
+.more-t {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  display: -webkit-box;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+  transition: all linear 0.2s;
+}
+
+/* ==================
+          flex布局(colorui里面也有相关基础样式)
+ ==================== */
+/* x水平排列*/
+.x-f {
+  display: flex;
+  align-items: center;
+}
+
+/*x两端且水平居中*/
+.x-bc {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+/*x平分且水平居中*/
+.x-ac {
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+}
+
+/*x水平靠上对齐*/
+.x-start {
+  display: flex;
+  align-items: flex-start;
+}
+
+/*x水平靠下对齐*/
+.x-end {
+  display: flex;
+  align-items: flex-end;
+}
+
+/*上下左右居中*/
+.x-c {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+/*y竖直靠左*/
+.y-start {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+}
+
+/*y竖直靠右*/
+.y-end {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-end;
+}
+
+/*y竖直居中*/
+.y-f {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+// y竖直两端
+.y-b {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+}
+
+/*y竖直两端居中*/
+.y-bc {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-between;
+}
+/* layout */
+.acea-row {
+  display: flex;
+  flex-wrap: wrap;
+  /* 辅助类 */
+}
+.acea-row.row-middle {
+  align-items: center;
+}
+.acea-row.row-top {
+  align-items: flex-start;
+}
+.acea-row.row-bottom {
+  align-items: flex-end;
+}
+.acea-row.row-center {
+  justify-content: center;
+}
+.acea-row.row-right {
+  justify-content: flex-end;
+}
+.acea-row.row-left {
+  justify-content: flex-start;
+}
+.acea-row.row-between {
+  justify-content: space-between;
+}
+.acea-row.row-around {
+  justify-content: space-around;
+}
+.acea-row.row-column-around {
+  flex-direction: column;
+  justify-content: space-around;
+}
+.acea-row.row-column {
+  flex-direction: column;
+}
+.acea-row.row-column-between {
+  flex-direction: column;
+  justify-content: space-between;
+}
+/* 上下左右垂直居中 */
+.acea-row.row-center-wrapper {
+  align-items: center;
+  justify-content: center;
+}
+/* 上下两边居中对齐 */
+.acea-row.row-between-wrapper {
+  align-items: center;
+  justify-content: space-between;
+}
+
+/*每个页面公共css */
+.ellipsis{
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+}
+.ellipsis2{
+	overflow:hidden; 
+	text-overflow:ellipsis;
+	display:-webkit-box; 
+	-webkit-box-orient:vertical;
+	-webkit-line-clamp:2; 
+}
+radio .wx-radio-input{
+  width: 36rpx;
+  height: 36rpx;
+  border: 1px solid #CCCCCC;
+}
+/* 选中后的 背景样式  */
+radio .wx-radio-input.wx-radio-input-checked{
+	background: linear-gradient(135deg, #66b2ef  0%, #018C39 100%);
+	border: 1px solid #018C39;
+}
+/* 选中后的 对勾样式 (白色对勾) */
+radio .wx-radio-input.wx-radio-input-checked::before{
+	color: #ffffff;
+}
+checkbox .wx-checkbox-input{
+	width: 36rpx;
+	height: 36rpx;
+	border: 1px solid #CCCCCC;
+	border-radius: 50%;
+}
+checkbox .wx-checkbox-input.wx-checkbox-input-checked {
+	background: linear-gradient(135deg, #66b2ef 0%, #018C39 100%);
+	border: 1px solid #018C39;
+	border-radius: 50%;
+}
+checkbox .wx-checkbox-input.wx-checkbox-input-checked::before {
+	color: #ffffff;
+}
+::-webkit-scrollbar {
+   width: 0;
+   height: 0;
+   color: transparent;
+ }
+ /* 暂无数据 */
+.no-data-box{
+	padding: 100upx 50upx;
+	text-align: center;
+	image{
+		width: 372rpx;
+		height: 240rpx;
+	}
+	.empty-title{
+		margin-top: 20rpx;
+		font-size: 32rpx;
+		color: #bbbbbb;
+		 
+	}
+}
+.Loads {
+  height: 0.8*100rpx;
+  font-size: 0.25*100rpx;
+  color: #000;
+}
+.Loads .iconfont {
+  font-size: 0.3*100rpx;
+  margin-right: 0.1*100rpx;
+  height: 0.32*100rpx;
+  line-height: 0.32*100rpx;
+}
+/*加载动画*/
+@keyframes load {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+.loadingpic {
+  animation: load 3s linear 1s infinite;
+}
+.loading {
+  animation: load linear 1s infinite;
+}
+
+ .back-box{
+	position: relative;
+	.title{
+		position: absolute;
+		left: 50%;
+		top: 50%;
+		transform: translate(-50%,-50%);
+	}
+}

+ 137 - 0
assets/css/common.scss

@@ -0,0 +1,137 @@
+// 字体
+@for $i from 20 through 100{
+    .fs#{$i} {
+			font-size: #{$i}rpx;
+    }
+}
+// 颜色
+@for $i from 0 through 9{
+    .color#{$i} {
+			color: #{$i}#{$i}#{$i};
+    }
+}
+// padding
+@for $i from 1 through 100{
+    .p#{$i} {
+			padding: #{$i}rpx;
+    }
+}
+@for $i from 1 through 100{
+    .ptb#{$i} {
+			padding-top: #{$i}rpx ;
+			padding-bottom: #{$i}rpx ;
+    }
+}
+@for $i from 1 through 100{
+    .plr#{$i} {
+			padding-left: #{$i}rpx;
+			padding-right: #{$i}rpx;
+    }
+}
+@for $i from 1 through 200{
+    .pt#{$i} {
+			padding-top: #{$i}rpx;
+    }
+}
+@for $i from 1 through 100{
+    .pl#{$i} {
+			padding-left: #{$i}rpx;
+    }
+}
+@for $i from 1 through 100{
+    .pr#{$i} {
+			padding-right: #{$i}rpx;
+    }
+}
+@for $i from 1 through 200{
+    .pb#{$i} {
+			padding-bottom: #{$i}rpx;
+    }
+}
+// margin
+@for $i from 1 through 100{
+    .m#{$i} {
+			margin: #{$i}rpx;
+    }
+}
+@for $i from 1 through 100{
+    .mtb#{$i} {
+			margin-top: #{$i}rpx ;
+			margin-bottom: #{$i}rpx ;
+    }
+}
+@for $i from 1 through 100{
+    .mlr#{$i} {
+			margin-left: #{$i}rpx;
+			margin-right: #{$i}rpx;
+    }
+}
+@for $i from 1 through 100{
+    .mt#{$i} {
+			margin-top: #{$i}rpx;
+    }
+}
+@for $i from 1 through 100{
+    .ml#{$i} {
+			margin-left: #{$i}rpx;
+    }
+}
+@for $i from 1 through 100{
+    .mr#{$i} {
+			margin-right: #{$i}rpx;
+    }
+}
+@for $i from 1 through 100{
+    .mb#{$i} {
+			margin-bottom: #{$i}rpx;
+    }
+}
+// 圆角
+@for $i from 0 through 100{
+    .radius#{$i} {
+			border-radius: #{$i}rpx;
+    }
+}
+// padding 左右+width自动计算
+@for $i from 10 through 60{
+    .w-calc-#{$i} {
+			width: calc(100% - #{$i*2}rpx);
+			padding-left:  #{$i}rpx;
+			padding-right:  #{$i}rpx;
+    }
+}
+
+// gap
+@for $i from 1 through 100{
+	.gap#{$i} {
+		gap: #{$i}rpx;
+	}
+}
+
+// 高
+@for $i from 1 through 900{
+	.h#{$i} {
+		height: #{$i}rpx;
+	}
+}
+// 宽
+@for $i from 1 through 900{
+	.w#{$i} {
+		width: #{$i}rpx;
+	}
+}
+// 宽
+@for $i from 1 through 900{
+	.lh#{$i} {
+		line-height: #{$i}rpx;
+	}
+}
+
+
+// font-weight
+$steps: 100 200 300 400 500 600 700 800 bold;
+@each $i in $steps {
+	.weight-#{$i} {
+		font-weight: $i;
+	}
+}

+ 141 - 0
assets/css/commonTheme.css

@@ -0,0 +1,141 @@
+.hb {
+	height: 100%;
+	box-sizing: border-box;
+}
+	
+.hidden {
+	overflow: hidden;
+}
+.w100 {
+	width: 100%;
+}
+
+.h100 {
+	height: 100%;
+}
+.row {
+	display: flex;
+	flex-direction: row;
+}
+
+.column {
+	display: flex;
+	flex-direction: column;
+}
+
+.justify-start {
+	display: flex;
+	justify-content: flex-start;
+}
+
+.justify-center {
+	display: flex;
+	justify-content: center;
+}
+
+.justify-end {
+	display: flex;
+	justify-content: flex-end;
+}
+
+.justify-around {
+	display: flex;
+	justify-content: space-around;
+}
+.justify-evenly {
+	display: flex;
+	justify-content: space-evenly;
+}
+
+.justify-between {
+	display: flex;
+	justify-content: space-between;
+}
+
+.align-start {
+	display: flex;
+	align-items: flex-start;
+}
+
+.align-center {
+	display: flex;
+	align-items: center;
+}
+
+.align-end {
+	display: flex;
+	align-items: flex-end;
+}
+
+.center {
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.centerV {
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	flex-direction: column;
+}
+
+.wrap {
+	flex-wrap: wrap;
+}
+
+.flex-1 {
+	flex: 1;
+}
+.ellipsis {
+	overflow: hidden;
+	text-overflow: ellipsis;
+	display: -webkit-box;
+	-webkit-box-orient: vertical;
+	box-sizing: border-box;
+	width: 100%;
+	-webkit-line-clamp: 1;
+}
+
+.lines-2 {
+	-webkit-line-clamp: 2 !important;
+}
+
+.lines-3 {
+	-webkit-line-clamp: 3 !important;
+}
+
+.bold {
+	font-weight: bold;
+}
+
+.line-through {
+	text-decoration: line-through;
+}
+
+.nowrap {
+	white-space: nowrap;
+}
+
+.scrollx {
+	overflow-x: scroll;
+}
+
+.scrolly {
+	overflow-y: scroll;
+}
+.base-textcol{
+	color: var(--base-color-text);
+}
+.color9{
+	color: #999;
+}
+.color6{
+	color: #666;
+}
+.bgf{
+	background-color: #fff;
+}
+.base-color{
+	color: #018C39;
+}

+ 34 - 0
assets/css/theme.scss

@@ -0,0 +1,34 @@
+// 这一套作为默认
+/*自定义主题色 */
+$--base-color:#018c39;
+$--base-color-text:#626468;
+$--base-color2:#e7f1fe;
+$--base-color3:#425034;
+$--base-color-a:#FF5C03;
+$--base-color-price:#FF1212;
+$--base-color-gray:#DEDFE4;
+$--base-color-dark:#313131;
+$--base-color-red:#ef4c50;
+$--base-color-dark2:#3E3E3E;
+$--base-color-success:#a3db42;
+$--base-color-false:#f93e3e;
+$--base-color-0:#000;
+$--base-color-1:#111;
+$--base-color-3:#333;
+$--base-color-6:#666;
+$--base-color-9:#999;
+$--base-color-f8:#f8f8f8;
+$--base-color-f5:#f5f5f5;
+$--base-bg: #1773ff;
+$--base-bg2:#e7f1fe;
+$--base-bor-red:#f7a1a1;
+$--base-bor-blue:#c9e1fb;
+$--base-cont-bg:#F3F5F9;
+$--base-false-bg:#fae7e7;
+$--base-sure-bg:#e7f2fe;
+$--base-bg-f:#fff;
+$--base-bg-red:#ee0a25;
+$--base-bg-blue:#1677ff;
+$--base-bg-orange:#FF7F00;
+
+

文件差異過大導致無法顯示
+ 2 - 0
assets/iconfont/iconfont.css


二進制
assets/iconfont/iconfont.ttf


+ 80 - 0
common/request.js

@@ -0,0 +1,80 @@
+// uni-app请求封装
+export default class Request {
+	http(router, data = {}, method,contentType) {
+		let that = this;
+		// let path = 'http://localhost:7014';
+		// let path = 'http://192.168.10.158:7014';
+		let path = 'https://userapp.beliyostore.com'; 
+		// let path = "http://d7zwsx.natappfree.cc"
+		uni.setStorageSync('requestPath',path)
+		// uni.showLoading({
+		// 	title: '加载中'
+		// });
+		return new Promise((resolve, reject) => {
+			let token = uni.getStorageSync('AppToken');
+			var httpContentType='application/x-www-form-urlencoded';
+			if(contentType!=undefined){
+				//application/json;charset=UTF-8
+				httpContentType=contentType;
+			}
+			var routers=router;
+			// 请求
+			uni.request({
+				header: {
+					// 'Content-Type': 'application/x-www-form-urlencoded',
+					'Content-Type': httpContentType,
+					'AppToken': token
+				},
+				url: `${path}${router}`,
+				data: data,
+				method: method,
+				success: (res) => {
+					//收到开发者服务器成功返回的回调函数
+					if(res.data.code==401){//没有权限直接退出到登录界面
+						let pages = getCurrentPages();
+						pages.forEach(function(element) {
+						  if(element!=undefined&&element.route=="pages/auth/login"){
+						  	resolve(res.data)
+						  	return;
+						  }
+						});
+						// let url = pages[ pages.length - 1]; //当前页页面实例
+						// //如果登录界面已打开,自动关闭
+						// if(url!=undefined&&url.route=="pages/auth/login"){
+						//  	resolve(res.data)
+						// 	return;
+						// }
+						uni.navigateTo({
+							url:'/pages/auth/login',
+							success: () => {
+								uni.hideLoading();
+								
+							},
+							fail: () => {
+								uni.hideLoading();
+							}
+						})
+						return;
+					}
+					if (res.data.token) {
+						uni.setStorageSync('AppToken',res.data.token)
+					}
+					resolve(res.data)
+				},
+				fail:(res) =>{
+					//接口调用失败的回调函数
+				},
+				complete:(res) =>{
+					//接口调用结束的回调函数(调用成功、失败都会执行)
+					if (res.data && res.data.code == 401) {
+						return false
+					}
+					uni.hideLoading();
+				}
+				
+			})
+		})
+		 
+	}
+	
+}

+ 21 - 0
components/Loading.vue

@@ -0,0 +1,21 @@
+<template>
+  <view class="Loads acea-row row-center-wrapper" v-if="loading || !loaded" style="margin-top: 20rpx;">
+    <template v-if="loading">
+      <view class="iconfont icon-jiazai loading acea-row row-center-wrapper"></view>
+      正在加载中
+    </template>
+    <template v-if="!loading">
+      上拉加载更多
+    </template>
+  </view>
+</template>
+
+<script>
+  export default {
+    name: "Loading",
+    props: {
+      loaded: Boolean,
+      loading: Boolean
+    }
+  };
+</script>

+ 147 - 0
components/Menu.vue

@@ -0,0 +1,147 @@
+<template>
+	<view class="menu-list-box" v-if="carousel" :style="list.length <= menu ? `height:160rpx` : `height:320rpx`">
+		<swiper
+			class="menu-swiper-box"
+			:style="list.length <= menu ? `height:160rpx` : `height:320rpx`"
+			@change="onSwiper"
+			circular
+			:autoplay="false"
+			:interval="3000"
+			:duration="1000"
+		>
+			<swiper-item class="menu-swiper-item" v-for="(itemList, index) in carousel" :key="index" :style="list.length <= menu ? `height:200rpx` : `height:340rpx`">
+				<view class="menu-tab-box">
+					<view class="tab-list"  v-for="item in itemList" :key="item.menuName" @tap="routerTo(item)">
+						<image class="tab-img Shop-selector-circular" :style="{ width: imgW + 'rpx', height: imgW + 'rpx' }" :src="item.icon"></image>
+						<text class="Shop-selector-rect">{{ item.menuName }}</text>
+					</view>
+				</view>
+			</swiper-item>
+		</swiper>
+		<view class="menu-dots" v-if="carousel.length > 1">
+			<text :class="menuCurrent === index ? 'dot-active' : 'dot'" v-for="(dot, index) in carousel.length" :key="index"></text>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	components: {},
+	data() {
+		return {
+			menuCurrent: 0 //轮播下标
+		};
+	},
+	props: {
+		list: {
+			type: Array,
+			default: []
+		},
+		menu: {
+			default: 4
+		},
+		imgW: {
+			type: Number,
+			default: 88
+		}
+	},
+	computed: {
+		carousel() {
+			if (this.list) {
+				let data = this.sortData(this.list, this.menu * 2);
+				return data;
+			}
+		}
+	},
+	created() {},
+	methods: {
+		// 数据分层
+		sortData(oArr, length) {
+			let arr = [];
+			let minArr = [];
+			oArr.forEach(c => {
+				if (minArr.length === length) {
+					minArr = [];
+				}
+				if (minArr.length === 0) {
+					arr.push(minArr);
+				}
+				minArr.push(c);
+			});
+		 
+			return arr;
+		},
+		// 轮播
+		onSwiper(e) {
+			this.menuCurrent = e.detail.current;
+		},
+		routerTo(item) {
+			 this.$emit('menuClick',item);
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+.menu-list-box {
+	padding: 0rpx;
+	background: #fff;
+	box-sizing: border-box;
+	
+}
+.menu-list-box,
+.menu-swiper-box {
+	position: relative;
+	background: #fff;
+	.menu-swiper-item {
+		background: #fff;
+		height: 100%;
+		width: 100%;
+	}
+	.menu-tab-box {
+		display: flex;
+		flex-wrap: wrap;
+		.tab-list {
+			width: 25%;
+			display: -webkit-box;
+			display: -webkit-flex;
+			display: flex;
+			-webkit-box-orient: vertical;
+			-webkit-box-direction: normal;
+			-webkit-flex-direction: column;
+			flex-direction: column;
+			-webkit-box-align: center;
+			-webkit-align-items: center;
+			align-items: center;
+			font-size: 22rpx;
+			font-family: PingFang SC;
+			font-weight: 500;
+			color: rgba(51, 51, 51, 1);
+			padding-bottom: 30rpx;
+			.tab-img {
+				border-radius: 25rpx;
+				margin-bottom: 10rpx;
+			}
+		}
+	}
+	.menu-dots {
+		display: flex;
+		position: absolute;
+		left: 50%;
+		transform: translateX(-50%);
+		.dot {
+			width: 40rpx;
+			height: 3rpx;
+			background: #eeeeee;
+			margin-right: 10rpx;
+		}
+
+		.dot-active {
+			width: 40rpx;
+			height: 3rpx;
+			background: #018C39;
+			margin-right: 10rpx;
+		}
+	}
+}
+</style>

+ 166 - 0
components/chengpeng-audio/free-audio.vue

@@ -0,0 +1,166 @@
+<template>
+	<!-- 音频播放器组件 -->
+	<view v-if='url' class='flex justify-between align-center audio' >
+		<view class='mr-3'  @click='start(audioId)'>
+			<image :src='startPic' class='icon' v-show='!status'></image>
+			<image :src='endPic' class='icon' v-show='status'></image>
+		</view>
+		<view class='flex-1'>
+			<slider 
+				@change='changeAudio' 
+				:activeColor='activeColor' 
+				:min='0' 
+				:max='duration.toFixed(0)' 
+				:value='currentTime.toFixed(0)' 
+				:step='0.1'
+				backgroundColor="#E9F0F0"
+				:block-size='14'
+				block-color='#018C39'>
+			</slider>
+		</view>
+		<view class='ml-3'>{{getTime(Math.round(currentTime))}}</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				context: null,
+				currentTime: 0,
+				duration: 100,
+				status: false
+			}
+		},
+		props: {
+			url: String,
+			activeColor: {
+				type: String,
+				default: '#0E7EFC'
+			},
+			startPic: String,
+			endPic: String,
+			audioId: [String,Number]
+		},
+		created() {
+			this.context = uni.createInnerAudioContext();
+			this.context.src = this.url;
+			this.onTimeUpdate();
+			this.onCanplay();
+			this.onEnded();
+			uni.$on('stop',(id)=> {
+				if(id && id != this.audioId) {
+					this.context.stop();
+					this.status = false;
+				} else if(!id){
+					this.context.stop();
+					this.status = false;
+				}
+			})
+		},
+		methods: {
+			start(id) { //点击播放
+				let audioId = id;
+				if(this.status) {
+					this.context.pause();
+					this.status = !this.status;
+				}else {
+					uni.$emit('stop',id)
+					this.context.play()
+					this.status = !this.status;
+				}
+			},
+			onCanplay() { //进入可播放状态
+				this.context.onCanplay(() => {
+					this.context.duration;
+					setTimeout(()=>{
+						this.duration = this.context.duration;
+					},1000)
+				})
+			},
+			onTimeUpdate() { //音频播放进度
+				 this.context.onTimeUpdate(() => {
+					 if (!Number.isFinite( this.context.duration)) {
+						this.context.currentTime = Number.MAX_SAFE_INTEGER;
+						this.context.currentTime = 0;
+					 } else {
+						 this.duration = this.context.duration;
+						 this.currentTime = this.context.currentTime;
+					 }
+				 })
+			},
+			onEnded() { //播放结束
+				this.context.onEnded(()=> {
+					this.status = false;
+					this.currentTime = 0;
+				})
+			},
+			changeAudio(e) {
+				let paused = this.context.paused;
+				this.context.pause();
+				this.context.seek(e.detail.value)
+				if(!paused) {
+					this.context.play();
+				} 
+			},
+			getTime(time) {
+				let m = parseInt(time / 60);
+				let s = time % 60;
+				return this.towNum(m) + ':' + this.towNum(s);
+			},
+			towNum(num) {
+				if(num >= 10) {
+					return num;
+				}else {
+					return '0' + num;
+				}
+			}
+		}
+	}
+</script>
+
+<style>
+	.audio {
+		background: #F5F7F7;
+		padding: 30upx 20upx;
+	}
+	
+	.icon {
+		width: 54upx;
+		height: 54upx;
+	}
+	slider{
+		margin: 0;
+	}
+	.flex {
+		display: flex;
+		flex-direction: row;
+	}
+	
+	.justify-between {
+		justify-content: between;
+	}
+	
+	.align-center {
+		align-items: center;
+	}
+	
+	.flex-1 {
+		flex: 1;
+	}
+	
+	.ml-3 {
+		margin-left: 20upx;
+		font-size: 24upx;
+		font-family: PingFang SC;
+		font-weight: 500;
+		color: #666666;
+	}
+	
+	.mr-3 {
+		margin-right: 30upx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+</style>

+ 42 - 0
components/chengpeng-audio/redme.md

@@ -0,0 +1,42 @@
+## 参数
+
+| url      | activeColor | startPic       | endPic         | 组件id                                                |
+| -------- | ----------- | -------------- | -------------- | ----------------------------------------------------- |
+| 音频链接 | 进度条颜色  | 开始播放的图片 | 暂停播放的图片 | audioId(必填,且id不可为数字0,建议格式 ‘audio’+数字) |
+
+## 使用方法
+
+```javascript
+//html
+<template>
+  <free-audio startPic='/static/images/icon/play.png' endPic='/static/images/icon/stop.png' :audioId='audio1' :url='path'></free-audio>
+</template>
+
+//js
+
+import freeAudio from '@/components/free-audio.vue'
+export default {
+    components: {freeAudio},
+    data() {
+        return{
+            path: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-hello-uniapp/2cc220e0-c27a-11ea-9dfb-6da8e309e0d8.mp3'
+        }
+    },
+    methods: {
+
+    },
+} 
+
+//暂停所有音频(一般用于页面切换时停止正在播放的音频)
+onUnload() { //普通页面在 onUnload 生命周期中执行
+  uni.$emit('stop')
+},
+onHide() { //tabBar页面在onHide生命周期中执行
+  uni.$emit('stop')
+}
+
+
+
+
+```
+

二進制
components/chengpeng-audio/static/play.png


二進制
components/chengpeng-audio/static/stop.png


+ 143 - 0
components/evan-switch/evan-switch.vue

@@ -0,0 +1,143 @@
+<template>
+	<!-- <view @click="toggle" class="evan-switch" :class="{'evan-switch--disabled':disabled}" :style="{width:2*size+'px',height:switchHeight,borderRadius:size+'px',backgroundColor:currentValue===activeValue?activeColor:inactiveColor}">
+		<view class="evan-switch__circle" :style="{width:size+'px',height:size+'px',transform:currentValue===activeValue?`translateX(${size}px)`:`translateX(0)`}"></view>
+	</view> -->
+	<view @click="toggle" class="evan-switch" :class="{'evan-switch--disabled':disabled}" :style="{backgroundColor:currentValue===activeValue?activeColor:inactiveColor}">
+		<view class="evan-switch__circle" :style="{transform:currentValue===activeValue?`translateX(${29}px)`:`translateX(0)`}"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'EvanSwitch',
+		props: {
+			value: {
+				type: [String, Number, Boolean],
+				default: false
+			},
+			activeColor: {
+				type: String,
+				default: '#108ee9'
+			},
+			inactiveColor: {
+				type: String,
+				default: '#fff'
+			},
+			size: {
+				type: Number,
+				default: 30
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			activeValue: {
+				type: [String, Number, Boolean],
+				default: true
+			},
+			inactiveValue: {
+				type: [String, Number, Boolean],
+				default: false
+			},
+			beforeChange: {
+				type: Function,
+				default: null
+			},
+			extraData: null,
+			contextLevel: {
+				type: Number,
+				default: 1
+			}
+		},
+		computed: {
+			switchHeight() {
+				// #ifdef APP-NVUE
+				return this.size + 2 + 'px'
+				// #endif
+				// #ifndef APP-NVUE
+				return this.size + 'px'
+				// #endif
+			}
+		},
+		watch: {
+			value: {
+				immediate: true,
+				handler(value) {
+					this.currentValue = value
+				}
+			}
+		},
+		data() {
+			return {
+				currentValue: false
+			}
+		},
+		methods: {
+			toggle() {
+				if (!this.disabled) {
+					if (this.beforeChange && typeof this.beforeChange === 'function') {
+						let context = this
+						for (let i = 0; i < this.contextLevel; i++) {
+							context = context.$options.parent
+						}
+						const result = this.beforeChange(this.currentValue === this.activeValue ? this.inactiveValue : this.activeValue,
+							this.extraData, context)
+						if (typeof result === 'object') {
+							result.then(() => {
+								this.toggleValue()
+							}).catch(() => {})
+						} else if (typeof result === 'boolean' && result) {
+							this.toggleValue()
+						}
+					} else {
+						this.toggleValue()
+					}
+				}
+			},
+			toggleValue() {
+				this.currentValue = this.currentValue === this.activeValue ? this.inactiveValue : this.activeValue
+				this.$emit('input', this.currentValue)
+				this.$emit('change', this.currentValue)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.evan-switch {
+		position: relative;
+		border-width: 1px;
+		border-color: rgba(0, 0, 0, 0.1);
+		border-style: solid;
+		transition: background-color 0.3s;
+		width: 100upx;
+		height: 36upx;
+		background: #018C39;
+		border-radius: 18upx;
+		/* #ifndef APP-NVUE */
+		box-sizing: content-box;
+		/* #endif */
+	}
+
+	.evan-switch--disabled {
+		opacity: 0.3;
+	}
+
+	.evan-switch__circle {
+		position: absolute;
+		left: -4upx;
+		top: -8upx;
+		width: 50upx;
+		height: 50upx;
+		background: #FFFFFF;
+		box-shadow: 0px 2px 10px 0px rgba(166, 217, 212, 0.49);
+		border-radius: 50%;
+		/* #ifndef APP-NVUE */
+		box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		box-shadow: 1px 0 0px 0 rgba(0, 0, 0, 0.05);
+		/* #endif */
+		transition: transform 0.3s;
+	}
+</style>

+ 68 - 0
components/im/base/common.js

@@ -0,0 +1,68 @@
+export function caculateTimeago(dateTimeStamp) {
+  const minute = 1000 * 60; // 把分,时,天,周,半个月,一个月用毫秒表示
+
+  const hour = minute * 60;
+  const day = hour * 24;
+  const week = day * 7;
+  const now = new Date().getTime(); // 获取当前时间毫秒
+
+  const diffValue = now - dateTimeStamp; // 时间差
+
+  let result = '';
+
+  if (diffValue < 0) {
+    return;
+  }
+
+  const minC = diffValue / minute; // 计算时间差的分,时,天,周,月
+
+  const hourC = diffValue / hour;
+  const dayC = diffValue / day;
+  const weekC = diffValue / week;
+
+  if (weekC >= 1 && weekC <= 4) {
+    result = ` ${parseInt(weekC, 10)}周前`;
+  } else if (dayC >= 1 && dayC <= 6) {
+    result = ` ${parseInt(dayC, 10)}天前`;
+  } else if (hourC >= 1 && hourC <= 23) {
+    result = ` ${parseInt(hourC, 10)}小时前`;
+  } else if (minC >= 1 && minC <= 59) {
+    result = ` ${parseInt(minC, 10)}分钟前`;
+  } else if (diffValue >= 0 && diffValue <= minute) {
+    result = '刚刚';
+  } else {
+    const datetime = new Date();
+    datetime.setTime(dateTimeStamp);
+    const Nyear = datetime.getFullYear();
+    const Nmonth = datetime.getMonth() + 1 < 10 ? `0${datetime.getMonth() + 1}` : datetime.getMonth() + 1;
+    const Ndate = datetime.getDate() < 10 ? `0${datetime.getDate()}` : datetime.getDate();
+    result = `${Nyear}-${Nmonth}-${Ndate}`;
+  }
+
+  return result;
+}
+export function formateTime(secondTime) {
+  const time = secondTime;
+  let newTime;
+  let hour;
+  let minite;
+  let seconds;
+  if (time >= 3600) {
+    hour = parseInt(time / 3600) < 10 ? `0${parseInt(time / 3600)}` : parseInt(time / 3600);
+    minite = parseInt(time % 60 / 60) < 10 ? `0${parseInt(time % 60 / 60)}` : parseInt(time % 60 / 60);
+    seconds = time % 3600 < 10 ? `0${time % 3600}` : time % 3600;
+    if (seconds > 60) {
+      minite = parseInt(seconds / 60) < 10 ? `0${parseInt(seconds / 60)}` : parseInt(seconds / 60);
+      seconds = seconds % 60 < 10 ? `0${seconds % 60}` : seconds % 60;
+    }
+    newTime = `${hour}:${minite}:${seconds}`;
+  } else if (time >= 60 && time < 3600) {
+    minite = parseInt(time / 60) < 10 ? `0${parseInt(time / 60)}` : parseInt(time / 60);
+    seconds = time % 60 < 10 ? `0${time % 60}` : time % 60;
+    newTime = `00:${minite}:${seconds}`;
+  } else if (time < 60) {
+    seconds = time < 10 ? `0${time}` : time;
+    newTime = `00:00:${seconds}`;
+  }
+  return newTime;
+}

+ 146 - 0
components/im/base/emojiMap.js

@@ -0,0 +1,146 @@
+export const emojiUrl = 'https://web.sdk.qcloud.com/im/assets/emoji/';
+export const emojiMap = {
+  '[NO]': 'emoji_0@2x.png',
+  '[OK]': 'emoji_1@2x.png',
+  '[下雨]': 'emoji_2@2x.png',
+  '[么么哒]': 'emoji_3@2x.png',
+  '[乒乓]': 'emoji_4@2x.png',
+  '[便便]': 'emoji_5@2x.png',
+  '[信封]': 'emoji_6@2x.png',
+  '[偷笑]': 'emoji_7@2x.png',
+  '[傲慢]': 'emoji_8@2x.png',
+  '[再见]': 'emoji_9@2x.png',
+  '[冷汗]': 'emoji_10@2x.png',
+  '[凋谢]': 'emoji_11@2x.png',
+  '[刀]': 'emoji_12@2x.png',
+  '[删除]': 'emoji_13@2x.png',
+  '[勾引]': 'emoji_14@2x.png',
+  '[发呆]': 'emoji_15@2x.png',
+  '[发抖]': 'emoji_16@2x.png',
+  '[可怜]': 'emoji_17@2x.png',
+  '[可爱]': 'emoji_18@2x.png',
+  '[右哼哼]': 'emoji_19@2x.png',
+  '[右太极]': 'emoji_20@2x.png',
+  '[右车头]': 'emoji_21@2x.png',
+  '[吐]': 'emoji_22@2x.png',
+  '[吓]': 'emoji_23@2x.png',
+  '[咒骂]': 'emoji_24@2x.png',
+  '[咖啡]': 'emoji_25@2x.png',
+  '[啤酒]': 'emoji_26@2x.png',
+  '[嘘]': 'emoji_27@2x.png',
+  '[回头]': 'emoji_28@2x.png',
+  '[困]': 'emoji_29@2x.png',
+  '[坏笑]': 'emoji_30@2x.png',
+  '[多云]': 'emoji_31@2x.png',
+  '[大兵]': 'emoji_32@2x.png',
+  '[大哭]': 'emoji_33@2x.png',
+  '[太阳]': 'emoji_34@2x.png',
+  '[奋斗]': 'emoji_35@2x.png',
+  '[奶瓶]': 'emoji_36@2x.png',
+  '[委屈]': 'emoji_37@2x.png',
+  '[害羞]': 'emoji_38@2x.png',
+  '[尴尬]': 'emoji_39@2x.png',
+  '[左哼哼]': 'emoji_40@2x.png',
+  '[左太极]': 'emoji_41@2x.png',
+  '[左车头]': 'emoji_42@2x.png',
+  '[差劲]': 'emoji_43@2x.png',
+  '[弱]': 'emoji_44@2x.png',
+  '[强]': 'emoji_45@2x.png',
+  '[彩带]': 'emoji_46@2x.png',
+  '[彩球]': 'emoji_47@2x.png',
+  '[得意]': 'emoji_48@2x.png',
+  '[微笑]': 'emoji_49@2x.png',
+  '[心碎了]': 'emoji_50@2x.png',
+  '[快哭了]': 'emoji_51@2x.png',
+  '[怄火]': 'emoji_52@2x.png',
+  '[怒]': 'emoji_53@2x.png',
+  '[惊恐]': 'emoji_54@2x.png',
+  '[惊讶]': 'emoji_55@2x.png',
+  '[憨笑]': 'emoji_56@2x.png',
+  '[手枪]': 'emoji_57@2x.png',
+  '[打哈欠]': 'emoji_58@2x.png',
+  '[抓狂]': 'emoji_59@2x.png',
+  '[折磨]': 'emoji_60@2x.png',
+  '[抠鼻]': 'emoji_61@2x.png',
+  '[抱抱]': 'emoji_62@2x.png',
+  '[抱拳]': 'emoji_63@2x.png',
+  '[拳头]': 'emoji_64@2x.png',
+  '[挥手]': 'emoji_65@2x.png',
+  '[握手]': 'emoji_66@2x.png',
+  '[撇嘴]': 'emoji_67@2x.png',
+  '[擦汗]': 'emoji_68@2x.png',
+  '[敲打]': 'emoji_69@2x.png',
+  '[晕]': 'emoji_70@2x.png',
+  '[月亮]': 'emoji_71@2x.png',
+  '[棒棒糖]': 'emoji_72@2x.png',
+  '[汽车]': 'emoji_73@2x.png',
+  '[沙发]': 'emoji_74@2x.png',
+  '[流汗]': 'emoji_75@2x.png',
+  '[流泪]': 'emoji_76@2x.png',
+  '[激动]': 'emoji_77@2x.png',
+  '[灯泡]': 'emoji_78@2x.png',
+  '[炸弹]': 'emoji_79@2x.png',
+  '[熊猫]': 'emoji_80@2x.png',
+  '[爆筋]': 'emoji_81@2x.png',
+  '[爱你]': 'emoji_82@2x.png',
+  '[爱心]': 'emoji_83@2x.png',
+  '[爱情]': 'emoji_84@2x.png',
+  '[猪头]': 'emoji_85@2x.png',
+  '[猫咪]': 'emoji_86@2x.png',
+  '[献吻]': 'emoji_87@2x.png',
+  '[玫瑰]': 'emoji_88@2x.png',
+  '[瓢虫]': 'emoji_89@2x.png',
+  '[疑问]': 'emoji_90@2x.png',
+  '[白眼]': 'emoji_91@2x.png',
+  '[皮球]': 'emoji_92@2x.png',
+  '[睡觉]': 'emoji_93@2x.png',
+  '[磕头]': 'emoji_94@2x.png',
+  '[示爱]': 'emoji_95@2x.png',
+  '[礼品袋]': 'emoji_96@2x.png',
+  '[礼物]': 'emoji_97@2x.png',
+  '[篮球]': 'emoji_98@2x.png',
+  '[米饭]': 'emoji_99@2x.png',
+  '[糗大了]': 'emoji_100@2x.png',
+  '[红双喜]': 'emoji_101@2x.png',
+  '[红灯笼]': 'emoji_102@2x.png',
+  '[纸巾]': 'emoji_103@2x.png',
+  '[胜利]': 'emoji_104@2x.png',
+  '[色]': 'emoji_105@2x.png',
+  '[药]': 'emoji_106@2x.png',
+  '[菜刀]': 'emoji_107@2x.png',
+  '[蛋糕]': 'emoji_108@2x.png',
+  '[蜡烛]': 'emoji_109@2x.png',
+  '[街舞]': 'emoji_110@2x.png',
+  '[衰]': 'emoji_111@2x.png',
+  '[西瓜]': 'emoji_112@2x.png',
+  '[调皮]': 'emoji_113@2x.png',
+  '[象棋]': 'emoji_114@2x.png',
+  '[跳绳]': 'emoji_115@2x.png',
+  '[跳跳]': 'emoji_116@2x.png',
+  '[车厢]': 'emoji_117@2x.png',
+  '[转圈]': 'emoji_118@2x.png',
+  '[鄙视]': 'emoji_119@2x.png',
+  '[酷]': 'emoji_120@2x.png',
+  '[钞票]': 'emoji_121@2x.png',
+  '[钻戒]': 'emoji_122@2x.png',
+  '[闪电]': 'emoji_123@2x.png',
+  '[闭嘴]': 'emoji_124@2x.png',
+  '[闹钟]': 'emoji_125@2x.png',
+  '[阴险]': 'emoji_126@2x.png',
+  '[难过]': 'emoji_127@2x.png',
+  '[雨伞]': 'emoji_128@2x.png',
+  '[青蛙]': 'emoji_129@2x.png',
+  '[面条]': 'emoji_130@2x.png',
+  '[鞭炮]': 'emoji_131@2x.png',
+  '[风车]': 'emoji_132@2x.png',
+  '[飞吻]': 'emoji_133@2x.png',
+  '[飞机]': 'emoji_134@2x.png',
+  '[饥饿]': 'emoji_135@2x.png',
+  '[香蕉]': 'emoji_136@2x.png',
+  '[骷髅]': 'emoji_137@2x.png',
+  '[麦克风]': 'emoji_138@2x.png',
+  '[麻将]': 'emoji_139@2x.png',
+  '[鼓掌]': 'emoji_140@2x.png',
+  '[龇牙]': 'emoji_141@2x.png'
+};
+export const emojiName = ['[龇牙]', '[调皮]', '[流汗]', '[偷笑]', '[再见]', '[敲打]', '[擦汗]', '[猪头]', '[玫瑰]', '[流泪]', '[大哭]', '[嘘]', '[酷]', '[抓狂]', '[委屈]', '[便便]', '[炸弹]', '[菜刀]', '[可爱]', '[色]', '[害羞]', '[得意]', '[吐]', '[微笑]', '[怒]', '[尴尬]', '[惊恐]', '[冷汗]', '[爱心]', '[示爱]', '[白眼]', '[傲慢]', '[难过]', '[惊讶]', '[疑问]', '[困]', '[么么哒]', '[憨笑]', '[爱情]', '[衰]', '[撇嘴]', '[阴险]', '[奋斗]', '[发呆]', '[右哼哼]', '[抱抱]', '[坏笑]', '[飞吻]', '[鄙视]', '[晕]', '[大兵]', '[可怜]', '[强]', '[弱]', '[握手]', '[胜利]', '[抱拳]', '[凋谢]', '[米饭]', '[蛋糕]', '[西瓜]', '[啤酒]', '[瓢虫]', '[勾引]', '[OK]', '[爱你]', '[咖啡]', '[月亮]', '[刀]', '[发抖]', '[差劲]', '[拳头]', '[心碎了]', '[太阳]', '[礼物]', '[皮球]', '[骷髅]', '[挥手]', '[闪电]', '[饥饿]', '[困]', '[咒骂]', '[折磨]', '[抠鼻]', '[鼓掌]', '[糗大了]', '[左哼哼]', '[打哈欠]', '[快哭了]', '[吓]', '[篮球]', '[乒乓]', '[NO]', '[跳跳]', '[怄火]', '[转圈]', '[磕头]', '[回头]', '[跳绳]', '[激动]', '[街舞]', '[献吻]', '[左太极]', '[右太极]', '[闭嘴]', '[猫咪]', '[红双喜]', '[鞭炮]', '[红灯笼]', '[麻将]', '[麦克风]', '[礼品袋]', '[信封]', '[象棋]', '[彩带]', '[蜡烛]', '[爆筋]', '[棒棒糖]', '[奶瓶]', '[面条]', '[香蕉]', '[飞机]', '[左车头]', '[车厢]', '[右车头]', '[多云]', '[下雨]', '[钞票]', '[熊猫]', '[灯泡]', '[风车]', '[闹钟]', '[雨伞]', '[彩球]', '[钻戒]', '[沙发]', '[纸巾]', '[手枪]', '[青蛙]'];

+ 113 - 0
components/im/base/message-facade.js

@@ -0,0 +1,113 @@
+import {
+  emojiMap,
+  emojiUrl
+} from './emojiMap';
+/** 传入message.element(群系统消息SystemMessage,群提示消息GroupTip除外)
+ * content = {
+ *  type: 'TIMTextElem',
+ *  content: {
+ *    text: 'AAA[龇牙]AAA[龇牙]AAA[龇牙AAA]'
+ *  }
+ *}
+ **/
+// 群提示消息的含义 (opType)
+
+const GROUP_TIP_TYPE = {
+  MEMBER_JOIN: 1,
+  MEMBER_QUIT: 2,
+  MEMBER_KICKED_OUT: 3,
+  MEMBER_SET_ADMIN: 4,
+  // 被设置为管理员
+  MEMBER_CANCELED_ADMIN: 5,
+  // 被取消管理员
+  GROUP_INFO_MODIFIED: 6,
+  // 修改群资料,转让群组为该类型,msgBody.msgGroupNewInfo.ownerAccount表示新群主的ID
+  MEMBER_INFO_MODIFIED: 7 // 修改群成员信息
+
+}; // 解析小程序text, 表情信息也是[嘻嘻]文本
+
+export function parseText(message) {
+  const renderDom = [];
+  let temp = message.payload.text;
+  let left = -1;
+  let right = -1;
+
+  while (temp !== '') {
+    left = temp.indexOf('[');
+    right = temp.indexOf(']');
+
+    switch (left) {
+      case 0:
+        if (right === -1) {
+          renderDom.push({
+            name: 'span',
+            text: temp
+          });
+          temp = '';
+        } else {
+          const _emoji = temp.slice(0, right + 1);
+
+          if (emojiMap[_emoji]) {
+            renderDom.push({
+              name: 'img',
+              src: emojiUrl + emojiMap[_emoji]
+            });
+            temp = temp.substring(right + 1);
+          } else {
+            renderDom.push({
+              name: 'span',
+              text: '['
+            });
+            temp = temp.slice(1);
+          }
+        }
+
+        break;
+
+      case -1:
+        renderDom.push({
+          name: 'span',
+          text: temp
+        });
+        temp = '';
+        break;
+
+      default:
+        renderDom.push({
+          name: 'span',
+          text: temp.slice(0, left)
+        });
+        temp = temp.substring(left);
+        break;
+    }
+  }
+
+  return renderDom;
+} 
+// 解析图片消息
+
+export function parseImage(message) {
+  const renderDom = [{
+    name: 'image',
+    // 这里默认渲染的是 1080P 的图片
+    src: message.payload.imageInfoArray[0].url
+  }];
+  return renderDom;
+} // 解析视频消息
+
+export function parseVideo(message) {
+  const renderDom = {
+    name: 'video',
+    src: message.payload.videoUrl
+  };
+  return renderDom;
+} // 解析语音消息
+
+export function parseAudio(message) {
+  const renderDom = {
+    name: 'audio',
+    src: message.payload.url,
+    second: message.payload.second === 0 ? 1 : message.payload.second
+  };
+  return renderDom;
+}

+ 29 - 0
components/im/tui-chat/message-elements/audio-message/index.css

@@ -0,0 +1,29 @@
+.audio-message {
+	padding: 10rpx 18rpx;
+	border-radius: 2px 10px 10px 10px;
+	border: 1px solid #D9D9D9;
+	display: flex;
+}
+
+.audio-icon {
+	width: 28px;
+	height: 28px;
+}
+
+.my-audio {
+	border-radius: 10px 2px 10px 10px;
+	background: rgba(0, 110, 255, 0.10);
+	border: 1px solid rgba(0, 110, 255, 0.30);
+}
+
+.audio {
+	/*border-radius: 2px 10px 10px 10px;*/
+	height: 60rpx;
+	font-family: PingFangSC-Medium;
+	font-size: 28rpx;
+	color: #000000;
+	line-height: 28rpx;
+	display: flex;
+	align-items: center;
+	justify-content: flex-end;
+}

+ 67 - 0
components/im/tui-chat/message-elements/audio-message/index.vue

@@ -0,0 +1,67 @@
+<template>
+	<view :class="'audio-message ' + (isMine ? 'my-audio' : '')">
+		<image class="audio-icon" src="../../../../../static/images/audio.png"></image>
+		<view class="audio " @click="handlePlayAudioMessage" :style="'width: ' + 120 + 'rpx'">{{ '" ' + message.payload.second }}</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			audio: {}
+		};
+	},
+
+	components: {},
+	props: {
+		message: {
+			type: Object,
+			default: () => {}
+		},
+		isMine: {
+			type: Boolean,
+			default: true
+		}
+	},
+	watch: {
+		message: {
+			handler: function(newVal) {
+				this.setData({
+					message: newVal
+				});
+			},
+			immediate: true,
+			deep: true
+		}
+	},
+
+	beforeMount() {
+		this.audio = uni.createInnerAudioContext();
+		this.audio.onPlay(() => {
+			console.log('开始播放');
+		});
+		this.audio.onEnded(() => {
+			console.log('停止播放');
+		});
+		this.audio.onError(e => {
+			console.error(e, 'onError');
+			// ios 音频播放无声,可能是因为系统开启了静音模式
+			uni.showToast({
+				icon: 'none',
+				title: '该音频暂不支持播放'
+			});
+		});
+	},
+
+	methods: {
+		handlePlayAudioMessage() {
+			this.audio.src = this.message.payload.url;
+			this.audio.play();
+		}
+	}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 103 - 0
components/im/tui-chat/message-elements/custom-message/index.css

@@ -0,0 +1,103 @@
+.custom-message {
+	display: flex;
+	padding: 10rpx 24rpx;
+	background-color: #fff;
+	border-radius: 2px 10px 10px 10px;
+	border: 1px solid #D9D9D9;
+}
+
+.my-custom {
+	border-radius: 10px 2px 10px 10px;
+	border: 1px solid rgba(0, 110, 255, 0.30);
+}
+
+.custom-content-title {
+	font-family: PingFangSC-Medium;
+	width: 278rpx;
+	line-height: 34rpx;
+	font-size: 24rpx;
+	color: #000000;
+	letter-spacing: 0;
+	margin-bottom: 12rpx;
+}
+
+.custom-content-description {
+	font-family: PingFangSC-Regular;
+	width: 278rpx;
+	line-height: 34rpx;
+	font-size: 28rpx;
+	color: #006EFF;
+	letter-spacing: 0;
+	margin-bottom: 12rpx;
+}
+
+.custom-content-price {
+	font-family: PingFangSC-Medium;
+	line-height: 50rpx;
+	color: #FF7201;
+	letter-spacing: 0;
+}
+
+.custom-image {
+	width: 135rpx;
+	height: 135rpx;
+	border-radius: 6rpx;
+	margin-right: 10rpx;
+	margin-top: 4rpx;
+}
+
+.custom-content-score {
+	display: flex;
+	align-items: center;
+	padding-bottom: 12rpx;
+}
+
+.custom-content-score .score-star {
+	width: 36rpx;
+	height: 36rpx;
+	margin-right: 10rpx;
+}
+
+.text-message {
+	display: inline-flex;
+	max-width: 60vw;
+	line-height: 52rpx;
+	padding: 12rpx 24rpx;
+	background: #F8F8F8;
+	border: 1px solid #D9D9D9;
+	border-radius: 2px 10px 10px 10px;
+}
+
+.my-text {
+	border-radius: 10px 2px 10px 10px;
+	border: 1px solid rgba(0, 110, 255, 0.30);
+	background: rgba(0, 110, 255, 0.10);
+}
+
+.message-body-span {
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	/*justify-content: flex-start;*/
+	flex-wrap: wrap;
+	outline: none;
+	font-size: 28rpx;
+	color: #333333;
+	position: relative;
+	max-width: 60vw;
+}
+
+.message-body-span-text {
+	width: 100%;
+	display: inline;
+	word-wrap: break-word;
+	word-break: break-all;
+}
+
+.custom-content-text {
+	font-family: PingFangSC-Regular;
+	height: 25px;
+	line-height: 25px;
+	font-size: 28rpx;
+	letter-spacing: 0;
+}

+ 236 - 0
components/im/tui-chat/message-elements/custom-message/index.vue

@@ -0,0 +1,236 @@
+<template>
+	<view>
+		<view v-if="renderDom[0].type === 'order'" :class="'custom-message ' + (isMine ? 'my-custom' : '')">
+			<image class="custom-image" :src="renderDom[0].imageUrl"></image>
+			<view class="custom-content">
+				<view class="custom-content-title">{{ renderDom[0].title }}</view>
+				<view class="custom-content-description">{{ renderDom[0].description }}</view>
+				<view class="custom-content-price">{{ renderDom[0].price }}</view>
+			</view>
+		</view>
+		<view v-if="renderDom[0].type === 'consultion'" :class="'custom-message ' + (isMine ? 'my-custom' : '')">
+			<view class="custom-content">
+				<view class="custom-content-title">{{ renderDom[0].title }}</view>
+				<view v-for="(item, index) in renderDom[0].item" :key="index" class="custom-content-description" :id="item.key">{{ item.key }}</view>
+				<view class="custom-content-description">{{ renderDom[0].description }}</view>
+			</view>
+		</view>
+		<view v-if="renderDom[0].type === 'evaluation'" :class="'custom-message ' + (isMine ? 'my-custom' : '')">
+			<view class="custom-content">
+				<view class="custom-content-title">{{ renderDom[0].title }}</view>
+				<view class="custom-content-score">
+					<image v-for="(item, index) in renderDom[0].score" :key="index" class="score-star" src="/static/images/star.png"></image>
+				</view>
+				<view class="custom-content-description">{{ renderDom[0].description }}</view>
+			</view>
+		</view>
+		<view v-if="renderDom[0].type === 'group_create'" :class="'custom-message ' + (isMine ? 'my-custom' : '')">
+			<view class="custom-content-text">{{ renderDom[0].text }}</view>
+		</view>
+		<view v-if="renderDom[0].type === 'c2cCalling' || renderDom[0].type === 'groupCalling'" :class="'custom-message ' + (isMine ? 'my-custom' : '')">
+			<view class="custom-content-text">{{ renderDom[0].text }}</view>
+		</view>
+		<view v-if="renderDom[0].type === 'notSupport'" class="message-body-span text-message">
+			<view class="message-body-span-text">{{ renderDom[0].text }}</view>
+		</view>
+		<view v-if="renderDom[0].type === 'finish'" :class="'custom-message ' + (isMine ? 'my-custom' : '')">
+			<view class="custom-content-text">{{ renderDom[0].text }}</view>
+		</view>
+	</view>
+</template>
+
+<script>
+import { formateTime } from '../../../base/common.js';
+export default {
+	data() {
+		return {};
+	},
+	components: {},
+	props: {
+		message: {
+			type: Object,
+			default: () => {}
+		},
+		isMine: {
+			type: Boolean,
+			default: true
+		}
+	},
+	watch: {
+		message: {
+			handler: function(newVal) {
+				this.setData({
+					message: newVal,
+					renderDom: this.parseCustom(newVal)
+				});
+			},
+			immediate: true,
+			deep: true
+		}
+	},
+	methods: {
+		// 解析音视频通话消息
+		extractCallingInfoFromMessage(message) {
+			const callingmessage = JSON.parse(message.payload.data);
+			if (callingmessage.businessID !== 1) {
+				return '';
+			}
+			const objectData = JSON.parse(callingmessage.data);
+			switch (callingmessage.actionType) {
+				case 1: {
+					if (objectData.call_end >= 0 && !callingmessage.groupID) {
+						return `通话时长:${formateTime(objectData.call_end)}`;
+					}
+					if (callingmessage.groupID) {
+						return '结束群聊';
+					}
+					if (objectData.data && objectData.data.cmd === 'switchToAudio') {
+						return '切换语音通话';
+					}
+					if (objectData.data && objectData.data.cmd === 'switchToVideo') {
+						return '切换视频通话';
+					}
+					return '发起通话';
+				}
+				case 2:
+					return '取消通话';
+				case 3:
+					if (objectData.data && objectData.data.cmd === 'switchToAudio') {
+						return '切换语音通话';
+					}
+					if (objectData.data && objectData.data.cmd === 'switchToVideo') {
+						return '切换视频通话';
+					}
+					return '已接听';
+				case 4:
+					return '拒绝通话';
+				case 5:
+					if (objectData.data && objectData.data.cmd === 'switchToAudio') {
+						return '切换语音通话';
+					}
+					if (objectData.data && objectData.data.cmd === 'switchToVideo') {
+						return '切换视频通话';
+					}
+					return '无应答';
+				default:
+					return '';
+			}
+		},
+		parseCustom(message) {
+			
+			// 约定自定义消息的 data 字段作为区分,不解析的不进行展示
+			if (message.payload.data === 'order') {
+				const extension = JSON.parse(message.payload.extension);
+				const renderDom = [
+					{
+						type: 'order',
+						name: 'custom',
+						title: extension.title || '',
+						imageUrl: extension.imageUrl || '',
+						price: extension.price || 0,
+						description: message.payload.description
+					}
+				];
+				return renderDom;
+			} // 客服咨询
+
+			if (message.payload.data === 'consultion') {
+				const extension = JSON.parse(message.payload.extension);
+				const renderDom = [
+					{
+						type: 'consultion',
+						title: extension.title || '',
+						item: extension.item || 0,
+						description: extension.description
+					}
+				];
+				return renderDom;
+			} // 服务评价
+
+			if (message.payload.data === 'evaluation') {
+				const extension = JSON.parse(message.payload.extension);
+				const renderDom = [
+					{
+						type: 'evaluation',
+						title: message.payload.description,
+						score: extension.score,
+						description: extension.comment
+					}
+				];
+				return renderDom;
+			} // 群消息解析
+			// 群消息解析
+			if (message.payload.data === 'group_create') {
+				const renderDom = [
+					{
+						type: 'group_create',
+						text: message.payload.extension
+					}
+				];
+				return renderDom;
+			}
+			if (message.payload.data === 'finish') {
+				console.log(111)
+				const renderDom = [
+					{
+						type: 'finish',
+						text: message.payload.extension
+					}
+				];
+				return renderDom;
+			}
+			// 音视频通话消息解析
+			const callingmessage = JSON.parse(message.payload.data);
+
+			if (callingmessage.businessID === 1) {
+				if (message.conversationType === 'GROUP') {
+					if (message.payload.data.actionType === 5) {
+						message.nick = message.payload.data.inviteeList ? message.payload.data.inviteeList.join(',') : message.from;
+					}
+					const _text = this.extractCallingInfoFromMessage(message);
+					const groupText = `${_text}`;
+					const renderDom = [
+						{
+							type: 'groupCalling',
+							text: groupText,
+							userIDList: []
+						}
+					];
+					return renderDom;
+				}
+				if (message.conversationType === 'C2C') {
+					const c2cText = this.extractCallingInfoFromMessage(message);
+					const renderDom = [
+						{
+							type: 'c2cCalling',
+							text: c2cText
+						}
+					];
+					return renderDom;
+				}
+			}
+
+			if (message.payload.data === 'group_create') {
+				const renderDom = [
+					{
+						type: 'group_create',
+						text: message.payload.extension
+					}
+				];
+				return renderDom;
+			}
+			
+
+			return [
+				{
+					type: 'notSupport',
+					text: '[自定义消息]'
+				}
+			];
+		}
+	}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 20 - 0
components/im/tui-chat/message-elements/emoji/index.css

@@ -0,0 +1,20 @@
+.TUI-Emoji {
+	display: flex;
+	justify-content: flex-start;
+	flex-wrap: wrap;
+	width: 100%;
+	height: 480rpx;
+	margin-left: 4vw;
+	overflow-y: scroll;
+}
+
+.TUI-emoji-image {
+	width: 9vw;
+	height: 9vw;
+	margin: 2vw;
+}
+
+.emoji-image {
+	width: 100%;
+	height: 100%;
+}

+ 48 - 0
components/im/tui-chat/message-elements/emoji/index.vue

@@ -0,0 +1,48 @@
+<template>
+	<view class="TUI-Emoji">
+		<view v-for="(item, index) in emojiList" :key="index" class="TUI-emoji-image">
+			<image :data-name="item.emojiName" class="emoji-image" :src="item.url" @tap="handleEnterEmoji"></image>
+		</view>
+	</view>
+</template>
+
+<script>
+import { emojiName, emojiUrl, emojiMap } from '../../../base/emojiMap';
+
+export default {
+	data() {
+		return {
+			emojiList: []
+		};
+	},
+
+	components: {},
+	props: {},
+
+	beforeMount() {
+		for (let i = 0; i < emojiName.length; i++) {
+			this.emojiList.push({
+				emojiName: emojiName[i],
+				url: emojiUrl + emojiMap[emojiName[i]]
+			});
+		}
+
+		this.setData({
+			emojiList: this.emojiList
+		});
+	},
+
+	methods: {
+		handleEnterEmoji(event) {
+			this.$emit('enterEmoji', {
+				detail: {
+					message: event.currentTarget.dataset.name
+				}
+			});
+		}
+	}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 13 - 0
components/im/tui-chat/message-elements/face-message/index.css

@@ -0,0 +1,13 @@
+.TUI-faceMessage {
+  width: 150px;
+  height: 110px;
+  max-width: 60vw;
+}
+.face-message {
+  width: 100%;
+  height: 100%;
+  border-radius: 10px 10px 10px 10px;
+}
+.my-image {
+  border-radius: 10px 2px 10px 10px;
+}

+ 57 - 0
components/im/tui-chat/message-elements/face-message/index.vue

@@ -0,0 +1,57 @@
+<template>
+	<view class="TUI-faceMessage" @tap="previewImage"><image class="face-message" :src="renderDom.src"></image></view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			renderDom: [],
+			percent: 0,
+			faceUrl: 'https://web.sdk.qcloud.com/im/assets/face-elem/'
+		};
+	},
+
+	components: {},
+	props: {
+		message: {
+			type: Object
+		},
+		isMine: {
+			type: Boolean,
+			default: true
+		}
+	},
+	watch: {
+		message: {
+			handler: function(newVal) {
+				this.setData({
+					renderDom: this.parseFace(newVal)
+				});
+			},
+			immediate: true,
+			deep: true
+		}
+	},
+	methods: {
+		// 解析face 消息
+		parseFace(message) {
+			const renderDom = {
+				src: `${this.faceUrl + message.payload.data}@2x.png`
+			};
+			return renderDom;
+		},
+
+		previewImage() {
+			uni.previewImage({
+				current: this.renderDom[0].src,
+				// 当前显示图片的http链接
+				urls: [this.renderDom[0].src]
+			});
+		}
+	}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 65 - 0
components/im/tui-chat/message-elements/file-message/index.css

@@ -0,0 +1,65 @@
+.TUI-fileMessage {
+	display: flex;
+	padding: 10rpx 24rpx;
+	background-color: #fff;
+	border-radius: 2px 10px 10px 10px;
+	border: 1px solid #D9D9D9;
+}
+
+.fileMessage {
+	display: flex;
+}
+
+.fileMessage-box {
+	display: flex;
+	background: white;
+	align-items: center;
+	height: 150rpx;
+}
+
+.file-icon {
+	width: 80rpx;
+	height: 80rpx;
+}
+
+.pop {
+	position: fixed;
+	width: 50%;
+	bottom: 400rpx;
+	margin-left: 90rpx;
+	background: rgba(0, 0, 0, 0.3);
+	z-index: 99999;
+}
+
+.text-box {
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	height: 112rpx;
+}
+
+.download-confirm {
+	font-family: PingFangSC-Regular;
+	font-size: 16px;
+	color: #E85454;
+	letter-spacing: 0;
+	text-align: center;
+	line-height: 22px;
+}
+
+.abandon {
+	opacity: 0.8;
+	font-family: PingFangSC-Regular;
+	font-size: 16px;
+	color: #FFFFFF;
+	letter-spacing: 0;
+	text-align: center;
+	line-height: 22px;
+}
+
+.file-title {
+	max-width: 53vw;
+	display: inline;
+	word-wrap: break-word;
+	word-break: break-all;
+}

+ 83 - 0
components/im/tui-chat/message-elements/file-message/index.vue

@@ -0,0 +1,83 @@
+<template>
+	<view>
+		<view class="TUI-fileMessage">
+			<view class="fileMessage">
+				<view class="fileMessage-box">
+					<image class="file-icon" src="../../../../../static/images/file.png"></image>
+					<label @tap="download" class="file-title">{{ filePayload.fileName }}</label>
+				</view>
+			</view>
+		</view>
+		<view class="pop" v-if="Show">
+			<view class="text-box"><text class="download-confirm" @tap.stop="downloadConfirm">下载</text></view>
+			<view class="text-box"><text class="abandon" @tap="cancel">取消</text></view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			Show: false,
+			filePayload: {}
+		};
+	},
+
+	components: {},
+	props: {
+		message: {
+			type: Object,
+			default: () => {}
+		},
+		isMine: {
+			type: Boolean,
+			default: true
+		}
+	},
+	watch: {
+		message: {
+			handler: function(newVal) {
+				this.setData({
+					filePayload: newVal.payload
+				});
+			},
+			immediate: true,
+			deep: true
+		}
+	},
+	methods: {
+		download() {
+			this.setData({
+				Show: true
+			});
+		},
+
+		downloadConfirm() {
+			uni.downloadFile({
+				url: this.filePayload.fileUrl,
+
+				success(res) {
+					const filePath = res.tempFilePath;
+					uni.openDocument({
+						filePath,
+
+						success() {
+							console.log('打开文档成功');
+						}
+					});
+				}
+			});
+		},
+
+		cancel() {
+			this.setData({
+				Show: false
+			});
+		}
+	}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 13 - 0
components/im/tui-chat/message-elements/image-message/index.css

@@ -0,0 +1,13 @@
+.TUI-ImageMessage {
+	width: 150px;
+}
+
+.image-message {
+	width: 100%;
+	height: 100%;
+	border-radius: 10px 10px 10px 10px;
+}
+
+.my-image {
+	border-radius: 10px 2px 10px 10px;
+}

+ 54 - 0
components/im/tui-chat/message-elements/image-message/index.vue

@@ -0,0 +1,54 @@
+<template>
+	<view class="TUI-ImageMessage" @tap="previewImage">
+		<image :class="'image-message ' + (isMine ? 'my-image' : '')" mode="widthFix" :src="renderDom[0].src"></image>
+	</view>
+</template>
+
+<script>
+import { parseImage } from '../../../base/message-facade';
+
+export default {
+	data() {
+		return {
+			renderDom: [],
+			percent: 0
+		};
+	},
+
+	components: {},
+	props: {
+		message: {
+			type: Object,
+			default: ''
+		},
+		isMine: {
+			type: Boolean,
+			default: true
+		}
+	},
+	watch: {
+		message: {
+			handler: function(newVal) {
+				this.setData({
+					renderDom: parseImage(newVal),
+					percent: newVal.percent
+				});
+			},
+			immediate: true,
+			deep: true
+		}
+	},
+	methods: {
+		previewImage() {
+			uni.previewImage({
+				current: this.renderDom[0].src,
+				// 当前显示图片的http链接
+				urls: [this.renderDom[0].src]
+			});
+		}
+	}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 29 - 0
components/im/tui-chat/message-elements/system-message/index.css

@@ -0,0 +1,29 @@
+.container {
+	width: 100%;
+	height: 200rpx;
+}
+
+.handle {
+	display: flex;
+	justify-content: space-between;
+}
+
+.card {
+	font-size: 14px;
+	margin: 20px;
+	padding: 20px;
+	box-sizing: border-box;
+	border: 1px solid #abdcff;
+	background-color: #f0faff;
+	border-radius: 12px;
+}
+
+.time {}
+
+.button {
+	color: blue;
+	border-radius: 8px;
+	line-height: 30px;
+	font-size: 16px;
+	width: 70px;
+}

+ 86 - 0
components/im/tui-chat/message-elements/system-message/index.vue

@@ -0,0 +1,86 @@
+<template>
+	<view>
+		<view v-if="message.payload.operationType === 1" class="card handle">
+			<view>
+				<view class="time">{{ messageTime }}</view>
+				{{ renderDom }}
+			</view>
+			<view class="choose"><view class="button" @tap="handleClick">处理</view></view>
+		</view>
+		<view class="card" v-else>
+			<view class="time">{{ messageTime }}</view>
+			{{ renderDom }}
+		</view>
+	</view>
+</template>
+
+<script>
+import { parseGroupSystemNotice } from '../../../base/message-facade';
+import { caculateTimeago } from '../../../base/common';
+
+export default {
+	data() {
+		return {
+			// message: {},
+			messageTime: '',
+			renderDom: ''
+		};
+	},
+
+	components: {},
+	props: {
+		message: {
+			type: Object
+		}
+	},
+	watch: {
+		message: {
+			handler: function(newVal) {
+				this.setData({
+					messageTime: caculateTimeago(newVal.time * 1000),
+					renderDom: parseGroupSystemNotice(newVal)
+				});
+			},
+			immediate: true,
+			deep: true
+		}
+	},
+
+	methods: {
+		handleClick() {
+			uni.showActionSheet({
+				itemList: ['同意', '拒绝'],
+				success: res => {
+					const option = {
+						handleAction: 'Agree',
+						handleMessage: '欢迎进群',
+						message: this.message
+					};
+
+					if (res.tapIndex === 1) {
+						option.handleAction = 'Reject';
+						option.handleMessage = '拒绝申请';
+					}
+
+					uni.$TUIKit
+						.handleGroupApplication(option)
+						.then(() => {
+							uni.showToast({
+								title: option.handleAction === 'Agree' ? '已同意申请' : '已拒绝申请'
+							});
+						})
+						.catch(error => {
+							uni.showToast({
+								title: error.message || '处理失败',
+								icon: 'none'
+							});
+						});
+				}
+			});
+		}
+	}
+};
+</script>
+<style scoped>
+@import './index.css';
+</style>

+ 47 - 0
components/im/tui-chat/message-elements/text-message/index.css

@@ -0,0 +1,47 @@
+.text-message {
+	display: inline-flex;
+	max-width: 60vw;
+	line-height: 52rpx;
+	padding: 12rpx 24rpx;
+	background: #F8F8F8;
+	border: 1px solid #D9D9D9;
+	border-radius: 2px 10px 10px 10px;
+}
+
+.my-text {
+	border-radius: 10px 2px 10px 10px;
+	border: 1px solid rgba(0, 110, 255, 0.30);
+	background: rgba(0, 110, 255, 0.10);
+}
+
+.message-body-span {
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	/*justify-content: flex-start;*/
+	flex-wrap: wrap;
+	outline: none;
+	font-size: 28rpx;
+	color: #333333;
+	position: relative;
+	max-width: 60vw;
+}
+
+.message-body-span-text {
+	width: 100%;
+	display: inline;
+	word-wrap: break-word;
+	word-break: break-all;
+}
+
+.message-body-span-image {
+	display: inline-block;
+	width: 32rpx;
+	height: 32rpx;
+	margin: 0 4rpx;
+}
+
+.emoji-icon {
+	width: 20px;
+	height: 20px;
+}

+ 55 - 0
components/im/tui-chat/message-elements/text-message/index.vue

@@ -0,0 +1,55 @@
+<template>
+	<view :class="'text-message ' + (isMine ? 'my-text' : '')">
+		<view v-for="(item, index) in renderDom" :key="index" class="message-body-span">
+			<span class="message-body-span-text" v-if="item.name === 'span'">{{ item.text }}</span>
+			<image v-if="item.name === 'img'" class="emoji-icon" :src="item.src"></image>
+		</view>
+	</view>
+</template>
+
+<script>
+import { parseText } from '../../../base/message-facade';
+
+export default {
+	data() {
+		return {
+			renderDom: []
+		};
+	},
+
+	components: {},
+	props: {
+		message: {
+			type: Object
+		},
+		isMine: {
+			type: Boolean,
+			default: true
+		}
+	},
+	watch: {
+		message: {
+			handler: function(newVal) {
+				this.setData({
+					renderDom: parseText(newVal)
+				});
+			},
+			immediate: true,
+			deep: true
+		}
+	},
+
+	beforeMount() {
+		// 在组件实例进入页面节点树时执行
+	},
+
+	destroyed() {
+		// 在组件实例被从页面节点树移除时执行
+	},
+
+	methods: {}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 9 - 0
components/im/tui-chat/message-elements/tip-message/index.css

@@ -0,0 +1,9 @@
+.tip-message {
+	width: 100%;
+}
+
+.text-message {
+	text-align: center;
+	font-size: 12px;
+	color: #999999;
+}

+ 46 - 0
components/im/tui-chat/message-elements/tip-message/index.vue

@@ -0,0 +1,46 @@
+<template>
+	<view class="tip-message">
+		<view class="text-message">{{ renderDom[0].text }}</view>
+	</view>
+</template>
+
+<script>
+import { parseGroupTip } from '../../../base/message-facade';
+
+export default {
+	data() {
+		return {};
+	},
+
+	components: {},
+	props: {
+		message: {
+			type: Object
+		}
+	},
+	watch: {
+		message: {
+			handler: function(newVal) {
+				this.setData({
+					renderDom: parseGroupTip(newVal)
+				});
+			},
+			immediate: true,
+			deep: true
+		}
+	},
+
+	beforeMount() {
+		// 在组件实例进入页面节点树时执行
+	},
+
+	destroyed() {
+		// 在组件实例被从页面节点树移除时执行
+	},
+
+	methods: {}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 27 - 0
components/im/tui-chat/message-elements/video-message/index.css

@@ -0,0 +1,27 @@
+.video-message {}
+
+.video-box {
+	width: 160px;
+	height: 120px;
+	background-color: rgba(0, 0, 0, 0.2);
+	border-radius: 10px 2px 10px 10px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.my-video {
+	border-radius: 10px 2px 10px 10px;
+}
+
+.icon {
+	position: absolute;
+	bottom: 30px;
+	right: 30px;
+}
+
+.video-icon {
+	display: block;
+	width: 32px;
+	height: 32px;
+}

+ 53 - 0
components/im/tui-chat/message-elements/video-message/index.vue

@@ -0,0 +1,53 @@
+<template>
+	<view :class="'video-box ' + (isMine ? 'my-video' : '')" @click="playerHander">
+		<image class="video-icon" src="../../../../../static/images/video-play.png"></image>
+	</view>
+</template>
+
+<script>
+import videoIcon from '../../../../../static/images/video-play.png';
+export default {
+	data() {
+		return {
+			isPlay: false,
+			videoIcon: videoIcon
+		};
+	},
+
+	components: {},
+	props: {
+		message: {
+			type: Object,
+			default: () => {}
+		},
+		isMine: {
+			type: Boolean,
+			default: true
+		}
+	},
+	watch: {
+		message: {
+			handler: function(newVal) {
+				this.message=newVal
+				 
+			},
+			immediate: true,
+			deep: true
+		}
+	},
+	methods: {
+		playerHander() {
+			uni.$emit('videoPlayerHandler', {
+				isPlay: true,
+				message: this.message
+			});
+		},
+		stopHander() {
+			this.isPlay = false;
+		}
+	}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 156 - 0
components/im/tui-chat/message-input/index.css

@@ -0,0 +1,156 @@
+.TUI-message-input-container {
+	background-color: #F1F1F1;
+	padding-bottom: 20rpx;
+}
+
+.TUI-message-input {
+	display: flex;
+	padding-bottom: 16rpx;
+	background-color: #F1F1F1;
+	width: 100vw;
+}
+
+.TUI-commom-function {
+	display: flex;
+	flex-wrap: nowrap;
+	width: 750rpx;
+	height: 106rpx;
+	background-color: #F1F1F1;
+	align-items: center;
+}
+
+.TUI-commom-function-item {
+	display: flex;
+	width: 136rpx;
+	justify-content: center;
+	align-items: center;
+	font-size: 24rpx;
+	color: #FFFFFF;
+	height: 48rpx;
+	margin-left: 16rpx;
+	border-radius: 24rpx;
+	background-color: #018C39;
+}
+
+.TUI-commom-function-item:first-child {
+	margin-left: 48rpx;
+}
+
+.TUI-message-input-functions {
+	display: flex;
+	align-items: center;
+}
+
+.TUI-message-input-main {
+	background-color: #fff;
+	flex: 1;
+	height: 66rpx;
+	margin: 0 10rpx;
+	padding: 0 5rpx;
+	border-radius: 5rpx;
+	display: flex;
+	align-items: center;
+}
+
+.TUI-message-input-area {
+	width: 100%;
+	height: 100%;
+}
+
+.TUI-icon {
+	width: 56rpx;
+	height: 56rpx;
+	margin: 0 16rpx;
+}
+
+.TUI-Extensions {
+	display: flex;
+	flex-wrap: wrap;
+	width: 100vw;
+	height: 450rpx;
+	margin-left: 14rpx;
+	margin-right: 14rpx;
+}
+
+.TUI-Extension-slot {
+	width: 128rpx;
+	height: 170rpx;
+	margin-left: 26rpx;
+	margin-right: 26rpx;
+	margin-top: 24rpx;
+}
+
+.TUI-Extension-icon {
+	width: 128rpx;
+	height: 128rpx;
+}
+
+.TUI-sendMessage-btn {
+	display: flex;
+	align-items: center;
+	margin: 0 10rpx;
+}
+
+.TUI-Emoji-area {
+	width: 100vw;
+	height: 450rpx;
+}
+
+.TUI-Extension-slot-name {
+	line-height: 34rpx;
+	font-size: 24rpx;
+	color: #333333;
+	letter-spacing: 0;
+	text-align: center;
+}
+
+.record-modal {
+	height: 300rpx;
+	width: 60vw;
+	background-color: #000;
+	opacity: 0.8;
+	position: fixed;
+	top: 670rpx;
+	z-index: 9999;
+	left: 20vw;
+	border-radius: 24rpx;
+	display: flex;
+	flex-direction: column;
+}
+
+.record-modal .wrapper {
+	display: flex;
+	height: 200rpx;
+	box-sizing: border-box;
+	padding: 10vw;
+}
+
+.record-modal .wrapper .modal-loading {
+	opacity: 1;
+	width: 40rpx;
+	height: 16rpx;
+	border-radius: 4rpx;
+	background-color: #006fff;
+	animation: loading 2s cubic-bezier(0.17, 0.37, 0.43, 0.67) infinite;
+}
+
+.modal-title {
+	text-align: center;
+	color: #fff;
+}
+
+@keyframes loading {
+	0% {
+		transform: translate(0, 0)
+	}
+
+	50% {
+		transform: translate(30vw, 0);
+		background-color: #f5634a;
+		width: 40px;
+	}
+
+	100% {
+		transform: translate(0, 0);
+	}
+}

+ 574 - 0
components/im/tui-chat/message-input/index.vue

@@ -0,0 +1,574 @@
+<template>
+	<view>
+		<view class="TUI-message-input-container">
+			<view class="TUI-commom-function">
+				<view v-for="(item, index) in commonFunction" :key="index" class="TUI-commom-function-item" :data-function="item" @tap="handleCommonFunctions">
+					{{ item.name }}
+				</view>
+			</view>
+			<view class="TUI-message-input">
+				<image class="TUI-icon" @tap="switchAudio" :src="isAudio ? '/static/assets/keyboard.svg' : '/static/assets/audio.svg'"></image>
+				<view v-if="!isAudio" class="TUI-message-input-main">
+					<input
+						class="TUI-message-input-area"
+						:adjust-position="true"
+						cursor-spacing="20"
+						v-model="inputText"
+						@input="onInputValueChange"
+						maxlength="140"
+						type="text"
+						placeholder-class="input-placeholder"
+						placeholder="请输入内容"
+						@focus="inputBindFocus"
+						@blur="inputBindBlur"
+					/>
+				</view>
+				<view
+					v-else
+					class="TUI-message-input-main"
+					@longpress="handleLongPress"
+					@touchmove="handleTouchMove"
+					@touchend="handleTouchEnd"
+					style="display: flex; justify-content: center; font-size: 32rpx; font-family: PingFangSC-Regular;"
+				>
+					<text>{{ text }}</text>
+				</view>
+				<view class="TUI-message-input-functions" hover-class="none">
+					<image class="TUI-icon" @tap="handleEmoji" src="/static/assets/face-emoji.svg"></image>
+					<view v-if="!sendMessageBtn" @tap="handleExtensions"><image class="TUI-icon" src="/static/assets/more.svg"></image></view>
+					<view v-else class="TUI-sendMessage-btn" @tap="sendTextMessage">发送</view>
+				</view>
+			</view>
+			<view v-if="displayFlag === 'emoji'" class="TUI-Emoji-area"><TUI-Emoji @enterEmoji="appendMessage"></TUI-Emoji></view>
+			<view v-if="displayFlag === 'extension'" class="TUI-Extensions">
+				<!-- TODO: 这里功能还没实现 -->
+				<!--        <camera device-position="back" flash="off" binderror="error" style="width: 100%; height: 300px;"></camera>-->
+				<view class="TUI-Extension-slot" @tap="handleSendPicture">
+					<image class="TUI-Extension-icon" src="/static/assets/take-photo.svg"></image>
+					<view class="TUI-Extension-slot-name">拍摄照片</view>
+				</view>
+				<view class="TUI-Extension-slot" @tap="handleSendImage">
+					<image class="TUI-Extension-icon" src="/static/assets/send-img.svg"></image>
+					<view class="TUI-Extension-slot-name">发送图片</view>
+				</view>
+				<view class="TUI-Extension-slot" @tap="handleShootVideo">
+					<image class="TUI-Extension-icon" src="/static/assets/take-video.svg"></image>
+					<view class="TUI-Extension-slot-name">拍摄视频</view>
+				</view>
+				<view class="TUI-Extension-slot" @tap="handleSendVideo">
+					<image class="TUI-Extension-icon" src="/static/assets/send-video.svg"></image>
+					<view class="TUI-Extension-slot-name">发送视频</view>
+				</view>
+				<!-- <view class="TUI-Extension-slot" @tap="handleCalling(1)">
+					<image class="TUI-Extension-icon" src="/static/assets/audio-calling.svg"></image>
+					<view class="TUI-Extension-slot-name">语音通话</view>
+				</view>
+				<view class="TUI-Extension-slot" @tap="handleCalling(2)">
+					<image class="TUI-Extension-icon" src="/static/assets/video-calling.svg"></image>
+					<view class="TUI-Extension-slot-name">视频通话</view>
+				</view> -->
+				<view class="TUI-Extension-slot" @tap="handleServiceEvaluation">
+					<image class="TUI-Extension-icon" src="/static/assets/service-assess.svg"></image>
+					<view class="TUI-Extension-slot-name">服务评价</view>
+				</view>
+				<!-- <view class="TUI-Extension-slot" @tap="handleSendOrder">
+					<image class="TUI-Extension-icon" src="/static/assets/send-order.svg"></image>
+					<view class="TUI-Extension-slot-name">发送订单</view>
+				</view> -->
+			</view>
+			<TUI-Common-Words class="tui-cards" :display="displayCommonWords" @sendMessage="$handleSendTextMessage" @close="$handleCloseCards"></TUI-Common-Words>
+			<TUI-Order-List class="tui-cards" :display="displayOrderList" @sendCustomMessage="$handleSendCustomMessage" @close="$handleCloseCards"></TUI-Order-List>
+			<TUI-Service-Evaluation
+				class="tui-cards"
+				:display="displayServiceEvaluation"
+				@sendCustomMessage="$handleSendCustomMessage"
+				@close="$handleCloseCards"
+			></TUI-Service-Evaluation>
+		</view>
+		<view class="record-modal" v-if="popupToggle" @longpress="handleLongPress" @touchmove="handleTouchMove" @touchend="handleTouchEnd">
+			<view class="wrapper"><view class="modal-loading"></view></view>
+			<view class="modal-title">{{ title }}</view>
+		</view>
+	</view>
+</template>
+
+<script>
+import TUIEmoji from '../message-elements/emoji/index';
+import TUICommonWords from '../message-private/common-words/index';
+import TUIOrderList from '../message-private/order-list/index';
+import TUIServiceEvaluation from '../message-private/service-evaluation/index';
+
+export default {
+	data() {
+		return {
+			 
+			firstSendMessage: true,
+			inputText: '',
+			extensionArea: false,
+			sendMessageBtn: false,
+			displayFlag: '',
+			isAudio: false,
+			bottomVal: 0,
+			startPoint: 0,
+			popupToggle: false,
+			isRecording: false,
+			canSend: true,
+			text: '按住说话',
+			title: ' ',
+			notShow: false,
+			isShow: true,
+			recordTime: 0,
+			recordTimer: null,
+			commonFunction: [
+				{
+					name: '常用语',
+					key: '0'
+				},
+				// {
+				// 	name: '发送订单',
+				// 	key: '1'
+				// },
+				{
+					name: '服务评价',
+					key: '2'
+				}
+			],
+			displayServiceEvaluation: false,
+			displayCommonWords: false,
+			displayOrderList: false
+		};
+	},
+	components: {
+		TUIEmoji,
+		TUICommonWords,
+		TUIOrderList,
+		TUIServiceEvaluation
+	},
+	props: {
+		conversation: {
+			type: Object,
+			default: () => {}
+		},
+		toUser: {
+			type: String,
+			default: () => {}
+		}
+	},
+	watch: {
+		conversation: {
+			handler: function(newVal) {
+				// todo 值会被改变
+				// this.setData({
+				//   conversation: newVal
+				// });
+			},
+			immediate: true,
+			deep: true
+		}
+	},
+
+	beforeMount() {
+		var that=this;
+		// 加载声音录制管理器
+		this.recorderManager = uni.getRecorderManager();
+		this.recorderManager.onStop(res => {
+			clearInterval(this.recordTimer);
+			// 兼容 uniapp 打包app,duration 和 fileSize 需要用户自己补充
+			// 文件大小 = (音频码率) x 时间长度(单位:秒) / 8
+			let msg = {
+				duration: res.duration ? res.duration : this.recordTime * 1000,
+				tempFilePath: res.tempFilePath,
+				fileSize: res.fileSize ? res.fileSize : ((48 * this.recordTime) / 8) * 1024
+			};
+			uni.hideLoading();
+			// 兼容 uniapp 语音消息没有duration
+			if (this.canSend) {
+				if (msg.duration < 1000) {
+					uni.showToast({
+						title: '录音时间太短',
+						icon: 'none'
+					});
+				} else {
+					var orderId=uni.getStorageSync('orderId');
+					// res.tempFilePath 存储录音文件的临时路径
+					const message = uni.$TUIKit.createAudioMessage({
+						to: this.getToAccount(),
+						conversationType: this.conversation.type,
+						payload: {
+							file: msg
+						},
+						cloudCustomData: 'orderId='+orderId
+					});
+					this.$sendTIMMessage(message);
+				}
+			}
+
+			that.setData({
+				startPoint: 0,
+				popupToggle: false,
+				isRecording: false,
+				canSend: true,
+				title: ' ',
+				text: '按住说话'
+			});
+		});
+	},
+
+	methods: {
+		switchAudio() {
+			this.isAudio= !this.isAudio;
+			this.text='按住说话';
+			
+		},
+		handleLongPress(e) {
+			this.recorderManager.start({
+				duration: 60000,
+				// 录音的时长,单位 ms,最大值 600000(10 分钟)
+				sampleRate: 44100,
+				// 采样率
+				numberOfChannels: 1,
+				// 录音通道数
+				encodeBitRate: 192000,
+				// 编码码率
+				format: 'aac' // 音频格式,选择此格式创建的音频消息,可以在即时通信 IM 全平台(Android、iOS、微信小程序和Web)互通
+			});
+			this.setData({
+				startPoint: e.touches[0],
+				title: '正在录音',
+				// isRecording : true,
+				// canSend: true,
+				notShow: true,
+				isShow: false,
+				isRecording: true,
+				popupToggle: true,
+				recordTime: 0
+			});
+			this.recordTimer = setInterval(() => {
+				this.recordTime++;
+			}, 1000);
+		},
+
+		// 录音时的手势上划移动距离对应文案变化
+		handleTouchMove(e) {
+			if (this.isRecording) {
+				if (this.startPoint.clientY - e.touches[e.touches.length - 1].clientY > 100) {
+					this.setData({
+						text: '抬起停止',
+						title: '松开手指,取消发送',
+						canSend: false
+					});
+				} else if (this.startPoint.clientY - e.touches[e.touches.length - 1].clientY > 20) {
+					this.setData({
+						text: '抬起停止',
+						title: '上划可取消',
+						canSend: true
+					});
+				} else {
+					this.setData({
+						text: '抬起停止',
+						title: '正在录音',
+						canSend: true
+					});
+				}
+			}
+		},
+
+		// 手指离开页面滑动
+		handleTouchEnd() {
+			this.setData({
+				isRecording: false,
+				popupToggle: false
+			});
+			uni.hideLoading();
+			this.recorderManager.stop();
+		},
+		handleEmoji() {
+			let targetFlag = 'emoji';
+
+			if (this.displayFlag === 'emoji') {
+				targetFlag = '';
+			}
+			this.displayFlag=targetFlag;
+			 
+		},
+
+		handleExtensions() {
+			let targetFlag = 'extension';
+
+			if (this.displayFlag === 'extension') {
+				targetFlag = '';
+			}
+			this.displayFlag=targetFlag;
+		},
+
+		error(e) {
+			console.log(e.detail);
+		},
+
+		handleSendPicture() {
+			this.sendImageMessage('camera');
+		},
+
+		handleSendImage() {
+			this.sendImageMessage('album');
+		},
+
+		sendImageMessage(type) {
+		
+			uni.chooseImage({
+				sourceType: [type],
+				count: 1,
+				success: res => {
+					if (res) {
+						var orderId=uni.getStorageSync('orderId');
+						const message = uni.$TUIKit.createImageMessage({
+							to: this.getToAccount(),
+							conversationType: this.conversation.type,
+							payload: {
+								file: res
+							},
+							cloudCustomData: 'orderId='+orderId,
+							onProgress: percent => {
+								message.percent = percent;
+							}
+						});
+						this.$sendTIMMessage(message);
+					}
+				}
+			});
+		},
+
+		handleShootVideo() {
+			this.sendVideoMessage('camera');
+		},
+
+		handleSendVideo() {
+			this.sendVideoMessage('album');
+		},
+
+		sendVideoMessage(type) {
+			uni.chooseVideo({
+				sourceType: [type],
+				// 来源相册或者拍摄
+				maxDuration: 60,
+				// 设置最长时间60s
+				camera: 'back',
+				// 后置摄像头
+				success: res => {
+					if (res) {
+						var orderId=uni.getStorageSync('orderId');
+						const message = uni.$TUIKit.createVideoMessage({
+							to: this.getToAccount(),
+							conversationType: this.conversation.type,
+							payload: {
+								file: res
+							},
+							cloudCustomData: 'orderId='+orderId,
+							onProgress: percent => {
+								message.percent = percent;
+							}
+						});
+						this.$sendTIMMessage(message);
+					}
+				}
+			});
+		},
+
+		handleCommonFunctions(e) {
+			switch (e.target.dataset.function.key) {
+				case '0':
+					this.setData({
+						displayCommonWords: true
+					});
+					break;
+
+				// case '1':
+				// 	this.setData({
+				// 		displayOrderList: true
+				// 	});
+				// 	break;
+
+				case '2':
+					this.setData({
+						displayServiceEvaluation: true
+					});
+					break;
+
+				default:
+					break;
+			}
+		},
+
+		handleSendOrder() {
+			this.setData({
+				displayOrderList: true
+			});
+		},
+
+		appendMessage(e) {
+			this.setData({
+				inputText: this.inputText + e.detail.message,
+				sendMessageBtn: true
+			});
+		},
+
+		getToAccount() {
+			return this.toUser;
+		},
+		handleCalling(value) {
+			// todo 目前支持单聊
+			if (this.conversation.type === 'GROUP') {
+				uni.showToast({
+					title: '群聊暂不支持',
+					icon: 'none'
+				});
+				return;
+			}
+			const { userID } = this.conversation.userProfile;
+
+			// #ifdef APP-PLUS
+			if(typeof(uni.$TUICalling) === 'undefined') {
+					logger.error('请使用真机运行并且自定义基座调试,可能影响音视频功能~ 插件地址:https://ext.dcloud.net.cn/plugin?id=7097 , 调试地址:https://nativesupport.dcloud.net.cn/NativePlugin/use/use');
+					uni.showToast({
+						title: '请使用真机运行并且自定义基座调试,可能影响音视频功能~ ',
+						icon: 'none',
+						duration: 3000
+					});
+			} else {
+				uni.$TUICalling.call(
+					{
+						userID: userID,
+						type: value
+					},
+					res => {
+						console.log(JSON.stringify(res));
+					}
+				);
+			}
+			// #endif
+			// #ifdef MP-WEIXIN
+			uni.showToast({
+				title: '微信小程序暂不支持',
+				icon: 'none'
+			});
+			// uni.$wxTUICalling.call({userID, type: value})
+			// #endif
+		},
+		sendTextMessage(msg, flag) {
+			var orderId=uni.getStorageSync('orderId');
+			 console.log(this.conversation.type)
+			const to = this.getToAccount();
+			const text = flag ? msg : this.inputText;
+			const message = uni.$TUIKit.createTextMessage({
+				to,
+				conversationType: this.conversation.type,
+				payload: {
+					text:text
+				},
+				cloudCustomData: 'orderId='+orderId
+			});
+			this.setData({
+				inputText: '',
+				sendMessageBtn: false
+			});
+			this.$sendTIMMessage(message);
+		},
+
+		onInputValueChange(event) {
+			if (event.detail.value) {
+				this.setData({
+					sendMessageBtn: true
+				});
+			} else {
+				this.setData({
+					sendMessageBtn: false
+				});
+			}
+		},
+
+		$handleSendTextMessage(event) {
+			this.sendTextMessage(event.detail.message, true);
+			this.setData({
+				displayCommonWords: false
+			});
+		},
+
+		$handleSendCustomMessage(e) {
+			var orderId=uni.getStorageSync('orderId');
+			const message = uni.$TUIKit.createCustomMessage({
+				to: this.getToAccount(),
+				conversationType: this.conversation.type,
+				payload: e.detail.payload,
+				cloudCustomData: 'orderId='+orderId
+			});
+			this.$sendTIMMessage(message);
+			this.setData({
+				displayOrderList: false
+			});
+		},
+
+		$handleCloseCards(e) {
+			switch (e.detail.key) {
+				case '0':
+					this.setData({
+						displayCommonWords: false
+					});
+					break;
+
+				case '1':
+					this.setData({
+						displayOrderList: false
+					});
+					break;
+
+				case '2':
+					this.setData({
+						displayServiceEvaluation: false
+					});
+					break;
+
+				default:
+					break;
+			}
+		},
+		$sendTIMMessage(message) {
+			this.$emit('sendMessage', {
+				detail: {
+					message
+				}
+			});
+			uni.$TUIKit.sendMessage(message).then((res) => {
+				this.firstSendMessage = false
+			}).catch((error) => {
+				 
+			})
+			this.setData({
+				displayFlag: ''
+			});
+		},
+
+		handleClose() {
+			this.setData({
+				displayFlag: ''
+			});
+		},
+
+		handleServiceEvaluation() {
+			this.setData({
+				displayServiceEvaluation: true
+			});
+		},
+
+		inputBindFocus() {
+			console.log('占位:函数 inputBindFocus 未声明');
+		},
+
+		inputBindBlur() {
+			console.log('占位:函数 inputBindBlur 未声明');
+		}
+	}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 70 - 0
components/im/tui-chat/message-list/index.css

@@ -0,0 +1,70 @@
+.message-list-container {
+	width: 100%;
+	height: 100%;
+}
+
+.t-message-item {
+	/*max-width: 60vw;*/
+	padding: 16rpx 0;
+}
+
+.t-recieve-message {
+	display: flex;
+	flex-direction: row;
+	justify-items: flex-start;
+	align-items: center;
+	width: 100vw;
+}
+
+.t-message-avatar {
+	margin-left: 20rpx;
+	margin-right: 12rpx;
+	border-radius: 10rpx;
+	width: 80rpx;
+	height: 80rpx;
+}
+
+.t-self-message {
+	display: flex;
+	flex-direction: row;
+	justify-content: flex-end;
+	/*align-items: center;*/
+	width: 100vw;
+}
+
+.t-self-message-body {
+	display: flex;
+	justify-content: flex-start;
+	flex-wrap: wrap;
+	outline: none;
+}
+
+.t-recieve-message-body {
+	display: flex;
+	justify-content: flex-start;
+	flex-wrap: wrap;
+	outline: none;
+	/*background: #F8F8F8;*/
+	border-radius: 2px 10px 10px 10px;
+	margin-left: 8rpx;
+
+}
+
+.read-receipts {
+	line-height: 42px;
+	height: 42px;
+	font-size: 12px;
+	color: #6e7981;
+	margin-right: 10px
+}
+
+.no-message {
+	text-align: center;
+	position: fixed;
+	width: 100%;
+	font-size: 12px;
+	color: #a5b5c1;
+	height: 40px;
+	top: -40px;
+	right: 0;
+}

+ 195 - 0
components/im/tui-chat/message-list/index.vue

@@ -0,0 +1,195 @@
+<template>
+	<scroll-view
+		class="message-list-container"
+		scroll-y="true"
+		:scroll-into-view="scrollView"
+		:refresher-enabled="true"
+		@refresherrefresh="refresh"
+		:scroll-top="scrollTop"
+		:refresher-triggered="triggered"
+	>
+		<view id="message-scroll" style="width:100%">
+			<view class="no-message" v-if="isCompleted">没有更多啦</view>
+			<view v-for="item in messageList" :key="item.ID" class="t-message">
+				<view v-if="conversation.type !== '@TIM#SYSTEM'" :id="item.ID">
+					<view class="t-message-item">
+						<TUI-TipMessage v-if="item.type === 'TIMGroupTipElem'" :message="item"></TUI-TipMessage>
+						<view v-if="item.type !== 'TIMGroupTipElem'" :class="item.flow === 'out' ? 't-self-message' : 't-recieve-message'">
+							<image
+								class="t-message-avatar"
+								v-if="item.flow === 'in'"
+								:src="item.avatar || 'https://sdk-web-1252463788.cos.ap-hongkong.myqcloud.com/component/TUIKit/assets/avatar_21.png'"
+							></image>
+							<view class="read-receipts" v-if="conversation.type === 'C2C' && item.flow === 'out'">
+								<view v-if="item.isPeerRead">已读</view>
+								<view v-else>未读</view>
+							</view>
+							<view>
+								<TUI-TextMessage v-if="item.type === 'TIMTextElem'" :message="item" :isMine="item.flow === 'out'"></TUI-TextMessage>
+								<TUI-ImageMessage v-if="item.type === 'TIMImageElem'" :message="item" :isMine="item.flow === 'out'"></TUI-ImageMessage>
+								<TUI-VideoMessage v-if="item.type === 'TIMVideoFileElem'" :message="item" :isMine="item.flow === 'out'"></TUI-VideoMessage>
+								<TUI-AudioMessage v-if="item.type === 'TIMSoundElem'" :message="item" :isMine="item.flow === 'out'"></TUI-AudioMessage>
+								<TUI-CustomMessage v-if="item.type === 'TIMCustomElem'" :message="item" :isMine="item.flow === 'out'"></TUI-CustomMessage>
+								<TUI-FaceMessage v-if="item.type === 'TIMFaceElem'" :message="item" :isMine="item.flow === 'out'"></TUI-FaceMessage>
+								<TUI-FileMessage v-if="item.type === 'TIMFileElem'" :message="item" :isMine="item.flow === 'out'"></TUI-FileMessage>
+							</view>
+							<image
+								class="t-message-avatar"
+								v-if="item.flow === 'out'"
+								:src="item.avatar || 'https://sdk-web-1252463788.cos.ap-hongkong.myqcloud.com/component/TUIKit/assets/avatar_21.png'"
+							></image>
+						</view>
+					</view>
+				</view>
+				<view v-else :id="item.ID" :data-value="item.ID"><TUI-SystemMessage :message="item"></TUI-SystemMessage></view>
+			</view>
+		</view>
+	</scroll-view>
+</template>
+
+<script>
+import TUITextMessage from '../message-elements/text-message/index';
+import TUIImageMessage from '../message-elements/image-message/index';
+import TUIVideoMessage from '../message-elements/video-message/index';
+import TUIAudioMessage from '../message-elements/audio-message/index';
+import TUICustomMessage from '../message-elements/custom-message/index';
+import TUITipMessage from '../message-elements/tip-message/index';
+import TUISystemMessage from '../message-elements/system-message/index';
+import TUIFaceMessage from '../message-elements/face-message/index';
+import TUIFileMessage from '../message-elements/file-message/index';
+
+export default {
+	data() {
+		return {
+			conversation:null,
+			// 当前会话
+			messageList: [],
+			// 自己的 ID 用于区分历史消息中,哪部分是自己发出的
+			scrollView: '',
+			scrollTop: 0,
+			triggered: true,
+			nextReqMessageID: '',
+			// 下一条消息标志
+			isCompleted: false // 当前会话消息是否已经请求完毕
+		};
+	},
+
+	components: {
+		TUITextMessage,
+		TUIImageMessage,
+		TUIVideoMessage,
+		TUIAudioMessage,
+		TUICustomMessage,
+		TUITipMessage,
+		TUISystemMessage,
+		TUIFaceMessage,
+		TUIFileMessage
+	},
+	mounted() {
+		uni.$TUIKit.on(uni.$TUIKitEvent.MESSAGE_RECEIVED, this.$onMessageReceived, this);
+		uni.$TUIKit.on(uni.$TUIKitEvent.MESSAGE_READ_BY_PEER, this.$onMessageReadByPeer, this);
+		
+	},
+	destroyed() {
+		// 一定要解除相关的事件绑定
+		uni.$TUIKit.off(uni.$TUIKitEvent.MESSAGE_RECEIVED, this.$onMessageReceived);
+	},
+	methods: {
+		refresh() {
+			if (this.isCompleted) {
+				this.setData({
+					isCompleted: true,
+					triggered: false
+				});
+				return;
+			}
+			this.getMessageList(this.conversation);
+			setTimeout(() => {
+				this.setData({
+					triggered: false
+				});
+			}, 2000);
+		},
+		getMessageList(conversation) {
+			this.conversation=conversation
+			var that=this;
+			if (!this.isCompleted) {
+				uni.$TUIKit
+					.getMessageList({
+						conversationID: that.conversation.conversationID,
+						nextReqMessageID: that.nextReqMessageID,
+						count: 15
+					})
+					.then(res => {
+						const { messageList } = res.data; // 消息列表。
+						this.nextReqMessageID = res.data.nextReqMessageID; // 用于续拉,分页续拉时需传入该字段。
+						this.isCompleted = res.data.isCompleted; // 表示是否已经拉完所有消息。
+						this.messageList = [...messageList, ...this.messageList];
+						this.$handleMessageRender(this.messageList, messageList);
+					});
+			}
+		},
+
+		// 自己的消息上屏
+		updateMessageList(msg) {
+			this.messageList = [...this.messageList, msg];
+			this.scrollToButtom();
+		},
+
+		// 消息已读更新
+		$onMessageReadByPeer() {
+			this.setData({
+				messageList: this.messageList
+			});
+		},
+		scrollToButtom() {
+			const query = uni.createSelectorQuery().in(this);
+			let nodesRef = query.select('#message-scroll');
+			nodesRef
+				.boundingClientRect(res => {
+					this.$nextTick(() => {
+						//进入页面滚动到底部
+						this.scrollTop = res.height;
+					});
+				})
+				.exec();
+		},
+		// 收到的消息
+		$onMessageReceived(value) {
+			console.log(value)
+			// 若需修改消息,需将内存的消息复制一份,不能直接更改消息,防止修复内存消息,导致其他消息监听处发生消息错误
+			const event = value;
+			const list = [];
+			event.data.forEach(item => {
+				if (item.conversationID === this.conversation.conversationID) {
+					list.push(Object.assign(item));
+					if(item.type=="TIMCustomElem"&&item.payload.data=='finish'){
+						this.$emit("finish");
+					}
+				}
+			});
+			this.messageList = this.messageList.concat(list);
+			this.scrollToButtom();
+		},
+
+		// 历史消息渲染
+		$handleMessageRender(messageList) {
+			if (messageList.length > 0) {
+				this.setData(
+					{
+						messageList
+					},
+					() => {}
+				);
+				this.$nextTick(() => {
+					//进入页面滚动到底部
+					this.scrollTop = 9999;
+				});
+			}
+		}
+	}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 86 - 0
components/im/tui-chat/message-private/common-words/index.css

@@ -0,0 +1,86 @@
+.tui-common-words-container {
+	position: fixed;
+	width: 100vw;
+	height: 100vh;
+	z-index: 100;
+	top: 0;
+	/*  #ifdef  H5  */
+	top: calc(88rpx + constant(safe-area-inset-top));
+	top: calc(88rpx + env(safe-area-inset-top));
+	/*  #endif  */
+	background: rgba(0, 0, 0, 0.5);
+}
+
+.tui-common-words-box {
+	position: absolute;
+	width: 100%;
+	height: 60%;
+	bottom: 0;
+	background: rgba(255, 255, 255, 1);
+	padding-bottom: 68rpx;
+	z-index: 200;
+}
+
+.tui-common-words-title {
+	display: flex;
+	flex-wrap: nowrap;
+	justify-content: space-between;
+	padding-left: 40rpx;
+	padding-right: 40rpx;
+	padding-top: 48rpx;
+	font-family: PingFangSC-Medium;
+	font-size: 36rpx;
+	color: #000000;
+	letter-spacing: 0;
+	line-height: 50rpx;
+}
+
+.tui-search-bar {
+	display: flex;
+	flex-wrap: nowrap;
+	align-items: center;
+	margin: 32rpx 40rpx;
+	width: 670rpx;
+	height: 80rpx;
+	background: #FFFFFF;
+	border-radius: 40rpx;
+	border-radius: 40rpx;
+	background-color: #F8F8F8;
+}
+
+.tui-searchcion {
+	display: inline-block;
+	margin-left: 24rpx;
+	width: 48rpx;
+	height: 48rpx;
+}
+
+.tui-search-bar-input {
+	margin-left: 16rpx;
+	line-height: 40rpx;
+	font-size: 28rpx;
+	width: 100%;
+	display: inline-block;
+}
+
+.tui-common-words-list {
+	position: absolute;
+	top: 242rpx;
+	bottom: 68rpx;
+	width: 750rpx;
+}
+
+.tui-common-words-item {
+	width: 750rpx;
+	height: 112rpx;
+	border-bottom: 2rpx solid #EEF0F3;
+	background-color: #FFFFFF;
+	font-family: PingFangSC-Regular;
+	font-size: 32rpx;
+	color: #333333;
+	letter-spacing: 0;
+	line-height: 44rpx;
+	padding: 0 40rpx;
+	display: flex;
+	align-items: center;
+}

+ 85 - 0
components/im/tui-chat/message-private/common-words/index.vue

@@ -0,0 +1,85 @@
+<template>
+	<view v-show="display" class="tui-common-words-container">
+		<view class="tui-common-words-box">
+			<view class="tui-common-words-title">
+				<view>请选择常用语</view>
+				<view style="color: #006EFF; font-family: PingFangSC-Regular;" class="tui-common-words-close" @tap="handleClose">关闭</view>
+			</view>
+			<view class="tui-search-bar">
+				<image class="tui-searchcion" src="/static/assets/serach-icon.svg"></image>
+				<input class="tui-search-bar-input" :value="words" placeholder="请输入关键字搜索" @input="wordsInput" />
+			</view>
+			<scroll-view class="tui-common-words-list" scroll-y="true" enable-flex="true">
+				<view v-for="(item, index) in commonWordsMatch" :key="index" class="tui-common-words-item" @tap="sendMessage" :data-words="item">{{ item }}</view>
+			</scroll-view>
+		</view>
+	</view>
+</template>
+
+<script>
+const commonWordsList = [
+	'你好在吗',
+	'问题A',
+	'问题B'
+];
+
+export default {
+	data() {
+		return {
+			words: '',
+			commonWordsMatch: commonWordsList
+		};
+	},
+
+	components: {},
+	props: {
+		display: {
+			type: Boolean,
+			default: false
+		}
+	},
+	watch: {
+		display: {
+			handler: function(newVal) {
+				// this.setData({
+				//   display: newVal
+				// });
+			},
+			immediate: true
+		}
+	},
+	methods: {
+		handleClose() {
+			this.$emit('close', {
+				detail: {
+					key: '0'
+				}
+			});
+		},
+
+		wordsInput(e) {
+			(this.commonWordsMatch = []),
+				commonWordsList.forEach(item => {
+					if (item.indexOf(e.detail.value) > -1) {
+						this.commonWordsMatch.push(item);
+					}
+				});
+			this.setData({
+				words: e.detail.value,
+				commonWordsMatch: this.commonWordsMatch
+			});
+		},
+
+		sendMessage(e) {
+			this.$emit('sendMessage', {
+				detail: {
+					message: e.currentTarget.dataset.words
+				}
+			});
+		}
+	}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 178 - 0
components/im/tui-chat/message-private/order-list/index.css

@@ -0,0 +1,178 @@
+.tui-cards-container {
+	position: fixed;
+	width: 100vw;
+	height: 100vh;
+	z-index: 100;
+	top: 0;
+	/*  #ifdef  H5  */
+	top: calc(88rpx + constant(safe-area-inset-top));
+	top: calc(88rpx + env(safe-area-inset-top));
+	/*  #endif  */
+	background: rgba(0, 0, 0, 0.5);
+}
+
+.tui-cards-box {
+	position: absolute;
+	width: 100%;
+	height: 60%;
+	bottom: 0;
+	background: #F4F5F9;
+	padding-bottom: 68rpx;
+	z-index: 200;
+}
+
+.tui-cards-title {
+	display: flex;
+	flex-wrap: nowrap;
+	justify-content: space-between;
+	padding-left: 40rpx;
+	padding-right: 40rpx;
+	padding-top: 48rpx;
+	font-family: PingFangSC-Medium;
+	font-size: 36rpx;
+	color: #000000;
+	letter-spacing: 0;
+	line-height: 50rpx;
+}
+
+.tui-search-bar {
+	display: flex;
+	flex-wrap: nowrap;
+	align-items: center;
+	margin: 32rpx 40rpx;
+	width: 670rpx;
+	height: 80rpx;
+	background: #FFFFFF;
+	border-radius: 40rpx;
+	border-radius: 40rpx;
+	background-color: #F8F8F8;
+}
+
+.tui-searchcion {
+	display: inline-block;
+	margin-left: 24rpx;
+	width: 48rpx;
+	height: 48rpx;
+}
+
+.tui-search-bar-input {
+	margin-left: 16rpx;
+	line-height: 40rpx;
+	font-size: 28rpx;
+	width: 100%;
+	display: inline-block;
+}
+
+.tui-order-list {
+	position: absolute;
+	top: 242rpx;
+	bottom: 68rpx;
+	width: 750rpx;
+}
+
+.tui-order-item {
+	width: 670rpx;
+	margin: 32rpx 40rpx;
+	height: 388rpx;
+	background-color: #FFFFFF;
+	border-radius: 4px;
+	display: flex;
+	flex-wrap: wrap;
+	align-items: center;
+}
+
+.order-title {
+	width: 670rpx;
+	height: 102rpx;
+	padding: 32rpx 40rpx;
+	padding-bottom: 0;
+	border-bottom: 2rpx solid #EEF0F3;
+}
+
+.order-title>.order-number {
+	font-family: PingFangSC-Medium;
+	font-size: 32rpx;
+	line-height: 44rpx;
+	color: #000000;
+	letter-spacing: 0;
+	margin-bottom: 8rpx;
+}
+
+.order-title>.order-time {
+	font-family: PingFangSC-Regular;
+	font-size: 24rpx;
+	line-height: 34rpx;
+	color: #999999;
+	letter-spacing: 0;
+}
+
+.order-info {
+	display: flex;
+	flex-wrap: nowrap;
+	width: 670rpx;
+	height: 236rpx;
+	padding: 32rpx 40rpx;
+}
+
+.order-content {
+	width: 450rpx;
+	margin-left: 32rpx;
+}
+
+.order-content-title {
+	font-family: PingFangSC-Medium;
+	width: 378rpx;
+	line-height: 34rpx;
+	font-size: 24rpx;
+	color: #000000;
+	letter-spacing: 0;
+	margin-bottom: 12rpx;
+}
+
+.order-content-description {
+	display: flex;
+	flex-wrap: nowrap;
+	font-family: PingFangSC-Regular;
+	max-width: 410rpx;
+	line-height: 34rpx;
+	font-size: 24rpx;
+	color: #999999;
+	letter-spacing: 0;
+	margin-bottom: 12rpx;
+}
+
+.order-content-price {
+	font-family: PingFangSC-Medium;
+	font-size: 36rpx;
+	line-height: 50rpx;
+	color: #FF7201;
+	letter-spacing: 0;
+}
+
+.order-image {
+	width: 156rpx;
+	height: 156rpx;
+}
+
+.btn-send-order {
+	width: 176rpx;
+	height: 58rpx;
+	background-color: #006EFF;
+	border-radius: 14.5px;
+	font-family: PingFangSC-Regular;
+	font-size: 24rpx;
+	color: #FFFFFF;
+	line-height: 28px;
+	text-align: center;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	margin-right: 40rpx;
+}
+
+.btn-send-text {
+	font-family: PingFangSC-Regular;
+	font-size: 12px;
+	color: #FFFFFF;
+	line-height: 14px;
+}

+ 137 - 0
components/im/tui-chat/message-private/order-list/index.vue

@@ -0,0 +1,137 @@
+<template>
+	<view v-if="display" class="tui-cards-container">
+		<view class="tui-cards-box">
+			<view class="tui-cards-title">
+				<view>请选择你要发送的订单</view>
+				<view style="color: #006EFF; font-family: PingFangSC-Regular;" class="tui-cards-close" @tap="handleClose">关闭</view>
+			</view>
+			<view class="tui-search-bar">
+				<image class="tui-searchcion" src="/static/assets/serach-icon.svg"></image>
+				<input class="tui-search-bar-input" :value="words" placeholder="搜索" @input="wordsInput" />
+			</view>
+			<scroll-view class="tui-order-list" scroll-y="true" enable-flex="true">
+				<view v-for="(item, index) in orderMatch" :key="index" class="tui-order-item">
+					<view class="order-title">
+						<view class="order-number">订单编号: {{ item.orderNum }}</view>
+						<view class="order-time">{{ item.time }}</view>
+					</view>
+					<view class="order-info">
+						<image class="order-image" :src="item.imageUrl"></image>
+						<view class="order-content">
+							<view class="order-content-title">{{ item.title }}</view>
+							<view class="order-content-description">{{ item.description }}</view>
+							<view style="display: flex; flex-wrap: no-wrap; justify-content: space-between;">
+								<view class="order-content-price">{{ item.price }}</view>
+								<view class="btn-send-order" :data-order="item" @tap.stop="sendMessage"><text class="btn-send-text">发送此订单</text></view>
+							</view>
+						</view>
+					</view>
+				</view>
+			</scroll-view>
+		</view>
+	</view>
+</template>
+
+<script>
+const orderList = [
+	{
+		orderNum: 1,
+		time: '2021-7-20 20:45',
+		title: '[天博检验]新冠核酸检测/预约',
+		description: '专业医学检测,电子报告',
+		imageUrl: 'https://sdk-web-1252463788.cos.ap-hongkong.myqcloud.com/component/TUIKit/assets/miles.jpeg',
+		price: '80元'
+	},
+	{
+		orderNum: 2,
+		time: '2021-7-20 22:45',
+		title: '[路边]新冠核酸检测/预约',
+		description: '专业医学检测,电子报告',
+		imageUrl: 'https://sdk-web-1252463788.cos.ap-hongkong.myqcloud.com/component/TUIKit/assets/miles.jpeg',
+		price: '7000元'
+	}
+];
+
+export default {
+	data() {
+		return {
+			words: '',
+			orderMatch: orderList
+		};
+	},
+
+	components: {},
+	props: {
+		display: {
+			type: Boolean,
+			default: false
+		},
+		conversation: {
+			type: Object,
+			default: () => {}
+		}
+	},
+	watch: {
+		display: {
+			handler: function(newVal) {
+				// this.setData({
+				//   display: newVal
+				// });
+			},
+			immediate: true
+		},
+		conversation: {
+			
+			handler: function(newVal) {
+				this.conversation=newVal
+			},
+			immediate: true,
+			deep: true
+		}
+	},
+	methods: {
+		handleClose() {
+			this.$emit('close', {
+				detail: {
+					key: '1'
+				}
+			});
+		},
+		wordsInput(e) {
+			var that=this;
+			(this.orderMatch = []),
+				orderList.forEach(item => {
+					if (item.title.indexOf(e.detail.value) > -1 || item.orderNum === ~~e.detail.value) {
+						this.orderMatch.push(item);
+					}
+				});
+			that.setData({
+				words: e.detail.value,
+				orderMatch: this.orderMatch
+			});
+		},
+
+		sendMessage(e) {
+			const { order } = e.currentTarget.dataset;
+			this.$emit('sendCustomMessage', {
+				detail: {
+					payload: {
+						// data 字段作为表示,可以自定义
+						data: 'order',
+						description: order.description,
+						// 获取骰子点数
+						extension: JSON.stringify({
+							title: order.title,
+							imageUrl: order.imageUrl,
+							price: order.price
+						})
+					}
+				}
+			});
+		}
+	}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 93 - 0
components/im/tui-chat/message-private/service-evaluation/index.css

@@ -0,0 +1,93 @@
+.tui-cards-container {
+	position: fixed;
+	width: 100vw;
+	height: 100vh;
+	z-index: 100;
+	top: 0;
+	/*  #ifdef  H5  */
+	top: calc(88rpx + constant(safe-area-inset-top));
+	top: calc(88rpx + env(safe-area-inset-top));
+	/*  #endif  */
+	background: rgba(0, 0, 0, 0.5);
+}
+
+.service-evaluation {
+	position: absolute;
+	bottom: 0;
+	right: 0;
+	left: 0;
+	background: #FFFFFF;
+	padding: 48rpx 40rpx;
+}
+
+.header {
+	display: flex;
+	justify-content: space-between;
+	font-family: PingFangSC-Regular;
+}
+
+.btn {
+	width: 100%;
+	padding: 0;
+	margin: 0 auto;
+	text-align: center;
+	background: none;
+}
+
+.btn-close {
+	color: #006EFF;
+}
+
+.header-label {
+	font-size: 18px;
+	color: #000000;
+	letter-spacing: 0;
+	line-height: 25px;
+}
+
+.header .btn {
+	font-size: 16px;
+	color: #006EFF;
+	letter-spacing: 0;
+	line-height: 24px;
+}
+
+.main {
+	display: flex;
+	flex-direction: column;
+	padding: 48rpx 0;
+}
+
+.main-evaluation-score {
+	padding: 0 60rpx 48rpx;
+	display: flex;
+	justify-content: space-between;
+	align-items: flex-end;
+}
+
+.main-evaluation-score .score-star {
+	width: 72rpx;
+	height: 72rpx;
+}
+
+.main-textarea {
+	background: #F8F8F8;
+	border: 0 solid #D9D9D9;
+	border-radius: 4px;
+	font-size: 14px;
+	padding: 16rpx 32rpx;
+}
+
+.textarea-placeholder {
+	color: #B0B0B0;
+}
+
+.footer .btn {
+	width: 100%;
+	padding: 26rpx 0;
+	background: #006EFF;
+	border-radius: 24px;
+	border-radius: 24px;
+	font-size: 16px;
+	color: #FFFFFF;
+}

+ 116 - 0
components/im/tui-chat/message-private/service-evaluation/index.vue

@@ -0,0 +1,116 @@
+<template>
+	<view class="tui-cards-container" v-if="display">
+		<view class="service-evaluation">
+			<view class="header">
+				<label class="header-label">请对本次服务进行评价</label>
+				<view class="btn-close" @tap="handleClose">关闭</view>
+			</view>
+			<view class="main">
+				<view class="main-evaluation-score">
+					<image
+						v-for="(item, index) in scoreList"
+						:key="index"
+						class="score-star"
+						:data-score="item"
+						:src="'/static/images/star' + (item > score ? '-grey' : '') + '.png'"
+						@tap="handleScore"
+					></image>
+				</view>
+				<textarea
+					class="main-textarea"
+					cols="30"
+					rows="10"
+					@input="bindTextAreaInput"
+					placeholder="请输入评语"
+					placeholder-style="textarea-placeholder"
+				></textarea>
+			</view>
+			<view class="footer"><view class="btn" @tap="sendMessage" :disabled="score === 0 && !comment">提交评价</view></view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			scoreList: [1, 2, 3, 4, 5],
+			score: 5,
+			comment: ''
+		};
+	},
+
+	components: {},
+	props: {
+		display: {
+			type: Boolean,
+			default: ''
+		}
+	},
+	watch: {
+		display: {
+			handler: function(newVal) {},
+			immediate: true
+		}
+	},
+
+	onPageShow() {
+		this.score= 0;
+		this.comment='';
+		 
+	},
+
+	methods: {
+		handleClose() {
+			this.$emit('close', {
+				detail: {
+					key: '2'
+				}
+			});
+		},
+
+		handleScore(e) {
+			let { score } = e.currentTarget.dataset;
+
+			if (score === this.score) {
+				score = 0;
+			}
+
+			this.setData({
+				score
+			});
+		},
+
+		bindTextAreaInput(e) {
+			this.setData({
+				comment: e.detail.value
+			});
+		},
+
+		sendMessage() {
+			this.$emit('sendCustomMessage', {
+				detail: {
+					payload: {
+						// data 字段作为表示,可以自定义
+						data: 'evaluation',
+						description: '对本次服务的评价',
+						// 获取骰子点数
+						extension: JSON.stringify({
+							score: this.score,
+							comment: this.comment
+						})
+					}
+				}
+			});
+			this.setData({
+				score: 0,
+				comment: ''
+			});
+			this.handleClose();
+		}
+	}
+};
+</script>
+<style>
+@import './index.css';
+</style>

+ 208 - 0
components/likeProduct.vue

@@ -0,0 +1,208 @@
+<template>
+   <view>
+		<view class="like-title">
+			<image src="/static/images/like.png" mode=""></image>
+			<text class="text">猜你喜欢</text>
+		</view>
+		<view class="like-list">
+			<view class="item" v-for="(item,index) in list" :key="index" @click="showProduct(item)">
+				<view class="img-box">
+					<image :src="item.image" mode=""></image>
+				</view>
+				<view class="info-box">
+					<view class="title ellipsis2">{{ item.productName }}</view>
+					<view class="price-box">
+						<view class="now">
+							<text class="unit">¥</text>
+							<text class="num" v-if="userinfoa.isShow==1&&isuser==false">{{item.price.toFixed(2)}}</text>
+							<text class="num" v-else>{{item.otPrice.toFixed(2)}}</text>
+						</view>
+						<view class="old">¥{{item.otPrice.toFixed(2)}}</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<Loading :loaded="loaded" :loading="loading"></Loading>
+   </view>
+</template>
+
+<script>
+  import {getGoodsProducts} from '@/api/product'
+  import {getUserInfo} from '@/api/user'
+  import Loading from "@/components/Loading";
+  export default {
+	components: {Loading },
+    name: "likeProduct",
+	data() {
+		return {
+			page:{
+				page: 1,
+				pageSize: 10
+			},
+			total:0,
+			list:[],
+			loaded: false,
+			loading: false,
+			userinfoa:[],
+			isuser:false,
+		};
+	},
+	created() {
+	},
+	mounted() {
+		this.getGoodsProducts();
+		if(uni.getStorageSync('AppToken')){
+			this.getUserInfos()
+		}else{
+			this.isuser=true
+		}
+	},
+	
+	methods: {
+		getUserInfos(){
+			getUserInfo().then(res => {
+					if(res.code==200){
+						if(res.user!=null){
+							
+							this.userinfoa=res.user
+							console.log(this.userinfoa.isShow,78787)
+						}
+					}else{
+						uni.showToast({
+							icon:'none',
+							title: "请求失败",
+						});
+					}
+				},
+				rej => {}
+			);
+		},
+		getGoodsProducts(){
+			console.log(1)
+			var that=this;
+			if (that.loaded == true || that.loading == true) return;
+			that.loading = true;
+			uni.showLoading({
+				title:"加载中..."
+			})
+			getGoodsProducts(that.page).then(
+				res => {
+					if(res.code==200){
+						that.total=res.data.total;
+						that.list.push.apply(that.list, res.data.list);
+						that.loading = false;
+						that.loaded = that.list.length<that.total?false:true;
+						that.page.page = that.page.page + 1;
+						uni.hideLoading()
+					}
+				},
+				err => {
+					uni.hideLoading()
+					uni.showToast({
+						title: err.msg ,
+						icon: 'none',
+						duration: 2000
+					});
+				}
+			);
+		},
+		showProduct(item){
+			uni.navigateTo({
+				url: '/pages/shopping/productDetails?productId='+item.productId
+			})
+		},
+	}
+ 
+  };
+</script>
+<style lang="scss">
+	.like-title{
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		padding: 30upx 0;
+		image{
+			width: 37upx;
+			height: 37upx;
+			margin-right: 20upx;
+		}
+		.text{
+			font-size: 36upx;
+			font-family: PingFang SC;
+			font-weight: bold;
+			color: #111111;
+			line-height: 1;
+		}
+	}
+	.like-list{
+		display: flex;
+		flex-wrap: wrap;
+		.item{
+			margin-right: 20rpx;
+			margin-bottom: 20rpx;
+			width: 345rpx;
+			background: #FFFFFF;
+			box-shadow: 0px 0px 10rpx 4rpx rgba(199, 199, 199, 0.22);
+			border-radius: 20rpx;
+			overflow: hidden;
+			&:nth-child(2n) {
+				margin-right: 0;
+			}
+			.img-box{
+				width: 100%;
+				height: 334upx;
+				image{
+					width: 100%;
+					height: 100%;
+				}
+			}
+			.info-box{
+				box-sizing: border-box;
+				height: 182upx;
+				padding: 20upx 20upx 30upx;
+				display: flex;
+				flex-direction: column;
+				justify-content: space-between;
+				.title{
+					font-size: 26upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #111111;
+					line-height: 40upx;
+				}
+				.price-box{
+					display: flex;
+					align-items: flex-end;
+					.now{
+						display: flex;
+						align-items: flex-end;
+						margin-right: 20upx;
+						.unit{
+							font-size: 24upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #FF6633;
+							line-height: 1.2;
+							margin-right: 4upx;
+						}
+						.num{
+							font-size: 36upx;
+							font-family: PingFang SC;
+							font-weight: bold;
+							color: #FF6633;
+							line-height: 1;
+						}
+					}
+					.old{
+						font-size: 26upx;
+						font-family: PingFang SC;
+						font-weight: 500;
+						text-decoration: line-through;
+						color: #BBBBBB;
+						line-height: 1.1;
+					}
+				}
+			}
+		}
+	}
+</style>

+ 315 - 0
components/px-popup-bottom/px-popup-bottom.vue

@@ -0,0 +1,315 @@
+<template>
+	<view :class="['popup',{'popup-show':show}]" @mousewheel.prevent.stop @touchmove.stop.prevent
+		:style="{'z-index':zindex}">
+		<view class="mask" :style="{'z-index':maskZindex,bottom:bottom+'rpx'}" v-show="show" @click.stop="onClose"
+			@touchmove.prevent.stop></view>
+		<view :class="['content',{show}]" @click.stop @touchmove.prevent.stop :style="{'background-color':bgColor,height:`${height}px`,maxHeight:show ? cotMaxHeight:0,'border-top-right-radius':cotRadius,
+			'border-top-left-radius':cotRadius,transition: `all ${animaTime}s ease-in`,bottom:bottom+'rpx','z-index':zindex}">
+			<view id="title-bar" class="title-bar" v-show="title">
+				<view class="title" :style="{fontWeight:fontweight}">{{title}}</view>
+				<view class="close-wrap" @click.stop="onClose">
+					<image class="close-icon" :src="closeIcon" mode="widthFix"></image>
+				</view>
+			</view>
+			<view class="scroll-wrap">
+				<scroll-view :class="{'scroll-view':isAnimaStart}" scroll-y="true" style="height:100%;"
+					@scrolltolower="onScrollToLower">
+					<view id="popup_content" class="popup_content">
+						<slot></slot>
+					</view>
+				</scroll-view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import iconClose from '@/static/images/close40.png'
+	export default {
+		props: {
+			title: { //标题
+				type: String,
+				default: ''
+			},
+			fontweight: {
+				type: [String, Number],
+				default: 'normal'
+			},
+			visible: { //隐藏显示标识
+				type: Boolean,
+				default: false
+			},
+			maxHeight: { //内容区域最大高度
+				type: [String, Number],
+				default: '75%'
+			},
+			radius: { //顶部圆角
+				type: [String, Number],
+				default: '0'
+			},
+			animaTime: { //弹窗动画时间
+				type: Number,
+				default: 0.2
+			},
+			bottom: { //离底部距离
+				type: [String, Number],
+				default: 0
+			},
+			bgColor: {
+				type: [String],
+				default: '#ffffff'
+			},
+			zindex: {
+				type: [String, Number],
+				default: 1000
+			},
+			maskZindex: {
+				type: [String, Number],
+				default: 999
+			},
+			always: { //是否每次打开都重新计算内容高度
+				type: Boolean,
+				default: false
+			},
+
+		},
+		data() {
+			return {
+				show: false,
+				height: 0,
+				PopHeight: 0,
+				cotMaxHeight: '',
+				isAnimaStart: false,
+				rpxRate: "",
+				cotRadius: 0,
+				closeIcon: iconClose
+			}
+		},
+		watch: {
+			visible(newval) {
+				this.isAnimaStart = true;
+				setTimeout(() => {
+					this.isAnimaStart = false;
+				}, this.animaTime * 1000)
+
+				if (newval && this.height === 0) {
+					if (this.PopHeight === 0 || this.always) {
+						this.setContViewHeight();
+
+					} else {
+						this.height = this.PopHeight
+					}
+
+					// #ifdef H5 
+					this.setBodyOverFlow('hidden') //阻止滚动穿透
+					//#endif
+					this.$emit('open')
+
+				} else {
+					this.height = 0;
+					// #ifdef H5 
+					this.setBodyOverFlow('visible')
+					//#endif
+
+				}
+
+				this.show = newval
+
+			},
+			maxHeight: {
+				handler(newval) {
+					this.cotMaxHeight = this.unitCheck(newval);
+
+				},
+				immediate: true
+			},
+			radius: {
+				handler(newval) {
+					this.cotRadius = this.unitCheck(newval);
+
+				},
+				immediate: true
+			}
+		},
+		created() {
+			this.rpxRate = this.getRpxRate()
+		},
+		mounted() {
+			this.$nextTick(() => {
+				// #ifdef H5
+				this.preventTouch(document.querySelector(
+					'.scroll-wrap .uni-scroll-view .uni-scroll-view')); //防止浏览器报错
+				//#endif
+			})
+		},
+		methods: {
+			onClose() {
+				this.$emit("update:visible", false);
+				this.$emit('close')
+			},
+			//触底
+			onScrollToLower(e) {
+				this.$emit("reachBottom");
+			},
+			getRpxRate() {
+				let res = uni.getSystemInfoSync();
+				let width = res.windowWidth;
+				let rate = 750.00 / width;
+				return rate
+			},
+			unitCheck(value) {
+				const val = String(value);
+				if (!val.includes('px') && !val.includes('%')) {
+					return `${val}rpx`;
+				}
+				return val;
+
+			},
+			preventTouch(el) {
+				el.addEventListener('touchmove', function(e) {
+					e.stopPropagation();
+
+				}, {
+					passive: false
+				});
+			},
+			setBodyOverFlow(val) {
+				document.body.style.overflow = val
+			},
+
+			//设置内容区域高度
+			async setContViewHeight() {
+				let data = await this.computeHeight();
+				this.height = data.height + (this.title ? 100 / parseFloat(this.rpxRate) : 0);
+				this.PopHeight = this.height;
+			},
+			//计算内容区域高度
+			computeHeight() {
+				return new Promise(resolve => {
+					this.$nextTick(() => {
+						const query = uni.createSelectorQuery().in(this);
+						query.select('#popup_content').boundingClientRect(data => {
+							resolve(data)
+						}).exec();
+					})
+				})
+			}
+
+		}
+
+
+	}
+</script>
+
+<style lang="scss" scoped>
+	.popup {
+
+		&.popup-show {
+			position: fixed;
+			top: 0;
+			right: 0;
+			left: 0;
+			bottom: 0;
+			overflow: hidden;
+			z-index: 999;
+		}
+
+		.mask {
+			position: fixed;
+			top: 0;
+			right: 0;
+			bottom: 0;
+			left: 0;
+			background-color: rgba($color: #000000, $alpha: 0.5);
+			z-index: 999;
+		}
+
+		.content {
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			right: 0;
+			height: 0;
+			height: auto;
+			background-color: #ffffff;
+			transition: all 0.2s ease-in;
+			z-index: 1000;
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			overflow: hidden;
+
+			.title-bar {
+				width: 100%;
+				flex-shrink: 0;
+				text-align: center;
+				position: relative;
+				padding: 10rpx 70rpx 0;
+				box-sizing: border-box;
+				height: 80rpx;
+
+				.title {
+					font-size: 34upx;
+					font-family: PingFang SC;
+					font-weight: bold !important;
+					color: #111111;
+					width: 100%;
+					overflow: hidden;
+					text-overflow: ellipsis;
+					white-space: nowrap;
+				}
+
+				.close-wrap {
+					position: absolute;
+					top: 20rpx;
+					right: 10rpx;
+					padding: 10rpx 20rpx;
+					box-sizing: border-box;
+				}
+
+				.close-icon {
+					width: 40rpx;
+					height: 40rpx;
+				}
+			}
+
+			.scroll-wrap {
+				flex: 1;
+				height: 0;
+				width: 100%;
+			}
+
+			&.visible {
+				max-height: 75%;
+				overflow-y: hidden;
+				height: auto;
+
+			}
+		}
+	}
+
+	.scroll-view ::-webkit-scrollbar {
+		display: none !important;
+		width: 0 !important;
+		height: 0 !important;
+		-webkit-appearance: none;
+		background: transparent;
+
+	}
+
+	.popup_content {
+		width: 100%;
+		padding: 0rpx 30rpx;
+		box-sizing: border-box;
+
+		&::after {
+			display: block;
+			width: 100%;
+			content: "\00A0";
+			overflow: hidden;
+			opacity: 0;
+			height: 1rpx;
+		}
+
+	}
+</style>

+ 94 - 0
components/tabbar/tabbar.vue

@@ -0,0 +1,94 @@
+<template>
+	<!-- 使用得时候必须加上style  不然没有--colorxxxxx之类得变量 -->
+	<view class="tabbar align-center" :style="$store.state.theme.currentMoban">
+		<view v-for="(item, index) in tabbarList" :key="index" @click="switchTabs(item)" class="tablist">
+			<view class="column align-center justify-center" >
+				<image :src="actindex==index?item.selectedIconPath:item.iconPath" class="w48 h48"></image>
+				<text class="fs24 base-textcol" :class="actindex==index?'actcolor':'morecolor'">{{item.Text}}</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "tabbar",
+		props: {
+			actindex: {
+				type: Number,
+				default: 0
+			}
+		},
+		data() {
+			return {
+				themes: 'beiliyou',
+				tabbarList: [],
+			};
+		},
+		mounted() {
+			this.themeicon()
+			console.log(this.$store.state.theme.currentMoban['--base-color'])
+		},
+		methods: {
+			switchTabs(item) {
+				// 到时候要设置两个tabbar   但是一教育页面得隐藏掉   这里得页面不能配置到tabbar得list里面
+				
+				uni.navigateTo({
+					url: item.url
+				})
+			},
+			themeicon() {
+				const theme = this.themes
+				this.tabbarList = [{
+						iconPath: `/static/images/tabbar/${theme}/home.png`,
+						selectedIconPath: `/static/images/tabbar/${theme}/home_on.png`,
+						Text: '首页',
+						url: '/pages/home/index'
+					},
+					{
+						iconPath: `/static/images/tabbar/${theme}/ENCYCLOPEDIA.png`,
+						selectedIconPath: `/static/images/tabbar/${theme}/ENCYCLOPEDIA_on.png`,
+						Text: '企业理念',
+						url: '/pages/enterprise/enterprise'
+
+					},
+					{
+						iconPath: `/static/images/tabbar/${theme}/mall.png`,
+						selectedIconPath: `/static/images/tabbar/${theme}/mall_on.png`,
+						Text: '健康商城',
+						url: '/pages/shopping/index'
+					},
+					{
+						iconPath: `/static/images/tabbar/${theme}/mine.png`,
+						selectedIconPath: `/static/images/tabbar/${theme}/mine_on.png`,
+						Text: '会员中心',
+						url: '/pages/user/index'
+					},
+				]
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.tabbar {
+		display: flex;
+		position: fixed;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		background-color: #fff;
+		z-index: 1000;
+		height: 100rpx;
+	}
+
+	.tablist {
+		width: 25%;
+	}
+	.morecolor{
+		color: #626468;
+	}
+	.actcolor {
+		color: #018C39;
+	}
+</style>

+ 210 - 0
components/tuiProduct.vue

@@ -0,0 +1,210 @@
+<template>
+   <view>
+		<!-- <view class="like-title">
+			<image src="/static/images/tui.png" mode=""></image>
+			<text class="text">精选商品</text>
+		</view> -->
+		<view class="like-list">
+			<view class="item" v-for="(item,index) in list" :key="index" @click="showProduct(item)">
+				<view class="img-box">
+					<image :src="item.image" mode=""></image>
+				</view>
+				<view class="info-box">
+					<view class="title ellipsis2">{{ item.productName }}</view>
+					<view class="price-box">
+						<view class="now">
+							<text class="unit">¥</text>
+							<text class="num"  v-if="userinfoa.isShow==1&&isuser==false">{{item.price.toFixed(2)}}</text>
+							<text class="num" v-else>{{item.otPrice.toFixed(2)}}</text>
+						</view>
+						<view class="old" v-if="userinfoa.isShow==1&&isuser==false">¥{{item.otPrice.toFixed(2)}}</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<Loading :loaded="loaded" :loading="loading"></Loading>
+   </view>
+</template>
+
+<script>
+  import {getTuiProducts} from '@/api/product'
+  import {getUserInfo} from '@/api/user'
+  import Loading from "@/components/Loading";
+  export default {
+	components: {Loading },
+    name: "likeProduct",
+	data() {
+		return {
+			page:{
+				page: 1,
+				pageSize: 10
+			},
+			total:0,
+			list:[],
+			loaded: false,
+			loading: false,
+			userinfoa:[],
+			isuser:false,
+		};
+	},
+	created() {
+	},
+	mounted() {
+		this.getTuiProducts();
+		if(uni.getStorageSync('AppToken')){
+			this.getUserInfos()
+		}else{
+			this.isuser=true
+		}
+	},
+	
+	methods: {
+		getUserInfos(){
+			getUserInfo().then(res => {
+					if(res.code==200){
+						if(res.user!=null){
+							// if(res.user.isPromoter==null||res.user.isPromoter==0){
+							// 	this.tuiModalControl=true
+							// }
+							this.userinfoa=res.user
+							console.log(this.userinfoa.isShow,78787)
+						}
+					}else{
+						uni.showToast({
+							icon:'none',
+							title: "请求失败",
+						});
+					}
+				},
+				rej => {}
+			);
+		},
+		getTuiProducts(){
+			console.log(1)
+			var that=this;
+			if (that.loaded == true || that.loading == true) return;
+			that.loading = true;
+			uni.showLoading({
+				title:"加载中..."
+			})
+			getTuiProducts(that.page).then(
+				res => {
+					if(res.code==200){
+						that.total=res.data.total;
+						that.list.push.apply(that.list, res.data.list);
+						that.loading = false;
+						that.loaded = that.list.length<that.total?false:true;
+						that.page.page = that.page.page + 1;
+						uni.hideLoading()
+					}
+				},
+				err => {
+					uni.hideLoading()
+					uni.showToast({
+						title: err.msg ,
+						icon: 'none',
+						duration: 2000
+					});
+				}
+			);
+		},
+		showProduct(item){
+			uni.navigateTo({
+				url: '/pages/shopping/productDetails?productId='+item.productId
+			})
+		},
+	}
+ 
+  };
+</script>
+<style lang="scss">
+	.like-title{
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		padding: 15upx 0rpx 30upx 0rpx;
+		image{
+			width: 37upx;
+			height: 37upx;
+			margin-right: 20upx;
+		}
+		.text{
+			font-size: 36upx;
+			font-family: PingFang SC;
+			font-weight: bold;
+			color: #111111;
+			line-height: 1;
+		}
+	}
+	.like-list{
+		display: flex;
+		flex-wrap: wrap;
+		.item{
+			margin-right: 20rpx;
+			margin-bottom: 20rpx;
+			width: 345rpx;
+			background: #FFFFFF;
+			box-shadow: 0px 0px 10rpx 4rpx rgba(199, 199, 199, 0.22);
+			border-radius: 20rpx;
+			overflow: hidden;
+			&:nth-child(2n) {
+				margin-right: 0;
+			}
+			.img-box{
+				width: 100%;
+				height: 334upx;
+				image{
+					width: 100%;
+					height: 100%;
+				}
+			}
+			.info-box{
+				box-sizing: border-box;
+				height: 182upx;
+				padding: 20upx 20upx 30upx;
+				display: flex;
+				flex-direction: column;
+				justify-content: space-between;
+				.title{
+					font-size: 26upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #111111;
+					line-height: 40upx;
+				}
+				.price-box{
+					display: flex;
+					align-items: flex-end;
+					.now{
+						display: flex;
+						align-items: flex-end;
+						margin-right: 20upx;
+						.unit{
+							font-size: 24upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #FF6633;
+							line-height: 1.2;
+							margin-right: 4upx;
+						}
+						.num{
+							font-size: 36upx;
+							font-family: PingFang SC;
+							font-weight: bold;
+							color: #FF6633;
+							line-height: 1;
+						}
+					}
+					.old{
+						font-size: 26upx;
+						font-family: PingFang SC;
+						font-weight: 500;
+						text-decoration: line-through;
+						color: #BBBBBB;
+						line-height: 1.1;
+					}
+				}
+			}
+		}
+	}
+</style>

+ 325 - 0
components/z-modal/z-modal.vue

@@ -0,0 +1,325 @@
+<template>
+	<view>
+		<view class="mask" :style="{'opacity':show?'1':'0','visibility':show?'visible':'hidden'}"></view>
+		<view class="modal-box" :style="{'display':show?'block':'none','width':modalWidth}">
+			<view class="modal-title" :style="{'padding':titlePadding,'fontSize':titleSize,'color':titleColor}">
+				{{titleText}}
+			</view>
+			<view class="modal-content" v-if="contentType==1" :style="{'fontSize':contentSize,'padding':contentPadding,'color':contentColor}">
+				{{contentText}}
+			</view>
+			<view class="modal-content" v-if="contentType==2" :style="{'padding':contentPadding}">
+				<input :placeholder="placeholderText" v-model="inputText" :maxlength="maxLength" :placeholder-style="placeholderStyleString" :style="{'borderColor':inputBorderColor,'fontSize':contentSize,'color':contentColor}" class="input-area"/>
+			</view>
+			<view class="modal-content" v-if="contentType==3" :style="{'padding':contentPadding}">
+				<textarea :placeholder="placeholderText" v-model="textareaText" :maxlength="maxLength" :placeholder-style="placeholderStyleString" :style="{'borderColor':inputBorderColor,'fontSize':contentSize,'color':contentColor}"/>
+			</view>
+			<view class="model-bottom" :style="{'padding':bottomPadding,'justify-content':btnLength>1?'space-between':'center'}">
+				<block v-for="(item,index) in btnGroup" :key='index'>
+					<view class="modal-btn" :style="{'width':item.width,'height':item.height,'color':item.color,'background-color':item.bgColor,'font-size':bottomFontSize,'border-radius':shapeObj[item.shape]}" @tap="btnClick(index)">
+						{{item.text}}
+					</view>
+				</block>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "z-modal",
+		props: {
+			// **************** 使用配置项 ****************
+			// 文本校验?
+			check:{
+				type:Boolean,
+				default:false
+			},
+			checkItem:{
+				// isRequired-是否必填/ isNumber-是否为纯数字 isChinese-是否为纯中文 isEnglish-是否为纯英文 isEmail-是否为邮箱格式 isIdNum-是否为身份证格式
+				type:Array,
+				default:()=>{
+					return []
+				}
+			},
+			/*
+			支持自定义校验,格式为{
+				key:正则
+			}
+			例如{
+				'isNumber':/^\+?[0-9][0-9]*$/
+			}
+			*/
+			selfCheckItem:{
+				type:Object,
+				default:()=>{
+					return {}
+				}
+			},
+			// 控制modal的显示隐藏
+			show:{
+				type:Boolean,
+				default:false
+			},
+			// 底部按钮组
+			btnGroup: {
+				type: Array,
+				default: () => {
+					return [{
+						text: '取消',
+						color: '#FFFFFF',
+						bgColor: '#999999',
+						width: '220rpx',
+						height: '80rpx',
+						shape: 'circle',
+						eventName: 'cancle'
+					}, {
+						text: '确定',
+						color: '#FFFFFF',
+						bgColor: '#007AFF',
+						width: '220rpx',
+						height: '80rpx',
+						shape: 'circle',
+						eventName: 'sure'
+					}]
+				}
+			},
+			// 文本类型 1-展示文字 2-input 3-textarea
+			contentType:{
+				type:[Number,String],
+				default:1
+			},
+			// contentType为2或3时的字数限制
+			maxLength:{
+				type:Number,
+				default:20
+			},
+			// **************** 尺寸&大小 ****************
+			// modal整体宽度 rpx
+			modalWidth:{
+				type:String,
+				default:'580rpx'
+			},
+			// title区域文字大小
+			titleSize:{
+				type:String,
+				default:'32rpx'
+			},
+			// content区域文字大小
+			contentSize:{
+				type:String,
+				default:'28rpx'
+			},
+			// 底部(按钮)区域的字号
+			bottomFontSize:{
+				type:String,
+				default:'28rpx'
+			},
+			// title(标题) 区域的padding
+			titlePadding:{
+				type:String,
+				default:'20rpx 0'
+			},
+			// content(内容) 区域的padding
+			contentPadding:{
+				type:String,
+				default:'10rpx 40rpx'
+			},
+			// 底部(按钮)区域的padding
+			bottomPadding:{
+				type:String,
+				default:'30rpx 40rpx'
+			},
+			// **************** 颜色 ****************
+			// 标题文字颜色
+			titleColor:{
+				type:String,
+				default:'#333333'
+			},
+			// 内容文字颜色
+			contentColor:{
+				type:String,
+				default:'#333333'
+			},
+			// placeholderColor-提示文字的颜色
+			placeholderColor:{
+				type:String,
+				default:'#999'
+			},
+			inputBorderColor:{
+				type:String,
+				default:'#999'
+			},
+			// **************** 内容 ****************
+			// 标题内容
+			titleText:{
+				type:String,
+				default:'titleText'
+			},
+			// 文本内容
+			contentText:{
+				type:String,
+				default:'Please type in your text'
+			},
+			// input或textarea的placeholder
+			placeholderText:{
+				type:String,
+				default:'请输入你的内容'
+			}
+		},
+		computed:{
+			btnLength(){
+				return this.btnGroup.length
+			},
+			placeholderStyleString(){
+				return `color:${this.placeholderColor};font-size:${this.contentSize}`
+			}
+		},
+		data() {
+			return {
+				// 底部按钮shape对应值
+				shapeObj:{
+					'circle':'1000rpx',
+					'straight':'0',
+					'fillet':'12rpx'
+				},
+				inputText:'',
+				textareaText:'',
+				// ***校验项,是否通过,true-通过,false不通过
+				checkCollection: {
+					isRequired :function(val){
+						return !(val === null || val === '' || val === undefined)
+					},
+					isNumber :function(val){
+						let reg = /^\+?[0-9][0-9]*$/
+						return reg.test(val)
+					},
+					isChinese :function(val){
+						let reg = /^[\u4e00-\u9fa5]+$/
+						return reg.test(val)
+					},
+					isEnglish :function(val){
+						let reg = /^[a-zA-Z]+$/
+						return reg.test(val)
+					},
+					isEmail :function(val){
+						let reg = /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/
+						return reg.test(val)
+					},
+					isIdNum :function(val){
+						let reg = /^\d{6}(18|19|20)?\d{2}(0[1-9]|1[12])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i
+						return reg.test(val)
+					}
+				}
+			};
+		},
+		methods:{
+			btnClick(index){
+				let val = this.contentType==2?this.inputText:this.textareaText
+				if(this.check && this.checkItem.length && this.contentType!=1){
+					let err = false
+					// 进入校验,如果不通过直接返回,通过则吐出按钮事件
+					for(let item of this.checkItem){
+						if(!this.checkCollection[item](val)){
+							this.$emit('error',item)
+							err = true
+							break
+						}
+					}
+					if(err) return
+				}
+				let selfCheckArr = Object.entries(this.selfCheckItem)
+				if(this.check && selfCheckArr.length && this.contentType!=1){
+					let err = false
+					for(let item of selfCheckArr){
+						let reg = new RegExp(item[1])
+						if(!reg.test(val)){
+							this.$emit('error',item[0])
+							err = true
+							break
+						}
+					}
+					if(err) return
+				}
+				this.$emit(this.btnGroup[index]['eventName'],{
+					inputText:this.inputText || '',
+					textareaText:this.textareaText || ''
+				})
+				this.inputText = ''
+				this.textareaText = ''
+			}
+		}
+	}
+</script>
+
+<style>
+	.mask {
+		position: fixed;
+		z-index: 98;
+		background-color: rgba(0, 0, 0, .7);
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		visibility: hidden;
+		opacity: 0;
+		transition: all .3s;
+	}
+
+	.modal-box {
+		background-color: #FFFFFF;
+		position: fixed;
+		z-index: 99;
+		border-radius: 12rpx;
+		left: 50%;
+		top: 50%;
+		transform: translate(-50%, -50%);
+	}
+
+	.modal-title {
+		box-sizing: border-box;
+		color: #333333;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.modal-content {
+		box-sizing: border-box;
+		color: #333333;
+		word-break: break-all;
+		display: flex;
+		justify-content: center;
+	}
+
+	.model-bottom {
+		display: flex;
+		align-items: center;
+	}
+
+	.modal-btn {
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+	
+	.input-area{
+		border: 1rpx solid #999;
+		width: 100%;
+		padding:0 16rpx;
+		box-sizing: border-box;
+		height: 60rpx;
+		border-radius: 6rpx;
+		outline: none;
+	}
+	
+	textarea{
+		border: 1rpx solid #999;
+		width: 92%;
+		padding:16rpx;
+		box-sizing: border-box;
+		border-radius: 6rpx;
+		height: 200rpx;
+	}
+
+</style>

+ 25 - 0
main.js

@@ -0,0 +1,25 @@
+import Vue from 'vue'
+import App from './App'
+
+Vue.config.productionTip = false
+
+import uView from 'uview-ui'
+Vue.use(uView)
+// uni.$u.config.unit = 'rpx'
+
+import utils from './utils/common.js'
+Vue.prototype.utils = utils;
+
+import {
+	setData
+} from './utils/common.js'
+// vuex
+import store from '@/store/index.js'
+Vue.prototype.setData = setData;
+
+App.mpType = 'app'
+const app = new Vue({
+	...App,
+	store
+})
+app.$mount()

+ 93 - 0
manifest.json

@@ -0,0 +1,93 @@
+{
+    "name" : "倍力优",
+    "appid" : "__UNI__58B30F8",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {},
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {},
+            /* SDK配置 */
+            "sdkConfigs" : {}
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "wx11a2ce7c2bbc4521",
+        "lazyCodeLoading" : "requiredComponents",
+        "setting" : {
+            "urlCheck" : false,
+            "minified" : true
+        },
+        "optimization" : {
+            "subPackages" : true
+        },
+        "usingComponents" : true,
+        "permission" : {
+            "scope.userLocation" : {
+                "desc" : "获取位置用于给您推送相关信息"
+            }
+        }
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "vueVersion" : "2",
+    "h5" : {
+        "title" : "倍力优",
+        "devServer" : {
+            "https" : false
+        },
+        "optimization" : {
+            "treeShaking" : {
+                "enable" : true
+            }
+        }
+    }
+}

+ 23 - 0
package-lock.json

@@ -0,0 +1,23 @@
+{
+    "name": "shop",
+    "version": "1.0.0",
+    "lockfileVersion": 1,
+    "requires": true,
+    "dependencies": {
+        "animate.css": {
+            "version": "3.7.2",
+            "resolved": "https://registry.npmmirror.com/animate.css/-/animate.css-3.7.2.tgz",
+            "integrity": "sha512-0bE8zYo7C0KvgOYrSVfrzkbYk6IOTVPNqkiHg2cbyF4Pq/PXzilz4BRWA3hwEUBoMp5VBgrC29lQIZyhRWdBTw=="
+        },
+        "dayjs": {
+            "version": "1.11.13",
+            "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
+            "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
+        },
+        "uview-ui": {
+            "version": "2.0.36",
+            "resolved": "https://registry.npmmirror.com/uview-ui/-/uview-ui-2.0.36.tgz",
+            "integrity": "sha512-ASSZT6M8w3GTO1eFPbsgEFV0U5UujK+8pTNr+MSUbRNcRMC1u63DDTLJVeArV91kWM0bfAexK3SK9pnTqF9TtA=="
+        }
+    }
+}

+ 11 - 0
package.json

@@ -0,0 +1,11 @@
+{
+    "name": "shop",
+    "version": "1.0.0",
+    "description": "",
+    "keywords": [],
+    "dependencies": {
+        "animate.css": "^3.7.2",
+        "dayjs": "^1.11.13",
+        "uview-ui": "^2.0.36"
+    }
+}

+ 1257 - 0
pages.json

@@ -0,0 +1,1257 @@
+{
+	"easycom": {
+		"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
+	 },
+	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+		{
+			"path": "pages/common/launch"
+		},
+		{
+			"path": "pages/auth/login",
+			"style": {
+				"navigationBarTitleText": "授权登录",
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/auth/wxLogin",
+			"style": {
+				"navigationBarTitleText": "公众号授权",
+				"navigationStyle": "custom"
+			}
+			
+		},
+		{
+			"path": "pages/home/index",
+			"style": {
+				"navigationBarTitleText": "倍力优",
+                "enablePullDownRefresh": false,
+                "navigationStyle": "custom",
+				"app-plus": {
+					"titleNView": false
+				}
+			}
+		},
+		// {
+  //           "path" : "pages/home/doctorCase",
+  //           "style" :                                                                                    
+  //           {
+  //               "navigationBarTitleText": "问诊案例",
+		// 		"app-plus": {
+		// 			"titleNView": false
+		// 		}
+  //           }
+            
+  //       },
+		{
+            "path" : "pages/home/productSearch",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "商品搜索",
+				"app-plus": {
+					"titleNView": false
+				}
+            }
+            
+        },
+		{
+            "path" : "pages/home/productList",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "商品列表",
+				"app-plus": {
+					"titleNView": false
+				}
+            }
+        },
+		{
+            "path" : "pages/healthy/index",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "健康知识",
+                "enablePullDownRefresh": false,
+                "navigationStyle": "custom",
+				"app-plus": {
+					"titleNView": false
+				}
+            }
+            
+        },
+		{
+            "path" : "pages/healthy/detail",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "",
+                "enablePullDownRefresh": false,
+				"app-plus": {
+					"titleNView": false
+				}
+            }
+        },
+		{
+            "path" : "pages/healthy/readUsers",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "阅读用户",
+                "enablePullDownRefresh": false,
+				"app-plus": {
+					"titleNView": false
+				}
+            }
+        },
+		{
+            "path" : "pages/shopping/index",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "商城",
+                "navigationStyle": "custom",
+                "enablePullDownRefresh": false
+            }
+            
+        },
+		{
+			"path": "pages/user/index",
+			"style": {
+				"navigationBarTitleText": "我的",
+                "navigationStyle": "custom",
+				"app-plus": {
+					"titleNView": false
+				}
+			}
+		}
+        ,{
+            "path" : "pages/shopping/productDetails",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "商品详情",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/shopping/cart",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "购物车",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/shopping/productList",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "商品列表",
+                "enablePullDownRefresh": false,
+                "navigationStyle": "custom",
+                "app-plus": {
+                	"titleNView": false
+                }
+            }
+            
+        }
+        ,{
+            "path" : "pages/shopping/confirmOrder",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "确认订单",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/shopping/paymentOrder",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "支付订单",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+		,{
+		    "path" : "pages/shopping/payOrder",
+		    "style" :                                                                                    
+		    {
+		        "navigationBarTitleText": "推荐订单支付",
+		        "enablePullDownRefresh": false
+		    }
+		}
+    //     ,{
+    //         "path" : "pages/shopping/prescribe",
+    //         "style" :                                                                                    
+    //         {
+    //             "navigationBarTitleText": "填写处方信息",
+				// "navigationStyle": "custom",
+    //             "enablePullDownRefresh": false
+    //         }
+            
+    //     }
+		,{
+		    "path" : "pages/shopping/success",
+		    "style" :                                                                                    
+		    {
+		        "navigationBarTitleText": "支付成功",
+		        "enablePullDownRefresh": false
+		    }
+		    
+		}
+		,{
+		    "path" : "pages/home/content",
+		    "style" :                                                                                    
+		    {
+		        "navigationBarTitleText": "详情",
+		        "enablePullDownRefresh": false
+		    }
+		    
+		}
+		,{
+		    "path" : "pages/home/h5",
+		    "style" :                                                                                    
+		    {
+		        "navigationBarTitleText": "详情",
+		        "enablePullDownRefresh": false
+		    }
+		    
+		}
+		,{
+		    "path" : "pages/home/cert",
+		    "style" :                                                                                    
+		    {
+		        "navigationBarTitleText": "资质证明",
+		        "enablePullDownRefresh": false
+		    }
+		    
+		},
+		// {
+		//     "path" : "pages/shopping/confirmPackageOrder",
+		//     "style" :                                                                                    
+		//     {
+		//         "navigationBarTitleText": "确认支付",
+		//         "enablePullDownRefresh": false
+		//     }
+		    
+		// }
+		// ,{
+		//     "path" : "pages/shopping/confirmCreateOrder",
+		//     "style" :                                                                                    
+		//     {
+		//         "navigationBarTitleText": "确认订单",
+		//         "enablePullDownRefresh": false
+		//     }
+		// },
+		{
+		    "path" : "pages/user/test",
+		    "style" :                                                                                    
+		    {
+		        "navigationBarTitleText": "测一测",
+				"app-plus": {
+					"titleNView": false
+				}
+		    }
+		},
+		// {
+		//     "path" : "pages/doctor/doctorQr",
+		//     "style" :
+		//     {
+		//        "navigationBarTitleText": "用药咨询",
+		// 		"app-plus": {
+		// 			"titleNView": false
+		// 		}
+		//     }
+		// },
+		{
+			"path" : "pages/user/test/test",
+			"style" : 
+			{
+				"navigationBarTitleText" : ""
+			}
+		},
+		{
+			"path" : "pages/user/test/test1",
+			"style" : 
+			{
+				"navigationBarTitleText" : ""
+			}
+		},
+		{
+			"path" : "pages/enterprise/enterprise",
+			"style" : 
+			{
+				"navigationBarTitleText" : "企业理念",
+				"navigationStyle": "custom",
+				"enablePullDownRefresh": false
+			}
+		},
+		{
+			"path" : "pages/home/vipBenefit",
+			"style" : 
+			{
+				"navigationBarTitleText" : "会员福利"
+			}
+		},
+		{
+			"path" : "pages/home/healthCourse",
+			"style" : 
+			{
+				"navigationBarTitleText" : "健康课堂"
+			}
+		}
+		
+    ],
+	"subPackages": [
+		
+		{
+			"root": "pages_index",
+			"pages": [
+				{
+				    "path" : "index/medicatedFoodList",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "药膳食疗",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/medicatedFoodDetails",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "药膳食疗",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				
+				{
+				    "path" : "index/vesselList",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "经络穴位",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/vesselDetails",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "经络穴位",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/questionsList",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "问答专区",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/questionsDetails",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "问答专区",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/diseaseList",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "疾病保健",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/diseaseDetails",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "疾病",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				
+				{
+				    "path" : "index/chineseMedicineList",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "中药图解",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/chineseMedicineDetails",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "中药图解",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				
+				{
+				    "path" : "index/famousPrescribeList",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "名方今用",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/famousPrescribeDetails",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "名方今用",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				
+					
+				{
+				    "path" : "index/test",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "测一测",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/testList",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "测一测",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/testDetails",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "测一测",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/testResult",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "测试结果",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/articleList",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "健康知识",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+					"path" : "index/healthAdvice",
+					"style" : 
+					{
+						"navigationBarTitleText" : "健康咨询"
+					}
+				},
+				{
+				    "path" : "index/articleDetails",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "文章详情",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				
+				{
+				    "path" : "index/doctorArticleList",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "康复医案",
+						"enablePullDownRefresh": false,
+						"navigationStyle": "custom",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				{
+				    "path" : "index/doctorArticleDetails",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "康复医案",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				}
+			]
+		},
+		
+		
+		{
+			"root": "pages_user",
+			"pages": [
+				{
+					"path": "user/addPatient",
+					"style": {
+						"navigationBarTitleText": "创建就诊人",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				}
+				,{
+					"path" : "user/message",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "消息",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/msgDetail",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "系统消息",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/storeOrder",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "我的订单",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/storeOrderDetail",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "订单详情",
+						"navigationStyle": "custom",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/doctorOrder",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "问诊列表",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/patient",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "病人列表",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/addAddress",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "新建收货地址",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/address",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "收货地址",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/integral",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "我的积分",
+						"navigationStyle": "custom",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/refundOrderList",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "售后订单",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/refundOrderDetail",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "处理进度",
+						"navigationStyle": "custom",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/refundOrderLogs",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "退款详情",
+						"navigationStyle": "custom",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/storeOrderDelivery",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "物流信息",
+						"navigationStyle": "custom",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/refundOrder",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "申请售后",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/prescribeOrder",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "处方单",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/pay",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "收款",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/success",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "支付结果",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/refundOrderProduct",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "订单售后",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/refundOrderDelivery",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "物流信息",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/userTui",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "我的推广",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/userTuiProduct",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "推广商品",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/userTuiImg",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "推广海报",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/userTuiList",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "我的推荐人",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/userTuiMoneyList",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "佣金记录",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/userTuiOrderList",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "订单记录",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/storeProductRelation",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "我的足迹",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/personInfo",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "个人信息",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/userTuiMoney",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "提现管理",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/userTuiExtractLog",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "提现记录",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/doc",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "健康档案",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/addDoc",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "创建健康档案",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/docDetail",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "健康档案",
+						"navigationBarBackgroundColor": "#dff9f5",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/docRecord",
+					"style":                                                                                  
+					{
+						"navigationBarTitleText": "健康记录",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/addDocRecord",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "添加健康记录",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/userTuiAdd",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "申请推广员",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+				    "path" : "user/paymentOrderRemain",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "支付尾款",
+				        "enablePullDownRefresh": false
+				    }
+				    
+				}
+				,{
+					"path" : "user/otherPaymentOrder",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "亲友代付",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/otherPaySuccess",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "支付成功",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				,{
+					"path" : "user/otherPaymentOrderRemain",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "亲友代付尾款",
+						"enablePullDownRefresh": false
+					}
+					
+				}
+				
+			]
+		},
+		{
+			"root": "pages_company",
+			"pages": [
+				{
+					"path": "auth/login",
+					"style": {
+						"navigationBarTitleText": "销售员登录",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "index",
+					"style": {
+						"navigationBarTitleText": "销售管理首页",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "storeOrder",
+					"style": {
+						"navigationBarTitleText": "订单管理",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				}
+				,{
+					"path" : "storeOrderDetail",
+					"style" :                                                                                    
+					{
+						"navigationBarTitleText": "订单详情",
+						"navigationStyle": "custom",
+						"enablePullDownRefresh": false
+					}
+					
+				},
+				{
+					"path": "storeProductPackage",
+					"style": {
+						"navigationBarTitleText": "商品套餐",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "storeProductPackageDetails",
+					"style": {
+						"navigationBarTitleText": "套餐详情",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "coupon",
+					"style": {
+						"navigationBarTitleText": "优惠券",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "couponDetails",
+					"style": {
+						"navigationBarTitleText": "优惠券详情",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "order/productList",
+					"style": {
+						"navigationBarTitleText": "商品列表",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "order/productDetails",
+					"style": {
+						"navigationBarTitleText": "商品详情",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "order/cart",
+					"style": {
+						"navigationBarTitleText": "购物车",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "order/confirmOrder",
+					"style": {
+						"navigationBarTitleText": "推荐订单信息",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "order/confirmCompanyOrder",
+					"style": {
+						"navigationBarTitleText": "推荐订单",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "order/coupon",
+					"style": {
+						"navigationBarTitleText": "制单优惠券",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "order/productShowDetails",
+					"style": {
+						"navigationBarTitleText": "商品详情",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "alipayImg",
+					"style": {
+						"navigationBarTitleText": "支付宝收款",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				},
+				{
+					"path": "card",
+					"style": {
+						"navigationBarTitleText": "我的名片",
+						"app-plus": {
+							"titleNView": false
+						}
+					}
+				}
+			]
+		},
+		{
+			"root": "pages_shopping",
+			"pages": [
+				{
+				    "path" : "shopping/confirmCreateOrder",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "确认订单",
+				        "enablePullDownRefresh": false
+				    }
+				    
+				},
+				{
+				    "path" : "shopping/confirmPackageOrder",
+				    "style" :                                                                                    
+				    {
+				        "navigationBarTitleText": "确认支付",
+				        "enablePullDownRefresh": false
+				    }
+				    
+				},
+				 {
+				 	"path" : "shopping/coupon",
+				 	"style" :                                                                                    
+				 	{
+				 		"navigationBarTitleText": "优惠券",
+				 		"enablePullDownRefresh": false
+				 	}
+				 	
+				 }
+				 ,{
+				 	"path" : "shopping/myCoupon",
+				 	"style" :                                                                                    
+				 	{
+				 		"navigationBarTitleText": "我的优惠券",
+				 		"enablePullDownRefresh": false
+				 	}
+				 	
+				 }
+				 ,{
+				 	"path" : "shopping/activityDetails",
+				 	"style" :                                                                                    
+				 	{
+				 		"navigationBarTitleText": "活动",
+				 		"enablePullDownRefresh": false
+				 	}
+				 	
+				 }
+				 ,{
+				 	"path" : "store/index",
+				 	"style" :                                                                                    
+				 	{
+				 		"navigationBarTitleText": "",
+				 		"enablePullDownRefresh": false,
+						"navigationStyle": "custom"
+				 	}
+				 	
+				 }
+			]
+		},
+		{
+			"root": "pages_doctor",
+			"pages": [
+				{
+					  "path" : "doctorCase",
+					  "style" :                                                                                    
+					  {
+						  "navigationBarTitleText": "问诊案例",
+							"app-plus": {
+								"titleNView": false
+							}
+					  }
+					  
+				  },
+				{
+				    "path" : "doctorQr",
+				    "style" :
+				    {
+				       "navigationBarTitleText": "用药咨询",
+						"app-plus": {
+							"titleNView": false
+						}
+				    }
+				},
+				 {
+				     "path" : "doctorOrderIM",
+				     "style" :                                                                                    
+				     {
+				         "navigationBarTitleText": "问诊会话",
+				         "enablePullDownRefresh": false
+				     }
+				     
+				 },
+				 {
+				     "path" : "paymentOrder",
+				     "style" :                                                                                    
+				     {
+				         "navigationBarTitleText": "支付订单",
+				         "enablePullDownRefresh": false
+				     }
+				     
+				 },
+				 {
+				     "path" : "doctorIm",
+				     "style" :                                                                                    
+				     {
+				         "navigationBarTitleText": "问诊会话",
+				         "enablePullDownRefresh": false
+				     }
+				     
+				 },
+				 {
+				     "path" : "index",
+				     "style" :                                                                                    
+				     {
+				         "navigationBarTitleText": "问诊",
+				         "navigationStyle": "custom",
+				         "enablePullDownRefresh": false
+				     }
+				 },
+				 {
+				     "path" : "doctorList",
+				     "style" :                                                                                    
+				     {
+				         "navigationBarTitleText": "医生列表",
+				         "enablePullDownRefresh": false
+				     }
+				     
+				 },
+				 {
+				     "path" : "doctorDetail",
+				     "style" :                                                                                    
+				     {
+				         "navigationBarTitleText": "医生详情",
+				         "navigationStyle": "custom",
+				         "enablePullDownRefresh": false
+				     }
+				     
+				 },
+				 {
+				     "path" : "submitOrder",
+				     "style" :                                                                                    
+				     {
+				         "navigationBarTitleText": "发布问诊",
+				         "enablePullDownRefresh": false
+				     }
+				     
+				 }
+			]
+		}
+	],
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "倍力优",
+		"navigationBarBackgroundColor": "#FFFFFF",
+		"backgroundColor": "#FFFFFF"
+	},
+	"tabBar": {
+		"animation": false,
+		"color": "#666666",
+		"selectedColor": "#018C39",
+		"borderStyle": "white",
+		"backgroundColor": "#ffffff",
+		"height": "70px",
+		"fontSize":"12px",
+		"iconWidth":"24px",
+		"iconHeight":"24px",
+		"spacing": "6px",
+		"list": [
+			{
+				"pagePath": "pages/home/index",
+				"iconPath": "/static/images/tabbar/beiliyou/home.png",
+				"selectedIconPath": "/static/images/tabbar/beiliyou/home_on.png",
+				"text": "首页"
+			},
+			{
+				"pagePath": "pages/enterprise/enterprise",
+				"iconPath": "/static/images/tabbar/beiliyou/ENCYCLOPEDIA.png",
+				"selectedIconPath": "/static/images/tabbar/beiliyou/ENCYCLOPEDIA_on.png",
+				"text": "企业理念"
+			},
+			/* {
+				"pagePath": "pages/doctor/index",
+				"iconPath": "/static/images/see_doctor.png",
+				"selectedIconPath": "/static/images/see_doctor_sel.png",
+				"text": "问诊"
+			} */
+			{
+				"pagePath": "pages/shopping/index",
+				"iconPath": "/static/images/tabbar/beiliyou/mall.png",
+				"selectedIconPath": "/static/images/tabbar/beiliyou/mall_on.png",
+				"text": "健康产品"
+			},
+			{
+				"pagePath": "pages/user/index",
+				"iconPath": "/static/images/tabbar/beiliyou/mine.png",
+				"selectedIconPath": "/static/images/tabbar/beiliyou/mine_on.png",
+				"text": "我的"
+			}
+		]
+	}
+}

+ 385 - 0
pages/auth/login.vue

@@ -0,0 +1,385 @@
+<template>
+  <view class="container">
+    <!-- #ifdef MP-WEIXIN -->
+    <view  class="force-login-wrap">
+      <view class="force-login__content y-f">
+        <open-data class="user-avatar" type="userAvatarUrl"></open-data>
+        <open-data class="user-name" type="userNickName"></open-data>
+        <view class="login-notice">为了提供更优质的服务,请先登录</view>
+		
+		<button
+			class="author-btn"
+			open-type="getPhoneNumber"
+			@getphonenumber="phoneLogin"  >手机号一键登录</button>
+       <!-- <button class="close-btn" @tap="back">暂不登录</button> -->
+		 <view class="tips">
+			 <checkbox  :checked="isAgreement" @click="handleAgreement()" />
+			 <view  @click="handleAgreement()">您同意并接受</view>
+		 	<view class="btn"  @click="openH5('/h5/userAgreement')">《用户协议》</view>
+		 	<view class="btn" @click="openH5('/h5/privacyPolicy')">《隐私保护》</view>
+		 </view>
+      </view>
+    </view>
+    <!-- #endif -->
+	 
+    
+  </view>
+</template>
+
+<script>
+import { loginByMiniApp,getUserInfo,loginByMp } from '@/api/user'
+export default {
+	data() {
+		return {
+			code:null,
+			isAgreement:false,
+		}
+	},
+	computed: {
+	},
+	onLoad(option) 
+	{
+		// #ifdef MP-WEIXIN
+		uni.$on('refreshLogin', () => {
+			uni.navigateBack({
+				delta:1
+			})
+		})
+		//选获取CODE,防止后请求的时候腾讯服务端未同步报错
+		this.getCode();
+		// #endif
+		
+		// #ifdef H5
+		if (this.checkWeixin()) {
+			this.getWxCode()
+		} else {
+			uni.showToast({
+				icon:'none',
+				title: "请在微信中打开",
+			});
+			//跳转到手机号密码登录
+		}
+		// #endif
+	 
+	},
+	onUnload() {
+	},
+	mounted() {
+    
+	},
+	methods: {
+		checkWeixin(){
+			var ua = window.navigator.userAgent.toLowerCase();
+			if (ua.match(/micromessenger/i) == 'micromessenger') {
+				return true;
+			} else {
+				return false;
+			}
+		},
+		//URL地址是否存在CODE
+		getUrlCode(name) {
+			return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ''])[1]
+				.replace(/\+/g, '%20')) || null
+		},
+		//获取微信CODE
+		getWxCode() {
+			//在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头; 
+			//http://shequ.natapp1.cc/#/pages/index/index?deviceId=8
+			var appId="wx11a2ce7c2bbc4521";
+			var url="https://userapp.bly.ylrztop.com";
+			window.location.href ='https://open.weixin.qq.com/connect/oauth2/authorize?appid='+appId+'&redirect_uri=' +encodeURIComponent(url+"/#/pages/auth/wxLogin") +'&response_type=code&scope=snsapi_userinfo&state=JeffreySu-954&connect_redirect=1#wechat_redirect';
+			//console.log('https://open.weixin.qq.com/connect/oauth2/authorize?appid='+appId+'&redirect_uri=' +encodeURIComponent("http://shequ.natapp1.cc/#/pages/index/index?deviceId="+this.deviceId) +'&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect')
+			// redirect_uri是授权成功后,跳转的url地址,微信会帮我们跳转到该链接,并且通过?的形式拼接code
+		},
+		handleAgreement(){
+			this.isAgreement=!this.isAgreement;
+		},
+		openH5(url){
+			var requestPath = uni.getStorageSync('requestPath');
+			uni.setStorageSync('url',requestPath+url);
+			uni.navigateTo({
+				url: '../home/h5'
+			})
+		},
+		getCode(){
+			var that=this;
+			this.utils.getProvider()
+			.then(provider => {
+				console.log('当前的环境商',provider)
+				if (!provider) {
+				  reject()
+				}
+				// uni登录
+				uni.login({
+					provider: provider,
+					success: async loginRes => {
+						that.code = loginRes.code
+					}
+				})
+			})
+			.catch(err => {
+				
+			})
+		},
+		// 微信用户手机号登录
+		phoneLogin(e) {
+			var that=this;
+			if(!this.isAgreement){
+				uni.showToast({
+					icon:'none',
+					title: "请先同意协议后再登录",
+				});
+				return false;
+			}
+			uni.showLoading({
+				title:"处理中..."
+			})
+			if (e.mp.detail.errMsg == 'getPhoneNumber:ok') {
+				this.utils.getProvider()
+				.then(provider => {
+					console.log('当前的环境商',provider)
+					if (!provider) {
+					  reject()
+					}
+					// uni登录
+					uni.login({
+						provider: provider,
+						success: async loginRes => {
+							console.log(loginRes)
+							let code = loginRes.code // 获取开发code
+							var userCode=uni.getStorageSync('userCode');
+							loginByMiniApp({
+							   encryptedData: e.mp.detail.encryptedData,
+							   iv: e.mp.detail.iv,
+							   code: code,
+							   // userCode:userCode
+							})
+							.then( res => {
+								if(res.code==200){
+									uni.hideLoading();
+									uni.showToast({
+										icon:'none',
+										title: "登录成功",
+									});
+									uni.setStorageSync('AppToken',res.token);
+									uni.setStorageSync('userInfo',JSON.stringify(res.user));
+									uni.hideLoading()
+									//that.getUserInfo()
+									uni.$emit('refreshLogin');
+									uni.navigateBack({
+										delta:1
+									})
+								}
+								else{
+									uni.hideLoading();
+									uni.showToast({
+										icon:'none',
+										title: "授权登录失败,请重新登录",
+									});
+								}
+							   
+							 })
+							 .catch(error => {
+								console.log(error)
+								uni.hideLoading();
+								uni.showToast({
+									icon:'none',
+									title: "登录接口调用失败",
+								});
+							 })
+							 
+						}
+					})
+				})
+				.catch(err => {
+					uni.showToast({
+						icon:'none',
+						title: err,
+					});
+				})
+				 
+			} else {
+				uni.showToast({
+					title: '已拒绝授权',
+					icon: 'none',
+					duration: 2000,
+				})
+			}
+		},
+		back() {
+			// uni.switchTab({
+			// 	url: '/pages/home/index'
+			// });
+			uni.navigateBack()
+		}
+	}
+}
+</script>
+
+<style lang="scss">
+.container {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-start;
+  position: relative;
+}
+
+.force-login-wrap {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  z-index: 11111;
+  top: 0;
+
+  .force-login__content {
+    position: absolute;
+    left: 50%;
+    top: 40%;
+    transform: translate(-50%, -50%);
+
+    .user-avatar {
+		border: 4upx solid #FFFFFF;
+		box-shadow: 0px 5px 15px 2px rgba(0,0,0,0.1);
+		width: 160rpx;
+		height: 160rpx;
+		border-radius: 50%;
+		overflow: hidden;
+		margin-bottom: 40rpx;
+    }
+
+    .user-name {
+      font-size: 35rpx;
+      font-family: PingFang SC;
+      font-weight: bold;
+      color: #000;
+      margin-bottom: 30rpx;
+    }
+
+    .login-notice {
+      font-size: 28rpx;
+      font-family: PingFang SC;
+      font-weight: 400;
+      color: #000;
+      line-height: 44rpx;
+      width: 500rpx;
+      text-align: center;
+      margin-bottom: 80rpx;
+    }
+
+    .author-btn {
+      width: 630rpx;
+      height: 80rpx;
+      background: linear-gradient(to right, #56ef8e  0%, #018C39 100%);
+      background: -moz-linear-gradient(to right, #56ef8e 0%, #018C39 100%);
+      // box-shadow: 0px 7rpx 6rpx 0px rgba(229, 138, 0, 0.22);
+      border-radius: 40rpx;
+      font-size: 30rpx;
+      font-family: PingFang SC;
+      font-weight: 500;
+      color: rgba(255, 255, 255, 1);
+    }
+
+    .close-btn {
+      width: 630rpx;
+      height: 80rpx;
+      margin-top: 30rpx;
+      border-radius: 40rpx;
+      border: 2rpx solid #018C39;
+      background: none;
+      font-size: 30rpx;
+      font-family: PingFang SC;
+      font-weight: 500;
+      color: #018C39;
+    }
+  }
+}
+.tips{
+	margin-top: 30rpx;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	font-size: 28rpx;
+	color: #000;
+	checkbox{
+	}
+	.btn{
+		color: #018C39;
+	}
+}
+
+
+.wx-login{
+	background: rgba(0,0,0,0.7);
+	z-index: 99999;
+	position: fixed;
+	top: 0;
+	left: 0;
+	height: 100%;
+	width: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	.form{
+		border-radius: 20rpx;
+		padding: 60rpx 30rpx;
+		width: 500upx;
+		height: 300upx;
+		background-color: #fff;
+		.title{
+			font-size: 32upx;
+			font-family: PingFang SC;
+			font-weight: bold;
+			
+		}
+		.desc{
+			font-size: 28upx;
+			margin: 60upx 0upx 60upx 0upx;
+			font-family: PingFang SC;
+			font-weight: 500;
+		}
+		.btn-box{
+			margin-top: 30rpx;
+			width: 100%;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			
+			.btn{
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				margin-left: 10upx;
+				width: 50%;
+				height: 80rpx;
+				border-radius: 5rpx;
+				background-color: #018C39;
+				font-size: 30rpx;
+				font-family: PingFang SC;
+				font-weight: 500;
+				color: #fff;
+				position: relative;
+			}
+			.btn-close{
+				margin-right: 10upx;
+				width: 50%;
+				height: 80rpx;
+				border-radius: 5rpx;
+				border: 2rpx solid #018C39;
+				background: none;
+				font-size: 30rpx;
+				font-family: PingFang SC;
+				font-weight: 500;
+				color: #018C39;
+			}
+		}
+	}
+}
+.auth_btn{
+	width: 100%;
+	height: 100%;
+	top:0upx;
+	position: absolute;
+	opacity:0.0;
+}
+</style>

+ 107 - 0
pages/auth/wxLogin.vue

@@ -0,0 +1,107 @@
+<template>
+  <view class="container">
+    
+  </view>
+</template>
+
+<script>
+import { loginByMp } from '@/api/user'
+export default {
+	data() {
+		return {
+			code:null,
+		}
+	},
+	computed: {
+	},
+	onLoad(option) 
+	{
+		// #ifdef H5
+		if (this.checkWeixin()) {
+			let code = this.getUrlCode('code')
+			if (code==null||code==undefined) {
+				uni.showToast({
+					icon:'none',
+					title: "code不存在",
+				});
+			} else {
+				this.code = code
+				this.loginByMp();
+			}
+		} else {
+			uni.showToast({
+				icon:'none',
+				title: "请在微信中打开",
+			});
+			//跳转到手机号密码登录
+		}
+		// #endif
+	},
+	onUnload() {
+	},
+	mounted() {
+    
+	},
+	methods: {
+		loginByMp(){
+			let code = this.code // 获取开发code
+			var tuiUserId=uni.getStorageSync('tuiUserId');
+			uni.showLoading({
+				title:"处理中..."
+			})
+			loginByMp({
+			   code: code,
+			   tuiUserId:tuiUserId
+			})
+			.then( res => {
+				if(res.code==200||res.code==40163){
+					uni.hideLoading();
+					uni.showToast({
+						icon:'none',
+						title: "登录成功",
+					});
+					uni.setStorageSync('AppToken',res.token);
+					uni.setStorageSync('userInfo',JSON.stringify(res.user));
+					//that.getUserInfo()
+					uni.$emit('refreshLogin');
+					uni.reLaunch({
+						url:"/pages/home/index"
+					})
+				}
+				else{
+					uni.hideLoading();
+					uni.showToast({
+						icon:'none',
+						title: res.msg,
+					});
+				}
+			   
+			 })
+			 .catch(error => {
+				console.log(error)
+				uni.hideLoading();
+				uni.showToast({
+					icon:'none',
+					title: "登录接口调用失败",
+				});
+			 })
+		},
+		checkWeixin(){
+			var ua = window.navigator.userAgent.toLowerCase();
+			if (ua.match(/micromessenger/i) == 'micromessenger') {
+				return true;
+			} else {
+				return false;
+			}
+		},
+		//URL地址是否存在CODE
+		getUrlCode(name) {
+			return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ''])[1]
+				.replace(/\+/g, '%20')) || null
+		}
+	}
+}
+</script>
+
+<style lang="scss">
+</style>

+ 84 - 0
pages/common/launch.vue

@@ -0,0 +1,84 @@
+<template>
+	<view class="content">
+		<view class="loadding" v-if="loadding==true">
+			<image src="/static/images/logo.png"></image>
+			<text class="text">倍力优</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {getDicts} from '@/api/index'
+	export default {
+		data() {
+			return {
+				loadding:true,
+			};
+		},
+		methods: {
+			
+			getDicts:function(){
+				getDicts().then(
+					res => {
+						if(res.code==200){
+							console.log(res)
+							uni.setStorageSync('dicts',JSON.stringify(res));
+							
+						}else{
+							 
+						}
+						this.loadding=false;
+						this.navigatHandler();
+					},
+					rej => {}
+				);
+			},
+			navigatHandler: function() {
+				uni.reLaunch({
+					url: '../home/index',
+					animationType: 'pop-in',
+					animationDuration: 100
+				})
+			},
+			
+		},
+		onLoad() {
+			this.getDicts()
+		}
+	};
+ 
+</script>
+
+.
+<style lang="scss">
+	content {
+		height: 100%;
+		width: 100%;
+		position: relative;
+		padding-top: 0;
+		
+	}
+	.loadding{
+		background-color: #fff;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		position: absolute;
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100%;
+		z-index: 9999;
+		image{
+			border-radius: 50%;
+			animation: load linear 1s infinite;
+			width: 120rpx;
+			height:120rpx;
+		}
+		.text{
+			font-size: 28rpx;
+			margin-top: 20rpx;
+		}
+	}
+</style>

+ 583 - 0
pages/doctor/doctorDetail.vue

@@ -0,0 +1,583 @@
+<template>
+	<view>
+		<view class="top-cont">
+			<!-- 背景图片 -->
+			<image class="bg" src="/static/images/doctordetail_top_bg.png" mode=""></image>
+			<view class="top-inner">			
+				<!-- 这里是状态栏 -->
+				<view class="status_bar" :style="{height: statusBarHeight}"></view>
+				<view class="back-box" @click="back">
+					<image src="../../static/images/back.png" mode=""></image>
+				</view>
+				<!-- 医生信息 -->
+				<view class="doctor-info">
+					<view class="inner">
+						<!-- 头像 -->
+						<view class="head-img">
+							<image :src="doctor.headImg" mode="aspectFill"></image>
+						</view>
+						<!-- 姓名 -->
+						<view class="name-box">
+							<text class="name">{{doctor.doctorName}}</text>
+							<view class="line"></view>
+							<text class="other">
+								{{utils.getDictLabelName("doctorPosition",doctor.position)}}
+							</text>
+							<view class="line"></view>
+							<text class="other">{{doctor.departmentName}}</text>
+							<view class="line"></view>
+							<view class="years">从业1年</view>
+						</view>
+						<!-- 单位 -->
+						<view class="unit-box">
+							<!-- <view class="level">三甲</view> -->
+							<view class="name">{{doctor.hospitalName}}</view>
+						</view>
+						<!-- 评分等 -->
+						<!-- <view class="param-box">
+							<view class="item">
+								<view class="top">
+									<text class="num">{{doctor.pings}}</text>
+									<text class="unit">分</text>
+								</view>
+								<view class="label">评分</view>
+							</view>
+							<view class="item">
+								<view class="top">
+									<text class="num">{{doctor.orders}}</text>
+									<text class="unit">人</text>
+								</view>
+								<view class="label">接诊数</view>
+							</view>
+							<view class="item">
+								<view class="top">
+									<text class="num">{{doctor.speed}}</text>
+									<text class="unit">分钟</text>
+								</view>
+								<view class="label">响应速度</view>
+							</view>
+						</view> -->
+					</view>
+				</view>
+				<view class="content">
+					<!-- 擅长 -->
+					<view class="expertise">
+						<image class="label-img" src="../../static/images/sc_word.png" mode=""></image>
+						<text :class="showExpert?'text':'text ellipsis3'" id="expert">{{doctor.doctorDesc}}</text>
+						<!-- 查看更多按钮 -->
+						<view v-if="!showExpert" class="show-more" @click="showMoreExpert">
+							<image class="mask" src="../../static/images/mask.png" mode=""></image>
+							<view class="inner">
+								<text class="btn">查看全部</text>
+								<image src="../../static/images/arrow3.png" mode=""></image>
+							</view>
+						</view>
+					</view>
+					<!-- 问诊方式 -->
+					<view class="mode-box">
+						<view v-for="(price,index) in prices" :class="price.priceId == priceId?'item active':'item'" @click="choseMode(price)">
+							<image v-if="price.priceType==1" class="img" src="../../static/images/picture_ask.png" mode=""></image>
+							<image v-if="price.priceType==2" class="img" src="../../static/images/phone_ask.png" mode=""></image>
+							<view class="info">
+								<text v-if="price.priceType==1" class="label">图文问诊</text>
+								<text v-if="price.priceType==2" class="label">电话问诊</text>
+								<view class="price" v-if="price.priceType==1">
+									<text class="num">{{price.price}}</text>
+									<text class="unit">元</text>
+									<text class="gray">/次</text>
+								</view>
+								<view class="price" v-if="price.priceType==2">
+									<text class="num">{{price.price}}</text>
+									<text class="unit">元</text>
+									<text class="gray">{{price.times}}分</text>
+								</view>
+							</view>
+							<!-- 选中的角标 -->
+							<image v-if="price.priceId == priceId" class="active-img" src="../../static/images/sel_right50.png" mode=""></image>
+						</view>
+						 
+					</view>
+					 
+				</view>
+			
+			</view>
+		</view>
+		
+		<!-- 底部去支付按钮 -->
+		<view class="btn-foot">
+			<view class="menu-box">
+				<view class="item" @click="goHome">
+					<image src="../../static/images/back_home.png" mode=""></image>
+					<text>首页</text>
+				</view>
+				<view class="item" @click="changeFollow">
+					<image v-if="!isFollow" src="../../static/images/focus.png" mode=""></image>
+					<image v-show="isFollow" src="../../static/images/focus_sel.png" mode=""></image>
+					<text>关注</text>
+				</view>
+			</view>
+			<!-- <view class="btn" @click="submitOrder()">问诊</view> -->
+		</view>
+	</view>
+</template>
+
+<script>
+	import {uploadOSS} from '@/api/common.js'
+	import {getDoctorDetail,create} from '@/api/doctorOrder.js'
+	export default {
+		data() {
+			return {
+				doctorId:null,
+				doctor:{},
+				prices:[],
+				priceId:null,
+				
+				// 状态栏的高度
+				statusBarHeight: uni.getStorageSync('menuInfo').statusBarHeight,
+				// 是否显示全擅长文字
+				showExpert: true,
+				
+				// 是否关注
+				isFollow: false
+			};
+		},
+		onLoad(option) {
+			this.doctorId=option.doctorId;
+			
+		},
+		onShow() {
+			this.getDoctorDetail()
+		},
+		methods: {
+			getDoctorDetail(){
+				let data = {doctorId:this.doctorId};
+				var that=this;
+				getDoctorDetail(data).then(
+					res => {
+						if(res.code==200){
+							 this.doctor=res.doctor;
+							 this.prices=res.prices;
+							 setTimeout(function(){
+								  that.getExpertHeight()
+							 },200)
+						}else{
+							uni.showToast({
+								icon:'none',
+								title: "请求失败",
+							});
+						}
+					},
+					rej => {}
+				);
+			},
+			back() {
+				uni.navigateBack()
+			},
+			// 获取擅长文字是否超过三行,超过三行显示“查看全部”
+			getExpertHeight() {
+				const query = uni.createSelectorQuery().in(this);
+				query.select('#expert').boundingClientRect(data => {
+					let containerLength = data.height // 文本内容高度
+					console.log(containerLength)
+					let lineHeight = 24 // 行高
+					if(containerLength / lineHeight > 3){
+					  	// 执行代码
+						this.showExpert = false
+					} else {
+						this.showExpert = true
+					}
+				}).exec();
+			},
+			// 查看更多擅长文字
+			showMoreExpert() {
+				this.showExpert = true
+			},
+			// 选择问诊方式
+			choseMode(item) {
+				this.priceId = item.priceId
+			},
+			
+			// 回到首页
+			goHome() {
+				uni.switchTab({
+					url: '/pages/home/index'
+				})
+			},
+			// 关注,取消关注
+			changeFollow() {
+				let that = this
+				if(that.isFollow) {
+					uni.showModal({
+						title: '提示',
+						content: '确定要取消关注吗?',
+						cancelText: '取消',
+						confirmText: '确定',
+						success: res => {
+							if (res.confirm) {
+								that.isFollow = false
+							}
+						},
+					})
+				} else {
+					that.isFollow = true
+				}
+			},
+			submitOrder() {
+				
+				if(this.priceId==null){
+					uni.showToast({
+						icon:'none',
+						title: '请选择问诊类型',
+					});
+					return;
+				}
+				 uni.navigateTo({
+				 	url:"submitOrder?doctorId="+this.doctorId+"&priceId="+this.priceId
+				 }) 
+				 return;
+				 
+				
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.top-cont{
+		
+		width: 100%;
+		height: 400upx;
+		position: relative;
+		.bg{
+			width: 100%;
+			height: 100%;
+			position: absolute;
+			top: 0;
+			left: 0;
+			z-index: 1;
+		}
+		.top-inner{
+			width: 100%;
+			height: 100%;
+			position: absolute;
+			top: 0;
+			left: 0;
+			z-index: 2;
+			.back-box{
+				height: 88upx;
+				padding-left: 22upx;
+				display: flex;
+				align-items: center;
+				image{
+					width: 40upx;
+					height: 40upx;
+				}
+			}
+			.doctor-info{
+				box-sizing: border-box;
+				padding: 0 20upx;
+				margin-top: 70upx;
+				.inner{
+					box-sizing: border-box;
+					// height: 347upx;
+					background: #FFFFFF;
+					border-radius: 16upx;
+					position: relative;
+					padding: 90upx 30upx 0;
+					.head-img{
+						width: 128upx;
+						height: 128upx;
+						background: #EDF1F4;
+						border: 4upx solid #FFFFFF;
+						border-radius: 50%;
+						overflow: hidden;
+						position: absolute;
+						left: 26upx;
+						top: -63upx;
+						image{
+							width: 100%;
+							height: 100%;
+						}
+					}
+					.name-box{
+						display: flex;
+						align-items: center;
+						line-height: 1;
+						font-family: PingFang SC;
+						.name{
+							font-size: 36upx;
+							font-weight: bold;
+							color: #111111;
+						}
+						.line{
+							width: 1px;
+							height: 26upx;
+							background: #DDDDDD;
+							margin: 0 20upx;
+						}
+						.other{
+							font-size: 30upx;
+							font-weight: 500;
+							color: #333333;
+						}
+						.years{
+							padding: 0 10upx;
+							height: 36upx;
+							line-height: 36upx;
+							font-size: 24upx;
+							font-weight: 500;
+							color: #CEA764;
+							background: #FFF1DD;
+							border-radius: 6upx;
+						}
+					}
+					.unit-box{
+						display: flex;
+						margin-top: 30upx;
+						.level{
+							padding: 0 10upx;
+							height: 30upx;
+							line-height: 30upx;
+							font-size: 22upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #FFFFFF;
+							background: #018C39;
+							border-radius: 10upx 4upx 10upx 4upx;
+							margin-right: 12upx;
+						}
+						.name{
+							font-size: 30upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #333333;
+							line-height: 30upx;
+						}
+					}
+					.param-box{
+						padding: 0 50upx;
+						display: flex;
+						align-items: center;
+						justify-content: space-between;
+						margin-top: 50upx;
+						.item{
+							display: flex;
+							flex-direction: column;
+							line-height: 1;
+							font-family: PingFang SC;
+							.top{
+								display: flex;
+								align-items: flex-end;
+								color: #CEA764;
+								margin-bottom: 18upx;
+								.num{
+									font-size: 36upx;
+									font-weight: bold;
+								}
+								.unit{
+									font-size: 24upx;
+								}
+							}
+							.label{
+								font-size: 24upx;
+								font-weight: 500;
+								color: #666666;
+								text-align: center;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	.content{
+		padding: 0 20upx;
+		margin-bottom: 141rpx;
+	}
+	.expertise{
+		box-sizing: border-box;
+		min-height: 207upx;
+		background: #FFFFFF;
+		border: 4upx solid #FFFFFF;
+		border-radius: 16upx;
+		padding: 30upx 30upx;
+		display: flex;
+		position: relative;
+		.label-img{
+			width: 56upx;
+			height: 26upx;
+			flex-shrink: 0;
+			position: absolute;
+			top: 42upx;
+			left: 30upx;
+		}
+		.text{
+			font-size: 30upx;
+			font-family: PingFang SC;
+			font-weight: 500;
+			color: #666666;
+			line-height: 48upx;
+			text-indent: 70upx;
+			&.ellipsis3{
+				overflow:hidden;
+				text-overflow:ellipsis;
+				display:-webkit-box; 
+				-webkit-box-orient:vertical;
+				-webkit-line-clamp: 3;
+			}
+		}
+		.show-more{
+			display: flex;
+			align-items: center;
+			position: absolute;
+			right: 25upx;
+			bottom: 35upx;
+			.mask{
+				width: 56upx;
+				height: 34upx;
+			}
+			.inner{
+				background-color: #FFFFFF;
+				display: flex;
+				align-items: center;
+				.btn{
+					font-size: 28upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #018C39;
+				}
+				image{
+					width: 14upx;
+					height: 25upx;
+					margin-left: 10upx;
+				}
+			}
+		}
+	}
+	.mode-box{
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		margin-top: 20upx;
+		.item{
+			box-sizing: border-box;
+			width: 345upx;
+			height: 150upx;
+			background: #FFFFFF;
+			border: 2upx solid #FFFFFF;
+			border-radius: 16upx;
+			padding: 33upx 40upx;
+			display: flex;
+			align-items: center;
+			.img{
+				width: 84upx;
+				height: 84upx;
+				margin-right: 26upx;
+			}
+			.active-img{
+				width: 51upx;
+				height: 51upx;
+				position: absolute;
+				right: 0;
+				bottom: 0;
+				z-index: 1;
+				display: none;
+			}
+			&.active{
+				position: relative;
+				border: 2upx solid #018C39;
+				.active-img{
+					display: block;
+				}
+			}
+			.info{
+				box-sizing: border-box;
+				height: 84upx;
+				display: flex;
+				flex-direction: column;
+				justify-content: space-between;
+				padding: 5upx 0 4upx;
+				font-family: PingFang SC;
+				.label{
+					font-size: 32upx;
+					line-height: 1;
+					font-weight: bold;
+					color: #333333;
+				}
+				.price{
+					display: flex;
+					align-items: flex-end;
+					color: #018C39;
+					.num{
+						font-size: 30upx;
+						font-weight: bold;
+						line-height: 1;
+					}
+					.unit{
+						font-size: 24upx;
+						line-height: 26upx;
+					}
+					.gray{
+						font-size: 24upx;
+						color: #999999;
+						line-height: 26upx;
+					}
+				}
+			}
+		}
+	}
+	 
+		
+	.btn-foot{
+		width: 100%;
+		position: fixed;
+		left: 0;
+		bottom: 0;
+		z-index: 99;
+		height: 121upx;
+		background: #FFFFFF;
+		
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		.menu-box{
+			margin-left: 32rpx;
+			display: flex;
+			align-items: center;
+			.item{
+				display: flex;
+				align-items: center;
+				flex-direction: column;
+				margin-right: 50upx;
+				&:last-child{
+					margin-right: 0;
+				}
+				image{
+					width: 36upx;
+					height: 36upx;
+					margin-bottom: 10upx;
+				}
+				text{
+					font-size: 20upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #666666;
+					text-align: center;
+				}
+			}
+		}
+		.btn{
+			margin-right: 32rpx;
+			width: 527upx;
+			height: 88upx;
+			line-height: 88upx;
+			font-size: 30upx;
+			font-family: PingFang SC;
+			font-weight: bold;
+			color: #FFFFFF;
+			background: #018C39;
+			border-radius: 44upx;
+			text-align: center;
+		}
+	}
+</style>

+ 518 - 0
pages/doctor/doctorIm.vue

@@ -0,0 +1,518 @@
+<template>
+	<view class="content" ref="showPanel">
+		<view class="chat-cont" @click="closeBottom">
+			<!-- 大夫 -->
+			<view class="chat-item" v-for="(item) in msg" :class="item.from==doctorId?'':'my'">
+				<view class="time">{{utils.parseTime(item.time)}}</view>
+				<view class="peop-info" v-if="item.from==doctorId">
+					<view class="img-box">
+						<image :src="item.avatar" mode=""></image>
+					</view>
+					<view class="info">
+						<view class="name">{{item.nick}}</view>
+						<view class="words">
+							{{item.payload.text}}
+						</view>
+					</view>
+				</view>
+				<view class="peop-info" v-if="item.from==user.userId">
+					<view class="info">
+						<view class="name">{{item.nick}}</view>
+						<view class="words">
+							{{item.payload.text}}
+						</view>
+					</view>
+					<view class="img-box">
+						<image :src="item.avatar" mode=""></image>
+					</view>
+				</view>
+			</view>
+			<!-- 我 -->
+			<!-- <view class="chat-item my">
+				<view class="time">2021-03-02  10:10:10</view>
+				<view class="peop-info">
+					<view class="info">
+						<view class="name">张雪勤</view>
+						<view class="words">
+							嗯
+						</view>
+					</view>
+					<view class="img-box">
+						<image :src="item.avatar" mode=""></image>
+					</view>
+				</view>
+			</view> -->
+			<!-- 大夫 -->
+			
+			<!-- 我 -->
+			<!-- <view class="chat-item my">
+				<view class="time">2021-03-02  10:10:10</view>
+				<view class="peop-info">
+					<view class="info">
+						<view class="name">张雪勤</view>
+						<view class="words">
+							嗯
+						</view>
+					</view>
+					<view class="img-box">
+						<image src="../../static/images/head.jpg" mode=""></image>
+					</view>
+				</view>
+			</view> -->
+		</view>
+		<view class="input-box"  id="chatCont" :style="{paddingBottom:bottomBlackLineHeight + 'rpx'}">
+			<!-- 常用话术 -->
+			<view class="used-phrases">
+				<view v-for="(item,index) in 2" :key="index" class="item">换个人问问</view>
+			</view>
+			<!-- 输入框 -->
+			<view class="input-inner">
+				<input 
+					type="text" 
+					value="" 
+					placeholder="请向医生详细描述您的症状" 
+					:focus='setFocus' 
+					placeholder-class="input-place" 
+					confirm-type="发送" 
+					 v-model="sendText"
+					@input="textInput" 
+				/>
+				<image v-if="!hasSendValue" src="../../static/images/add26.png" mode="" @click="showMoreMenu"></image>
+				<view v-if="hasSendValue" class="send-btn" @click="sendMsg">发送</view>
+			</view>
+			<!-- 功能按钮 -->
+			<view :class="showBottomMenu?'bottom-menu show':'bottom-menu'">
+				<view class="item">
+					<view class="img-box">
+						<image src="../../static/images/health.png" mode=""></image>
+					</view>
+					<text class="text">投诉反馈</text>
+				</view>
+				<view class="item">
+					<view class="img-box">
+						<image src="../../static/images/health.png" mode=""></image>
+					</view>
+					<text class="text">常见问题</text>
+				</view>
+			</view>
+		</view>
+		<!-- 图片放大查看 -->
+		<popupBottom ref="popup" :visible.sync="imgVisible" title="电子处方"  radius="32"  maxHeight="1200">
+			<view class="popup-img-cont">
+				<image :src="url" mode="widthFix"></image>
+			</view>
+		</popupBottom>
+		
+	</view>
+</template>
+
+<script>
+	import {getUserInfo} from '@/api/user'
+	import {getImOrderDetail} from '@/api/doctorOrder.js'
+	import popupBottom from '@/components/px-popup-bottom/px-popup-bottom.vue'
+	export default {
+		components: {
+			popupBottom
+		},
+		data() {
+			return {
+				order:null,
+				doctor:null,
+				user:null,
+				// user:{
+				// 	userId:'user2',
+				// 	avatar:"https://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoQkMEXbsBBmgltByzYibp97iaX23nibxKwSyj88yaHoqXS4H7aliaum7G9xbjLxydEtIPa84C5CUwMLA/132",
+				// 	nickname:"张三"
+				// },
+				msg:[],
+				doctorId:null,
+				orderId:null,
+				// 图片放大弹窗
+				imgVisible: false,
+				// 内容发送框是否有值
+				hasSendValue: false,
+				// 功能按钮是否显示
+				showBottomMenu: false,
+				// 聊天输入框是否聚焦
+				setFocus: false,
+				// 输入框要发送的内容
+				sendText: '',
+				// iphoneX底部一条黑线,有些页面要避开
+				bottomBlackLineHeight: uni.getStorageSync('bottomBlackLineHeight'),
+				url: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fitem%2F202007%2F06%2F20200706230613_ikvtn.thumb.1000_0.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1650117742&t=f64aa5215aeda871eb9a69a70329f7a0'
+			}
+		},
+		onLoad(option) {
+			console.log(option.orderId)
+			this.orderId=option.orderId;
+			this.getImOrderDetail();
+			this.getUserInfo()
+			var that=this;
+			//登录 可以放到IM外登录 考虑是否按时付费
+			uni.$TUIKit.login({
+				userID: that.user.userId,
+				userSig: "eJwtzE0LgkAUheH-MttCruNcZYR2Qp*kqBC0E2a0S6XDaCJF-z1Tl*d54XxYfsqcXlsWMu4AW0*blK47KmniV6stX0Kr7oUxpFjoCgD0pSe8uejBkNWjIyIHgFk7ev7NFxK5BHfRlqrxtyqP8uG-d4fgVp-TeD-0mZBekgeRKLEp*uQSUyq31xU0G-b9ARDtMKA_"
+			}).then((res) => {
+				setTimeout(function(){
+					let promise = uni.$TUIKit.updateMyProfile({
+					  nick: that.user.nickname,
+					  avatar: that.user.avatar,
+					  gender: uni.$TUIKitTIM.TYPES.GENDER_MALE,
+					  selfSignature: '我的个性签名',
+					  allowType: uni.$TUIKitTIM.TYPES.ALLOW_TYPE_ALLOW_ANY
+					});
+					promise.then(function(imResponse) {
+					  console.log(imResponse.data); // 更新资料成功
+					}).catch(function(imError) {
+					  console.warn('updateMyProfile error:', imError); // 更新资料失败的相关信息
+					});
+					that.getMessageList();
+				},1000);
+				 
+				
+			}).catch((error) => {
+				 
+			});
+			uni.$TUIKit.on(uni.$TUIKitTIM.EVENT.MESSAGE_RECEIVED, this.onMessageReceived);
+			
+		},
+		methods: {
+			getUserInfo(){
+				getUserInfo().then(
+					res => {
+						if(res.code==200){
+							if(res.user!=null){
+								this.user=res.user;
+							}
+							
+						}else{
+							uni.showToast({
+								icon:'none',
+								title: "请求失败",
+							});
+						}
+					},
+					rej => {}
+				);
+			},
+			getImOrderDetail(){
+				let data = {orderId:this.orderId};
+				var that=this;
+				getImOrderDetail(data).then(
+					res => {
+						if(res.code==200){
+							 this.doctor=res.doctor;
+							 this.order=res.order;
+							 uni.setNavigationBarTitle({
+							 	title:'与'+this.doctor.doctorName+'医生聊天中'
+							 })
+							 
+						}else{
+							uni.showToast({
+								icon:'none',
+								title: "请求失败",
+							});
+						}
+					},
+					rej => {}
+				);
+			},
+			onMessageReceived(event){
+				console.log(event)
+				if(event.name=='onMessageReceived'){
+					this.msg=this.msg.concat(event.data);
+					console.log(this.msg)
+				}
+			},
+			getMessageList(){
+				var that=this;
+				let promise = uni.$TUIKit.getMessageList({conversationID: 'C2C'+that.doctorId, count: 15});
+				promise.then(function(imResponse) {
+				  that.msg = imResponse.data.messageList; // 消息列表。
+				  console.log(that.msg)
+				  // const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于续拉,分页续拉时需传入该字段。
+				  // const isCompleted = imResponse.data.isCompleted; // 表示是否已经拉完所有消息。
+				});
+			},
+			sendMessage(msg){
+				var that=this;
+				let message = uni.$TUIKit.createTextMessage({
+				  to: that.doctorId,
+				  conversationType: uni.$TUIKitTIM.TYPES.CONV_C2C,
+				  // 消息优先级,用于群聊(v2.4.2起支持)。如果某个群的消息超过了频率限制,后台会优先下发高优先级的消息,详细请参考:https://cloud.tencent.com/document/product/269/3663#.E6.B6.88.E6.81.AF.E4.BC.98.E5.85.88.E7.BA.A7.E4.B8.8E.E9.A2.91.E7.8E.87.E6.8E.A7.E5.88.B6)
+				  // 支持的枚举值:TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL(默认), TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST
+				  // priority: TIM.TYPES.MSG_PRIORITY_NORMAL,
+				  payload: {
+				    text: msg
+				  },
+				  // 消息自定义数据(云端保存,会发送到对端,程序卸载重装后还能拉取到,v2.10.2起支持)
+				  // cloudCustomData: 'your cloud custom data'
+				});
+				// 2. 发送消息
+				let promise = uni.$TUIKit.sendMessage(message);
+				promise.then(function(imResponse) {
+				  // 发送成功
+				  console.log(imResponse);
+				  if(imResponse.code==0){
+					  that.msg.push(imResponse.data.message);
+					  that.hasSendValue = false
+					  that.sendText = ''
+					  that.setFocus = true
+				  }
+				  //更新列表
+				  
+				}).catch(function(imError) {
+				  // 发送失败
+				  console.warn('sendMessage error:', imError);
+				});
+			},
+			// 查看大图
+			showBigImg() {
+				this.imgVisible = true
+			},
+			// 展示更多菜单
+			showMoreMenu() {
+				if(!this.showBottomMenu) {
+					this.showBottomMenu = true
+				} else {
+					if(this.setFocus) {
+						this.setFocus = false
+					} else {
+						this.setFocus = true
+					}
+				}
+			},
+			// 输入框发送消息
+			sendMsg() {
+				this.sendMessage(this.sendText)
+				
+				
+			},
+			// 关闭底部更多菜单
+			closeBottom(e) {
+				if(e.target.id!=undefined && e.target.id!=="chatCont"){
+					this.showBottomMenu = false
+				}
+			},
+			// 监听输入框是否有值
+			textInput(e) {
+				if(e.detail.value) {
+					this.hasSendValue = true
+				} else {
+					this.hasSendValue = false
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page{
+		height: 100%;
+	}
+	.content{
+		height: 100%;
+		display: flex;
+		flex-direction: column;
+		justify-content: space-between;
+		.chat-cont{
+			box-sizing: border-box;
+			flex: 1;
+			overflow-y: auto;
+			background-color: #F2F5F9;
+			padding: 0 30upx 60upx;
+			.chat-item{
+				padding-top: 60upx;
+				.time{
+					font-size: 26upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #999999;
+					line-height: 1;
+					margin-bottom: 30upx;
+					text-align: center;
+				}
+				.peop-info{
+					display: flex;
+					.img-box{
+						width: 78upx;
+						height: 78upx;
+						border-radius: 50%;
+						overflow: hidden;
+						flex-shrink: 0;
+						margin-right: 20upx;
+						image{
+							width: 100%;
+							height: 100%;
+						}
+					}
+					.info{
+						.name{
+							font-size: 28upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #666666;
+							line-height: 1;
+							margin-bottom: 20upx;
+						}
+						.words{
+							box-sizing: border-box;
+							max-width: 520upx;
+							font-size: 32upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #111111;
+							line-height: 50upx;
+							padding: 20upx 30upx;
+							background: #FFFFFF;
+							border-radius: 0 20upx 20upx 20upx;
+							image{
+								width: 364upx;
+								height: auto;
+							}
+						}
+					}
+				}
+				&.my{
+					.peop-info{
+						justify-content: flex-end;
+						.img-box{
+							margin-right: 0;
+							margin-left: 20upx;
+						}
+						.info {
+							.name{
+								text-align: right;
+							}
+							.words{
+								background: #018C39;
+								color: #FFFFFF;
+								border-radius: 20upx 0 20upx 20upx;
+							}
+						}
+					}
+				}
+			}
+		}
+		.input-box{
+			box-sizing: border-box;
+			flex-shrink: 0;
+			background: #FFFFFF;
+			display: flex;
+			flex-direction: column;
+			padding: 20upx 30upx 0;
+			.used-phrases{
+				display: flex;
+				flex-wrap: wrap;
+				.item{
+					height: 64upx;
+					line-height: 64upx;
+					padding: 0 30upx;
+					border-radius: 32upx;
+					border: 1px solid #F7F7F7;
+					background-color: #FFFFFF;
+					font-size: 28upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #111111;
+					margin-right: 20upx;
+					margin-bottom: 20upx;
+				}
+			}
+			.input-inner{
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				input{
+					box-sizing: border-box;
+					// width: calc(100% - 82upx);
+					flex: 1;
+					height: 80upx;
+					background: #F2F2F2;
+					border-radius: 40upx;
+					padding: 0 30upx;
+					font-size: 28upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #000000;
+				}
+				.input-place{
+					font-size: 28upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #999999;
+				}
+				image{
+					flex-shrink: 0;
+					width: 52upx;
+					height: 52upx;
+					margin-left: 30upx;
+				}
+				.send-btn{
+					flex-shrink: 0;
+					height: 64upx;
+					line-height: 64upx;
+					border-radius: 32upx;
+					background: #018C39;
+					font-size: 28upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+					padding: 0 30upx;
+					margin-left: 30upx;
+				}
+			}
+			.bottom-menu{
+				height: 0;
+				display: flex;
+				flex-wrap: wrap;
+				overflow: hidden;
+				opacity: 0;
+				// transition: all 0.5s;
+				&.show{
+					padding: 30upx 30upx 0;
+					height: auto;
+					opacity: 1;
+				}
+				.item{
+					display: flex;
+					flex-direction: column;
+					align-items: center;
+					justify-content: center;
+					margin-right: 77upx;
+					margin-bottom: 30upx;
+					&:nth-child(4n) {
+						margin-right: 0;
+					}
+					.img-box{
+						width: 100upx;
+						height: 100upx;
+						background-color: #F5F5F5;
+						border-radius: 8upx;
+						display: flex;
+						align-items: center;
+						justify-content: center;
+						image{
+							width: 40upx;
+							height: 40upx;
+						}
+					}
+					.text{
+						font-size: 24upx;
+						font-family: PingFang SC;
+						font-weight: 500;
+						color: #333333;
+						margin-top: 20upx;
+					}
+				}
+			}
+		}
+	}
+	.popup-img-cont{
+		display: flex;
+		align-items: center;
+		image{
+			width: 100%;
+		}
+	}
+</style>

+ 434 - 0
pages/doctor/doctorList.vue

@@ -0,0 +1,434 @@
+<template>
+	<view>
+		<view class="top-fixed">
+			<!-- 搜索框 -->
+			<view class="search-cont">
+				<view class="inner">
+					<image class="icon-search" src="../../static/images/search.png" mode=""></image>
+					<input type="text" v-model="searchVal" placeholder="输入医生姓名搜索" confirm-type="搜索" @confirm="goSearch" placeholder-style="font-size:28rpx;color:#BBBBBB;font-family: PingFang SC;" />
+				</view>
+			</view>
+			<!-- tab切换 -->
+			<view class="pub-tab-box">
+				<view class="tab-inner">
+					<view 
+						v-for="(item,index) in depts" 
+						:key="index"
+						:class="deptId == item.departmentId?'item active':'item'"
+						@click="changeDept(item)"
+					>
+						<view class="text">
+							{{ item.departmentName }}
+							<image v-show="deptId == item.departmentId" class="tab-bg" src="../../static/images/tab_bg.png" mode=""></image>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+
+		<!-- 数据列表 -->
+		<mescroll-body ref="mescrollRef" top="190rpx" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption" :up="upOption">
+			<view class="doc-list">
+				<view class="item" v-for="(item,index) in dataList" :key="index" @click="showDetail(item)">
+					<!-- 头像 -->
+					<view class="head-box">
+						<image :src="item.headImg" mode="aspectFill"></image>
+					</view>
+					<!-- 详细信息 -->
+					<view class="info">
+						<!-- 姓名等 -->
+						<view class="top">
+							<text class="name">{{ item.doctorName }}</text>
+							<view class="line"></view>
+							<text class="other">{{utils.getDictLabelName("doctorPosition",item.position)}}</text>
+							<view class="line"></view>
+							<text class="other">{{ item.departmentName }}</text>
+						</view>
+						<!-- 单位 -->
+						<view class="unit-box">
+							<!-- <view class="level">三甲</view> -->
+							<view class="name">{{ item.hospitalName }}</view>
+						</view>
+						<!-- 擅长 -->
+						<view class="expertise ellipsis2">
+							擅长:{{ item.doctorDesc }}
+						</view>
+						<!-- 评分 -->
+						<!-- <view class="rate-box">
+							<view class="star">
+								<image src="../../static/images/star.png" mode=""></image>
+								<text>{{ item.pings }}</text>
+							</view>
+							<view class="line"></view>
+							<view class="num-box">
+								<text class="label">接诊数</text>
+								<text class="num">{{ item.orders }}</text>
+							</view>
+							<view class="line"></view>
+							<view class="num-box">
+								<text class="label">响应速度</text>
+								<text class="num">{{ item.speed }}分钟</text>
+							</view>
+						</view> -->
+						<!-- 价格 -->
+						<view class="price-box" v-if="item.price!=null&&item.price.length>0">
+							<view class="btn-item" v-for="(subitme) in item.price">
+								<text class="label" >{{subitme.priceType==1?'图文':'语音'}}</text>
+								<text class="num">¥{{subitme.price.toFixed(2)}}</text>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</mescroll-body>
+	</view>
+</template>
+
+<script>
+	import {getDepartmentList,getDoctorList} from '@/api/doctorOrder.js'
+	import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
+	export default {
+		mixins: [MescrollMixin], 
+		data() {
+			return {
+				searchVal:"",
+				depts:[],
+				deptId:0,
+				doctorType:0,
+				// tab切换
+				mescroll:null,
+				// 上拉加载的配置
+				upOption: {
+					onScroll:true,
+					use: true, // 是否启用上拉加载; 默认true
+					page: {
+						num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
+						size: 10 // 每页数据的数量,默认10
+					},
+					noMoreSize: 10, // 配置列表的总数量要大于等于5条才显示'-- END --'的提示
+					empty: {
+						icon:'/static/images/no_data.png',
+						tip: '暂无数据'
+					}
+				},
+				// 列表数据
+				dataList: []
+			};
+		},
+		onLoad(option) {
+			if(option.doctorType!=null){
+				this.doctorType=option.doctorType
+			}
+			this.getDepartmentList();
+		},
+		methods: {
+			getDepartmentList(){
+				getDepartmentList().then(res => {
+					if(res.code==200){
+						var allDept={departmentId:0,departmentName:"全部"}
+						this.depts.push(allDept);
+						this.depts=this.depts.concat(res.data);
+						console.log(this.depts)
+						
+					}else{
+						uni.showToast({
+							icon:'none',
+							title: "请求失败",
+						});
+					}
+				});
+			
+			},
+			// tab切换
+			changeDept(item) {
+				this.deptId = item.departmentId;
+				this.mescroll.resetUpScroll()
+				
+			},
+			mescrollInit(mescroll) {
+				this.mescroll = mescroll;
+			},
+			/*下拉刷新的回调 */
+			downCallback(mescroll) {
+				mescroll.resetUpScroll()
+			},
+			upCallback(page) {
+				//联网加载数据
+				var that = this;
+				var data = {
+					doctorType:this.doctorType,
+					departmentId:this.deptId,
+					doctorName:this.searchVal,
+					page: page.num,
+					pageSize: page.size
+				};
+				getDoctorList(data).then(res => {
+					if(res.code==200){
+						//设置列表数据
+						if (page.num == 1) {
+							that.dataList = res.data.list; 
+							
+						} else {
+							that.dataList = that.dataList.concat(res.data.list);
+							 
+						}
+						that.mescroll.endBySize(res.data.list.length, res.data.total);
+						
+					}else{
+						uni.showToast({
+							icon:'none',
+							title: "请求失败",
+						});
+						that.dataList = null;
+						that.mescroll.endErr();
+					}
+				});
+			},
+			 goSearch(){
+				 this.mescroll.resetUpScroll()
+			 },
+			// 查看医生资料详情
+			showDetail(item) {
+				uni.navigateTo({
+					url: './doctorDetail?doctorId=' + item.doctorId
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.top-fixed{
+		width: 100%;
+		position: fixed;
+		top: 0;
+		left: 0;
+		z-index: 10;
+	}
+	.search-cont{
+		padding: 16upx 30upx;
+		background-color: #FFFFFF;
+		.inner{
+			box-sizing: border-box;
+			width: 100%;
+			height: 72upx;
+			background: #F7F7F7;
+			border-radius: 36upx;
+			display: flex;
+			align-items: center;
+			padding: 0 30upx;
+			.icon-search{
+				width: 28upx;
+				height: 28upx;
+				margin-right: 20upx;
+			}
+			input{
+				flex: 1;
+				height: 60upx;
+				line-height: 60upx;
+			}
+		}
+	}
+	.pub-tab-box{
+		padding: 0 33upx;
+		background-color: #FFFFFF;
+		.tab-inner{
+			height: 88upx;
+			line-height: 88upx;
+			display: flex;
+			overflow-x: auto;
+		}
+		.item{
+			font-size: 28upx;
+			white-space: nowrap;
+			line-height: 1;
+			font-family: PingFang SC;
+			font-weight: 500;
+			color: #666666;
+			margin-right: 60upx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			&:last-child{
+				margin-right: 0;
+			}
+			&.active{
+				font-weight: bold;
+				color: #333333;
+			}
+			.text{
+				position: relative;
+				z-index: 1;
+			}
+			.tab-bg{
+				width: 72upx;
+				height: 28upx;
+				position: absolute;
+				top: 17upx;
+				left: 50%;
+				transform: translateX(-36upx);
+				z-index: -1;
+			}
+		}
+	}
+	.top-seat{
+		width: 100%;
+		height: 192upx;
+	}
+	.doc-list{
+		padding: 20upx;
+		.item{
+			box-sizing: border-box;
+			// height: 433upx;
+			background: #FFFFFF;
+			border: 4upx solid #FFFFFF;
+			border-radius: 16upx;
+			padding: 40upx 30upx;
+			display: flex;
+			margin-bottom: 20upx;
+			.head-box{
+				width: 120upx;
+				height: 120upx;
+				background: #EDF1F4;
+				border-radius: 50%;
+				overflow: hidden;
+				margin-right: 30upx;
+				image{
+					width: 100%;
+					height: 100%;
+				}
+			}
+			.info{
+				width: calc(100% - 150upx);
+				.top{
+					display: flex;
+					align-items: center;
+					font-family: PingFang SC;
+					line-height: 1;
+					.name{
+						font-size: 34upx;
+						font-weight: bold;
+						color: #111111;
+					}
+					.line{
+						width: 1px;
+						height: 26upx;
+						background: #DDDDDD;
+						margin: 0 20upx;
+					}
+					.other{
+						font-size: 28upx;
+						font-weight: 500;
+						color: #333333;
+					}
+				}
+				.unit-box{
+					display: flex;
+					margin-top: 24upx;
+					.level{
+						padding: 0 10upx;
+						height: 30upx;
+						line-height: 30upx;
+						font-size: 22upx;
+						font-family: PingFang SC;
+						font-weight: 500;
+						color: #FFFFFF;
+						background: #018C39;
+						border-radius: 10upx 4upx 10upx 4upx;
+						margin-right: 12upx;
+					}
+					.name{
+						font-size: 28upx;
+						font-family: PingFang SC;
+						font-weight: 500;
+						color: #333333;
+						line-height: 30upx;
+					}
+				}
+				.expertise{
+					font-size: 26upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #666666;
+					line-height: 42upx;
+					margin: 22upx 0 0upx;
+				}
+				.rate-box{
+					display: flex;
+					align-items: center;
+					.star{
+						display: flex;
+						align-items: center;
+						image{
+							width: 22upx;
+							height: 22upx;
+							margin-right: 10upx;
+						}
+						text{
+							font-size: 26upx;
+							font-family: PingFang SC;
+							font-weight: bold;
+							color: #CEA764;
+							line-height: 1;
+						}
+					}
+					.line{
+						width: 1px;
+						height: 20upx;
+						background: #DDDDDD;
+						margin: 0 20upx;
+					}
+					.num-box{
+						display: flex;
+						align-items: center;
+						font-family: PingFang SC;
+						.label{
+							font-size: 24upx;
+							font-weight: 500;
+							color: #999999;
+							line-height: 1;
+							margin-right: 7px;
+						}
+						.num{
+							font-size: 26upx;
+							font-weight: bold;
+							color: #CEA764;
+							line-height: 1;
+						}
+					}
+				}
+				.price-box{
+					display: flex;
+					align-items: center;
+					margin-top: 38upx;
+					.btn-item{
+						display: flex;
+						align-items: center;
+						justify-content: center;
+						width: 164upx;
+						height: 56upx;
+						line-height: 56upx;
+						border: 1px solid rgba(43, 199, 185, 0.5);
+						border-radius: 28upx;
+						font-family: PingFang SC;
+						margin-right: 30upx;
+						&:last-child{
+							margin-right: 0;
+						}
+						.label{
+							font-size: 26upx;
+							font-weight: 500;
+							color: #018C39;
+							margin-right: 5upx;
+						}
+						.num{
+							font-size: 28upx;
+							font-weight: bold;
+							color: #018C39;
+						}
+					}
+				}
+			}
+		}
+	}
+</style>

+ 319 - 0
pages/doctor/doctorOrderIM.vue

@@ -0,0 +1,319 @@
+<template>
+	 <view class="container">
+	 		<view class="message-list" @tap="triggerClose"><TUI-message-list id="message-list" @finish="finish" ref="messageList" :conversation="conversation" /></view>
+	 		<view v-if="videoPlay" class="container-box" @tap.stop="stopVideoHander">
+	 			<video
+	 				v-if="videoPlay"
+	 				class="video-message"
+	 				:src="videoMessage.payload.videoUrl"
+	 				:poster="videoMessage.payload.thumbUrl"
+	 				object-fit="cover"
+	 				error="videoError"
+	 				autoplay="true"
+	 				direction="0"
+	 			/>
+	 		</view>
+	 		<view v-if="showChat" class="message-input">
+	 			<TUI-message-input id="message-input" ref="messageInput" :toUser="toUser" :conversation="conversation" @sendMessage="sendMessage" />
+	 		</view>
+	 	</view>
+	 
+</template>
+
+<script>
+	import {getTlsSig} from '@/api/common.js'
+	import {getUserInfo} from '@/api/user'
+	import {getImOrderDetail,pingOrder} from '@/api/doctorOrder.js'
+	import TUIMessageList from '../../components/im/tui-chat/message-list/index';
+	import TUIMessageInput from '../../components/im/tui-chat/message-input/index';
+	export default {
+		components: {
+			TUIMessageList,
+			TUIMessageInput,
+		},
+		data() {
+			return {
+				toUser:"",
+				conversationName: '',
+				conversation: {},
+				messageList: [],
+				showChat: true,
+				conversationID: null,
+				videoPlay: false,
+				videoMessage: {},
+				order:null,
+				doctor:null,
+				user:null,
+				doctorId:null,
+				orderId:null,
+			}
+		
+		},
+		created() {
+			uni.$on('videoPlayerHandler', value => {
+				this.videoPlay = value.isPlay;
+				this.videoMessage = value.message;
+			});
+		},
+		onLoad(option) {
+			console.log(option.orderId)
+			this.orderId=option.orderId;
+			
+			this.getImOrderDetail();
+			 
+		},
+		onShow() {
+			uni.setStorageSync('orderId',this.orderId);
+		},
+		methods: {
+			finish(){
+				this.showChat=false
+				uni.$emit('refreshDoctorOrder');
+			},
+			stopVideoHander() {
+				this.videoPlay = false;
+			},
+			triggerClose() {
+				if (this.showChat) {
+					this.$refs.messageInput.handleClose();
+				}
+			},
+			sendMessage(event) {
+				// 将自己发送的消息写进消息列表里面
+				this.$refs.messageList.updateMessageList(event.detail.message);
+				console.log(event.detail.message);
+				if(event.detail.message.type=="TIMCustomElem"){
+					if(event.detail.message.payload.data=="evaluation"){
+						//提交评价extension {"score":3,"comment":"q2"}
+						var jsonObj=JSON.parse(event.detail.message.payload.extension)
+						var data={orderId:this.order.orderId,pingStar:jsonObj.score,pingContent:jsonObj.comment}
+						pingOrder(data).then(
+							res => {
+								if(res.code==200){
+									uni.showToast({
+										icon:'success',
+										title: "评价成功",
+									});
+									
+								}else{
+									uni.showToast({
+										icon:'none',
+										title: res.msg,
+									});
+								}
+							},
+							rej => {}
+						);
+					}
+				}
+			},
+			getUserInfo(){
+				var that=this;
+				getUserInfo().then(
+					res => {
+						if(res.code==200){
+							if(res.user!=null){
+								this.user=res.user;
+								
+								this.getTlsSig()
+							}
+							
+						}else{
+							uni.showToast({
+								icon:'none',
+								title: "请求失败",
+							});
+						}
+					},
+					rej => {}
+				);
+			},
+			getTlsSig(){
+				var that=this;
+				var data={userId:'user'+this.user.userId}
+				getTlsSig(data).then(
+					res => {
+						if(res.code==200){
+							that.loginIm(res.data);
+						}else{
+							uni.showToast({
+								icon:'none',
+								title: "请求失败",
+							});
+						}
+					},
+					rej => {}
+				);
+			},
+			loginIm(sign){
+				var that=this;
+				uni.$TUIKit.login({
+					userID: 'user'+that.user.userId,
+					userSig: sign
+				}).then((res) => {
+					console.log("IM登录成功")
+					setTimeout(function(){
+						let promise = uni.$TUIKit.updateMyProfile({
+						  nick: that.user.nickname,
+						  avatar: that.user.avatar,
+						  gender: uni.$TUIKitTIM.TYPES.GENDER_MALE,
+						  selfSignature: '我的个性签名',
+						  allowType: uni.$TUIKitTIM.TYPES.ALLOW_TYPE_ALLOW_ANY
+						});
+						promise.then(function(imResponse) {
+						  console.log(imResponse.data); // 更新资料成功
+						  that.setRead()
+						  var conversation={conversationID:that.conversationID,type:uni.$TUIKitTIM.TYPES.CONV_C2C}
+						  that.conversation = conversation;
+						  that.$refs.messageList.getMessageList(conversation);
+						  
+						}).catch(function(imError) {
+						  console.warn('updateMyProfile error:', imError); // 更新资料失败的相关信息
+						});
+					},1000);
+					
+				}).catch((error) => {
+					 
+				});
+			},
+			setRead(){
+				var that=this;
+				uni.$TUIKit.setMessageRead({
+					conversationID:that.conversationID
+				})
+				.then(() => {
+					
+				});
+				
+				// uni.$TUIKit.getConversationProfile(that.conversationID).then(res => {
+				// 	const { conversation } = res.data;
+				// 	that.conversation = conversation;
+				// 	console.log(that.conversation)
+				// 	that.setData({
+				// 		conversationName: this.getConversationName(conversation),
+				// 		isShow: conversation.type === 'GROUP'
+				// 	});
+				// });
+			},
+			getImOrderDetail(){
+				let data = {orderId:this.orderId};
+				var that=this;
+				getImOrderDetail(data).then(
+					res => {
+						if(res.code==200){
+							 this.doctor=res.doctor;
+							 this.order=res.order;
+							 this.toUser="doctor"+this.doctor.doctorId;
+							 this.conversationID='C2Cdoctor'+this.doctor.doctorId
+							 uni.setNavigationBarTitle({
+							 	title:'与'+this.doctor.doctorName+'医生聊天中'
+							 })
+							 this.getUserInfo();
+							 
+						}else{
+							uni.showToast({
+								icon:'none',
+								title: "请求失败",
+							});
+						}
+					},
+					rej => {}
+				);
+			},
+			 
+		}
+	}
+</script>
+
+<style lang="scss">
+	.container {
+		width: 100vw;
+		height: 100vh;
+		position: fixed;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		display: flex;
+		flex-direction: column;
+	}
+	
+	.tui-chatroom-navigatorbar {
+		position: relative;
+		/*top: 0;*/
+		flex-shrink: 0;
+		width: 750rpx;
+		height: 176rpx;
+		background-color: #006EFF;
+	}
+	
+	.tui-chatroom-navigatorbar-back {
+		position: absolute;
+		width: 48rpx;
+		height: 48rpx;
+		left: 24rpx;
+		bottom: 20rpx;
+	}
+	
+	.conversation-title {
+		position: absolute;
+		width: 350rpx;
+		height: 88rpx;
+		line-height: 56rpx;
+		font-size: 36rpx;
+		color: #FFFFFF;
+		z-index: 100;
+		bottom: 0;
+		left: 200rpx;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+	}
+	
+	.message-list {
+		flex: 1;
+		width: 100vw;
+		overflow-y: scroll;
+	}
+	
+	.message-input {
+		flex-shrink: 0;
+		width: 100%;
+	}
+	
+	.calling {
+		position: fixed;
+		z-index: 199;
+		top: 0;
+		/*  #ifdef  H5  */
+		top: calc(88rpx + constant(safe-area-inset-top));
+		top: calc(88rpx + env(safe-area-inset-top));
+		/*  #endif  */
+		bottom: 0;
+		right: 0;
+	}
+	
+	.group-profile {
+		top: 176rpx;
+		left: 0;
+		z-index: 1111
+	}
+	
+	.container-box {
+		position: fixed;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		top: 0;
+		background-color: rgba(0, 0, 0, 0.5);
+	}
+	
+	.video-message {
+		width: 90vw;
+		height: 300px;
+	}
+
+</style>

+ 490 - 0
pages/doctor/index.vue

@@ -0,0 +1,490 @@
+<template>
+	<view>
+		<view class="top-fixed">
+			<!-- 这里是状态栏 -->
+			<view class="status_bar" :style="{height: statusBarHeight}"></view>
+			<view class="top-title">在线问诊</view>
+			<!-- 搜索框 -->
+			<view class="search-cont">
+				<view class="inner">
+					<image class="icon-search" src="../../static/images/search.png" mode=""></image>
+					<input type="text" :value="searchValue" placeholder="输入关键字" placeholder-style="font-size:28rpx;color:#BBBBBB;font-family: PingFang SC;" />
+				</view>
+			</view>
+		</view>
+		<!-- 快速问诊、找医生 -->
+		<view class="online-inquiry" :style="{marginTop:top}">
+			<view class="item" @click="navTo('./postConsult')">
+				<image class="bg-img" src="../../static/images/online_treat.png" mode=""></image>
+				<view class="inner">
+					<text class="title">快速问诊</text>
+					<text class="sub-title">智能科室 快速匹配</text>
+					<image src="../../static/images/fast_ask.png" mode=""></image>
+				</view>
+			</view>
+			<view class="item" @click="navTo('./doctorList')">
+				<image class="bg-img" src="../../static/images/chu_query.png" mode=""></image>
+				<view class="inner">
+					<text class="title">找医生</text>
+					<text class="sub-title">全国60万医生任你选</text>
+					<image src="../../static/images/doctor_blue.png" mode=""></image>
+				</view>
+			</view>
+		</view>
+		<!-- 专家问诊 -->
+		<view class="index-cont" >
+			<view class="pub-item">
+				<view class="pub-title-box">
+					<text class="left">专家问诊</text>
+				</view>
+				<view class="inner">
+					<!-- tab切换 -->
+					<view class="pub-tab-box">
+						<view class="tab-inner">
+							<view 
+								v-for="(item,index) in orderTypes" 
+								:key="index"
+								:class="item.id == param.orderType?'item cases active':'item cases'"
+								@click="orderTypeChange(item)"
+							>
+								<view class="text">
+									{{ item.name }}
+									<image v-show="item.id ==  param.orderType" class="tab-bg" src="../../static/images/tab_bg.png" mode=""></image>
+								</view>
+							</view>
+						</view>
+					</view>
+					<!-- 案例列表 -->
+					<view class="cases-list">
+						<view class="item" v-for="(item,index) in list" :key="index">
+							<!-- 文字 -->
+							<view class="dec-text ellipsis2">{{item.title}}</view>
+							<!-- 有图 -->
+							<view class="images-box"  v-if="item.imgs!=null"  >
+								<view class="img-item" v-for="(subitem,j) in utils.photosToArr(item.imgs)" @click="showImg(item.imgs)" :key="j">
+									<image :src="subitem" mode="aspectFill" ></image>
+								</view>
+							</view>
+							<!-- 医生信息 -->
+							<view class="doc-info">
+								<view class="head">
+									<image :src="item.doctorHeadImg" mode="aspectFill"></image>
+								</view>
+								<view class="name">{{item.doctorName}}</view>
+								<view class="line"></view>
+								<view class="posit">
+									{{utils.getDictLabelName("doctorPosition",item.doctorPosition)}}
+								</view>
+								<view class="line"></view>
+								<view class="address">{{item.hospitalName}}</view>
+							</view>
+							<view class="answer-box">
+								<!-- 文字回答 -->
+								<text class="text-inner" v-if="item.orderType == '1' ">{{item.replyContent}}</text>
+								<!-- 语音回答 -->
+								<view class="voice-inner" v-if="item.orderType == '2'">
+									<free-audio 
+										startPic='/static/images/play.png' 
+										endPic='/static/images/pause.png'
+										activeColor="#018C39"
+										:audioId="'audio'+index"
+										:url='item.replyAudioUrl'
+									></free-audio>
+								</view>
+							</view>
+							<view class="read-box">
+								<image src="../../static/images/eye.png" mode=""></image>
+								<text class="text">{{item.views}}人看过</text>
+							</view>
+						</view>
+						
+					</view>
+					<Loading :loaded="loaded" :loading="loading"></Loading>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {getDepartmentList,getDoctorCase} from '@/api/doctorOrder.js'
+	import Loading from "@/components/Loading";
+	import tabBg from "@/static/images/tab_bg.png"
+	import freeAudio from '@/components/chengpeng-audio/free-audio.vue'
+	export default {
+		components: {freeAudio,Loading},
+		data() {
+			return {
+				doctorOrderList:[],
+				orderTypes: [{name:'全部',id:0,},{name:'图文',id:1,},{name:'语音',id:2,}],
+				top:'0px',
+				// 状态栏的高度
+				statusBarHeight: uni.getStorageSync('menuInfo').statusBarHeight,
+				searchValue: '',
+				tabBg: tabBg, // tab切换背景
+				current: 0,
+				param: {
+				  orderType:0,
+				  page: 1,
+				  pageSize: 10
+				},
+				list: [],
+				loaded: false,
+				loading: false
+			};
+		},
+		onShow() {
+			var that=this;
+			let info = uni.createSelectorQuery().select(".top-fixed");
+	     	info.boundingClientRect(function(data) { //data - 各种参数
+				console.log(data.height) 
+				that.top=data.height+"px";
+	      }).exec()
+			this.getDoctorCase()
+		},
+		methods:{
+			showImg(urls) {
+				 var imgArr =urls.split(',');
+				 //预览图片
+				 uni.previewImage({
+				 	urls: imgArr,
+				 	current: imgArr[0]
+				 });
+			},
+			getDoctorCase(){
+				let that = this;
+				if (that.loaded == true || that.loading == true) return;
+				that.loading = true;
+				uni.showLoading({
+					title:"加载中..."
+				})
+				getDoctorCase(this.param).then(
+					res => {
+						that.loading = false;
+						that.loaded = res.data.list.length < that.param.pageSize;
+						that.param.page = that.param.page + 1;
+						that.list.push.apply(that.list, res.data.list);
+						uni.hideLoading()
+					},
+					err => {
+						uni.hideLoading()
+						uni.showToast({
+							title: err.msg ,
+							icon: 'none',
+							duration: 2000
+						});
+					}
+				);
+			},
+			orderTypeChange(item) {
+				this.param.orderType = item.id;
+				this.param.page=1;
+				this.list=[];
+				this.loaded=false;
+				this.loading=false;
+				this.getDoctorCase();
+			},
+			// 访问新页面
+			navTo(url){
+				uni.navigateTo({
+					url: url
+				})
+			}, 
+		}
+	}
+</script>
+
+<style lang="scss">
+	.top-fixed{
+		background: #fff;
+		width: 100%;
+		position: fixed;
+		top: 0;
+		left: 0;
+		z-index: 10;
+	}
+	.top-title{
+		height: 88upx;
+		line-height: 88upx;
+		font-size: 42upx;
+		font-family: Source Han Sans CN;
+		font-weight: bold;
+		color: #222222;
+		padding-left: 41upx;
+		background-color: #FFFFFF;
+	}
+	.search-cont{
+		padding: 16upx 30upx;
+		background-color: #FFFFFF;
+		.inner{
+			box-sizing: border-box;
+			width: 100%;
+			height: 72upx;
+			background: #F7F7F7;
+			border-radius: 36upx;
+			display: flex;
+			align-items: center;
+			padding: 0 30upx;
+			.icon-search{
+				width: 28upx;
+				height: 28upx;
+				margin-right: 20upx;
+			}
+			input{
+				height: 60upx;
+				line-height: 60upx;
+				flex: 1;
+			}
+		}
+	}
+	
+	.online-inquiry{
+		box-sizing: border-box;
+		width: 100%;
+		padding: 20upx;
+		background: linear-gradient(180deg, rgba(255, 255, 255, 0.9) 59%, rgba(255, 255, 255, 0) 100%);
+		display: flex;
+		justify-content: space-between;
+		.item{
+			width: 346upx;
+			height: 150upx;
+			position: relative;
+			.bg-img,
+			.inner{
+				width: 100%;
+				height: 100%;
+				position: absolute;
+				top: 0;
+				left: 0;
+				z-index: 1;
+			}
+			.inner{
+				box-sizing: border-box;
+				z-index: 2;
+				display: flex;
+				flex-direction: column;
+				justify-content: center;
+				padding-left: 32upx;
+				.title{
+					font-size: 30upx;
+					line-height: 1;
+					font-family: PingFang SC;
+					font-weight: bold;
+					color: #111111;
+					margin-bottom: 20upx;
+				}
+				.sub-title{
+					font-size: 24upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #666666;
+				}
+				image{
+					width: 80upx;
+					height: 90upx;
+					position: absolute;
+					right: 7upx;
+					bottom: 7upx;
+				}
+			}
+		}
+	}
+	
+	.index-cont{
+		box-sizing: border-box;
+		padding: 0 20upx;
+		.pub-item{
+			background: #FFFFFF;
+			border-radius: 16upx;
+			margin-bottom: 20upx;
+			.pub-title-box{
+				box-sizing: border-box;
+				padding: 36upx 30upx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				.left{
+					font-size: 36upx;
+					line-height: 1;
+					font-family: PingFang SC;
+					font-weight: bold;
+					color: #111111;
+				}
+				.right{
+					display: flex;
+					align-items: center;
+					justify-content: center;
+					.text{
+						font-size: 26upx;
+						line-height: 1;
+						font-family: PingFang SC;
+						font-weight: 500;
+						color: #999999;
+						margin-right: 10upx;
+					}
+					image{
+						width: 14upx;
+						height: 24upx;
+						margin-top: 5upx;
+					}
+				}
+			}
+			.inner{
+				padding: 0 30upx;
+			}
+			// 健康知识
+			.pub-tab-box{
+				position: relative;
+				.tab-inner{
+					padding: 14upx 0 30upx;
+					display: flex;
+					overflow-x: auto;
+				}
+				.item{
+					font-size: 28upx;
+					white-space: nowrap;
+					line-height: 1;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #666666;
+					margin-right: 40upx;
+					position: relative;
+					&:last-child{
+						margin-right: 0;
+					}
+					&.active{
+						font-weight: bold;
+						color: #333333;
+					}
+					&.cases{
+						margin-right: 60upx;
+					}
+					.text{
+						position: relative;
+						z-index: 1;
+					}
+					.tab-bg{
+						width: 72upx;
+						height: 28upx;
+						position: absolute;
+						top: 17upx;
+						left: 50%;
+						transform: translateX(-36upx);
+						z-index: -1;
+					}
+				}
+				
+			}
+			// 问诊案例
+			.cases-list{
+				padding-bottom: 10upx;
+				.item{
+					padding: 30upx 0;
+					border-bottom: 1px solid #F0F0F0;
+					&:last-child{
+						border-bottom: none;
+					}
+					.dec-text{
+						font-size: 32upx;
+						font-family: PingFang SC;
+						font-weight: bold;
+						color: #111111;
+						line-height: 48upx;
+					}
+					.images-box{
+						margin-top: 10upx;
+						display: flex;
+						flex-wrap: wrap;
+						.img-item{
+							width: 155upx;
+							height: 155upx;
+							background: #F5F5F5;
+							border-radius: 8upx;
+							margin: 0 10upx 10upx 0;
+							overflow: hidden;
+							image{
+								width: 100%;
+								height: 100%;
+							}
+							&:nth-child(4n){
+								margin-right: 0;
+							}
+						}
+					}
+					.doc-info{
+						display: flex;
+						align-items: center;
+						margin: 30upx 0 20upx;
+						.head{
+							width: 60upx;
+							height: 60upx;
+							background: #F2F5F9;
+							border-radius: 50%;
+							margin-right: 20upx;
+							overflow: hidden;
+							image{
+								width: 100%;
+								height: 100%;
+							}
+						}
+						.name{
+							font-size: 28upx;
+							line-height: 1;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #111111;
+						}
+						.line{
+							width: 1px;
+							height: 22upx;
+							background: #DDDDDD;
+							margin: 0 16upx;
+						}
+						.posit,
+						.address{
+							font-size: 26upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #999999;
+						}
+					}
+					.answer-box{
+						width: 100%;
+						// height: 117upx;
+						background: #F5F7F7;
+						border-radius: 10upx;
+						display: flex;
+						flex-direction: column;
+						justify-content: center;
+						.text-inner{
+							// height: 84upx;
+							font-size: 28upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #666666;
+							line-height: 42upx;
+							padding: 15upx;
+						}
+					}
+					.read-box{
+						margin-top: 30upx;
+						display: flex;
+						align-items: center;
+						justify-content: flex-end;
+						image{
+							width: 24upx;
+							height: 19upx;
+							margin-right: 10upx;
+						}
+						.text{
+							font-size: 24upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #999999;
+						}
+					}
+				}
+			}
+		}
+	}
+</style>

+ 317 - 0
pages/doctor/paymentOrder.vue

@@ -0,0 +1,317 @@
+<template>
+	<view class="content">
+		<view class="inner">
+		
+			<view class="time-price">
+				<text class="time">订单金额</text>
+				<view class="price-box">
+					<text class="unit">¥</text>
+					<text class="num">{{order.payMoney}}</text>
+				</view>
+			</view>
+			<!-- 支付方式 -->
+			<view class="pay-type">
+				<view class="title">支付方式</view>
+				<view class="item">
+					<view class="left">
+						<image src="../../static/images/wecha_pay.png" mode=""></image>
+						<text class="text">微信支付</text>
+					</view>
+					<label>
+						<checkbox disabled value="" :checked="wxPay" />
+					</label>
+				</view>
+			</view>
+			<!-- 订单详情查看 -->
+			<view class="order-info">
+				<view class="title">订单信息</view>
+				<view class="item">
+					<text class="label">订单编号</text>
+					<view class="sn-box">
+						<text class="text">{{order.orderSn}}</text>
+						<view class="copy-btn" @click="copyOrderSn(order.orderSn)">复制</view>
+					</view>
+				</view>
+				<view class="item">
+					<text class="label">下单时间</text>
+					<text class="text">{{order.createTime}}</text>
+				</view>
+				<view class="item">
+					<text class="label">支付方式</text>
+					<text class="text">微信支付</text>
+				</view>
+				 
+			</view>
+			
+		</view>
+		<view class="btn-box">
+			<view class="btn" @click="payOrder()">去支付</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {pay,getDoctorOrderDetail} from '@/api/doctorOrder.js'
+	export default {
+		data() {
+			return {
+				payLimitTime:null,
+				order:null,
+				// 默认选中微信支付
+				wxPay: true,
+			}
+		},
+		onLoad(option) {
+			this.orderId=JSON.parse(option.orderId);
+			this.getDoctorOrderDetail();
+		},
+		methods: {
+			copyOrderSn(text) {
+				// 复制方法
+				uni.setClipboardData({
+					data:text,
+					success:()=>{
+						uni.showToast({
+							title:'内容已成功复制到剪切板',
+							icon:'none'
+						})
+					}
+				});
+			},
+			getDoctorOrderDetail(){
+				var data = {orderId:this.orderId};
+				var that=this;
+				uni.showLoading();
+				getDoctorOrderDetail(data).then(
+					res => {
+						if(res.code==200){
+							 console.log(res);
+							  uni.hideLoading();
+							  that.order=res.order;
+						}else{
+							uni.showToast({
+								icon:'none',
+								title: res.msg,
+							});
+						}
+					},
+					rej => {}
+				);
+			},
+			payOrder(){
+				var data = {orderId:this.order.orderId};
+				var that=this;
+				uni.showLoading();
+				pay(data).then(
+					res => {
+						if(res.code==200){
+							 uni.requestPayment({
+							 	provider: 'wxpay',
+							 	timeStamp: res.result.timeStamp,
+							 	nonceStr: res.result.nonceStr,
+							 	package: res.result.packageValue,
+							 	signType: res.result.signType,
+							 	paySign: res.result.paySign,
+							 	success: function(res) {
+							 		 uni.hideLoading();
+									 uni.redirectTo({
+									  	url: './doctorOrderIM?orderId='+that.order.orderId
+									 })
+							 	},
+							 	fail: function(err) {
+							 		console.log('fail:' + JSON.stringify(err));
+							 		uni.hideLoading();
+							 	}
+							 });
+						}else{
+							uni.showToast({
+								icon:'none',
+								title: res.msg,
+							});
+						}
+					},
+					rej => {}
+				);
+				
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page{
+		height: 100%;
+	}
+	.content{
+		height: 100%;
+		display: flex;
+		flex-direction: column;
+		justify-content: space-between;
+		.inner{
+			padding: 20upx;
+			.time-price{
+				box-sizing: border-box;
+				height: 200upx;
+				background: #FFFFFF;
+				border-radius: 16upx;
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				padding-top: 50upx;
+				.time{
+					font-size: 26upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #999999;
+					line-height: 1;
+					text-align: center;
+				}
+				.price-box{
+					display: flex;
+					align-items: flex-end;
+					margin-top: 28upx;
+					.unit{
+						font-size: 32upx;
+						font-family: PingFang SC;
+						font-weight: bold;
+						color: #FF6633;
+						line-height: 1.3;
+						margin-right: 10upx;
+					}
+					.num{
+						font-size: 56upx;
+						font-family: PingFang SC;
+						font-weight: bold;
+						color: #FF6633;
+						line-height: 1;
+					}
+				}
+			}
+			.pay-type{
+				box-sizing: border-box;
+				height: 192upx;
+				background: #FFFFFF;
+				border-radius: 16upx;
+				margin-top: 20upx;
+				padding: 40upx 30upx;
+				display: flex;
+				flex-direction: column;
+				justify-content: space-between;
+				.title{
+					font-size: 28upx;
+					font-family: PingFang SC;
+					font-weight: 500;
+					color: #999999;
+					line-height: 1;
+				}
+				.item{
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					.left{
+						display: flex;
+						align-items: center;
+						image{
+							width: 44upx;
+							height: 44upx;
+							margin-right: 20upx;
+						}
+						.text{
+							font-size: 30upx;
+							font-family: PingFang SC;
+							font-weight: bold;
+							color: #222222;
+							line-height: 1;
+						}
+					}
+				}
+			}
+			.order-info{
+				margin-top: 20upx;
+				background: #FFFFFF;
+				border-radius: 16upx;
+				padding: 40upx 30upx;
+				.title{
+					font-size: 30upx;
+					font-family: PingFang SC;
+					font-weight: bold;
+					color: #222222;
+					line-height: 1;
+				}
+				.item{
+					margin-top: 40upx;
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					.label{
+						font-size: 26upx;
+						font-family: PingFang SC;
+						font-weight: 500;
+						color: #666666;
+						line-height: 1;
+					}
+					.text{
+						font-size: 26upx;
+						font-family: PingFang SC;
+						font-weight: 500;
+						color: #222222;
+						line-height: 32upx;
+					}
+					.cont-text{
+						font-size: 26upx;
+						font-family: PingFang SC;
+						font-weight: 500;
+						color: #666666;
+						.bold{
+							color: #111111;
+						}
+					}
+					.sn-box{
+						display: flex;
+						align-items: center;
+						.copy-btn{
+							width: 58upx;
+							height: 32upx;
+							line-height: 32upx;
+							text-align: center;
+							font-size: 22upx;
+							font-family: PingFang SC;
+							font-weight: 500;
+							color: #222222;
+							background: #F5F5F5;
+							border-radius: 4upx;
+							margin-left: 24upx;
+						}
+					}
+					 
+				}
+				.line{
+					width: 100%;
+					height: 1px;
+					background: #F0F0F0;
+					margin-top: 30upx;
+				}
+			}
+		}
+		.btn-box{
+			height: 121upx;
+			background: #FFFFFF;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			.btn{
+				width: 91.73%;
+				height: 88upx;
+				line-height: 88upx;
+				font-size: 30upx;
+				font-family: PingFang SC;
+				font-weight: bold;
+				color: #FFFFFF;
+				text-align: center;
+				background: #018C39;
+				border-radius: 44upx;
+			}
+		}
+	}
+	
+</style>

部分文件因文件數量過多而無法顯示