Ver código fonte

考试系统

xionghaojie 3 anos atrás
commit
767ea2f6cf
100 arquivos alterados com 6859 adições e 0 exclusões
  1. 1 0
      .gitignore
  2. 20 0
      .hbuilderx/launch.json
  3. 52 0
      App.css
  4. 19 0
      App.vue
  5. 511 0
      components/biaofun-datetime-picker/biaofun-datetime-picker.vue
  6. 313 0
      components/biaofun-datetime-picker/utils.js
  7. 30 0
      components/biaofun-datetime-picker/使用说明.md
  8. 165 0
      components/circle-progress-bar/circle-progress-bar.vue
  9. 21 0
      components/echarts/echarts.simple.min.js
  10. 50 0
      components/foot/index.vue
  11. 35 0
      components/header/index.vue
  12. 134 0
      components/left-nav/index.vue
  13. 409 0
      components/mp-html/mp-html.vue
  14. 493 0
      components/mp-html/node/node.vue
  15. 1095 0
      components/mp-html/parser.js
  16. 123 0
      components/mpvue-echarts/src/echarts.vue
  17. 73 0
      components/mpvue-echarts/src/wx-canvas.js
  18. 50 0
      components/service-tab/service-tab.vue
  19. 35 0
      components/travel-tab/travel-tab.vue
  20. 211 0
      components/uni-countdown/uni-countdown.vue
  21. 18 0
      main.js
  22. 78 0
      manifest.json
  23. 17 0
      package.json
  24. 48 0
      pages.json
  25. 179 0
      pages/certificateDetail/certificateDetail.css
  26. 178 0
      pages/certificateDetail/certificateDetail.vue
  27. 75 0
      pages/certificateQuery/certificateQuery.css
  28. 70 0
      pages/certificateQuery/certificateQuery.vue
  29. 0 0
      pages/index/index.css
  30. 200 0
      pages/index/index.vue
  31. 259 0
      pages/login/login.css
  32. 257 0
      pages/login/login.vue
  33. 179 0
      pages/scoreQuery/scoreQuery.css
  34. 120 0
      pages/scoreQuery/scoreQuery.vue
  35. 342 0
      pages/test/test.css
  36. 529 0
      pages/test/test.vue
  37. 470 0
      static/css/main.css
  38. BIN
      static/images/back.png
  39. BIN
      static/images/back1.png
  40. BIN
      static/images/back2.png
  41. BIN
      static/images/back3.png
  42. BIN
      static/images/bdico1.png
  43. BIN
      static/images/bdico2.png
  44. BIN
      static/images/bdico3.png
  45. BIN
      static/images/bfico1.png
  46. BIN
      static/images/bfico1_h.png
  47. BIN
      static/images/bg.png
  48. BIN
      static/images/bico.png
  49. BIN
      static/images/certificate_bottom_bg.png
  50. BIN
      static/images/certificate_top_bg.png
  51. BIN
      static/images/cjwt.png
  52. BIN
      static/images/close.png
  53. BIN
      static/images/close1.png
  54. BIN
      static/images/delete.png
  55. BIN
      static/images/download.png
  56. BIN
      static/images/empty.png
  57. BIN
      static/images/gou.png
  58. BIN
      static/images/guoqi.png
  59. BIN
      static/images/idxico1.png
  60. BIN
      static/images/idxico2.png
  61. BIN
      static/images/idxico3.png
  62. BIN
      static/images/idxico4.png
  63. BIN
      static/images/idxico5.png
  64. BIN
      static/images/ing.png
  65. BIN
      static/images/jgbg.png
  66. BIN
      static/images/jgbg1.png
  67. BIN
      static/images/jgbg2.png
  68. BIN
      static/images/jia.png
  69. BIN
      static/images/jjico.png
  70. BIN
      static/images/ksgg.png
  71. BIN
      static/images/loginBg.png
  72. BIN
      static/images/logo_home.png
  73. BIN
      static/images/navico0.png
  74. BIN
      static/images/navico0_h.png
  75. BIN
      static/images/navico1.png
  76. BIN
      static/images/navico10.png
  77. BIN
      static/images/navico10_h.png
  78. BIN
      static/images/navico11.png
  79. BIN
      static/images/navico11_h.png
  80. BIN
      static/images/navico12.png
  81. BIN
      static/images/navico12_h.png
  82. BIN
      static/images/navico1_h.png
  83. BIN
      static/images/navico2.png
  84. BIN
      static/images/navico2_h.png
  85. BIN
      static/images/navico3.png
  86. BIN
      static/images/navico3_h.png
  87. BIN
      static/images/navico4.png
  88. BIN
      static/images/navico4_h.png
  89. BIN
      static/images/navico5.png
  90. BIN
      static/images/navico5_h.png
  91. BIN
      static/images/navico6.png
  92. BIN
      static/images/navico6_h.png
  93. BIN
      static/images/navico7.png
  94. BIN
      static/images/navico7_h.png
  95. BIN
      static/images/navico8.png
  96. BIN
      static/images/navico8_h.png
  97. BIN
      static/images/navico9.png
  98. BIN
      static/images/navico9_h.png
  99. BIN
      static/images/next.png
  100. BIN
      static/images/note.png

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+/unpackage/

+ 20 - 0
.hbuilderx/launch.json

@@ -0,0 +1,20 @@
+{ // 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": [{
+     	"default" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"h5" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"mp-weixin" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"type" : "uniCloud"
+     }
+    ]
+}

+ 52 - 0
App.css

@@ -0,0 +1,52 @@
+/* App.css */
+page{
+	--main: #DF230F;
+	--minor: #1890FF;
+	color: #333;
+	background: #f5f5f5;
+	-webkit-user-select: text;
+}
+button {background: none;border-radius: 0;margin: 0;padding: 0;line-height: initial;}
+button::after {border: none;border-radius: 0;}
+image{display: block;}
+.tover{text-overflow: ellipsis;white-space: nowrap;overflow: hidden;}
+.tovers{overflow : hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;}
+.dflex{display: flex;display: -webkit-flex;align-items: center;}
+.flex{flex: 1;-webkit-flex: 1;overflow: hidden;}
+.ddflex{display: flex;display: -webkit-flex;align-items: center;}
+.fflex{flex: 1;-webkit-flex: 1;overflow: hidden;}
+input,textarea{caret-color: var(--main);}
+.navigator-hover{background-color: rgba(0, 0, 0, 0.1); opacity: 1;}
+
+a{text-decoration: none;}
+
+
+/* 暂无数据 */
+.nodata{text-align: center;padding: 300rpx 0 80rpx;}
+.nodata image{width: 223px;height: 197px;margin: 0 auto 15px;}
+.nodata view{font-size: 14px;color: #999;}
+
+/* ios底部安全距离-padding */
+.savepadding{
+    padding-bottom: constant(safe-area-inset-bottom);  
+    padding-bottom: env(safe-area-inset-bottom); 
+    /* box-sizing: content-box; */
+}
+
+/* ios底部安全距离-bottom */
+.savebottom{
+    bottom: constant(safe-area-inset-bottom);  
+    bottom: env(safe-area-inset-bottom); 
+}
+
+.placeholder-view{height: 52px;}
+
+.wrap{margin: 0 auto;}
+
+.align-start{align-items: flex-start;}
+
+.max{width: 575px;}
+.large{width: 375px;}
+.small{width: 165px;}
+
+.btn-type{cursor: pointer;}

+ 19 - 0
App.vue

@@ -0,0 +1,19 @@
+<script>
+	export default {
+		onLaunch: function() {
+			console.log('App Launch')
+		},
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		}
+	}
+</script>
+
+<style>
+	/*每个页面公共css */
+	@import './App.css';
+	@import '/static/css/main.css';
+</style>

+ 511 - 0
components/biaofun-datetime-picker/biaofun-datetime-picker.vue

@@ -0,0 +1,511 @@
+<!-- 
+ * @插件:日期时间选择器
+ * @作者:陈万照
+ * @公司:山东标梵互动信息技术有限公司
+ * @官网:http://biaofun.com/
+ * @微信:C207668802
+ * @QQ:207668802
+ * @邮箱:cwz@biaofun.com || 207668802@qq.com
+ * @版本:v1.0.8
+ -->
+<template>
+	<view class="datatime">
+		<picker mode="multiSelector" :range="range" range-key="text" @change="change" @columnchange="columnchange" :value="value" :disabled="disabled">
+			<view class="content1" :class="{ placeholder: !dateStr }">
+				<text>{{ dateStr ? dateStr : placeholder }}</text>
+			</view>
+		</picker>
+	</view>
+</template>
+
+<script>
+import utils from './utils.js'; // 封装的工具集
+export default {
+	/**
+	 * 数据
+	 */
+	props: {
+		// 是否禁用
+		disabled: {
+			type: Boolean,
+			default: false
+		},
+
+		// 占位符
+		placeholder: {
+			type: String,
+			default: '请选择日期时间'
+		},
+
+		// 表示有效日期时间范围的开始,
+		// 字符串格式为 "YYYY-MM-DD hh:mm"
+		start: {
+			type: String,
+			default: '1970-1-1 00:00'
+		},
+
+		// 表示有效日期时间范围的结束
+		// 字符串格式为 "YYYY-MM-DD hh:mm"
+		end: {
+			type: String,
+			default: '2300-1-1 00:00'
+		},
+
+		// 表示选择器的粒度,有效值:year | month | day | hour | minute
+		fields: {
+			type: String,
+			default: 'minute'
+		},
+
+		// 默认值
+		// 字符串格式为 "YYYY-MM-DD hh:mm"
+		defaultValue: {
+			type: String,
+			default: ''
+		}
+	},
+
+	/**
+	 * 数据
+	 */
+	data() {
+		return {
+			range: [],
+			value: [],
+			dateStr: '', // 最终显示的字符串
+			dtStart: null, // 有效范围开始
+			dtEnd: null, // 有效范围结束
+		};
+	},
+	
+	/**
+	 * 监听数据
+	 */ 
+	watch: {
+		// 默认值
+		defaultValue() {
+			// 设置默认值
+			this.setDefaultValue();
+		}
+	},
+
+	/**
+	 * 组件初次加载完成
+	 */
+	mounted() {
+		// 有效日期开始和结束
+		let start = this.start;
+		let end = this.end;
+		
+		// 验证是否是有效的开始和结束日期
+		if(!utils.isString(this.start)) {
+			console.log('开始日期需为String类型,格式为 "YYYY-MM-DD hh:mm"');
+			start = '1970-1-1 00:00';
+		}
+		if(!utils.isString(this.start)) {
+			console.log('结束日期需为String类型,格式为 "YYYY-MM-DD hh:mm"');
+			start = '2300-1-1 00:00';
+		}
+		
+		// 将开始日期和结束日期转为 Date 
+		let dtStart = utils.formatDate(start).dt;
+		let dtEnd = utils.formatDate(end).dt;
+		
+		// 判断有效日期结束是否大于有效日期开始,如果不是,则将有效日期结束修改为有效日期开始往后300年
+		if (dtEnd <= dtStart) {
+			dtEnd = utils.formatDate(start).dt;
+			dtEnd.setFullYear(dtStart.getFullYear() + 300);
+			dtEnd.setDate(dtEnd.getDate() - 1);
+		}
+		
+		// 更新开始日期和结束日期
+		this.dtStart = dtStart;
+		this.dtEnd = dtEnd;
+
+		// 设置默认值
+		this.setDefaultValue();
+	},
+
+	/**
+	 * 方法
+	 */
+	methods: {
+		/**
+		 * 确认选择
+		 */
+		change(event) {
+			let year, month, day, hour, minute;
+			if(this.fields == 'year') {
+				year = this.range[0][this.value[0]].number; // 年
+				let dtStr = `${year}`;
+				this.setDateStr(dtStr);
+				this.$emit('change', utils.formatDate(dtStr));
+				return;
+			}
+			else if(this.fields == 'month') {
+				year = this.range[0][this.value[0]].number; // 年
+				month = this.range[1][this.value[1]].number; // 月
+				let dtStr = `${year}-${month}`;
+				this.setDateStr(dtStr);
+				this.$emit('change', utils.formatDate(dtStr));
+				return;
+			}
+			else if(this.fields == 'day') {
+				year = this.range[0][this.value[0]].number; // 年
+				month = this.range[1][this.value[1]].number; // 月
+				day = this.range[2][this.value[2]].number; // 日
+				let dtStr = `${year}-${month}-${day}`;
+				this.setDateStr(dtStr);
+				this.$emit('change', utils.formatDate(dtStr));
+				return;
+			}
+			else if(this.fields == 'hour') {
+				year = this.range[0][this.value[0]].number; // 年
+				month = this.range[1][this.value[1]].number; // 月
+				day = this.range[2][this.value[2]].number; // 日
+				hour = this.range[3][this.value[3]].number; // 时
+				day = this.range[2][this.value[2]].number; // 日
+				let dtStr = `${year}-${month}-${day} ${hour}`;
+				this.setDateStr(dtStr);
+				this.$emit('change', utils.formatDate(dtStr));
+				return;
+			}
+			else if(this.fields == 'minute') {
+				year = this.range[0][this.value[0]].number; // 年
+				month = this.range[1][this.value[1]].number; // 月
+				day = this.range[2][this.value[2]].number; // 日
+				hour = this.range[3][this.value[3]].number; // 时
+				minute = this.range[4][this.value[4]].number; // 分
+				let dtStr = `${year}-${month}-${day} ${hour}:${minute}`;
+				this.setDateStr(dtStr);
+				this.$emit('change', utils.formatDate(dtStr));
+				return;
+			}
+		},
+
+		/**
+		 * 设置显示的值
+		 * @param {Date|String} date 日期字符串或日期对象
+		 */
+		setDateStr(date) {
+			let dt = utils.formatDate(date);
+			if(this.fields == 'year') {
+				this.dateStr = `${dt.YYYY}年`;
+				return;
+			}
+			if(this.fields == 'month') {
+				this.dateStr = `${dt.YYYY}年${dt.M}月`;
+				return;
+			}
+			if(this.fields == 'day') {
+				this.dateStr = `${dt.YYYY}-${dt.M}-${dt.D}`;
+				return;
+			}
+			if(this.fields == 'hour') {
+				this.dateStr = `${dt.YYYY}年${dt.M}月${dt.D}日 ${dt.h}时`;
+				return;
+			}
+			this.dateStr = `${dt.YYYY}年${dt.M}月${dt.D}日 ${dt.h}时${dt.m}分`;
+		},
+		
+		/**
+		 * 设置年数据
+		 */ 
+		setYearData() {
+			// 有效日期
+			let yearStart = this.dtStart.getFullYear();
+			let yearEnd = this.dtEnd.getFullYear();
+			// 年
+			let years = [];
+			for (let year = yearStart; year <= yearEnd; year++) {
+				let item = {
+					number: year,
+					text: `${year}年`,
+				};
+				years.push(item);
+			}
+			this.range.splice(0, 1, years);
+		},
+		
+		/**
+		 * 设置月数据
+		 * @param {Number} year 年 
+		 */ 
+		setMonthData(year) {
+			// 有效日期
+			let yearStart = this.dtStart.getFullYear();
+			let monthStart = this.dtStart.getMonth() + 1;
+			let yearEnd = this.dtEnd.getFullYear();
+			let monthEnd = this.dtEnd.getMonth() + 1;
+			
+			// 月
+			let months = [];
+			let monthStartIndex = year == yearStart ? monthStart : 1;
+			let monthEndIndex = year == yearEnd ? monthEnd : 12;
+			for (let month = monthStartIndex; month <= monthEndIndex; month++) {
+				let item = {
+					number: month,
+					text: `${month}月`,
+				};
+				months.push(item);
+			}
+			this.range.splice(1, 1, months);
+		},
+		
+		/**
+		 * 设置日数据
+		 * @param {Number} year 年 
+		 * @param {Number} month 月 
+		 */ 
+		setDayData(year, month) {
+			// 有效日期
+			let yearStart = this.dtStart.getFullYear();
+			let monthStart = this.dtStart.getMonth() + 1;
+			let dayStart = this.dtStart.getDate();
+			let yearEnd = this.dtEnd.getFullYear();
+			let monthEnd = this.dtEnd.getMonth() + 1;
+			let dayEnd = this.dtEnd.getDate();
+			
+			// 日
+			let days = [];
+			let dayStartIndex = year == yearStart && month == monthStart ? dayStart : 1;
+			let dayEndIndex; 
+			if(year == yearEnd && month == monthEnd) {
+				dayEndIndex = dayEnd;
+			} else {
+				dayEndIndex = (new Date(year, month, 0)).getDate();
+			}
+			for (let day = dayStartIndex; day <= dayEndIndex; day++) {
+				let item = {
+					number: day,
+					text: `${day}日`,
+				};
+				days.push(item);
+			}
+			this.range.splice(2, 1, days);
+		},
+		
+		/**
+		 * 设置时数据
+		 * @param {Number} year 年 
+		 * @param {Number} month 月 
+		 * @param {Number} day 日 
+		 */ 
+		setHourData(year, month, day) {
+			// 有效日期
+			let yearStart = this.dtStart.getFullYear();
+			let monthStart = this.dtStart.getMonth() + 1;
+			let dayStart = this.dtStart.getDate();
+			let hourStart = this.dtStart.getHours();
+			let yearEnd = this.dtEnd.getFullYear();
+			let monthEnd = this.dtEnd.getMonth() + 1;
+			let dayEnd = this.dtEnd.getDate();
+			let hourEnd = this.dtEnd.getHours();
+			
+			// 时
+			let hours = [];
+			let hourStartIndex = year == yearStart && month == monthStart && day == dayStart ? hourStart : 0;
+			let hourEndIndex = year == yearEnd && month == monthEnd && day == dayEnd ? hourEnd : 23;
+			for (let hour = hourStartIndex; hour <= hourEndIndex; hour++) {
+				let item = {
+					number: hour,
+					text: `${hour}时`,
+				};
+				hours.push(item);
+			}
+			this.range.splice(3, 1, hours);
+		},
+		
+		/**
+		 * 设置分数据
+		 * @param {Number} year 年 
+		 * @param {Number} month 月 
+		 * @param {Number} day 日
+		 * @param {Number} hour 时
+		 */ 
+		setMinuteData(year, month, day, hour) {
+			// 有效日期
+			let yearStart = this.dtStart.getFullYear();
+			let monthStart = this.dtStart.getMonth() + 1;
+			let dayStart = this.dtStart.getDate();
+			let hourStart = this.dtStart.getHours();
+			let minuteStart = this.dtStart.getMinutes();
+			let yearEnd = this.dtEnd.getFullYear();
+			let monthEnd = this.dtEnd.getMonth() + 1;
+			let dayEnd = this.dtEnd.getDate();
+			let hourEnd = this.dtEnd.getHours();
+			let minuteEnd = this.dtEnd.getMinutes();
+			
+			// 分
+			let minutes = [];
+			let minuteStartIndex = year == yearStart && month == monthStart && day == dayStart && hour == hourStart ? minuteStart : 0;
+			let minuteEndIndex = year == yearEnd && month == monthEnd && day == dayEnd && hour == hourEnd ? minuteEnd : 59;
+			for(let minute = minuteStartIndex; minute <= minuteEndIndex; minute++) {
+				let item = {
+					number: minute,
+					text: `${minute}分`,
+				}
+				minutes.push(item);
+			}
+			this.range.splice(4, 1, minutes);
+		},
+		
+		/**
+		 * 设置默认值
+		 */
+		setDefaultValue() {
+			// 默认日期
+			let dtDefault;
+			
+			// 开始日期和结束日期
+			let dtStart = this.dtStart;
+			let dtEnd = this.dtEnd;
+			
+			// 判断是否传了默认日期
+			// 传了默认日期,格式化默认日期为日期对象
+			if(this.defaultValue) {
+				dtDefault = utils.formatDate(this.defaultValue).dt;
+			} 
+			// 如果没有传默认日期,将默认日期设置为当前日期
+			else {
+				dtDefault = new Date();
+			}
+			
+			// 如果默认日期不在有效日期范围内,设置默认日期为有效日期开始值
+			if (dtDefault < dtStart || dtDefault > dtEnd) {
+				dtDefault = dtStart;
+			}
+			
+			// 更新 dateStr
+			if(this.defaultValue) this.setDateStr(dtDefault);
+			
+			// 默认值相关数据
+			let dfYear = dtDefault.getFullYear();
+			let dfMonth = dtDefault.getMonth() + 1;
+			let dfDay = dtDefault.getDate();
+			let dfHour = dtDefault.getHours();
+			let dfMinute = dtDefault.getMinutes();
+			
+			// 设置年数据
+			this.setYearData();
+			// 设置 Year 这一列的 value 值
+			let yearIndex = this.range[0].findIndex(year => {
+				return dfYear == year.number;
+			});
+			this.value.splice(0, 1, yearIndex >= 0 ? yearIndex : 0);
+			
+			// 设置月数据
+			if(this.fields == 'year') return;
+			this.setMonthData(dfYear);
+			// 设置 Month 这一列的 value 值
+			let monthIndex = this.range[1].findIndex(month => {
+				return dfMonth == month.number;
+			});
+			this.value.splice(1, 1, monthIndex >=0 ? monthIndex : 0);
+			
+			// 设置日数据
+			if(this.fields == 'month') return;
+			this.setDayData(dfYear, dfMonth);
+			// 设置 Day 这一列的 value 值
+			let dayIndex = this.range[2].findIndex(day => {
+				return dfDay == day.number;
+			});
+			this.value.splice(2, 1, dayIndex >=0 ? dayIndex : 0);
+			
+			// 设置时数据
+			if(this.fields == 'day') return;
+			this.setHourData(dfYear, dfMonth, dfDay);
+			// 设置 Hour 这一列的 value 值
+			let hourIndex = this.range[3].findIndex(hour => {
+				return dfHour == hour.number;
+			});
+			this.value.splice(3, 1, hourIndex >=0 ? hourIndex : 0);
+			
+			// 设置分数据
+			if(this.fields == 'hour') return;
+			this.setMinuteData(dfYear, dfMonth, dfDay, dfHour);
+			// 设置 Minute 这一列的 value 值
+			let minuteIndex = this.range[4].findIndex(minute => {
+				return dfMinute == minute.number;
+			});
+			this.value.splice(4, 1, minuteIndex >=0 ? minuteIndex : 0);
+		},
+
+		/**
+		 * 某一列的值改变时触发
+		 * @param {Number} event.detail.column 表示改变了第几列(下标从0开始)
+		 * @param {Number} event.detail.value 表示变更值的下标
+		 */
+		columnchange(event) {
+			let columnIndex = event.detail.column; // 改变的列的下标
+			let valueIndex = event.detail.value; // 变更值的下标
+			
+			// 更新改变列的 value
+			this.value.splice(columnIndex, 1, valueIndex);
+			
+			// 改变年要更新月数据
+			if(this.fields == 'year') return;
+			if (columnIndex == 0) {
+				// 当前选择的月
+				let monthBeforeUpdate = this.range[1][this.value[1]];
+				// 更新月数据
+				this.setMonthData(this.range[0][this.value[0]].number);
+				// 更新 Month Value
+				let monthIndex = this.range[1].findIndex(month => {
+					return month.number == monthBeforeUpdate.number;
+				});
+				this.value.splice(1, 1, monthIndex >= 0 ? monthIndex : 0);
+			}
+			
+			// 改变年、月都要更新日数据
+			if(this.fields == 'month') return;
+			if (columnIndex == 0 || columnIndex == 1) {
+				// 当前选择的日
+				let dayBeforeUpdate = this.range[2][this.value[2]];
+				// 更新日数据
+				this.setDayData(this.range[0][this.value[0]].number, this.range[1][this.value[1]].number);
+				// 更新 Day Value
+				let dayIndex = this.range[2].findIndex(day => {
+					return day.number == dayBeforeUpdate.number;
+				});
+				this.value.splice(2, 1, dayIndex >= 0 ? dayIndex : 0);
+			}
+			
+			// 改变年、月、日都要更新时数据
+			if(this.fields == 'day') return;
+			if (columnIndex == 0 || columnIndex == 1 || columnIndex == 2) {
+				// 当前选择的时
+				let hourBeforeUpdate = this.range[3][this.value[3]];
+				// 更新时数据
+				this.setHourData(this.range[0][this.value[0]].number, this.range[1][this.value[1]].number, this.range[2][this.value[2]].number);
+				// 更新 Hour Value
+				let hourIndex = this.range[3].findIndex(hour => {
+					return hour.number == hourBeforeUpdate.number;
+				});
+				this.value.splice(3, 1, hourIndex >= 0 ? hourIndex : 0);
+			}
+			
+			// 当前选择的分
+			if(this.fields == 'hour') return;
+			let minuteBeforeUpdate = this.range[4][this.value[4]];
+			// 更新分数据
+			this.setMinuteData(this.range[0][this.value[0]].number, this.range[1][this.value[1]].number, this.range[2][this.value[2]].number, this.range[3][this.value[3]].number);
+			// 更新 Minute Value
+			let minuteIndex = this.range[4].findIndex(minute => {
+				return minute.number == minuteBeforeUpdate.number;
+			});
+			this.value.splice(4, 1, minuteIndex >= 0 ? minuteIndex : 0);
+		},
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.content {
+	text-align: right;
+}
+
+.placeholder {
+	color: #949596;
+}
+</style>

+ 313 - 0
components/biaofun-datetime-picker/utils.js

@@ -0,0 +1,313 @@
+/**
+ * @说明:工具集
+ * @作者:陈万照
+ * @公司:山东标梵互动技术有限公司
+ * @官网:http://biaofun.com/
+ * @版本:v1.0.0
+ * @时间:2020年4月28日11:28:13
+ */
+export default {
+	/**
+	 * 同步 try catch 的进一步封装处理
+	 * 使用方法:
+	 * let [err, res] = await this.$utils.asyncTasks(Promise函数);
+	 * if(res) 成功
+	 * if(err) 失败
+	 */
+	asyncTasks(promise) {
+		return promise.then(data => {
+			return [null, data];
+		}).catch(err => [err]);
+	},
+
+	/**
+	 * 精确判断数据是否是 Object 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isObject(val) {
+		return Object.prototype.toString.call(val) === '[object Object]' && val !== null && val !== undefined;
+	},
+
+	/**
+	 * 判断数据是否是 Array 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isArray(val) {
+		return Object.prototype.toString.call(val) === '[object Array]';
+	},
+
+	/**
+	 * 判断数据是否是 String 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isString(val) {
+		return Object.prototype.toString.call(val) === '[object String]';
+	},
+
+	/**
+	 * 精确判断数据是否是 Date 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isDate(val) {
+		return Object.prototype.toString.call(val) === '[object Date]';
+	},
+
+	/**
+	 * 精确判断数据是否是 Function 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isFunction(val) {
+		return Object.prototype.toString.call(val) === '[object Function]';
+	},
+
+	/**
+	 * 精确判断数据是否是 Number 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isNumber(val) {
+		return Object.prototype.toString.call(val) === '[object Number]';
+	},
+
+	/**
+	 * 精确判断数据是否是 Boolean 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isBoolean(val) {
+		return Object.prototype.toString.call(val) === '[object Boolean]';
+	},
+
+	/**
+	 * 判断 URL 是否是绝对 URL。
+	 * @param {String} url 要判断的 URL
+	 * @return {Boolean} true:是绝对URL;false:不是绝对URL;
+	 */
+	isAbsoluteURL(url) {
+		// 如果 URL 以 “<scheme>://” 或 “//”(协议相对URL)开头,则认为它是绝对的
+		// RFC 3986 将方案名称定义为以字母开头的字符序列,然后是字母,数字,加号,句点或连字符的任意组合
+		return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
+	},
+
+	/**
+	 * 合并 baseURL 和相对 URL 成一个完整的 URL
+	 * @param {String} baseURL baseURL
+	 * @param {String} relativeURL 相对 URL
+	 * @returns {String} 返回组合后的完整 URL
+	 */
+	combineURLs(baseURL, relativeURL) {
+		return relativeURL && this.isString(relativeURL) && this.isString(baseURL) ? baseURL.replace(/\/+$/, '') + '/' +
+			relativeURL.replace(/^\/+/, '') : baseURL;
+	},
+
+	/**
+	 * 深度合并对象,只支持合并两个对象,该方法不会改变原有的对象
+	 * @param {Object} FirstOBJ 第一个对象
+	 * @param {Object} SecondOBJ 第二个对象
+	 * @return {Object} 返回深度合并后的对象
+	 */
+	deepMargeObject(FirstOBJ, SecondOBJ) {
+		let ResultOBJ = {};
+		for (let key in FirstOBJ) {
+			ResultOBJ[key] = ResultOBJ[key] && ResultOBJ[key].toString() === "[object Object]" ? this.deepMargeObject(ResultOBJ[
+				key], FirstOBJ[key]) : ResultOBJ[key] = FirstOBJ[key];
+		}
+		for (let key in SecondOBJ) {
+			ResultOBJ[key] = ResultOBJ[key] && ResultOBJ[key].toString() === "[object Object]" ? this.deepMargeObject(ResultOBJ[
+				key], SecondOBJ[key]) : ResultOBJ[key] = SecondOBJ[key];
+		}
+		return ResultOBJ;
+	},
+	
+	/**
+	 * 生成指定长度的随机字符串
+	 * @param {Number} min 最小程度
+	 * @param {Number} max 最大长度 
+	 * @return {String} 返回生成的字符串
+	 */
+	randomString(min, max) {
+		let returnStr = "",
+			range = (max ? Math.round(Math.random() * (max - min)) + min : min),
+			arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+				'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
+				'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
+			];
+		for (let i = 0; i < range; i++) {
+			let index = Math.round(Math.random() * (arr.length - 1));
+			returnStr += arr[index];
+		}
+		return returnStr;
+	},
+
+	/**
+	 * 格式化日期
+	 * @param {Date|String} date 日期或日期字符串
+	 */
+	formatDate(date) {
+		let YYYY = null;
+		let M = null;
+		let MM = null;
+		let D = null;
+		let DD = null;
+		let h = null;
+		let hh = null;
+		let m = null;
+		let mm = null;
+		let s = null;
+		let ss = null;
+		let ms = null;
+		let ms2 = null;
+		let ms3 = null;
+		let ms4 = null;
+		let dt = null;
+
+		// 如果 date 是 String 类型
+		if (date && this.isString(date)) {
+			// 真机运行时,如果直接用 new Date('YYYY-MM-DD hh:mm:ss') 会报 Invalid Date 错误,所以采用下面的方式创建日期
+			let dtArr = date.replace(/\//g, '.').replace(/-/g, '.').replace(/:/g, '.').replace(/T/g, ' ').replace(' ', '.').replace(
+				'Z', '').split('.');
+
+			let year = 2020;
+			let month = 12;
+			let day = 18;
+			let hour = 0;
+			let minute = 0;
+			let second = 0;
+			let millisecond = 0;
+			
+			// 年
+			if (dtArr.length > 0 && !isNaN(dtArr[0])) {
+				year = parseInt(dtArr[0]);
+			}
+			// 月
+			if (dtArr.length > 1 && !isNaN(dtArr[1])) {
+				month = parseInt(dtArr[1]);
+			}
+			// 日
+			if (dtArr.length > 2 && !isNaN(dtArr[2])) {
+				day = parseInt(dtArr[2]);
+			}
+			// 时
+			if (dtArr.length > 3 && !isNaN(dtArr[3])) {
+				hour = parseInt(dtArr[3]);
+			}
+			// 分
+			if (dtArr.length > 4 && !isNaN(dtArr[4])) {
+				minute = parseInt(dtArr[4]);
+			}
+			// 秒
+			if (dtArr.length > 5 && !isNaN(dtArr[5])) {
+				second = parseInt(dtArr[5]);
+			}
+			// 毫秒
+			if (dtArr.length > 6 && !isNaN(dtArr[6])) {
+				millisecond = parseInt(dtArr[6]);
+			}
+
+			date = new Date(year, month - 1, day, hour, minute, second, millisecond);
+		}
+
+		// 如果 date 是 Date 类型
+		if (date && this.isDate(date)) {
+			YYYY = date.getFullYear();
+			M = date.getMonth() + 1;
+			MM = M >= 10 ? M : '0' + M;
+			D = date.getDate();
+			DD = D >= 10 ? D : '0' + D;
+			h = date.getHours();
+			hh = h >= 10 ? h : '0' + h;
+			m = date.getMinutes();
+			mm = m >= 10 ? m : '0' + m;
+			s = date.getSeconds();
+			ss = s >= 10 ? s : '0' + s;
+			ms = date.getMilliseconds();
+			ms2 = ms;
+			ms3 = ms;
+			ms4 = ms;
+			if (ms < 10) {
+				ms2 = '0' + ms;
+				ms3 = '00' + ms;
+				ms4 = '000' + ms;
+			} else if (ms < 100) {
+				ms3 = '0' + ms;
+				ms4 = '00' + ms;
+			} else {
+				ms4 = '0' + ms;
+			}
+		}
+
+		// 返回的数据对象
+		let result = {
+			YYYY: YYYY,
+			MM: MM,
+			M: M,
+			DD: DD,
+			D: D,
+			hh: hh,
+			h: h,
+			mm: mm,
+			m: m,
+			ss: ss,
+			s: s,
+			ms: ms,
+			ms2: ms2,
+			ms3: ms3,
+			ms4: ms4,
+			dt: date,
+			f1: `${YYYY}-${MM}-${DD}`,
+			f2: `${YYYY}年${M}月${D}日`,
+			f3: `${YYYY}-${M}-${D} ${hh}:${mm}`,
+			f4: `${h}:${m}:${s}`,
+			f5: `${MM}-${DD}`,
+			f6: `${YYYY}-${MM}`,
+			f7: `${YYYY}年${M}月`,
+			f8: `${h}:${m}`,
+			f9: `${M}月${D}日`,
+			notes: 'YYYY(年),MM(月,补0),M(月,不补0),DD(日,补0),D(日,不补0),hh(时,补0),h(时,不补0),mm(分,补0),m(分,不补0),ss(秒,补0),s(秒,不补0),ms(毫秒,不补0),ms2(毫秒,补0到2位),ms3(毫秒,补0到3位),ms4(毫秒,补0到4位),其余的f1,f2,... 看格式就知道了!'
+		};
+		return result;
+	},
+
+	/**
+	 * 数字转中文
+	 * @param {Number} num 数字
+	 */
+	numberToChinese(num) {
+		if (!/^\d*(\.\d*)?$/.test(num)) return "Number is wrong!";
+		let AA = new Array("零", "一", "二", "三", "四", "五", "六", "七", "八", "九");
+		let BB = new Array("", "十", "百", "千", "万", "亿", "点", "");
+		let a = ("" + num).replace(/(^0*)/g, "").split("."),
+			k = 0,
+			re = "";
+		for (let i = a[0].length - 1; i >= 0; i--) {
+			switch (k) {
+				case 0:
+					re = BB[7] + re;
+					break;
+				case 4:
+					if (!new RegExp("0{4}\\d{" + (a[0].length - i - 1) + "}$").test(a[0]))
+						re = BB[4] + re;
+					break;
+				case 8:
+					re = BB[5] + re;
+					BB[7] = BB[5];
+					k = 0;
+					break;
+			}
+			if (k % 4 == 2 && a[0].charAt(i + 2) != 0 && a[0].charAt(i + 1) == 0) re = AA[0] + re;
+			if (a[0].charAt(i) != 0) re = AA[a[0].charAt(i)] + BB[k % 4] + re;
+			k++;
+		}
+		if (a.length > 1) //加上小数部分(如果有小数部分) 
+		{
+			re += BB[6];
+			for (let i = 0; i < a[1].length; i++) re += AA[a[1].charAt(i)];
+		}
+		return re;
+	},
+}

+ 30 - 0
components/biaofun-datetime-picker/使用说明.md

@@ -0,0 +1,30 @@
+### 组件说明
+* 日期时间选择器
+* 组件的默认日期有效期范围为:"1970-01-01 00:00" - "2300-01-01 00:00"。
+* 注意:如果您传递的日期有效范围的结束日期小于开始日期,则日期有效范围的结束日期会自动修正为开始日期+300年,比如,您传递的日期有效范围的开始日期为 "2020-11-11 18:30",
+* 结束日期为 "2018-11-11 18:30",则此时将会自动修正结束日期为 "2320-11-11 18:30"。
+* 注意:如果您传递的默认值不在日期有效范围内,则会自动修正默认值为当前日期时间,如果当前日期时间也不在日期有效范围内,则会再次修正为日期有效范围的开始日期。
+* 注意:该组件用到了我自己封装的 utils.js,位置在 '@/common/js/utils.js'。
+
+
+### 插件 props 属性
+* disabled: 是否禁用该组件?Boolean类型;
+* placeholder: 组件没有选中值时显示的内容,String类型;
+* start: 表示有效日期时间范围的开始,String类型,格式为 "YYYY-MM-DD hh:mm";
+* end: 表示有效日期时间范围的结束,String类型,格式必为 "YYYY-MM-DD hh:mm";
+* fields: 选择器的粒度,String类型,有效值为 year、month、day、hour、minute;
+* defaultValue: 默认值,String类型,格式为 "YYYY-MM-DD hh:mm";
+
+### 插件事件
+- change(date):选择日期时间后的回调事件。
+ * date.YYYY: 年;
+ * date.M: 月;
+ * date.MM: 月(补0);
+ * date.D: 日;
+ * date.DD: 日(补0);
+ * date.h: 时;
+ * date.hh: 时(补0);
+ * date.m: 分;
+ * date.mm: 分(补0);
+ * date.dt: Date对象;
+ * ... 还有一些其他的字段,具体看返回值吧!

+ 165 - 0
components/circle-progress-bar/circle-progress-bar.vue

@@ -0,0 +1,165 @@
+<template>
+	<view class="circle-progress-bar" :style="{
+		width: r_size + 'px',
+		height: r_size + 'px',
+		padding: bw_upx + 'px',
+		background: border_color
+	}">
+		<view class="content1" :style="{ background: background }">
+			<view class="inner">
+				<slot :pro="pro"></slot>
+			</view>
+		</view>
+		<view class="bar" :class="{ animate: animate }" :style="{ transform: `rotate(${start * 360}deg)` }">
+			<view class="back n1" v-show="show_back" :style="{ background: border_color, transform: `rotate(${(pro - 0.5) * 360}deg)` }"></view>
+			
+			<view class="back n1" v-show="show_back" :style="{ background: border_color, 'z-index': 3 }"></view>
+			
+			<view class="mask n1" :style="{ background: border_back_color, transform: `rotate(${pro * 360}deg)` }"></view>
+			<view class="mask n2" :style="{ background: border_back_color }"></view>
+			<view class="point s"
+			:style="{
+				width: bw_upx + 'px',
+				height: bw_upx + 'px',
+				left: `calc(50% - ${bw_upx / 2}px)`,
+				background: border_color,
+			}"></view>
+			<view class="point e" 
+			:style="{
+				width: bw_upx + 'px',
+				height: bw_upx + 'px',
+				left: `calc(50% - ${bw_upx / 2}px)`,
+				transform: `rotate(${pro * 360}deg)`,
+				'transform-origin': `${bw_upx / 2}px ${size_upx / 2}px`,
+				background: border_color,
+			}"></view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name:"circle-progress-bar",
+		props:{
+			//进度 0-1
+			pro: {
+				type: Number,
+				default: 0,
+			},
+			//起始位置 0-1
+			start: {
+				type: Number,
+				default: 0,
+			},
+			//圆形大小
+			size: {
+				type: Number,
+				default: 100
+			},
+			//线宽度
+			border_width: {
+				type: Number,
+				default: 5
+			},
+			//线颜色
+			border_color: {
+				type: String,
+				default: '#07C160',
+			},
+			//线背景色
+			border_back_color: {
+				type: String,
+				default: '#fff',
+			},
+			//中心内容背景色
+			background: {
+				type: String,
+				default: '#FFF',
+			},
+			//是否启用动画
+			animate:{
+				type: Boolean,
+				default: true,
+			}
+		},
+		data() {
+			return {
+				prev_pro: 0,
+			};
+		},
+		watch:{
+			pro(val, pval) {
+				this.prev_pro = pval;
+			}
+		},
+		computed:{
+			r_size() {
+				return this.size_upx -  (2 * this.bw_upx);
+			},
+			size_upx() {
+				return uni.upx2px(this.size)
+			},
+			bw_upx() {
+				return uni.upx2px(this.border_width)
+			},
+			show_back() {
+				return this.pro > 0.5 || (this.pro == 0.5 && this.prev_pro > this.pro)
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.circle-progress-bar{
+		border-radius: 50%;
+		overflow: hidden;
+		position: relative;
+	}
+	.content1, .bar{
+		height: 100%;
+		width: 100%;
+	}
+	.content1{
+		border-radius: 50%;
+		overflow: hidden;
+		position: relative;
+		z-index: 5;
+	}
+	.inner{
+		position: absolute;
+		left: 50%;
+		top: 50%;
+		transform: translate(-50%, -50%);
+	}
+	.bar, .mask, .back, .point {
+		position: absolute;
+	}
+	.bar{
+		top: 0upx;
+		left: 0upx;
+	}
+	.mask, .back{
+		top: 0upx;
+		width: 50%;
+		height: 100%;
+	}
+	.n1{
+		right: 0upx;
+		transform-origin: 0% 50%;
+		z-index: 2;
+	}
+	.n2{
+		left: 0upx;
+		z-index: 1;
+	}
+	.point{
+		z-index: 3;
+		top: 0upx;
+		border-radius: 50%;
+	}
+	.bar.animate {
+		&, .mask, .back, .point {
+			transition: transform 0.3s;
+		}
+	}
+</style>

Diferenças do arquivo suprimidas por serem muito extensas
+ 21 - 0
components/echarts/echarts.simple.min.js


+ 50 - 0
components/foot/index.vue

@@ -0,0 +1,50 @@
+<template>
+	<view>
+		<view class="footer" :style="havaBackground?'':'background: transparent;'">
+			<view class="wrap">
+				<!-- <view class="foot-nav dflex">
+					<view class="li">学习中心</view>
+					<text>|</text>
+					<view class="li">我的课程</view>
+					<text>|</text>
+					<view class="li">我的题库</view>
+					<text>|</text>
+					<view class="li">我的班级</view>
+					<text>|</text>
+					<view class="li">我的积分</view>
+					<text>|</text>
+					<view class="li">个人资料</view>
+				</view> -->
+				<!-- <view>版权所有 © 2020 湖南湘德教育有限公司  增值电信业务经营许可证:湘B2-20090096  出版物经营许可  营业执照</view> -->
+				<view>Copyright © 2020 imooc.com All Rights Reserved | <a href="">京ICP备 12003892号-11</a></view>
+			</view>
+		</view>
+		<view class="placeholder-view"></view>
+	</view>
+</template>
+<script>
+const app = getApp();
+export default {
+	data() {
+		return {
+		};
+	},
+
+	components: {},
+	props: {
+		havaBackground:{
+			type:Boolean,
+			default:true
+		}
+	},
+	watch: {},
+
+	mounted() {},
+
+	methods: {
+	}
+};
+</script>
+<style>
+@import '/static/css/main.css';
+</style>

+ 35 - 0
components/header/index.vue

@@ -0,0 +1,35 @@
+<template>
+	<view>
+		<view class="header">
+			<view class="wrap dflex">
+				<view class="header-title">
+					{{date.v4}} {{date.week}} {{date.text}}好!
+				</image></view>
+			</view>
+		</view>
+		<view class="placeholder-view"></view>
+	</view>
+</template>
+<script>
+const app = getApp();
+const req = require('../../utils/request.js');
+const utils = require('../../utils/util.js');
+export default {
+	data() {
+		return {
+			date:{}
+		};
+	},
+
+	mounted() {
+		this.date = req.dateFormat(new Date())
+		console.log(this.date)
+	},
+
+	methods: {
+	}
+};
+</script>
+<style>
+@import '/static/css/main.css';
+</style>

+ 134 - 0
components/left-nav/index.vue

@@ -0,0 +1,134 @@
+<template>
+	<view>
+		<view class="left">
+			<block v-if="userInfo.type==2&&!userInfo.isStaff">
+			<view @click="jumpUrl('/pages/index/index')" :class="'li dflex' + (currentTab == 'index' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'index' ? '0_h' : '0') + '.png'" class="navico"></image>
+				首页
+			</view>
+			<view class="left-line"></view>
+			<view class="left-tits">经营上报</view>
+			<view @click="jumpUrl('/pages/route/route')" :class="'li dflex' + (currentTab == 'route' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'route' ? '1_h' : '1') + '.png'" class="navico"></image>
+				旅游线路产品上报
+			</view>
+			<view @click="jumpUrl('/pages/business/business')" :class="'li dflex' + (currentTab == 'business' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'business' ? '2_h' : '2') + '.png'" class="navico"></image>
+				经营信息上报
+			</view>
+			<view @click="jumpUrl('/pages/flow/flow')" :class="'li dflex' + (currentTab == 'flow' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'flow' ? '3_h' : '3') + '.png'" class="navico"></image>
+				节假日客流上报
+			</view>
+			<view @click="jumpUrl('/pages/analysis/analysis')" :class="'li dflex' + (currentTab == 'analysis' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'analysis' ? '4_h' : '4') + '.png'" class="navico"></image>
+				上报数据分析
+			</view>
+			<view class="left-line"></view>
+			<view class="left-tits">人力资源</view>
+			<view @click="jumpUrl('/pages/personal/personal')" :class="'li dflex' + (currentTab == 'personal' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'personal' ? '5_h' : '5') + '.png'" class="navico"></image>
+				人员管理
+			</view>
+			<view @click="jumpUrl('/pages/personalDemand/personalDemand')" :class="'li dflex' + (currentTab == 'personal-demand' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'personal-demand' ? '6_h' : '6') + '.png'" class="navico"></image>
+				需求发布
+			</view>
+			<view class="left-line"></view>
+			<view class="left-tits">物资调配</view>
+			<view @click="jumpUrl('/pages/materials/materials')" :class="'li dflex' + (currentTab == 'materials' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'materials' ? '7_h' : '7') + '.png'" class="navico"></image>
+				物资管理
+			</view>
+			<view @click="jumpUrl('/pages/materialsDemand/materialsDemand')" :class="'li dflex' + (currentTab == 'materials-demand' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'materials-demand' ? '8_h' : '8') + '.png'" class="navico"></image>
+				需求发布
+			</view>
+			<view class="left-line"></view>
+			</block>
+			<view class="left-tits">学习中心</view>
+			<view @click="jumpUrl('/pages/learn/learn')" :class="'li dflex' + (currentTab == 'learn' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'learn' ? '9_h' : '9') + '.png'" class="navico"></image>
+				听课学习
+			</view>
+			<view @click="jumpUrl('/pages/learnRecord/learnRecord')" :class="'li dflex' + (currentTab == 'learnRecord' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'learnRecord' ? '10_h' : '10') + '.png'" class="navico"></image>
+				学习记录
+			</view>
+			<view @click="jumpUrl('/pages/exam/exam')" :class="'li dflex' + (currentTab == 'exam' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'exam' ? '11_h' : '11') + '.png'" class="navico"></image>
+				正在考试
+			</view>
+			<view @click="jumpUrl('/pages/examRecord/examRecord')" :class="'li dflex' + (currentTab == 'examRecord' ? ' active' : '')">
+				<image :src="'../../static/images/navico' + (currentTab == 'examRecord' ? '12_h' : '12') + '.png'" class="navico"></image>
+				成绩查询
+			</view>
+			<block v-if="userInfo.type==2&&!userInfo.isStaff">
+			<view class="left-line"></view>
+			<view @click="jumpUrl('/pages/complaint/complaint')" :class="'lis' + (currentTab == 'complaint' ? ' active' : '')">投诉管理</view>
+
+			<view @click="jumpUrl('/pages/award/award')" v-if="userInfo.categoryId == 'travel_agency'" :class="'lis' + (currentTab == 'award' ? ' active' : '')">
+				招徕奖励
+			</view>
+			<view @click="jumpUrl('/pages/auditScenicRecord/auditScenicRecord')"
+				v-if="userInfo.categoryId == 'scenic_spot'"
+				:class="'lis' + (currentTab == 'auditScenicRecord' ? ' active' : '')"
+			>
+				招徕管理
+			</view>
+			<view @click="jumpUrl('/pages/auditHotelRecord/auditHotelRecord')"
+				v-if="userInfo.categoryId == 'hotel'"
+				:class="'lis' + (currentTab == 'auditHotelRecord' ? ' active' : '')"
+			>
+				招徕管理
+			</view>
+			<view @click="jumpUrl('/pages/declareHonor/declareHonor')" :class="'lis' + (currentTab == 'declare' ? ' active' : '')">资质申报</view>
+			</block>
+			<block>
+			<view @click="jumpUrl('/pages/careerCentre/careerCentre')" :class="'lis' + (currentTab == 'career' ? ' active' : '')">人才交流</view>
+			</block>
+		</view>
+	</view>
+</template>
+<script>
+const app = getApp();
+const req = require('../../utils/request.js');
+const utils = require('../../utils/util.js');
+export default {
+	data() {
+		return {
+			userInfo: ''
+		};
+	},
+
+	components: {},
+	props: {
+		currentTab: {
+			type: String,
+			default: 'index'
+		}
+	},
+	watch: {},
+
+	mounted() {
+		this.userInfo = req.getStorage('userInfo');
+	},
+
+	methods: {
+		jumpUrl(url){
+			if(this.userInfo.type==1||this.userInfo.institutionState == 2){
+				uni.navigateTo({
+					url: url
+				})
+			}else{
+				uni.navigateTo({
+					url: '/pages/company/company'
+				})
+			}
+		}
+	}
+};
+</script>
+<style>
+@import '/static/css/main.css';
+</style>

+ 409 - 0
components/mp-html/mp-html.vue

@@ -0,0 +1,409 @@
+<template>
+  <view id="_root" :class="(selectable?'_select ':'')+'_root'">
+    <slot v-if="!nodes[0]" />
+    <!-- #ifndef APP-PLUS-NVUE -->
+    <node v-else :childs="nodes" :opts="[lazyLoad,loadingImg,errorImg,showImgMenu]" />
+    <!-- #endif -->
+    <!-- #ifdef APP-PLUS-NVUE -->
+    <web-view ref="web" src="/static/app-plus/mp-html/local.html" :style="'margin-top:-2px;height:' + height + 'px'" @onPostMessage="_onMessage" />
+    <!-- #endif -->
+  </view>
+</template>
+
+<script>
+/**
+ * mp-html v2.0.3
+ * @description 富文本组件
+ * @tutorial https://github.com/jin-yufeng/mp-html
+ * @property {String} content 用于渲染的 html 字符串
+ * @property {Boolean} copy-link 是否允许外部链接被点击时自动复制
+ * @property {String} domain 主域名,用于拼接链接
+ * @property {String} error-img 图片出错时的占位图链接
+ * @property {Boolean} lazy-load 是否开启图片懒加载
+ * @property {string} loading-img 图片加载过程中的占位图链接
+ * @property {Boolean} pause-video 是否在播放一个视频时自动暂停其他视频
+ * @property {Boolean} preview-img 是否允许图片被点击时自动预览
+ * @property {Boolean} scroll-table 是否给每个表格添加一个滚动层使其能单独横向滚动
+ * @property {Boolean} selectable 是否开启长按复制
+ * @property {Boolean} set-title 是否将 title 标签的内容设置到页面标题
+ * @property {Boolean} show-img-menu 是否允许图片被长按时显示菜单
+ * @property {Object} tag-style 标签的默认样式
+ * @property {Boolean | Number} use-anchor 是否使用锚点链接
+ * @event {Function} load dom 结构加载完毕时触发
+ * @event {Function} ready 所有图片加载完毕时触发
+ * @event {Function} imgTap 图片被点击时触发
+ * @event {Function} linkTap 链接被点击时触发
+ * @event {Function} error 媒体加载出错时触发
+ */
+const plugins=[]
+const parser = require('./parser')
+// #ifndef APP-PLUS-NVUE
+import node from './node/node'
+// #endif
+// #ifdef APP-PLUS-NVUE
+const dom = weex.requireModule('dom')
+// #endif
+export default {
+  name: 'mp-html',
+  data() {
+    return {
+      nodes: [],
+      // #ifdef APP-PLUS-NVUE
+      height: 0
+      // #endif
+    }
+  },
+  props: {
+    // #ifdef APP-PLUS-NVUE
+    bgColor: String,
+    // #endif
+    content: String,
+    copyLink: {
+      type: Boolean,
+      default: true
+    },
+    domain: String,
+    errorImg: {
+      type: String,
+      default: ''
+    },
+    lazyLoad: {
+      type: Boolean,
+      default: false
+    },
+    loadingImg: {
+      type: String,
+      default: ''
+    },
+    pauseVideo: {
+      type: Boolean,
+      default: true
+    },
+    previewImg: {
+      type: Boolean,
+      default: true
+    },
+    scrollTable: Boolean,
+    selectable: Boolean,
+    setTitle: {
+      type: Boolean,
+      default: true
+    },
+    showImgMenu: {
+      type: Boolean,
+      default: true
+    },
+    tagStyle: Object,
+    useAnchor: null
+  },
+  // #ifndef APP-PLUS-NVUE
+  components: {
+    node
+  },
+  // #endif
+  watch: {
+    content(content) {
+      this.setContent(content)
+    }
+  },
+  created() {
+    this.plugins = []
+    for (var i = plugins.length; i--;)
+      this.plugins.push(new plugins[i](this))
+  },
+  mounted() {
+    if (this.content && !this.nodes.length)
+      this.setContent(this.content)
+  },
+  beforeDestroy() {
+    this._hook('onDetached')
+    clearInterval(this._timer)
+  },
+  methods: {
+    /**
+     * @description 将锚点跳转的范围限定在一个 scroll-view 内
+     * @param {Object} page scroll-view 所在页面的示例
+     * @param {String} selector scroll-view 的选择器
+     * @param {String} scrollTop scroll-view scroll-top 属性绑定的变量名
+     */
+    in(page, selector, scrollTop) {
+      // #ifndef APP-PLUS-NVUE
+      if (page && selector && scrollTop)
+        this._in = {
+          page,
+          selector,
+          scrollTop
+        }
+      // #endif
+    },
+
+    /**
+     * @description 锚点跳转
+     * @param {String} id 要跳转的锚点 id
+     * @param {Number} offset 跳转位置的偏移量
+     * @returns {Promise}
+     */
+    navigateTo(id, offset) {
+      return new Promise((resolve, reject) => {
+        if (!this.useAnchor)
+          return reject('Anchor is disabled')
+        offset = offset || parseInt(this.useAnchor) || 0
+        // #ifdef APP-PLUS-NVUE
+        if (!id) {
+          dom.scrollToElement(this.$refs.web, {
+            offset
+          })
+          resolve()
+        } else {
+          this._navigateTo = {
+            resolve,
+            reject,
+            offset
+          }
+          this.$refs.web.evalJs('uni.postMessage({data:{action:"getOffset",offset:(document.getElementById(' + id + ')||{}).offsetTop}})')
+        }
+        // #endif
+        // #ifndef APP-PLUS-NVUE
+        var deep = ' '
+        // #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO
+        deep = '>>>'
+        // #endif
+        var selector = uni.createSelectorQuery()
+          // #ifndef MP-ALIPAY
+          .in(this._in ? this._in.page : this)
+          // #endif
+          .select((this._in ? this._in.selector : '._root') + (id ? `${deep}#${id}` : '')).boundingClientRect()
+        if (this._in)
+          selector.select(this._in.selector).scrollOffset()
+            .select(this._in.selector).boundingClientRect() // 获取 scroll-view 的位置和滚动距离
+        else
+          selector.selectViewport().scrollOffset() // 获取窗口的滚动距离
+        selector.exec(res => {
+          if (!res[0])
+            return reject('Label not found')
+          var scrollTop = res[1].scrollTop + res[0].top - (res[2] ? res[2].top : 0) + offset
+          if (this._in)
+            // scroll-view 跳转
+            this._in.page[this._in.scrollTop] = scrollTop
+          else
+            // 页面跳转
+            uni.pageScrollTo({
+              scrollTop,
+              duration: 300
+            })
+          resolve()
+        })
+        // #endif
+      })
+    },
+
+    /**
+     * @description 获取文本内容
+     * @return {String}
+     */
+    getText() {
+      var text = '';
+      (function traversal(nodes) {
+        for (var i = 0; i < nodes.length; i++) {
+          var node = nodes[i]
+          if (node.type == 'text')
+            text += node.text.replace(/&amp;/g, '&')
+          else if (node.name == 'br')
+            text += '\n'
+          else {
+            // 块级标签前后加换行
+            var isBlock = node.name == 'p' || node.name == 'div' || node.name == 'tr' || node.name == 'li' || (node.name[0] == 'h' && node.name[1] > '0' && node.name[1] < '7')
+            if (isBlock && text && text[text.length - 1] != '\n')
+              text += '\n'
+            // 递归获取子节点的文本
+            if (node.children)
+              traversal(node.children)
+            if (isBlock && text[text.length - 1] != '\n')
+              text += '\n'
+            else if (node.name == 'td' || node.name == 'th')
+              text += '\t'
+          }
+        }
+      })(this.nodes)
+      return text
+    },
+
+    /**
+     * @description 获取内容大小和位置
+     * @return {Promise}
+     */
+    getRect() {
+      return new Promise((resolve, reject) => {
+        uni.createSelectorQuery()
+          // #ifndef MP-ALIPAY
+          .in(this)
+          // #endif
+          .select('#_root').boundingClientRect().exec(res => res[0] ? resolve(res[0]) : reject('Root label not found'))
+      })
+    },
+
+    /**
+     * @description 设置内容
+     * @param {String} content html 内容
+     * @param {Boolean} append 是否在尾部追加
+     */
+    setContent(content, append) {
+      if (!append || !this.imgList)
+        this.imgList = []
+      var nodes = new parser(this).parse(content)
+      // #ifdef APP-PLUS-NVUE
+      if (this._ready)
+        this._set(nodes, append)
+      // #endif
+      this.$set(this, 'nodes', append ? (this.nodes || []).concat(nodes) : nodes)
+
+      // #ifndef APP-PLUS-NVUE
+      this._videos = []
+      this.$nextTick(() => {
+        this._hook('onLoad')
+        this.$emit('load')
+      })
+
+      // 等待图片加载完毕
+      var height
+      clearInterval(this._timer)
+      this._timer = setInterval(() => {
+        this.getRect().then(rect => {
+          // 350ms 总高度无变化就触发 ready 事件
+          if (rect.height == height) {
+            this.$emit('ready', rect)
+            clearInterval(this._timer)
+          }
+          height = rect.height
+        }).catch(() => { })
+      }, 350)
+      // #endif
+    },
+
+    /**
+     * @description 调用插件钩子函数
+     */
+    _hook(name) {
+      for (var i = plugins.length; i--;)
+        if (this.plugins[i][name])
+          this.plugins[i][name]()
+    },
+
+    // #ifdef APP-PLUS-NVUE
+    /**
+     * @description 设置内容
+     */
+    _set(nodes, append) {
+      this.$refs.web.evalJs('setContent(' + JSON.stringify(nodes) + ',' + JSON.stringify([this.bgColor, this.errorImg, this.loadingImg, this.pauseVideo, this.scrollTable, this.selectable]) + ',' + append + ')')
+    },
+
+    /**
+     * @description 接收到 web-view 消息
+     */
+    _onMessage(e) {
+      var message = e.detail.data[0]
+      switch (message.action) {
+        // web-view 初始化完毕
+        case 'onJSBridgeReady':
+          this._ready = true
+          if (this.nodes)
+            this._set(this.nodes)
+          break
+        // 内容 dom 加载完毕
+        case 'onLoad':
+          this.height = message.height
+          this._hook('onLoad')
+          this.$emit('load')
+          break
+        // 所有图片加载完毕
+        case 'onReady':
+          this.getRect().then(res => {
+            this.$emit('ready', res)
+          }).catch(() => { })
+          break
+        // 总高度发生变化
+        case 'onHeightChange':
+          this.height = message.height
+          break
+        // 图片点击
+        case 'onImgTap':
+          this.$emit('imgtap', message.attrs)
+          if (this.previewImg)
+            uni.previewImage({
+              current: parseInt(message.attrs.i),
+              urls: this.imgList
+            })
+          break
+        // 链接点击
+        case 'onLinkTap':
+          var href = message.attrs.href
+          this.$emit('linktap', message.attrs)
+          if (href) {
+            // 锚点跳转
+            if (href[0] == '#') {
+              if (this.useAnchor)
+                dom.scrollToElement(this.$refs.web, {
+                  offset: message.offset
+                })
+            }
+            // 打开外链
+            else if (href.includes('://')) {
+              if (this.copyLink)
+                plus.runtime.openWeb(href)
+            }
+            else
+              uni.navigateTo({
+                url: href,
+                fail() {
+                  wx.switchTab({
+                    url: href
+                  })
+                }
+              })
+          }
+          break
+        // 获取到锚点的偏移量
+        case 'getOffset':
+          if (typeof message.offset == 'number') {
+            dom.scrollToElement(this.$refs.web, {
+              offset: message.offset + this._navigateTo.offset
+            })
+            this._navigateTo.resolve()
+          } else
+            this._navigateTo.reject('Label not found')
+          break
+        // 点击
+        case 'onClick':
+          this.$emit('tap')
+          break
+        // 出错
+        case 'onError':
+          this.$emit('error', {
+            source: message.source,
+            attrs: message.attrs
+          })
+      }
+    }
+    // #endif
+  }
+}
+</script>
+
+<style>
+/* #ifndef APP-PLUS-NVUE */
+/* 根节点样式 */
+._root {
+  overflow: auto;
+  -webkit-overflow-scrolling: touch;
+  line-height: 1.7;
+  /* font-size: 34rpx; */color: #333;
+}
+
+._root rich-text{margin: 10rpx 0;/* padding: 0 30rpx; */display: block;}
+
+/* 长按复制 */
+._select {
+  user-select: text;
+}
+/* #endif */
+</style>

+ 493 - 0
components/mp-html/node/node.vue

@@ -0,0 +1,493 @@
+<template>
+  <view :id="attrs.id" :class="'_'+name+' '+attrs.class" :style="attrs.style">
+    <block v-for="(n, i) in childs" v-bind:key="i">
+      <!-- 图片 -->
+      <!-- 占位图 -->
+      <image v-if="n.name=='img'&&((opts[1]&&!ctrl[i])||ctrl[i]<0)" class="_img" :style="n.attrs.style" :src="ctrl[i]<0?opts[2]:opts[1]" mode="widthFix" />
+      <!-- 显示图片 -->
+      <!-- #ifdef H5 || APP-PLUS -->
+      <img v-if="n.name=='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]==-1?'display:none;':'')+n.attrs.style" :src="n.attrs.src||(ctrl.load?n.attrs['data-src']:'')" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap"/>
+      <!-- #endif -->
+      <!-- #ifndef H5 || APP-PLUS -->
+      <image v-if="n.name=='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]==-1?'display:none;':'')+'width:'+(ctrl[i]||1)+'px;height:1px;'+n.attrs.style" :src="n.attrs.src" :mode="n.h?'':'widthFix'" :lazy-load="opts[0]" :webp="n.webp" :show-menu-by-longpress="opts[3]&&!n.attrs.ignore" :image-menu-prevent="!opts[3]||n.attrs.ignore" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
+      <!-- #endif -->
+      <!-- 文本 -->
+      <!-- #ifndef MP-BAIDU -->
+      <text v-else-if="n.type=='text'" decode>{{n.text}}</text>
+      <!-- #endif -->
+      <text v-else-if="n.name=='br'">\n</text>
+      <!-- 链接 -->
+      <view v-else-if="n.name=='a'" :id="n.attrs.id" :class="(n.attrs.href?'_a ':'')+n.attrs.class" hover-class="_hover" :style="'display:inline;'+n.attrs.style" :data-i="i" @click.capture.stop="linkTap">
+        <!-- #ifdef MP-ALIPAY || MP-TOUTIAO -->
+        <rich-text :nodes="n.children" style="display:inline" />
+        <!-- #endif -->
+        <!-- #ifndef MP-ALIPAY || MP-TOUTIAO -->
+        <node name="span" :childs="n.children" :opts="opts" />
+        <!-- #endif -->
+      </view>
+      <!-- 视频 -->
+      <!-- #ifdef APP-PLUS -->
+      <view v-else-if="n.html" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" v-html="n.html" />
+      <!-- #endif -->
+      <!-- #ifndef APP-PLUS -->
+      <video v-else-if="n.name=='video'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :autoplay="n.attrs.autoplay" :controls="n.attrs.controls" :loop="n.attrs.loop" :muted="n.attrs.muted" :poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" @play="play" @error="mediaError" />
+      <!-- #endif -->
+      <!-- #ifdef H5 || APP-PLUS -->
+      <iframe v-else-if="n.name=='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen" :frameborder="n.attrs.frameborder" :src="n.attrs.src" />
+      <embed v-else-if="n.name=='embed'" :style="n.attrs.style" :src="n.attrs.src" />
+      <!-- #endif -->
+      <!-- #ifndef MP-TOUTIAO -->
+      <!-- 音频 -->
+      <audio v-else-if="n.name=='audio'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :author="n.attrs.author" :controls="n.attrs.controls" :loop="n.attrs.loop" :name="n.attrs.name" :poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" @play="play" @error="mediaError" />
+      <!-- #endif -->
+      <view v-else-if="(n.name=='table'&&n.c)||n.name=='li'" :id="n.attrs.id" :class="'_'+n.name+' '+n.attrs.class" :style="n.attrs.style">
+        <node v-if="n.name=='li'" :childs="n.children" :opts="opts" />
+        <view v-else v-for="(tbody, x) in n.children" v-bind:key="x" :class="'_'+tbody.name+' '+tbody.attrs.class" :style="tbody.attrs.style">
+          <node v-if="tbody.name=='td'||tbody.name=='th'" :childs="tbody.children" :opts="opts" />
+          <block v-else v-for="(tr, y) in tbody.children" v-bind:key="y">
+            <view v-if="tr.name=='td'||tr.name=='th'" :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
+              <node :childs="tr.children" :opts="opts" />
+            </view>
+            <view v-else :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
+              <view v-for="(td, z) in tr.children" v-bind:key="z" :class="'_'+td.name+' '+td.attrs.class" :style="td.attrs.style">
+                <node :childs="td.children" :opts="opts" />
+              </view>
+            </view>
+          </block>
+        </view>
+      </view>
+      
+      <!-- 富文本 -->
+      <!-- #ifdef H5 || MP-WEIXIN || MP-QQ || APP-PLUS || MP-360 -->
+      <rich-text v-else-if="handler.use(n)" :id="n.attrs.id" :style="n.f" :nodes="[n]" />
+      <!-- #endif -->
+      <!-- #ifndef H5 || MP-WEIXIN || MP-QQ || APP-PLUS || MP-360 -->
+      <rich-text v-else-if="!n.c" :id="n.attrs.id" :style="n.f+';display:inline'" :preview="false" :nodes="[n]" />
+      <!-- #endif -->
+      <!-- 继续递归 -->
+      <view v-else-if="n.c==2" :id="n.attrs.id" :class="'_'+n.name+' '+n.attrs.class" :style="n.f+';'+n.attrs.style">
+        <node v-for="(n2, j) in n.children" v-bind:key="j" :style="n2.f" :name="n2.name" :attrs="n2.attrs" :childs="n2.children" :opts="opts" />
+      </view>
+      <node v-else :style="n.f" :name="n.name" :attrs="n.attrs" :childs="n.children" :opts="opts" />
+    </block>
+  </view>
+</template>
+<script module="handler" lang="wxs">
+// 行内标签列表
+var inlineTags = {
+  abbr: true,
+  b: true,
+  big: true,
+  code: true,
+  del: true,
+  em: true,
+  i: true,
+  ins: true,
+  label: true,
+  q: true,
+  small: true,
+  span: true,
+  strong: true,
+  sub: true,
+  sup: true
+}
+/**
+ * @description 是否使用 rich-text 显示剩余内容
+ */
+module.exports = {
+  use: function (item) {
+  // 微信和 QQ 的 rich-text inline 布局无效
+  if (inlineTags[item.name] || (item.attrs.style || '').indexOf('display:inline') != -1)
+    return false
+  return !item.c
+  }
+}
+</script>
+<script>
+
+import node from './node'
+export default {
+  name: 'node',
+  // #ifdef MP-WEIXIN
+  options: {
+    virtualHost: true
+  },
+  // #endif
+  data() {
+    return {
+      ctrl: {}
+    }
+  },
+  props: {
+    name: String,
+    attrs: {
+      type: Object,
+      default() {
+        return {}
+      }
+    },
+    childs: Array,
+    opts: Array
+  },
+  components: {
+
+    node
+  },
+  mounted() {
+    for (this.root = this.$parent; this.root.$options.name != 'mp-html'; this.root = this.root.$parent);
+    // #ifdef H5 || APP-PLUS
+    if (this.opts[0]) {
+      for (var i = this.childs.length; i--;)
+        if (this.childs[i].name == 'img')
+          break
+      if (i != -1) {
+        this.observer = uni.createIntersectionObserver(this).relativeToViewport({
+          top: 500,
+          bottom: 500
+        })
+        this.observer.observe('._img', res => {
+          if (res.intersectionRatio) {
+            this.$set(this.ctrl, 'load', 1)
+            this.observer.disconnect()
+          }
+        })
+      }
+    }
+    // #endif
+  },
+  beforeDestroy() {
+    // #ifdef H5 || APP-PLUS
+    if (this.observer)
+      this.observer.disconnect()
+    // #endif
+  },
+  methods:{
+    // #ifdef MP-WEIXIN
+    toJSON() { },
+    // #endif
+    /**
+     * @description 播放视频事件
+     * @param {Event} e 
+     */
+    play(e) {
+      // #ifndef APP-PLUS
+      if (this.root.pauseVideo) {
+        var flag = false, id = e.target.id
+        for (var i = this.root._videos.length; i--;) {
+          if (this.root._videos[i].id == id)
+            flag = true
+          else
+            this.root._videos[i].pause() // 自动暂停其他视频
+        }
+        // 将自己加入列表
+        if (!flag) {
+          var ctx = uni.createVideoContext(id
+            // #ifndef MP-BAIDU
+            , this
+            // #endif
+          )
+          ctx.id = id
+          this.root._videos.push(ctx)
+        }
+      }
+      // #endif
+    },
+
+    /**
+     * @description 图片点击事件
+     * @param {Event} e 
+     */
+    imgTap(e) {
+      var attrs = this.childs[e.currentTarget.dataset.i].attrs
+      if (attrs.ignore)
+        return
+      attrs.src = attrs['data-src'] || attrs.src
+      this.root.$emit('imgtap', attrs)
+      // 自动预览图片
+      if (this.root.previewImg)
+        uni.previewImage({
+          current: parseInt(attrs.i),
+          urls: this.root.imgList
+        })
+    },
+
+    /**
+     * @description 图片长按
+     */
+    imgLongTap() {
+      // #ifdef APP-PLUS
+      var attrs = this.childs[e.currentTarget.dataset.i].attrs
+      if (!attrs.ignore)
+        uni.showActionSheet({
+          itemList: ['保存图片'],
+          success: () => {
+            uni.downloadFile({
+              url: this.root.imgList[attrs.i],
+              success: res => {
+                uni.saveImageToPhotosAlbum({
+                  filePath: res.tempFilePath,
+                  success() {
+                    uni.showToast({
+                      title: '保存成功'
+                    })
+                  }
+                })
+              }
+            })
+          }
+        })
+      // #endif
+    },
+
+    /**
+     * @description 图片加载完成事件
+     * @param {Event} e 
+     */
+    imgLoad(e) {
+      var i = e.currentTarget.dataset.i
+      // #ifndef H5 || APP-PLUS
+      // 设置原宽度
+      if (!this.childs[i].w)
+        this.$set(this.ctrl, i, e.detail.width)
+      else
+        // #endif
+        // 加载完毕,取消加载中占位图
+        if ((this.opts[1] && !this.ctrl[i]) || this.ctrl[i] == -1)
+          this.$set(this.ctrl, i, 1)
+    },
+
+    /**
+     * @description 链接点击事件
+     * @param {Event} e 
+     */
+    linkTap(e) {
+      var attrs = this.childs[e.currentTarget.dataset.i].attrs,
+        href = attrs.href
+      this.root.$emit('linktap', attrs)
+      if (href) {
+        // 跳转锚点
+        if (href[0] == '#')
+          this.root.navigateTo(href.substring(1)).catch(() => { })
+        // 复制外部链接
+        else if (href.includes('://')) {
+          if (this.root.copyLink) {
+            // #ifdef H5
+            window.open(href)
+            // #endif
+            // #ifdef MP
+            uni.setClipboardData({
+              data: href,
+              success: () =>
+                uni.showToast({
+                  title: '链接已复制'
+                })
+            })
+            // #endif
+            // #ifdef APP-PLUS
+            plus.runtime.openWeb(href)
+            // #endif
+          }
+        }
+        // 跳转页面
+        else
+          uni.navigateTo({
+            url: href,
+            fail() {
+              uni.switchTab({
+                url: href,
+                fail() { }
+              })
+            }
+          })
+      }
+    },
+
+    /**
+     * @description 错误事件
+     * @param {Event} e 
+     */
+    mediaError(e) {
+      var i = e.currentTarget.dataset.i,
+        node = this.childs[i]
+      // 加载其他源
+      if (node.name == 'video' || node.name == 'audio') {
+        var index = (this.ctrl[i] || 0) + 1
+        if (index > node.src.length)
+          index = 0
+        if (index < node.src.length)
+          return this.$set(this.ctrl, i, index)
+      }
+      // 显示错误占位图
+      else if (node.name == 'img' && this.opts[2])
+        this.$set(this.ctrl, i, -1)
+      if (this.root)
+        this.root.$emit('error', {
+          source: node.name,
+          attrs: node.attrs,
+          errMsg: e.detail.errMsg
+        })
+    }
+  }
+}
+</script>
+<style>
+/* a 标签默认效果 */
+._a {
+  padding: 1.5px 0 1.5px 0;
+  color: #366092;
+  word-break: break-all;
+}
+
+/* a 标签点击态效果 */
+._hover {
+  text-decoration: underline;
+  opacity: 0.7;
+}
+
+/* 图片默认效果 */
+._img {
+  max-width: 100%;
+  -webkit-touch-callout: none;
+}
+
+/* 内部样式 */
+
+._b,
+._strong {
+  font-weight: bold;
+}
+
+._code {
+  font-family: monospace;
+}
+
+._del {
+  text-decoration: line-through;
+}
+
+._em,
+._i {
+  font-style: italic;
+}
+
+._h1 {
+  font-size: 2em;
+}
+
+._h2 {
+  font-size: 1.5em;
+}
+
+._h3 {
+  font-size: 1.17em;
+}
+
+._h5 {
+  font-size: 0.83em;
+}
+
+._h6 {
+  font-size: 0.67em;
+}
+
+._h1,
+._h2,
+._h3,
+._h4,
+._h5,
+._h6 {
+  display: block;
+  font-weight: bold;
+}
+
+._image {
+  height: 1px;
+}
+
+._ins {
+  text-decoration: underline;
+}
+
+._li {
+  display: list-item;
+}
+
+._ol {
+  list-style-type: decimal;
+}
+
+._ol,
+._ul {
+  display: block;
+  padding-left: 40px;
+  margin: 1em 0;
+}
+
+._q::before {
+  content: '"';
+}
+
+._q::after {
+  content: '"';
+}
+
+._sub {
+  font-size: smaller;
+  vertical-align: sub;
+}
+
+._sup {
+  font-size: smaller;
+  vertical-align: super;
+}
+
+._thead,
+._tbody,
+._tfoot {
+  display: table-row-group;
+}
+
+._tr {
+  display: table-row;
+}
+
+._td,
+._th {
+  display: table-cell;
+  vertical-align: middle;
+}
+
+._th {
+  font-weight: bold;
+  text-align: center;
+}
+
+._ul {
+  list-style-type: disc;
+}
+
+._ul ._ul {
+  margin: 0;
+  list-style-type: circle;
+}
+
+._ul ._ul ._ul {
+  list-style-type: square;
+}
+
+._abbr,
+._b,
+._code,
+._del,
+._em,
+._i,
+._ins,
+._label,
+._q,
+._span,
+._strong,
+._sub,
+._sup {
+  display: inline;
+}
+</style>

+ 1095 - 0
components/mp-html/parser.js

@@ -0,0 +1,1095 @@
+"use strict";
+
+/**
+ * @fileoverview html 解析器
+ */
+// 配置
+var config = {
+  // 信任的标签(保持标签名不变)
+  trustTags: makeMap('a,abbr,ad,audio,b,blockquote,br,code,col,colgroup,dd,del,dl,dt,div,em,fieldset,h1,h2,h3,h4,h5,h6,hr,i,img,ins,label,legend,li,ol,p,q,ruby,rt,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video'),
+  // 块级标签(转为 div,其他的非信任标签转为 span)
+  blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,pre,section'),
+  // 要移除的标签
+  ignoreTags: makeMap('area,base,canvas,embed,frame,head,iframe,input,link,map,meta,param,rp,script,source,style,textarea,title,track,wbr'),
+  // 自闭合的标签
+  voidTags: makeMap('area,base,br,col,circle,ellipse,embed,frame,hr,img,input,line,link,meta,param,path,polygon,rect,source,track,use,wbr'),
+  // html 实体
+  entities: {
+    lt: '<',
+    gt: '>',
+    quot: '"',
+    apos: "'",
+    ensp: "\u2002",
+    emsp: "\u2003",
+    nbsp: '\xA0',
+    semi: ';',
+    ndash: '–',
+    mdash: '—',
+    middot: '·',
+    lsquo: '‘',
+    rsquo: '’',
+    ldquo: '“',
+    rdquo: '”',
+    bull: '•',
+    hellip: '…'
+  },
+  // 默认的标签样式
+  tagStyle: {
+    // #ifndef APP-PLUS-NVUE
+    address: 'font-style:italic',
+    big: 'display:inline;font-size:1.2em',
+    caption: 'display:table-caption;text-align:center',
+    center: 'text-align:center',
+    cite: 'font-style:italic',
+    dd: 'margin-left:40px',
+    mark: 'background-color:yellow',
+    pre: 'font-family:monospace;white-space:pre',
+    s: 'text-decoration:line-through',
+    small: 'display:inline;font-size:0.8em',
+    u: 'text-decoration:underline' // #endif
+
+  }
+};
+var windowWidth = uni.getSystemInfoSync().windowWidth;
+var blankChar = makeMap(' ,\r,\n,\t,\f');
+var idIndex = 0; // #ifdef H5 || APP-PLUS
+
+config.ignoreTags.iframe = void 0;
+config.trustTags.iframe = true;
+config.ignoreTags.embed = void 0;
+config.trustTags.embed = true; // #endif
+// #ifdef APP-PLUS-NVUE
+
+config.ignoreTags.source = void 0;
+config.ignoreTags.style = void 0; // #endif
+
+/**
+ * @description 创建 map
+ * @param {String} str 逗号分隔
+ */
+
+function makeMap(str) {
+  var map = Object.create(null),
+      list = str.split(',');
+
+  for (var i = list.length; i--;) {
+    map[list[i]] = true;
+  }
+
+  return map;
+}
+/**
+ * @description 解码 html 实体
+ * @param {String} str 要解码的字符串
+ * @param {Boolean} amp 要不要解码 &amp;
+ * @returns {String} 解码后的字符串
+ */
+
+
+function decodeEntity(str, amp) {
+  var i = str.indexOf('&');
+
+  while (i != -1) {
+    var j = str.indexOf(';', i + 3),
+        code = void 0;
+    if (j == -1) break;
+
+    if (str[i + 1] == '#') {
+      // &#123; 形式的实体
+      code = parseInt((str[i + 2] == 'x' ? '0' : '') + str.substring(i + 2, j));
+      if (!isNaN(code)) str = str.substr(0, i) + String.fromCharCode(code) + str.substr(j + 1);
+    } else {
+      // &nbsp; 形式的实体
+      code = str.substring(i + 1, j);
+      if (config.entities[code] || code == 'amp' && amp) str = str.substr(0, i) + (config.entities[code] || '&') + str.substr(j + 1);
+    }
+
+    i = str.indexOf('&', i + 1);
+  }
+
+  return str;
+}
+/**
+ * @description html 解析器
+ * @param {Object} vm 组件实例
+ */
+
+
+function parser(vm) {
+  this.options = vm || {};
+  this.tagStyle = Object.assign(config.tagStyle, this.options.tagStyle);
+  this.imgList = vm.imgList || [];
+  this.plugins = vm.plugins || [];
+  this.attrs = Object.create(null);
+  this.stack = [];
+  this.nodes = [];
+}
+/**
+ * @description 执行解析
+ * @param {String} content 要解析的文本
+ */
+
+
+parser.prototype.parse = function (content) {
+  // 插件处理
+  for (var i = this.plugins.length; i--;) {
+    if (this.plugins[i].onUpdate) content = this.plugins[i].onUpdate(content, config) || content;
+  }
+
+  new lexer(this).parse(content); // 出栈未闭合的标签
+
+  while (this.stack.length) {
+    this.popNode();
+  }
+
+  return this.nodes;
+};
+/**
+ * @description 将标签暴露出来(不被 rich-text 包含)
+ */
+
+
+parser.prototype.expose = function () {
+  // #ifndef APP-PLUS-NVUE
+  for (var i = this.stack.length; i--;) {
+    var item = this.stack[i];
+    if (item.name == 'a' || item.c) return;
+    item.c = 1;
+  } // #endif
+
+};
+/**
+ * @description 处理插件
+ * @param {Object} node 要处理的标签
+ * @returns {Boolean} 是否要移除此标签
+ */
+
+
+parser.prototype.hook = function (node) {
+  for (var i = this.plugins.length; i--;) {
+    if (this.plugins[i].onParse && this.plugins[i].onParse(node, this) == false) return false;
+  }
+
+  return true;
+};
+/**
+ * @description 将链接拼接上主域名
+ * @param {String} url 需要拼接的链接
+ * @returns {String} 拼接后的链接
+ */
+
+
+parser.prototype.getUrl = function (url) {
+  var domain = this.options.domain;
+
+  if (url[0] == '/') {
+    // // 开头的补充协议名
+    if (url[1] == '/') url = (domain ? domain.split('://')[0] : 'http') + ':' + url; // 否则补充整个域名
+    else if (domain) url = domain + url;
+  } else if (domain && !url.includes('data:') && !url.includes('://')) url = domain + '/' + url;
+
+  return url;
+};
+/**
+ * @description 解析样式表
+ * @param {Object} node 标签
+ * @returns {Object} 
+ */
+
+
+parser.prototype.parseStyle = function (node) {
+  var attrs = node.attrs,
+      list = (this.tagStyle[node.name] || '').split(';').concat((attrs.style || '').split(';')),
+      styleObj = {},
+      tmp = '';
+
+  if (attrs.id) {
+    // 暴露锚点
+    if (this.options.useAnchor) this.expose();else if (node.name != 'img' && node.name != 'a' && node.name != 'video' && node.name != 'audio') attrs.id = void 0;
+  } // #ifndef APP-PLUS-NVUE
+  // 转换 width 和 height 属性
+
+
+  if (attrs.width) {
+    styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px');
+    attrs.width = void 0;
+  }
+
+  if (attrs.height) {
+    styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px');
+    attrs.height = void 0;
+  } // #endif
+
+
+  for (var i = 0, len = list.length; i < len; i++) {
+    var info = list[i].split(':');
+    if (info.length < 2) continue;
+    var key = info.shift().trim().toLowerCase(),
+        value = info.join(':').trim(); // 兼容性的 css 不压缩
+
+    if (value[0] == '-' && value.lastIndexOf('-') > 0 || value.includes('safe')) tmp += ";".concat(key, ":").concat(value); // 重复的样式进行覆盖
+    else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import')) {
+        // 填充链接
+        if (value.includes('url')) {
+          var j = value.indexOf('(') + 1;
+
+          if (j) {
+            while (value[j] == '"' || value[j] == "'" || blankChar[value[j]]) {
+              j++;
+            }
+
+            value = value.substr(0, j) + this.getUrl(value.substr(j));
+          }
+        } // 转换 rpx(rich-text 内部不支持 rpx)
+        else if (value.includes('rpx')) value = value.replace(/[0-9.]+\s*rpx/g, function ($) {
+            return parseFloat($) * windowWidth / 750 + 'px';
+          });
+
+        styleObj[key] = value;
+      }
+  }
+
+  node.attrs.style = tmp;
+  return styleObj;
+};
+/**
+ * @description 解析到标签名
+ * @param {String} name 标签名
+ * @private
+ */
+
+
+parser.prototype.onTagName = function (name) {
+  this.tagName = this.xml ? name : name.toLowerCase();
+  if (this.tagName == 'svg') this.xml = true; // svg 标签内大小写敏感
+};
+/**
+ * @description 解析到属性名
+ * @param {String} name 属性名
+ * @private
+ */
+
+
+parser.prototype.onAttrName = function (name) {
+  name = this.xml ? name : name.toLowerCase();
+
+  if (name.substr(0, 5) == 'data-') {
+    // data-src 自动转为 src
+    if (name == 'data-src') this.attrName = 'src'; // a 和 img 标签保留 data- 的属性,可以在 imgtap 和 linktap 事件中使用
+    else if (this.tagName == 'img' || this.tagName == 'a') this.attrName = name; // 剩余的移除以减小大小
+      else this.attrName = void 0;
+  } else {
+    this.attrName = name;
+    this.attrs[name] = 'T'; // boolean 型属性缺省设置
+  }
+};
+/**
+ * @description 解析到属性值
+ * @param {String} val 属性值
+ * @private
+ */
+
+
+parser.prototype.onAttrVal = function (val) {
+  var name = this.attrName || ''; // 部分属性进行实体解码
+
+  if (name == 'style' || name == 'href') this.attrs[name] = decodeEntity(val, true); // 拼接主域名
+  else if (name.includes('src')) this.attrs[name] = this.getUrl(decodeEntity(val, true));else if (name) this.attrs[name] = val;
+};
+/**
+ * @description 解析到标签开始
+ * @param {Boolean} selfClose 是否有自闭合标识 />
+ * @private
+ */
+
+
+parser.prototype.onOpenTag = function (selfClose) {
+  // 拼装 node
+  var node = Object.create(null);
+  node.name = this.tagName;
+  node.attrs = this.attrs;
+  this.attrs = Object.create(null);
+  var attrs = node.attrs,
+      parent = this.stack[this.stack.length - 1],
+      siblings = parent ? parent.children : this.nodes,
+      close = this.xml ? selfClose : config.voidTags[node.name]; // 转换 embed 标签
+
+  if (node.name == 'embed') {
+    // #ifndef H5 || APP-PLUS
+    var src = attrs.src || ''; // 按照后缀名和 type 将 embed 转为 video 或 audio
+
+    if (src.includes('.mp4') || src.includes('.3gp') || src.includes('.m3u8') || (attrs.type || '').includes('video')) node.name = 'video';else if (src.includes('.mp3') || src.includes('.wav') || src.includes('.aac') || src.includes('.m4a') || (attrs.type || '').includes('audio')) node.name = 'audio';
+    if (attrs.autostart) attrs.autoplay = 'T';
+    attrs.controls = 'T'; // #endif
+    // #ifdef H5 || APP-PLUS
+
+    this.expose(); // #endif
+  } // #ifndef APP-PLUS-NVUE
+  // 处理音视频
+
+
+  if (node.name == 'video' || node.name == 'audio') {
+    // 设置 id 以便获取 context
+    if (node.name == 'video' && !attrs.id) attrs.id = 'v' + idIndex++; // 没有设置 controls 也没有设置 autoplay 的自动设置 controls
+
+    if (!attrs.controls && !attrs.autoplay) attrs.controls = 'T'; // 用数组存储所有可用的 source
+
+    node.src = [];
+
+    if (attrs.src) {
+      node.src.push(attrs.src);
+      attrs.src = void 0;
+    }
+
+    this.expose();
+  } // #endif
+  // 处理自闭合标签
+
+
+  if (close) {
+    if (!this.hook(node) || config.ignoreTags[node.name]) {
+      // 通过 base 标签设置主域名
+      if (node.name == 'base' && !this.options.domain) this.options.domain = attrs.href; // #ifndef APP-PLUS-NVUE
+      // 设置 source 标签(仅父节点为 video 或 audio 时有效)
+      else if (node.name == 'source' && parent && (parent.name == 'video' || parent.name == 'audio') && attrs.src) parent.src.push(attrs.src); // #endif
+
+      return;
+    } // 解析 style
+
+
+    var styleObj = this.parseStyle(node); // 处理图片
+
+    if (node.name == 'img') {
+      if (attrs.src) {
+        // 标记 webp
+        if (attrs.src.includes('webp')) node.webp = 'T'; // data url 图片如果没有设置 original-src 默认为不可预览的小图片
+
+        if (attrs.src.includes('data:') && !attrs['original-src']) attrs.ignore = 'T';
+
+        if (!attrs.ignore || node.webp || attrs.src.includes('cloud://')) {
+          var i;
+
+          for (i = this.stack.length; i--;) {
+            var item = this.stack[i];
+            if (item.name == 'a') break; // #ifndef H5 || APP-PLUS
+
+            var style = item.attrs.style || '';
+
+            if (style.includes('flex:') && !style.includes('flex:0') && !style.includes('flex: 0') && (!styleObj.width || !styleObj.width.includes('%'))) {
+              styleObj.width = '100% !important';
+              styleObj.height = '';
+
+              for (var j = i + 1; j < this.stack.length; j++) {
+                this.stack[j].attrs.style = (this.stack[j].attrs.style || '').replace('inline-', '');
+              }
+            } else if (style.includes('flex') && styleObj.width == '100%') {
+              for (var _j = i + 1; _j < this.stack.length; _j++) {
+                var _style = this.stack[_j].attrs.style || '';
+
+                if (!_style.includes(';width') && !_style.includes(' width') && _style.indexOf('width') != 0) {
+                  styleObj.width = '';
+                  break;
+                }
+              }
+            } else if (style.includes('inline-block')) {
+              if (styleObj.width && styleObj.width[styleObj.width.length - 1] == '%') {
+                item.attrs.style += ';max-width:' + styleObj.width;
+                styleObj.width = '';
+              } else item.attrs.style += ';max-width:100%';
+            } // #endif
+
+
+            item.c = 1;
+          }
+
+          if (i == -1) {
+            attrs.i = this.imgList.length.toString();
+
+            var _src = attrs['original-src'] || attrs.src; // #ifndef H5 || MP-ALIPAY || APP-PLUS || MP-360
+
+
+            if (this.imgList.includes(_src)) {
+              // 如果有重复的链接则对域名进行随机大小写变换避免预览时错位
+              var _i = _src.indexOf('://');
+
+              if (_i != -1) {
+                _i += 3;
+
+                var newSrc = _src.substr(0, _i);
+
+                for (; _i < _src.length; _i++) {
+                  if (_src[_i] == '/') break;
+                  newSrc += Math.random() > 0.5 ? _src[_i].toUpperCase() : _src[_i];
+                }
+
+                newSrc += _src.substr(_i);
+                _src = newSrc;
+              }
+            } // #endif
+
+
+            this.imgList.push(_src); // #ifdef H5 || APP-PLUS
+
+            if (this.options.lazyLoad) {
+              attrs['data-src'] = attrs.src;
+              attrs.src = void 0;
+            } // #endif
+
+          } else attrs.ignore = 'T';
+        }
+      }
+
+      if (styleObj.display == 'inline') styleObj.display = ''; // #ifndef APP-PLUS-NVUE
+
+      if (attrs.ignore) {
+        styleObj['max-width'] = '100%';
+        attrs.style += ';-webkit-touch-callout:none';
+      } // #endif
+      // 设置的宽度超出屏幕,为避免变形,高度转为自动
+
+
+      if (parseInt(styleObj.width) > windowWidth) styleObj.height = void 0; // 记录是否设置了宽高
+
+      if (styleObj.width) {
+        if (styleObj.width.includes('auto')) styleObj.width = '';else {
+          node.w = 'T';
+          if (styleObj.height && !styleObj.height.includes('auto')) node.h = 'T';
+        }
+      }
+    } else if (node.name == 'svg') {
+      siblings.push(node);
+      this.stack.push(node);
+      this.popNode();
+      return;
+    }
+
+    for (var key in styleObj) {
+      if (styleObj[key]) attrs.style += ";".concat(key, ":").concat(styleObj[key].replace(' !important', ''));
+    }
+
+    attrs.style = attrs.style.substr(1) || void 0;
+  } else {
+    if (node.name == 'pre' || (attrs.style || '').includes('white-space') && attrs.style.includes('pre')) this.pre = node.pre = true;
+    node.children = [];
+    this.stack.push(node);
+  } // 加入节点树
+
+
+  siblings.push(node);
+};
+/**
+ * @description 解析到标签结束
+ * @param {String} name 标签名
+ * @private
+ */
+
+
+parser.prototype.onCloseTag = function (name) {
+  // 依次出栈到匹配为止
+  name = this.xml ? name : name.toLowerCase();
+  var i;
+
+  for (i = this.stack.length; i--;) {
+    if (this.stack[i].name == name) break;
+  }
+
+  if (i != -1) {
+    while (this.stack.length > i) {
+      this.popNode();
+    }
+  } else if (name == 'p' || name == 'br') {
+    var siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes;
+    siblings.push({
+      name: name,
+      attrs: {}
+    });
+  }
+};
+/**
+ * @description 处理标签出栈
+ * @private
+ */
+
+
+parser.prototype.popNode = function () {
+  var node = this.stack.pop(),
+      attrs = node.attrs,
+      children = node.children,
+      parent = this.stack[this.stack.length - 1],
+      siblings = parent ? parent.children : this.nodes;
+
+  if (!this.hook(node) || config.ignoreTags[node.name]) {
+    // 获取标题
+    if (node.name == 'title' && children.length && children[0].type == 'text' && this.options.setTitle) uni.setNavigationBarTitle({
+      title: children[0].text
+    });
+    siblings.pop();
+    return;
+  }
+
+  if (node.pre) {
+    // 是否合并空白符标识
+    node.pre = this.pre = void 0;
+
+    for (var i = this.stack.length; i--;) {
+      if (this.stack[i].pre) this.pre = true;
+    }
+  }
+
+  var styleObj = {}; // 转换 svg
+
+  if (node.name == 'svg') {
+    // #ifndef APP-PLUS-NVUE
+    var src = '',
+        style = attrs.style;
+    attrs.style = '';
+    attrs.xmlns = 'http://www.w3.org/2000/svg';
+
+    (function traversal(node) {
+      src += '<' + node.name;
+
+      for (var item in node.attrs) {
+        var val = node.attrs[item];
+
+        if (val) {
+          if (item == 'viewbox') item = 'viewBox';
+          src += " ".concat(item, "=\"").concat(val, "\"");
+        }
+      }
+
+      if (!node.children) src += '/>';else {
+        src += '>';
+
+        for (var _i2 = 0; _i2 < node.children.length; _i2++) {
+          traversal(node.children[_i2]);
+        }
+
+        src += '</' + node.name + '>';
+      }
+    })(node);
+
+    node.name = 'img';
+    node.attrs = {
+      src: 'data:image/svg+xml;utf8,' + src.replace(/#/g, '%23'),
+      style: style,
+      ignore: 'T'
+    };
+    node.children = void 0; // #endif
+
+    this.xml = false;
+    return;
+  } // #ifndef APP-PLUS-NVUE
+  // 转换 align 属性
+
+
+  if (attrs.align) {
+    if (node.name == 'table') {
+      if (attrs.align == 'center') styleObj['margin-inline-start'] = styleObj['margin-inline-end'] = 'auto';else styleObj["float"] = attrs.align;
+    } else styleObj['text-align'] = attrs.align;
+
+    attrs.align = void 0;
+  } // 转换 font 标签的属性
+
+
+  if (node.name == 'font') {
+    if (attrs.color) {
+      styleObj.color = attrs.color;
+      attrs.color = void 0;
+    }
+
+    if (attrs.face) {
+      styleObj['font-family'] = attrs.face;
+      attrs.face = void 0;
+    }
+
+    if (attrs.size) {
+      var size = parseInt(attrs.size);
+
+      if (!isNaN(size)) {
+        if (size < 1) size = 1;else if (size > 7) size = 7;
+        styleObj['font-size'] = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'][size - 1];
+      }
+
+      attrs.size = void 0;
+    }
+  } // #endif
+  // 一些编辑器的自带 class
+
+
+  if ((attrs["class"] || '').includes('align-center')) styleObj['text-align'] = 'center';
+  Object.assign(styleObj, this.parseStyle(node));
+  if (parseInt(styleObj.width) > windowWidth) styleObj['max-width'] = '100%'; // #ifndef APP-PLUS-NVUE
+
+  if (config.blockTags[node.name]) node.name = 'div'; // 未知标签转为 span,避免无法显示
+  else if (!config.trustTags[node.name] && !this.xml) node.name = 'span';
+  if (node.name == 'a' || node.name == 'ad' // #ifdef H5 || APP-PLUS
+  || node.name == 'iframe' // #endif
+  ) this.expose(); // #ifdef APP-PLUS
+  else if (node.name == 'video') {
+      var str = '<video style="max-width:100%"';
+
+      for (var item in attrs) {
+        if (attrs[item]) str += ' ' + item + '="' + attrs[item] + '"';
+      }
+
+      if (this.options.pauseVideo) str += ' onplay="for(var e=document.getElementsByTagName(\'video\'),t=0;t<e.length;t++)e[t]!=this&&e[t].pause()"';
+      str += '>';
+
+      for (var _i3 = 0; _i3 < node.src.length; _i3++) {
+        str += '<source src="' + node.src[_i3] + '">';
+      }
+
+      str += '</video>';
+      node.html = str;
+    } // #endif
+    // 列表处理
+    else if ((node.name == 'ul' || node.name == 'ol') && node.c) {
+        var types = {
+          a: 'lower-alpha',
+          A: 'upper-alpha',
+          i: 'lower-roman',
+          I: 'upper-roman'
+        };
+
+        if (types[attrs.type]) {
+          attrs.style += ';list-style-type:' + types[attrs.type];
+          attrs.type = void 0;
+        }
+
+        for (var _i4 = children.length; _i4--;) {
+          if (children[_i4].name == 'li') children[_i4].c = 1;
+        }
+      } // 表格处理
+      else if (node.name == 'table') {
+          // cellpadding、cellspacing、border 这几个常用表格属性需要通过转换实现
+          var padding = parseFloat(attrs.cellpadding),
+              spacing = parseFloat(attrs.cellspacing),
+              border = parseFloat(attrs.border);
+
+          if (node.c) {
+            // padding 和 spacing 默认 2
+            if (isNaN(padding)) padding = 2;
+            if (isNaN(spacing)) spacing = 2;
+          }
+
+          if (border) attrs.style += ';border:' + border + 'px solid gray';
+
+          if (node.flag && node.c) {
+            // 有 colspan 或 rowspan 且含有链接的表格通过 grid 布局实现
+            styleObj.display = 'grid';
+
+            if (spacing) {
+              styleObj['grid-gap'] = spacing + 'px';
+              styleObj.padding = spacing + 'px';
+            } // 无间隔的情况下避免边框重叠
+            else if (border) attrs.style += ';border-left:0;border-top:0';
+
+            var width = [],
+                // 表格的列宽
+            trList = [],
+                // tr 列表
+            cells = [],
+                // 保存新的单元格
+            map = {}; // 被合并单元格占用的格子
+
+            (function traversal(nodes) {
+              for (var _i5 = 0; _i5 < nodes.length; _i5++) {
+                if (nodes[_i5].name == 'tr') trList.push(nodes[_i5]);else traversal(nodes[_i5].children || []);
+              }
+            })(children);
+
+            for (var row = 1; row <= trList.length; row++) {
+              var col = 1;
+
+              for (var j = 0; j < trList[row - 1].children.length; j++, col++) {
+                var td = trList[row - 1].children[j];
+
+                if (td.name == 'td' || td.name == 'th') {
+                  // 这个格子被上面的单元格占用,则列号++
+                  while (map[row + '.' + col]) {
+                    col++;
+                  }
+
+                  var _style2 = td.attrs.style || '',
+                      start = _style2.indexOf('width') ? _style2.indexOf(';width') : 0; // 提取出 td 的宽度
+
+
+                  if (start != -1) {
+                    var end = _style2.indexOf(';', start + 6);
+
+                    if (end == -1) end = _style2.length;
+                    if (!td.attrs.colspan) width[col] = _style2.substring(start ? start + 7 : 6, end);
+                    _style2 = _style2.substr(0, start) + _style2.substr(end);
+                  }
+
+                  _style2 += (border ? ";border:".concat(border, "px solid gray") + (spacing ? '' : ';border-right:0;border-bottom:0') : '') + (padding ? ";padding:".concat(padding, "px") : ''); // 处理列合并
+
+                  if (td.attrs.colspan) {
+                    _style2 += ";grid-column-start:".concat(col, ";grid-column-end:").concat(col + parseInt(td.attrs.colspan));
+                    if (!td.attrs.rowspan) _style2 += ";grid-row-start:".concat(row, ";grid-row-end:").concat(row + 1);
+                    col += parseInt(td.attrs.colspan) - 1;
+                  } // 处理行合并
+
+
+                  if (td.attrs.rowspan) {
+                    _style2 += ";grid-row-start:".concat(row, ";grid-row-end:").concat(row + parseInt(td.attrs.rowspan));
+                    if (!td.attrs.colspan) _style2 += ";grid-column-start:".concat(col, ";grid-column-end:").concat(col + 1); // 记录下方单元格被占用
+
+                    for (var k = 1; k < td.attrs.rowspan; k++) {
+                      map[row + k + '.' + col] = 1;
+                    }
+                  }
+
+                  if (_style2) td.attrs.style = _style2;
+                  cells.push(td);
+                }
+              }
+
+              if (row == 1) {
+                var temp = '';
+
+                for (var _i6 = 1; _i6 < col; _i6++) {
+                  temp += (width[_i6] ? width[_i6] : 'auto') + ' ';
+                }
+
+                styleObj['grid-template-columns'] = temp;
+              }
+            }
+
+            node.children = cells;
+          } else {
+            // 没有使用合并单元格的表格通过 table 布局实现
+            if (node.c) styleObj.display = 'table';
+            if (!isNaN(spacing)) styleObj['border-spacing'] = spacing + 'px';
+
+            if (border || padding) {
+              // 遍历
+              (function traversal(nodes) {
+                for (var _i7 = 0; _i7 < nodes.length; _i7++) {
+                  var _td = nodes[_i7];
+
+                  if (_td.name == 'th' || _td.name == 'td') {
+                    if (border) _td.attrs.style = "border:".concat(border, "px solid gray;").concat(_td.attrs.style || '');
+                    if (padding) _td.attrs.style = "padding:".concat(padding, "px;").concat(_td.attrs.style || '');
+                  } else if (_td.children) traversal(_td.children);
+                }
+              })(children);
+            }
+          } // 给表格添加一个单独的横向滚动层
+
+
+          if (this.options.scrollTable && !(attrs.style || '').includes('inline')) {
+            var table = Object.assign({}, node);
+            node.name = 'div';
+            node.attrs = {
+              style: 'overflow:auto'
+            };
+            node.children = [table];
+            attrs = table.attrs;
+          }
+        } else if ((node.name == 'td' || node.name == 'th') && (attrs.colspan || attrs.rowspan)) {
+          for (var _i8 = this.stack.length; _i8--;) {
+            if (this.stack[_i8].name == 'table') {
+              this.stack[_i8].flag = 1; // 指示含有合并单元格
+
+              break;
+            }
+          }
+        } // 转换 ruby
+        else if (node.name == 'ruby') {
+            node.name = 'span';
+
+            for (var _i9 = 0; _i9 < children.length - 1; _i9++) {
+              if (children[_i9].type == 'text' && children[_i9 + 1].name == 'rt') {
+                children[_i9] = {
+                  name: 'div',
+                  attrs: {
+                    style: 'display:inline-block'
+                  },
+                  children: [{
+                    name: 'div',
+                    attrs: {
+                      style: 'font-size:50%;text-align:start'
+                    },
+                    children: children[_i9 + 1].children
+                  }, children[_i9]]
+                };
+                children.splice(_i9 + 1, 1);
+              }
+            }
+          } else if (node.c) {
+            node.c = 2;
+
+            for (var _i10 = node.children.length; _i10--;) {
+              if (!node.children[_i10].c || node.children[_i10].name == 'table') node.c = 1;
+            }
+          }
+  if ((styleObj.display || '').includes('flex') && !node.c) for (var _i11 = children.length; _i11--;) {
+    var _item = children[_i11];
+
+    if (_item.f) {
+      _item.attrs.style = (_item.attrs.style || '') + _item.f;
+      _item.f = void 0;
+    }
+  } // flex 布局时部分样式需要提取到 rich-text 外层
+
+  var flex = parent && (parent.attrs.style || '').includes('flex') // #ifdef MP-WEIXIN
+  // 检查基础库版本 virtualHost 是否可用
+  && !(node.c && wx.getNFCAdapter) // #endif
+  // #ifndef MP-WEIXIN || MP-QQ || MP-BAIDU || MP-TOUTIAO
+  && !node.c; // #endif
+
+  if (flex) node.f = ';max-width:100%'; // #endif
+
+  for (var key in styleObj) {
+    if (styleObj[key]) {
+      var val = ";".concat(key, ":").concat(styleObj[key].replace(' !important', '')); // #ifndef APP-PLUS-NVUE
+
+      if (flex && (key.includes('flex') && key != 'flex-direction' || key == 'align-self' || styleObj[key][0] == '-' || key == 'width' && val.includes('%'))) {
+        node.f += val;
+        if (key == 'width') attrs.style += ';width:100%';
+      } else // #endif
+        attrs.style += val;
+    }
+  }
+
+  attrs.style = attrs.style.substr(1) || void 0;
+};
+/**
+ * @description 解析到文本
+ * @param {String} text 文本内容
+ */
+
+
+parser.prototype.onText = function (text) {
+  if (!this.pre) {
+    // 合并空白符
+    var trim = '',
+        flag;
+
+    for (var i = 0, len = text.length; i < len; i++) {
+      if (!blankChar[text[i]]) trim += text[i];else {
+        if (trim[trim.length - 1] != ' ') trim += ' ';
+        if (text[i] == '\n' && !flag) flag = true;
+      }
+    } // 去除含有换行符的空串
+
+
+    if (trim == ' ' && flag) return;
+    text = trim;
+  }
+
+  var node = Object.create(null);
+  node.type = 'text';
+  node.text = decodeEntity(text);
+
+  if (this.hook(node)) {
+    var siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes;
+    siblings.push(node);
+  }
+};
+/**
+ * @description html 词法分析器
+ * @param {Object} handler 高层处理器
+ */
+
+
+function lexer(handler) {
+  this.handler = handler;
+}
+/**
+ * @description 执行解析
+ * @param {String} content 要解析的文本
+ */
+
+
+lexer.prototype.parse = function (content) {
+  this.content = content || '';
+  this.i = 0; // 标记解析位置
+
+  this.start = 0; // 标记一个单词的开始位置
+
+  this.state = this.text; // 当前状态
+
+  for (var len = this.content.length; this.i != -1 && this.i < len;) {
+    this.state();
+  }
+};
+/**
+ * @description 检查标签是否闭合
+ * @param {String} method 如果闭合要进行的操作
+ * @returns {Boolean} 是否闭合
+ * @private
+ */
+
+
+lexer.prototype.checkClose = function (method) {
+  var selfClose = this.content[this.i] == '/';
+
+  if (this.content[this.i] == '>' || selfClose && this.content[this.i + 1] == '>') {
+    if (method) this.handler[method](this.content.substring(this.start, this.i));
+    this.i += selfClose ? 2 : 1;
+    this.start = this.i;
+    this.handler.onOpenTag(selfClose);
+    this.state = this.text;
+    return true;
+  }
+
+  return false;
+};
+/**
+ * @description 文本状态
+ * @private
+ */
+
+
+lexer.prototype.text = function () {
+  this.i = this.content.indexOf('<', this.i); // 查找最近的标签
+
+  if (this.i == -1) {
+    // 没有标签了
+    if (this.start < this.content.length) this.handler.onText(this.content.substring(this.start, this.content.length));
+    return;
+  }
+
+  var c = this.content[this.i + 1];
+
+  if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') {
+    // 标签开头
+    if (this.start != this.i) this.handler.onText(this.content.substring(this.start, this.i));
+    this.start = ++this.i;
+    this.state = this.tagName;
+  } else if (c == '/' || c == '!' || c == '?') {
+    if (this.start != this.i) this.handler.onText(this.content.substring(this.start, this.i));
+    var next = this.content[this.i + 2];
+
+    if (c == '/' && (next >= 'a' && next <= 'z' || next >= 'A' && next <= 'Z')) {
+      // 标签结尾
+      this.i += 2;
+      this.start = this.i;
+      return this.state = this.endTag;
+    } // 处理注释
+
+
+    var end = '-->';
+    if (c != '!' || this.content[this.i + 2] != '-' || this.content[this.i + 3] != '-') end = '>';
+    this.i = this.content.indexOf(end, this.i);
+
+    if (this.i != -1) {
+      this.i += end.length;
+      this.start = this.i;
+    }
+  } else this.i++;
+};
+/**
+ * @description 标签名状态
+ * @private
+ */
+
+
+lexer.prototype.tagName = function () {
+  if (blankChar[this.content[this.i]]) {
+    // 解析到标签名
+    this.handler.onTagName(this.content.substring(this.start, this.i));
+
+    while (blankChar[this.content[++this.i]]) {
+      ;
+    }
+
+    if (this.i < this.content.length && !this.checkClose()) {
+      this.start = this.i;
+      this.state = this.attrName;
+    }
+  } else if (!this.checkClose('onTagName')) this.i++;
+};
+/**
+ * @description 属性名状态
+ * @private
+ */
+
+
+lexer.prototype.attrName = function () {
+  var c = this.content[this.i];
+
+  if (blankChar[c] || c == '=') {
+    // 解析到属性名
+    this.handler.onAttrName(this.content.substring(this.start, this.i));
+    var needVal = c == '=',
+        len = this.content.length;
+
+    while (++this.i < len) {
+      c = this.content[this.i];
+
+      if (!blankChar[c]) {
+        if (this.checkClose()) return;
+
+        if (needVal) {
+          // 等号后遇到第一个非空字符
+          this.start = this.i;
+          return this.state = this.attrVal;
+        }
+
+        if (this.content[this.i] == '=') needVal = true;else {
+          this.start = this.i;
+          return this.state = this.attrName;
+        }
+      }
+    }
+  } else if (!this.checkClose('onAttrName')) this.i++;
+};
+/**
+ * @description 属性值状态
+ * @private
+ */
+
+
+lexer.prototype.attrVal = function () {
+  var c = this.content[this.i],
+      len = this.content.length; // 有冒号的属性
+
+  if (c == '"' || c == "'") {
+    this.start = ++this.i;
+    this.i = this.content.indexOf(c, this.i);
+    if (this.i == -1) return;
+    this.handler.onAttrVal(this.content.substring(this.start, this.i));
+  } // 没有冒号的属性
+  else for (; this.i < len; this.i++) {
+      if (blankChar[this.content[this.i]]) {
+        this.handler.onAttrVal(this.content.substring(this.start, this.i));
+        break;
+      } else if (this.checkClose('onAttrVal')) return;
+    }
+
+  while (blankChar[this.content[++this.i]]) {
+    ;
+  }
+
+  if (this.i < len && !this.checkClose()) {
+    this.start = this.i;
+    this.state = this.attrName;
+  }
+};
+/**
+ * @description 结束标签状态
+ * @returns {String} 结束的标签名
+ * @private
+ */
+
+
+lexer.prototype.endTag = function () {
+  var c = this.content[this.i];
+
+  if (blankChar[c] || c == '>' || c == '/') {
+    this.handler.onCloseTag(this.content.substring(this.start, this.i));
+
+    if (c != '>') {
+      this.i = this.content.indexOf('>', this.i);
+      if (this.i == -1) return;
+    }
+
+    this.start = ++this.i;
+    this.state = this.text;
+  } else this.i++;
+};
+
+module.exports = parser;

+ 123 - 0
components/mpvue-echarts/src/echarts.vue

@@ -0,0 +1,123 @@
+<template>
+	<canvas v-if="canvasId" class="ec-canvas" :id="canvasId" :canvasId="canvasId" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" @error="error"></canvas>
+</template>
+
+<script>
+import WxCanvas from './wx-canvas';
+
+export default {
+	props: {
+		canvasId: {
+			type: String,
+			default: 'ec-canvas'
+		},
+		lazyLoad: {
+			type: Boolean,
+			default: false
+		},
+		disableTouch: {
+			type: Boolean,
+			default: false
+		},
+		throttleTouch: {
+			type: Boolean,
+			default: false
+		}
+	},
+	// #ifdef H5
+	mounted() {
+		if (!this.lazyLoad) this.init();
+	},
+	// #endif
+	// #ifndef H5
+	onReady() {
+		if (!this.lazyLoad) this.init();
+	},
+	// #endif
+	methods: {
+		setChart(chart){
+			this.chart = chart
+		},
+		init() {
+			const { canvasId } = this;
+			this.ctx = wx.createCanvasContext(canvasId, this);
+
+			this.canvas = new WxCanvas(this.ctx, canvasId);
+
+			const query = wx.createSelectorQuery().in(this);
+			query
+				.select(`#${canvasId}`)
+				.boundingClientRect(res => {
+					if (!res) {
+						setTimeout(() => this.init(), 50);
+						return;
+					}
+					this.$emit('onInit', {
+						width: res.width,
+						height: res.height
+					});
+				})
+				.exec();
+		},
+		canvasToTempFilePath(opt) {
+			const { canvasId } = this;
+			this.ctx.draw(true, () => {
+				wx.canvasToTempFilePath({
+					canvasId,
+					...opt
+				});
+			});
+		},
+		touchStart(e) {
+			const { disableTouch, chart } = this;
+			if (disableTouch || !chart || !e.mp.touches.length) return;
+			const touch = e.mp.touches[0];
+			chart._zr.handler.dispatch('mousedown', {
+				zrX: touch.x,
+				zrY: touch.y
+			});
+			chart._zr.handler.dispatch('mousemove', {
+				zrX: touch.x,
+				zrY: touch.y
+			});
+		},
+		touchMove(e) {
+			const { disableTouch, throttleTouch, chart, lastMoveTime } = this;
+			if (disableTouch || !chart || !e.mp.touches.length) return;
+
+			if (throttleTouch) {
+				const currMoveTime = Date.now();
+				if (currMoveTime - lastMoveTime < 240) return;
+				this.lastMoveTime = currMoveTime;
+			}
+
+			const touch = e.mp.touches[0];
+			chart._zr.handler.dispatch('mousemove', {
+				zrX: touch.x,
+				zrY: touch.y
+			});
+		},
+		touchEnd(e) {
+			const { disableTouch, chart } = this;
+			if (disableTouch || !chart) return;
+			const touch = e.mp.changedTouches ? e.mp.changedTouches[0] : {};
+			chart._zr.handler.dispatch('mouseup', {
+				zrX: touch.x,
+				zrY: touch.y
+			});
+			chart._zr.handler.dispatch('click', {
+				zrX: touch.x,
+				zrY: touch.y
+			});
+		}
+	}
+};
+</script>
+
+<style scoped>
+.ec-canvas {
+	width: 100%;
+	height: 100%;
+	flex: 1;
+}
+</style>

+ 73 - 0
components/mpvue-echarts/src/wx-canvas.js

@@ -0,0 +1,73 @@
+export default class WxCanvas {
+  constructor(ctx, canvasId) {
+    this.ctx = ctx;
+    this.canvasId = canvasId;
+    this.chart = null;
+
+    WxCanvas.initStyle(ctx);
+    this.initEvent();
+  }
+
+  getContext(contextType) {
+    return contextType === '2d' ? this.ctx : null;
+  }
+
+  setChart(chart) {
+    this.chart = chart;
+  }
+
+  attachEvent() {
+    // noop
+  }
+
+  detachEvent() {
+    // noop
+  }
+
+  static initStyle(ctx) {
+    const styles = ['fillStyle', 'strokeStyle', 'globalAlpha',
+      'textAlign', 'textBaseAlign', 'shadow', 'lineWidth',
+      'lineCap', 'lineJoin', 'lineDash', 'miterLimit', 'fontSize'];
+
+    styles.forEach((style) => {
+      Object.defineProperty(ctx, style, {
+        set: (value) => {
+          if ((style !== 'fillStyle' && style !== 'strokeStyle')
+            || (value !== 'none' && value !== null)
+          ) {
+            ctx[`set${style.charAt(0).toUpperCase()}${style.slice(1)}`](value);
+          }
+        },
+      });
+    });
+
+    ctx.createRadialGradient = () => ctx.createCircularGradient(arguments);
+  }
+
+  initEvent() {
+    this.event = {};
+    const eventNames = [{
+      wxName: 'touchStart',
+      ecName: 'mousedown',
+    }, {
+      wxName: 'touchMove',
+      ecName: 'mousemove',
+    }, {
+      wxName: 'touchEnd',
+      ecName: 'mouseup',
+    }, {
+      wxName: 'touchEnd',
+      ecName: 'click',
+    }];
+
+    eventNames.forEach((name) => {
+      this.event[name.wxName] = (e) => {
+        const touch = e.mp.touches[0];
+        this.chart._zr.handler.dispatch(name.ecName, {
+          zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
+          zrY: name.wxName === 'tap' ? touch.clientY : touch.y,
+        });
+      };
+    });
+  }
+}

+ 50 - 0
components/service-tab/service-tab.vue

@@ -0,0 +1,50 @@
+<template>
+	<view>
+		<view class="nav-two nav-ser">
+			<navigator url="/pages/scenic/scenic" hover-class="none" class="lis">景区</navigator>
+			<navigator url="" hover-class="none" class="lis">公共图书馆</navigator>
+			<navigator url="" hover-class="none" class="lis">旅行社</navigator>
+			<navigator url="" hover-class="none" class="lis">博物馆</navigator>
+			<navigator url="" hover-class="none" class="lis">星级饭店</navigator>
+			<navigator url="" hover-class="none" class="lis">重点文物</navigator>
+			<navigator url="" hover-class="none" class="lis">文化场馆</navigator>
+			<navigator url="" hover-class="none" class="lis">商演机构</navigator>
+			<navigator url="" hover-class="none" class="lis">体育场馆</navigator>
+			<navigator url="" hover-class="none" class="lis">演出活动</navigator>
+			<navigator url="" hover-class="none" class="lis">导游领队</navigator>
+			<navigator url="" hover-class="none" class="lis">非物质文化遗产</navigator>
+		</view>
+	</view>
+</template>
+
+<script>
+const app = getApp();
+export default {
+	data() {
+		return {};
+	},
+
+	components: {},
+	props: {},
+	watch: {},
+
+	mounted() {},
+
+	methods: {
+		jumpReLaunchUrl(url) {
+			uni.reLaunch({
+				url: url
+			});
+		},
+
+		jumpUrl(url) {
+			uni.navigateTo({
+				url: url
+			});
+		}
+	}
+};
+</script>
+<style>
+@import '/static/css/main.css';
+</style>

+ 35 - 0
components/travel-tab/travel-tab.vue

@@ -0,0 +1,35 @@
+<template>
+	<view>
+		<view class="nav-two">
+			<navigator url="/pages/route/route" hover-class="none" class="lis">文旅线路</navigator>
+			<navigator url="" hover-class="none" class="lis">热门景点</navigator>
+		</view>
+	</view>
+</template>
+
+<script>
+const app = getApp();
+export default {
+	data() {
+		return {};
+	},
+	components: {},
+	props: {},
+	mounted() {},
+	methods: {
+		jumpReLaunchUrl(url) {
+			uni.reLaunch({
+				url: url
+			});
+		},
+		jumpUrl(url) {
+			uni.navigateTo({
+				url: url
+			});
+		}
+	}
+};
+</script>
+<style>
+@import '/static/css/main.css';
+</style>

+ 211 - 0
components/uni-countdown/uni-countdown.vue

@@ -0,0 +1,211 @@
+<template>
+	<view class="uni-countdown">
+		<text v-if="showDay" :style="{ borderColor: borderColor, color: color, backgroundColor: backgroundColor }" class="uni-countdown__number">{{ d }}</text>
+		<text v-if="showDay" :style="{ color: splitorColor }" class="uni-countdown__splitor">天</text>
+		<text :style="{ borderColor: borderColor, color: color, backgroundColor: backgroundColor }" class="uni-countdown__number">{{ h }}</text>
+		<text :style="{ color: splitorColor }" class="uni-countdown__splitor">{{ showColon ? '时' : ':' }}</text>
+		<text :style="{ borderColor: borderColor, color: color, backgroundColor: backgroundColor }" class="uni-countdown__number">{{ i }}</text>
+		<text :style="{ color: splitorColor }" class="uni-countdown__splitor">{{ showColon ? '分' : ':' }}</text>
+		<text :style="{ borderColor: borderColor, color: color, backgroundColor: backgroundColor }" class="uni-countdown__number">{{ s }}</text>
+		<text v-if="!showColon" :style="{ color: splitorColor }" class="uni-countdown__splitor">秒</text>
+	</view>
+</template>
+<script>
+	/**
+	 * Countdown 倒计时
+	 * @description 倒计时组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=25
+	 * @property {String} backgroundColor 背景色
+	 * @property {String} color 文字颜色
+	 * @property {Number} day 天数
+	 * @property {Number} hour 小时
+	 * @property {Number} minute 分钟
+	 * @property {Number} second 秒
+	 * @property {Number} timestamp 时间戳
+	 * @property {Boolean} showDay = [true|false] 是否显示天数
+	 * @property {Boolean} showColon = [true|false] 是否以冒号为分隔符
+	 * @property {String} splitorColor 分割符号颜色
+	 * @event {Function} timeup 倒计时时间到触发事件
+	 * @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown>
+	 */
+	export default {
+		name: 'UniCountdown',
+		props: {
+			showDay: {
+				type: Boolean,
+				default: true
+			},
+			showColon: {
+				type: Boolean,
+				default: true
+			},
+			backgroundColor: {
+				type: String,
+				default: '#FFFFFF'
+			},
+			borderColor: {
+				type: String,
+				default: '#000000'
+			},
+			color: {
+				type: String,
+				default: '#000000'
+			},
+			splitorColor: {
+				type: String,
+				default: '#000000'
+			},
+			day: {
+				type: Number,
+				default: 0
+			},
+			hour: {
+				type: Number,
+				default: 0
+			},
+			minute: {
+				type: Number,
+				default: 0
+			},
+			second: {
+				type: Number,
+				default: 0
+			},
+			timestamp: {
+				type: Number,
+				default: 0
+			}
+		},
+		data() {
+			return {
+				timer: null,
+				syncFlag: false,
+				d: '00',
+				h: '00',
+				i: '00',
+				s: '00',
+				leftTime: 0,
+				seconds: 0
+			}
+		},
+		watch: {
+			day(val) {
+				this.changeFlag()
+			},
+			hour(val) {
+				this.changeFlag()
+			},
+			minute(val) {
+				this.changeFlag()
+			},
+			second(val) {
+				this.changeFlag()
+			}
+		},
+		created: function(e) {
+			this.startData();
+		},
+		beforeDestroy() {
+			clearInterval(this.timer)
+		},
+		methods: {
+			toSeconds(timestamp, day, hours, minutes, seconds) {
+				if (timestamp) {
+					return timestamp - parseInt(new Date().getTime() / 1000, 10)
+				}
+				return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds
+			},
+			timeUp() {
+				clearInterval(this.timer)
+				this.$emit('timeup')
+			},
+			countDown() {
+				let seconds = this.seconds
+				let [day, hour, minute, second] = [0, 0, 0, 0]
+				if (seconds > 0) {
+					day = Math.floor(seconds / (60 * 60 * 24))
+					hour = Math.floor(seconds / (60 * 60)) - (day * 24)
+					minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
+					second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
+				} else {
+					this.timeUp()
+				}
+				if (day < 10) {
+					day = '0' + day
+				}
+				if (hour < 10) {
+					hour = '0' + hour
+				}
+				if (minute < 10) {
+					minute = '0' + minute
+				}
+				if (second < 10) {
+					second = '0' + second
+				}
+				this.d = day
+				this.h = hour
+				this.i = minute
+				this.s = second
+			},
+			startData() {
+				this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
+				if (this.seconds <= 0) {
+					return
+				}
+				this.countDown()
+				clearInterval(this.timer)
+				this.timer = setInterval(() => {
+					this.seconds--
+					if (this.seconds < 0) {
+						this.timeUp()
+						return
+					}
+					this.countDown()
+				}, 1000)
+			},
+			changeFlag() {
+				if (!this.syncFlag) {
+					this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
+					this.startData();
+					this.syncFlag = true;
+				}
+			}
+		}
+	}
+</script>
+<style scoped>
+	.uni-countdown {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: flex-start;
+		padding: 2rpx 0;
+	}
+
+	.uni-countdown__splitor {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		line-height: 35rpx;
+		font-size: 20rpx;
+	}
+
+	.uni-countdown__number {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		width: 35rpx;
+		height: 35rpx;
+		line-height: 35rpx;
+		margin: 5rpx;
+		text-align: center;
+		font-size: 20rpx;
+		border-radius: 6rpx;
+		
+	}
+</style>

+ 18 - 0
main.js

@@ -0,0 +1,18 @@
+import Vue from 'vue'
+import App from './App'
+import Header from './components/header/index'
+import Foot from './components/foot/index'
+import LeftNav from './components/left-nav/index'
+
+Vue.config.productionTip = false
+
+Vue.component('Headers', Header)
+Vue.component('Foot', Foot)
+Vue.component('Left-nav', LeftNav)
+
+App.mpType = 'app'
+
+const app = new Vue({
+    ...App
+})
+app.$mount()

+ 78 - 0
manifest.json

@@ -0,0 +1,78 @@
+{
+    "name" : "就培云考试系统",
+    "appid" : "__UNI__46C6092",
+    "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" : "",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "h5" : {
+        "title" : "就培云考试系统",
+        "router" : {
+            "mode" : "history"
+        },
+        "domain" : "qyfw.tongyu99.com"
+    }
+}

+ 17 - 0
package.json

@@ -0,0 +1,17 @@
+{
+    "id": "circle-progress-bar",
+    "name": "圆形进度条(纯Css)",
+    "version": "1.0.0",
+    "description": "纯css圆形进度条,不用担心canvas的兼容和各种问题啦",
+    "keywords": [
+        "圆形",
+        "圆形进度条",
+        "进度条"
+    ],
+    "dcloudext": {
+        "category": [
+            "前端组件",
+            "通用组件"
+        ]
+    }
+}

+ 48 - 0
pages.json

@@ -0,0 +1,48 @@
+{
+	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+		{
+			"path": "pages/index/index",
+			"style": {
+				"navigationBarTitleText": "就培云考试系统"
+			}
+		},
+		{
+			"path": "pages/login/login",
+			"style": {
+				"navigationBarTitleText": "就培云考试系统"
+			}
+		},
+		{
+			"path": "pages/test/test",
+			"style": {
+				"navigationBarTitleText": "就培云考试系统"
+			}
+		},
+		{
+			"path": "pages/scoreQuery/scoreQuery",
+			"style": {
+				"navigationBarTitleText": "就培云考试系统"
+			}
+		},
+		{
+			"path": "pages/certificateQuery/certificateQuery",
+			"style": {
+				"navigationBarTitleText": "证书查询系统"
+			}
+		},
+		{
+			"path": "pages/certificateDetail/certificateDetail",
+			"style": {
+				"navigationBarTitleText": "证书查询系统"
+			}
+		}
+		
+    ],
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "就培云考试系统",
+		"navigationBarBackgroundColor": "#F8F8F8",
+		"backgroundColor": "#F8F8F8",
+		"navigationStyle": "custom"
+	}
+}

+ 179 - 0
pages/certificateDetail/certificateDetail.css

@@ -0,0 +1,179 @@
+.project {
+	height: 70px;
+	line-height: 70px;
+	background: #1AA1E6;
+	font-size: 24px;
+	color: #FFFFFF;
+	font-weight: bold;
+}
+
+.project-content {
+	margin: 30px 0;
+	justify-content: center;
+	align-items: stretch;
+}
+
+/* 考试 */
+.test-box {
+	width: 890px;
+	/* min-height: 812px; */
+	background: #FFFFFF;
+	border-radius: 0px 0px 0px 0px;
+	opacity: 1;
+	border: 3px solid #FFFFFF;
+	position: relative;
+	padding: 30px;
+	box-sizing: border-box;
+}
+
+.test-title {
+	font-size: 18px;
+	font-family: Source Han Sans CN-Bold, Source Han Sans CN;
+	font-weight: bold;
+	color: #1AA1E6;
+	line-height: 36px;
+	text-align: center;
+}
+
+.table {
+	font-size: 16px;
+	align-items: flex-start;
+	margin-top: 30px;
+}
+
+.border {
+	border: 1px solid #DEDEDE;
+}
+
+.border-right {
+	border-right: 1px solid #DEDEDE;
+}
+
+.border-right-none {
+	border-right: none;
+}
+
+.border-bottom {
+	border-bottom: 1px solid #DEDEDE;
+}
+
+.border-bottom-none {
+	border-bottom: none;
+}
+
+.border-top-none {
+	border-top: none;
+}
+
+.padding-left {
+	padding-left: 10px
+}
+
+.height56 {
+	height: 56px;
+	box-sizing: border-box;
+}
+
+.width140 {
+	width: 140px;
+	box-sizing: border-box;
+}
+
+.width200 {
+	width: 200px;
+	box-sizing: border-box;
+}
+
+.text-center {
+	text-align: center;
+}
+
+.ddflex-jc {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.bg-color {
+	background: #F5F5F5;
+}
+
+.test-info {
+	width: 280px;
+	flex-direction: column;
+	margin-left: 30px;
+}
+
+/* 考试信息 */
+.test-people {
+	width: 100%;
+	background-color: #FFFFFF;
+	padding: 12px 11px;
+	box-sizing: border-box;
+}
+
+.test-people image {
+	width: 80px;
+	height: 89px;
+	margin-right: 19px;
+}
+
+.test-people-info {
+	flex-direction: column;
+	justify-content: space-between;
+	font-size: 14px;
+	flex: 1;
+	align-items: flex-start;
+}
+
+.test-people-label {
+	color: #999999;
+	line-height: 36px;
+	margin-right: 8px;
+}
+
+/* 考试公告 */
+.note-box {
+	width: 100%;
+	background-color: #FFFFFF;
+	padding: 20px;
+	box-sizing: border-box;
+	margin-top: 20px;
+}
+
+.note-title {
+	margin-bottom: 18px;
+	font-size: 16px;
+}
+
+.note-title-icon {
+	width: 18px;
+	height: 18px;
+	margin-right: 10px;
+}
+
+.note-item {
+	justify-content: space-between;
+	font-size: 12px;
+	font-weight: 400;
+	line-height: 30px;
+	font-family: Source Han Sans CN-Regular, Source Han Sans CN;
+	cursor: pointer;
+}
+
+.note-item-content {
+	color: #666666;
+	flex: 1;
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	margin-right: 10px;
+}
+
+.note-item-content:hover {
+	text-decoration: underline #666666;
+}
+
+.note-item-date {
+	color: #999999;
+}

+ 178 - 0
pages/certificateDetail/certificateDetail.vue

@@ -0,0 +1,178 @@
+<template>
+	<view>
+		<Headers></Headers>
+		<view class="project">
+			<view style="width: 1200px;margin: auto;">证书查询系统</view>
+		</view>
+		
+		<view class="project-content ddflex">
+			<!-- 成绩区域 -->
+			<view class="test-box">
+				<view class="test-title">二手车鉴定评估师证书查询结果</view>
+				<!-- 表格 -->
+				<view class="ddflex border table" style="">
+					<!-- 左边 -->
+					<view>
+						<view class="height56 ddflex-jc width140 bg-color border-bottom">姓&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;名</view>
+						<view class="height56 ddflex-jc width140 bg-color border-bottom">性&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;别</view>
+						<view class="height56 ddflex-jc width140 bg-color border-bottom">身份证号</view>
+						<view class="height56 ddflex-jc width140 bg-color border-bottom">培训工种</view>
+						<view class="height56 ddflex-jc width140 bg-color border-bottom">培训学校</view>
+						<view class="height56 ddflex-jc width140 bg-color border-bottom">办学编号</view>
+						<view class="height56 ddflex-jc width140 bg-color border-bottom">证书编号</view>
+						<view class="height56 ddflex-jc width140 bg-color border-bottom">培训结论</view>
+						<view class="height56 ddflex-jc width140 bg-color">发证日期</view>
+					</view>
+					<!-- 右边 -->
+					<view class="fflex">
+						<view class="dflex" style="align-items: stretch;">
+							<view>
+								<view class="height56 ddflex-jc border border-right-none border-top-none">李田</view>
+								<view>
+									<view class="ddflex">
+										<view class="height56 ddflex-jc width200 border border-bottom-none border-right-none border-top-none">男</view>
+										<view class="height56 ddflex-jc width140 bg-color border border-bottom-none border-right-none border-top-none">出生日期</view>
+										<view class="height56 ddflex-jc width140 border border-bottom-none border-right-none border-top-none">1998-05-26</view>
+									</view>
+									<view class="ddflex">
+										<view class="height56 ddflex-jc width200 border border-bottom-none border-right-none">430981199805268500</view>
+										<view class="height56 ddflex-jc width140 bg-color border border-bottom-none border-right-none">培训时间</view>
+										<view class="height56 ddflex-jc width140 border border-bottom-none border-right-none">2021-03-10</view>
+									</view>
+									<view class="ddflex">
+										<view class="height56 ddflex-jc width200 border border-right-none">二手车鉴定评估师</view>
+										<view class="height56 ddflex-jc width140 bg-color border border-right-none">培训等级</view>
+										<view class="height56 ddflex-jc width140 border border-right-none">高</view>
+									</view>
+								</view>
+							</view>
+							<view class="border fflex border-right-none border-top-none" style="box-sizing: border-box;padding: 20px;">
+								<image style="width: 100%;" src="https://img.tongyu99.com/IMAGE-198/20230106/5a473e98b1c643c385558c7ecf8871b1.png" mode="widthFix"></image>
+							</view>
+						</view>
+						<view class="height56 border ddflex border-top-none border-right-none padding-left">
+							湖南现代职业培训学校
+						</view>
+						<view class="height56 border ddflex border-top-none border-right-none padding-left">
+							1800003000182
+						</view>
+						<view class="height56 border ddflex border-top-none border-right-none padding-left">
+							210318546464654
+						</view>
+						<view class="height56 border ddflex border-top-none border-right-none padding-left">
+							成绩合格
+						</view>
+						<view class="height56 border ddflex border-top-none border-right-none padding-left border-bottom-none">
+							2022-09-07
+						</view>
+					</view>
+				</view>
+				<!-- 声明 -->
+				<view style="margin-top: 34px;">
+					<view style="font-size: 16px;font-weight: bold;">声明:</view>
+					<view style="font-size: 14px;line-height: 30px">
+						1、未经证书信息权属人同意,不得将本材料用于违背权属人意愿之用途。证书信息内容标注“*”号,表示该项内容不详。证书信息如有修改,请以网站在线查询内容为准。<br>
+						2、本材料是打印的证书查询结果凭证,仅供查询人使用,不具有再验证功能。
+					</view>
+				</view>
+			</view>
+			<!-- 答题卡区域 -->
+			<view class="test-info ddflex">
+				<view class="note-box">
+					<view class="note-title ddflex">
+						<image class="note-title-icon" src="/static/images/wzgg.png"></image>
+						<view>网站提醒</view>
+					</view>
+					<view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">谨防证书售假骗局</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">获取证书没有捷径,防止上当受骗</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+					</view>
+				</view>
+				<!-- 学习资料 -->
+				<view class="note-box">
+					<view class="note-title ddflex">
+						<image class="note-title-icon" src="/static/images/xxzl.png"></image>
+						<view>学习资料</view>
+					</view>
+					<view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">二手车评估师考试题库</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">中国汽车保值率研究报告</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">关于《职业技能等级标准开发指南(征求意</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">提升学历选哪个专业好?选错了专业后悔一</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">怎样鉴别事故车?教你几招快速鉴定</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+					</view>
+				</view>
+				<!-- 常见问题 -->
+				<view class="note-box">
+					<view class="note-title ddflex">
+						<image class="note-title-icon" src="/static/images/cjwt.png"></image>
+						<view>常见问题</view>
+					</view>
+					<view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">哪种电工证比较重要?</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">二手车评估师怎么考?考什么内容?</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">汽车维修工证书怎么考?</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">零基础考电工证要多久?电工证难考吗?</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">二手车鉴定评估师是哪里颁发证书</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		
+		<Foot></Foot>
+	</view>
+</template>
+
+
+<script>
+	export default {
+		data() {
+			return {
+			}
+		},
+		onReady() {},
+		methods: {
+		}
+	}
+
+</script>
+
+<style>
+	@import url('./certificateDetail.css');
+</style>

+ 75 - 0
pages/certificateQuery/certificateQuery.css

@@ -0,0 +1,75 @@
+.top-bg {
+	width: 100%;
+	z-index: 1;
+}
+
+.bottom_bg {
+	width: 100%;
+	position: fixed;
+	bottom: 50px;
+}
+
+.content-box {
+	z-index: 1;
+	justify-content: center;
+	margin-top: 60px;
+	position: relative;
+	margin-bottom: 80px;
+}
+
+.re-item {
+	margin-bottom: 20px;
+	margin-left: -100px;
+}
+
+.re-label {
+	font-size: 18px;
+	margin-right: 28px;
+}
+
+.re-li {
+	width: 355px;
+	height: 42px;
+	border: 1px solid #D8DCE6;
+	border-radius: 4px;
+	padding: 0 17px;
+	box-sizing: border-box;
+}
+
+.note {
+	justify-content: center;
+}
+
+.note image {
+	width: 16px;
+	height: 16px;
+	margin-right: 10px;
+}
+.note text {
+	font-size: 14px;
+}
+.query-btn{
+	width: 353px;
+	height: 42px;
+	line-height: 42px;
+	background: #1AA1E6;
+	border-radius: 5px 5px 5px 5px;
+	opacity: 1;
+	color: #fff;
+	text-align: center;
+	font-size: 16px;
+	margin: 27px 0 0 0;
+	cursor: pointer;
+}
+.link-btn{
+	background: #FFFFFF;
+	border-radius: 10px 10px 10px 10px;
+	opacity: 1;
+	padding: 10px 30px;
+	font-size: 16px;
+	margin-right: 20px;
+	cursor: pointer;
+}
+.link-btn:last-child{
+	margin-right: 0px;
+}

+ 70 - 0
pages/certificateQuery/certificateQuery.vue

@@ -0,0 +1,70 @@
+<template>
+	<view style="position: relative;">
+		<Headers></Headers>
+		
+		<image class="top-bg" src="/static/images/certificate_top_bg.png" mode="widthFix"></image>
+		
+		<view class="content-box ddflex">
+			<view>
+				<view class="ddflex re-item">
+					<view class="re-label">姓&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;名</view>
+					<view class="re-li dflex">
+						<input v-model="testNumber" type="number" placeholder="姓名" maxlength="11" placeholder-class="placeholder" class="re-ipt flex" />
+					</view>
+				</view>
+				<view class="ddflex re-item">
+					<view class="re-label">证书编号</view>
+					<view class="re-li dflex">
+						<input v-model="testNumber" type="number" placeholder="证书编号" maxlength="11" placeholder-class="placeholder" class="re-ipt flex" />
+					</view>
+				</view>
+				<view class="ddflex re-item">
+					<view class="re-label">身份证号</view>
+					<view class="re-li dflex">
+						<input v-model="testNumber" type="number" placeholder="身份证号" maxlength="11" placeholder-class="placeholder" class="re-ipt flex" />
+					</view>
+				</view>
+				<view class="note ddflex">
+					<image src="/static/images/note.png"></image>
+					<text>任意输入以上两项内容即可查询</text>
+				</view>
+				<view class="query-btn" @click="query">
+					立即查询
+				</view>
+			</view>
+		</view>
+		
+		<view class="ddflex" style="z-index: 1;position: relative;justify-content: center;text-align: center;margin-bottom: 60px;padding: 30px;">
+			<view>
+				<view>
+					第三方证书查询平台
+				</view>
+				<view class="ddflex" style="justify-content: center;margin-top: 18px">
+					<view class="link-btn" v-for="item in 6">国家职业资格证书查询</view>
+				</view>
+			</view>
+		</view>
+		<image class="bottom_bg" src="/static/images/certificate_bottom_bg.png" mode="widthFix"></image>
+		<Foot></Foot>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+			}
+		},
+		methods: {
+			query(){
+				uni.navigateTo({
+					url:'/pages/certificateDetail/certificateDetail'
+				})
+			}
+		}
+	}
+</script>
+
+<style>
+	@import url('./certificateQuery.css');
+</style>

+ 0 - 0
pages/index/index.css


+ 200 - 0
pages/index/index.vue

@@ -0,0 +1,200 @@
+<template>
+	<view>
+		<Headers></Headers>
+		<view class="content wrap dflex">
+			<Left-nav currentTab="index"></Left-nav>
+			<view class="right">
+				<view class="c-title">概况</view>
+				<view class="idx-nav dflex">
+					<navigator url="/pages/declareHonor/declareHonor" hover-class="none" class="li"><image src="../../static/images/sy_honor.png"></image></navigator>
+					<navigator url="/pages/declareFunds/declareFunds" hover-class="none" class="li"><image src="../../static/images/sy_declare.png"></image></navigator>
+				</view>
+				<view class="c-box hb-box">
+					<view class="sj-tits dflex">
+						<view class="flex">文旅红榜</view>
+						<navigator url="/pages/boardContent/boardContent" hover-class="none" class="sj-more">查看全部</navigator>
+					</view>
+					<view class="hb-list dflex">
+						<view v-if="index <= 5" v-for="(item, index) in moneyDeclareList" :key="index" @click="jumpUrl('/pages/content/content?id=' + item.id)" class="li dflex">
+							<image :src="'../../static/images/bdico' + getRandom() + '.png'"></image>
+							<view class="flex">
+								<view class="hb-tit tover">{{ item.title }}</view>
+								<view class="hb-bri tover">{{ removeHtmlStyle(item.text) }}</view>
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="c-box gk-info dflex">
+					<view class="li dflex">
+						<image src="../../static/images/idxico1.png"></image>
+						<view>
+							<text>累计营收</text>
+							¥{{ indexData.money ? indexData.money : '0.00' }}
+						</view>
+					</view>
+					<view class="li dflex">
+						<image src="../../static/images/idxico2.png"></image>
+						<view>
+							<text>累计客流量</text>
+							{{ indexData.person ? indexData.person : 0 }}
+						</view>
+					</view>
+					<view class="li dflex" @click="jumpUrl('/pages/personal/personal')">
+						<image src="../../static/images/idxico3.png"></image>
+						<view>
+							<text>人力资源</text>
+							{{ indexData.humanResources ? indexData.humanResources : 0 }}
+						</view>
+					</view>
+					<view class="li dflex" @click="jumpUrl('/pages/materials/materials')">
+						<image src="../../static/images/idxico4.png"></image>
+						<view>
+							<text>物资资源</text>
+							{{ indexData.material ? indexData.material : 0 }}
+						</view>
+					</view>
+					<view class="li dflex" @click="jumpUrl('/pages/complaint/complaint')">
+						<image src="../../static/images/idxico5.png"></image>
+						<view>
+							<text>累计投诉</text>
+							{{ indexData.complaint ? indexData.complaint : 0 }}
+						</view>
+					</view>
+				</view>
+				<view class="c-box sy-box">
+					<view class="sj-tit">营收额</view>
+					<view class="sye">
+						<view class="canvasView">
+							<!-- :echartsH5="true" :echartsApp="true" -->
+							<qiun-data-charts
+								type="line"
+								:chartData="Line"
+								:opts="{
+									legend: {
+										show: false
+									},
+									yAxis: {
+										showTitle: true,
+										data: [{ title: '单位(元)', titleOffsetY: -8 }]
+									}
+								}"
+							/>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<Foot></Foot>
+	</view>
+</template>
+<script>
+const app = getApp();
+const req = require('../../utils/request.js');
+const utils = require('../../utils/util.js');
+export default {
+	data() {
+		return {
+			indexData: '',
+			Line: {},
+			form: {
+				page: 1,
+				limit: 10
+			},
+			moneyDeclareList: []
+		};
+	},
+	onLoad() {
+		this.getHongBList();
+	},
+
+	onShow() {
+		let userInfo = req.getStorage('userInfo');
+		if (userInfo.type!=1&&userInfo.institutionState != 2) {
+			uni.navigateTo({
+				url: '/pages/company/company'
+			});
+		}
+		if(userInfo.type==1){
+			uni.navigateTo({
+				url: '/pages/learn/learn'
+			});
+			return 
+		}
+		this.getData();
+	},
+
+	methods: {
+		jumpUrl(url) {
+			uni.navigateTo({
+				url: url
+			});
+		},
+
+		removeHtmlStyle(text) {
+			var str = '';
+			if (text) {
+				str = utils.removeHtml(text);
+			}
+			return str;
+		},
+
+		getRandom() {
+			return parseInt(Math.random() * 3 + 1);
+		},
+
+		getHongBList() {
+			var formP = this.form;
+			formP.code = 'wenlvhonbang';
+			return new Promise((resolve, reject) => {
+				req.getRequest('/api/v3/content/page', formP, data => {
+					//资金申报公告
+					this.moneyDeclareList = data.list;
+					resolve();
+				});
+			});
+		},
+
+		getData() {
+			req.getRequest('/api/v3/hy/indexData/get', {}, data => {
+				this.indexData = data;
+				if (data.monitors && data.monitors.length > 0) {
+					this.Line = this.setStyleLine(data.monitors);
+				}
+			});
+		},
+
+		setStyleLine(data) {
+			var line = {};
+			if (data && data.length > 0) {
+				//获取时间轴数据;
+				line.categories = data.map(it => {
+					return it.name;
+				});
+				line.series = [];
+				var seriesItem = {};
+				var list = data.map(itx => {
+					return itx.value;
+				});
+				seriesItem.name = '';
+				seriesItem.data = list;
+				line.series.push(seriesItem);
+			}
+			return line;
+		}
+	}
+};
+</script>
+
+<style>
+.ec-canvas {
+	display: flex;
+	width: 100%;
+	height: 100%;
+	flex: 1;
+}
+.canvasView {
+	width: 100%;
+	margin-top: 30rpx;
+	height: 100%;
+}
+</style>

+ 259 - 0
pages/login/login.css

@@ -0,0 +1,259 @@
+.login {
+	width: 100%;
+	min-height: 100vh;
+	position: relative;
+}
+
+.bg {
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+}
+
+/* 注册登录 */
+.register {
+	background: #fff;
+	margin: 60px auto 0;
+	padding: 5px 110px;
+	position: relative;
+	border-radius: 40px;
+	position: relative;
+	width: 1200px;
+	box-sizing: border-box;
+}
+
+.re-con-pic {
+	position: relative;
+}
+
+.re-con-pic-title {
+	position: absolute;
+	top: 40px;
+	left: 60px;
+	font-size: 36px;
+	font-family: zihun143-zhengkuchaojihei-Regular, zihun143-zhengkuchaojihei;
+	font-weight: 400;
+	color: #1AA1E6;
+	z-index: 1;
+}
+
+.re-con-pic image {
+	width: 500px;
+	height: 500px;
+}
+
+.re-tit {
+	font-size: 24px;
+	color: #1AA1E6;
+	text-align: center;
+	font-weight: bold;
+	margin-bottom: 30rpx;
+}
+
+.re-con {
+	margin: 20px auto 0;
+	margin-left: 120px;
+}
+
+.re-li {
+	width: 260px;
+	height: 42px;
+	border: 1px solid #D8DCE6;
+	border-radius: 4px;
+	padding: 0 17px;
+	margin-bottom: 20px;
+	box-sizing: border-box;
+}
+
+/deep/.re-con .uni-select {
+	width: 260px;
+	height: 42px;
+	border: 1px solid #D8DCE6;
+	border-radius: 4px;
+	padding: 0 17px;
+	font-size: 14px;
+	color: #333;
+}
+
+/deep/.re-con .uni-select__input-placeholder {
+	font-size: 14px;
+	color: #909399;
+}
+
+.sjico {
+	width: 10px;
+	height: 15px;
+	margin-right: 11px;
+}
+
+.placeholder {
+	color: #909399;
+}
+
+.re-ipt {
+	font-size: 14px;
+	color: #333;
+	line-height: 34px;
+}
+
+.re-li-yzm {
+	width: 320px;
+	height: 36px;
+	padding: 0;
+	border: none;
+	justify-content: space-between;
+}
+
+.re-li-yzm .re-ipt {
+	width: 164px;
+	height: 34px;
+	border-radius: 4px;
+	padding: 0 17px;
+	border: 1px solid #D8DCE6;
+}
+
+.send {
+	width: 103px;
+	height: 34px;
+	border: 1px solid var(--main);
+	border-radius: 4px;
+	font-size: 14px;
+	color: var(--main);
+	text-align: center;
+	line-height: 34px;
+	cursor: pointer;
+}
+
+.send.gray {
+	color: #999;
+	border-color: #999;
+	cursor: default;
+}
+
+.re-btn {
+	width: 260px;
+	height: 42px;
+	background: #1AA1E6;
+	border-radius: 21px 21px 21px 21px;
+	font-size: 16px;
+	color: #fff;
+	text-align: center;
+	line-height: 42px;
+	margin-top: 30px;
+	cursor: pointer;
+}
+
+.re-btn-text {
+	width: 260px;
+	height: 20px;
+	font-size: 14px;
+	font-family: Source Han Sans CN-Regular, Source Han Sans CN;
+	font-weight: 400;
+	color: #1AA1E6;
+	text-align: center;
+	cursor: pointer;
+	margin-top: 20px;
+}
+
+.re-bot {
+	background: #EBEBEB;
+	height: 44px;
+	font-size: 14px;
+	color: #666;
+	padding: 0 40px;
+	line-height: 44px;
+	justify-content: space-between;
+	position: absolute;
+	left: 0;
+	right: 0;
+	bottom: 0;
+}
+
+.nowu navigator {
+	color: var(--main);
+}
+
+.re-check {
+	zoom: .5;
+	margin-right: 4px;
+}
+
+.yzm-box {
+	width: 115px;
+	height: 36px;
+	border-radius: 4px;
+	background: #B7B7B7;
+}
+
+.change-tab {
+	text-align: center;
+	margin: 10px 0;
+}
+
+.change-tab-item {
+	border: 1px solid #eeeeee;
+	padding: 5px 0px;
+}
+
+.change-tab .active {
+	border: 1px solid var(--main);
+}
+
+
+.bottom-content {
+	z-index: 1;
+	justify-content: space-between;
+	margin-top: 30px;
+	width: 1200px;
+	box-sizing: border-box;
+}
+
+/* 考试公告 */
+.note-box {
+	width: 580px;
+	height: 150px;
+	background: #FFFFFF;
+	border-radius: 20px 20px 20px 20px;
+	border: 3px solid #FFFFFF;
+	padding: 16px 30px;
+	box-sizing: border-box;
+}
+
+.note-title {
+	margin-bottom: 18px;
+	font-size: 16px;
+}
+
+.note-title-icon {
+	width: 18px;
+	height: 18px;
+	margin-right: 10px;
+}
+
+.note-item {
+	justify-content: space-between;
+	font-size: 12px;
+	font-weight: 400;
+	line-height: 24px;
+	font-family: Source Han Sans CN-Regular, Source Han Sans CN;
+	cursor: pointer;
+}
+
+.note-item-content {
+	color: #666666;
+	flex: 1;
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	margin-right: 10px;
+}
+
+.note-item-content:hover {
+	text-decoration: underline #666666;
+}
+
+.note-item-date {
+	color: #999999;
+}

+ 257 - 0
pages/login/login.vue

@@ -0,0 +1,257 @@
+<template>
+	<view class="login">
+		<Headers></Headers>
+		<image class="bg" src="/static/images/bg.png"></image>
+		<view class="ddflex" style="flex-direction: column;">
+			<view class="register ddflex">
+				<view class="re-con-pic">
+					<view class="re-con-pic-title">在线考试系统</view>
+					<image src="/static/images/loginBg.png"></image>
+				</view>
+				<view class="re-con">
+					<view class="re-tit">考生登录</view>
+					<view class="re-li dflex">
+						<!-- <image src="../../static/images/sjico.png" class="sjico"></image> -->
+						<input v-model="testNumber" type="number" placeholder="准考证号" maxlength="11" placeholder-class="placeholder" class="re-ipt flex" />
+					</view>
+					<uni-data-select
+					      v-model="password"
+					      :localdata="range"
+					      @change="changeTestPro"
+						  placeholder="考试项目"
+					    ></uni-data-select>
+					<!-- <view class="re-li re-li-yzm dflex">
+						<input v-model="code" maxlength="4" placeholder="请输入验证码" placeholder-class="placeholder" class="re-ipt" />
+						<view class="yzm-box" @click="refresh()"><canvas :style="{ width: width + 'px', height: height + 'px' }" canvas-id="imgcanvas"></canvas></view>
+					</view> -->
+					<view class="re-btn" @click="okLogin()">登录</view>
+					<view class="re-btn-text">考生成绩查询</view>
+				</view>
+			</view>
+			<view class="bottom-content ddflex">
+				<!-- 考试公告 -->
+				<view class="note-box">
+					<view class="note-title ddflex">
+						<image class="note-title-icon" src="/static/images/ksgg.png"></image>
+						<view>考试公告</view>
+					</view>
+					<view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">2022年“技能+学历”双证教育班培训简章2022年“技能+学历”双证教育班培训简章2022年“技能+学历”双证教育班培训简章</view>
+							<view class="note-item-date">2022-08-25</view>
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">2022年“技能+学历”双证教育班培训简章</view>
+							<view class="note-item-date">2022-08-25</view>
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">2022年“技能+学历”双证教育班培训简章</view>
+							<view class="note-item-date">2022-08-25</view>
+						</view>
+					</view>
+				</view>
+				<!-- 注意事项 -->
+				<view class="note-box">
+					<view class="note-title ddflex">
+						<image class="note-title-icon" src="/static/images/zysx.png"></image>
+						<view>注意事项</view>
+					</view>
+					<view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">2022年“技能+学历”双证教育班培训简章2022年“技能+学历”双证教育班培训简章2022年“技能+学历”双证教育班培训简章</view>
+							<view class="note-item-date">2022-08-25</view>
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">2022年“技能+学历”双证教育班培训简章</view>
+							<view class="note-item-date">2022-08-25</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<Foot :havaBackground='false'></Foot>
+	</view>
+</template>
+
+<script>
+const app = getApp();
+const req = require('../../utils/request.js');
+const utils = require('../../utils/util.js');
+export default {
+	data() {
+		return {
+			title: 'Hello',
+			width: 115,
+			height: 36,
+			testNumber: '',
+			password: '',
+			code: '',
+			isCheckArg: true,
+			range:[
+				{ value: 0, text: "考试项目1" },
+				{ value: 1, text: "考试项目2" },
+				{ value: 2, text: "考试项目3" }
+			]
+		};
+	},
+	onLoad() {
+		var tha = this;
+		setTimeout(function() {
+			tha.initCode();
+		}, 200);
+	},
+	methods: {
+		changeEnv() {
+			// this.isCheckArg = !this.isCheckArg;
+		},
+		
+		// 考试下拉框
+		changeTestPro(e){
+			console.log("e:", e);
+		},
+
+		okLogin() {
+			uni.reLaunch({
+				url: '/pages/test/test'
+			});
+			return false
+			
+			
+			if (!this.testNumber) {
+				return req.msg('请输入准考证号');
+			}
+			if (!this.password) {
+				return req.msg('请输入密码');
+			}
+			if (!this.code) {
+				return req.msg('请输入验证码');
+			}
+			var imgCode = uni.getStorageSync('imgcode');
+			if (this.code.toUpperCase() != imgCode.toUpperCase()) {
+				req.msg('请输入正确的验证码');
+				this.initCode();
+				return;
+			}
+			var formP = {
+				account: this.mobile,
+				password: this.password
+			};
+			req.postRequest('/api/v3/hy/account/pwdLogin', formP, data => {
+				this.getUserInfo();
+			});
+		},
+
+		getUserInfo() {
+			req.getRequest(
+				'/api/v3/hy/account/userInfo',
+				{},
+				data => {
+					req.setStorage('userInfo', data);
+					if(data.type==1||data.isStaff){
+						uni.reLaunch({
+							url: '/pages/learn/learn'
+						});
+					}else{
+						uni.reLaunch({
+							url: '/pages/index/index'
+						});
+					}
+				},
+				true
+			);
+		},
+
+		initCode() {
+			console.log('start');
+			var context = uni.createCanvasContext('imgcanvas', this),
+				w = this.width,
+				h = this.height;
+			context.setFillStyle('white');
+			context.setLineWidth(5);
+			context.fillRect(0, 0, w, h);
+			var pool = [
+					'A',
+					'B',
+					'C',
+					'D',
+					'E',
+					'F',
+					'G',
+					'H',
+					'I',
+					'J',
+					'K',
+					'L',
+					'I',
+					'M',
+					'N',
+					'O',
+					'P',
+					'Q',
+					'R',
+					'S',
+					'T',
+					'U',
+					'V',
+					'W',
+					'S',
+					'Y',
+					'Z',
+					'1',
+					'2',
+					'3',
+					'4',
+					'5',
+					'6',
+					'7',
+					'8',
+					'9',
+					'0'
+				],
+				str = '';
+			for (var i = 0; i < 4; i++) {
+				var c = pool[this.rn(0, pool.length - 1)]; //随机的字
+				var deg = this.rn(-30, 30); //字体的旋转角度
+				context.setFontSize(18);
+				context.setTextBaseline('top');
+				context.setFillStyle(this.rc(80, 150));
+				context.save();
+				context.translate(30 * i + 15, parseInt(h / 1.5));
+				context.rotate((deg * Math.PI) / 180);
+				context.fillText(c, -15 + 5, -15);
+				context.restore();
+				str += c;
+			}
+			uni.setStorage({
+				key: 'imgcode',
+				data: str
+			});
+			for (var i = 0; i < 40; i++) {
+				context.beginPath();
+				context.arc(this.rn(0, w), this.rn(0, h), 1, 0, 2 * Math.PI);
+				context.closePath();
+				context.setFillStyle(this.rc(150, 200));
+				context.fill();
+			}
+			context.draw();
+			console.log('end');
+		},
+		rc(min, max) {
+			var r = this.rn(min, max);
+			var g = this.rn(min, max);
+			var b = this.rn(min, max);
+			return 'rgb(' + r + ',' + g + ',' + b + ')';
+		},
+		rn(max, min) {
+			return parseInt(Math.random() * (max - min)) + min;
+		},
+		refresh() {
+			this.initCode();
+		}
+	}
+};
+</script>
+
+<style>
+	@import url('../login/login.css');
+</style>

+ 179 - 0
pages/scoreQuery/scoreQuery.css

@@ -0,0 +1,179 @@
+.project {
+	height: 70px;
+	line-height: 70px;
+	background: #1AA1E6;
+	font-size: 24px;
+	color: #FFFFFF;
+	font-weight: bold;
+}
+
+.project-content {
+	margin: 38px 0;
+	justify-content: center;
+	align-items: stretch;
+}
+
+/* 考试 */
+.test-box {
+	width: 890px;
+	/* min-height: 812px; */
+	background: #FFFFFF;
+	border-radius: 0px 0px 0px 0px;
+	opacity: 1;
+	border: 3px solid #FFFFFF;
+	position: relative;
+	padding: 30px;
+	box-sizing: border-box;
+}
+
+.test-title {
+	font-size: 30px;
+	font-family: Source Han Sans CN-Bold, Source Han Sans CN;
+	font-weight: bold;
+	color: #333333;
+	line-height: 36px;
+	text-align: center;
+	margin-top: 30px;
+}
+
+.test-time {
+	text-align: center;
+	margin-top: 10px;
+	font-size: 14px;
+}
+
+.yj-icon {
+	width: 77px;
+	height: 81px;
+	margin: 76px auto 0;
+}
+
+.yj-label {
+	text-align: center;
+	font-size: 18px;
+	margin-top: 18px;
+}
+.chufen-number{
+	color: #F45D44;
+	font-size: 46px;
+	margin: 76px auto 0;
+	text-align: center;
+}
+.score {
+	justify-content: center;
+	margin-top: 30px;
+	margin-bottom: 60px;
+	padding-left: 30px;
+}
+.score-label{
+	font-size: 16px;
+	color: #999999;
+}
+.score-value{
+	font-size: 24px;
+	color: #1AA1E6;
+	margin-top: 20px;
+}
+.line{
+	width: 1px;
+	height: 57px;
+	color: #DEDEDE;
+	background-color: #DEDEDE;
+	margin: 0 30px;
+}
+.back-btn{
+	width: 190px;
+	height: 46px;
+	background: #F5F5F5;
+	border-radius: 50px 50px 50px 50px;
+	opacity: 1;
+	font-size: 14px;
+	justify-content: center;
+	margin:200px auto 0;
+}
+.back-btn image{
+	width: 19px;
+	height: 15px;
+	margin-right: 10px;
+}
+
+
+.test-info {
+	width: 280px;
+	flex-direction: column;
+	margin-left: 30px;
+}
+
+/* 考试信息 */
+.test-people {
+	width: 100%;
+	background-color: #FFFFFF;
+	padding: 12px 11px;
+	box-sizing: border-box;
+}
+
+.test-people image {
+	width: 80px;
+	height: 89px;
+	margin-right: 19px;
+}
+
+.test-people-info {
+	flex-direction: column;
+	justify-content: space-between;
+	font-size: 14px;
+	flex: 1;
+	align-items: flex-start;
+}
+
+.test-people-label {
+	color: #999999;
+	line-height: 36px;
+	margin-right: 8px;
+}
+
+/* 考试公告 */
+.note-box {
+	width: 100%;
+	background-color: #FFFFFF;
+	padding: 20px;
+	box-sizing: border-box;
+	margin-top: 20px;
+}
+
+.note-title {
+	margin-bottom: 18px;
+	font-size: 16px;
+}
+
+.note-title-icon {
+	width: 18px;
+	height: 18px;
+	margin-right: 10px;
+}
+
+.note-item {
+	justify-content: space-between;
+	font-size: 12px;
+	font-weight: 400;
+	line-height: 30px;
+	font-family: Source Han Sans CN-Regular, Source Han Sans CN;
+	cursor: pointer;
+}
+
+.note-item-content {
+	color: #666666;
+	flex: 1;
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	margin-right: 10px;
+}
+
+.note-item-content:hover {
+	text-decoration: underline #666666;
+}
+
+.note-item-date {
+	color: #999999;
+}

+ 120 - 0
pages/scoreQuery/scoreQuery.vue

@@ -0,0 +1,120 @@
+<template>
+	<view>
+		<Headers></Headers>
+		<view class="project">
+			<view style="width: 1200px;margin: auto;">在线考试系统</view>
+		</view>
+		
+		<view class="project-content ddflex">
+			<!-- 成绩区域 -->
+			<view class="test-box">
+				<view class="test-title">二手车评估师考试</view>
+				<view class="test-time">
+					<text style="color: #999999;margin-right: 10px;">考试时间</text>
+					<text>2022-08-25 09:30:00</text>
+				</view>
+				
+				<view v-if="!true">
+					<image class="yj-icon" src="/static/images/yuejuan.png"></image>
+					<view class="yj-label">正在阅卷中... </view>
+				</view>
+				<view v-else class="chufen-number">
+					84<text style="font-size: 18px;margin-left: 10px;">分</text>
+					<view style="font-size: 16px;">考试不合格</view>
+				</view>
+				
+				<view class="score ddflex" >
+					<view>
+						<view class="score-label">总题数</view>
+						<view class="score-value">23</view>
+					</view>
+					<view class="line"></view>
+					<view>
+						<view class="score-label">考试用时</view>
+						<view class="score-value">20:42:14</view>
+					</view>
+				</view>
+				<view class="back-btn ddflex">
+					<image src="/static/images/back3.png"></image>
+					<text>返回上一页</text>
+				</view>
+			</view>
+			<!-- 答题卡区域 -->
+			<view class="test-info ddflex">
+				<view class="test-people ddflex">
+					<image></image>
+					<view class="test-people-info ddflex">
+						<view class="ddflex">
+							<view class="test-people-label">考生姓名</view>
+							<view class="fflex">李田</view>
+						</view>
+						<view class="ddflex">
+							<view class="test-people-label">准考证号</view>
+							<view class="fflex" style="word-break: break-all;">4512541244</view>
+						</view>
+						<view class="ddflex">
+							<view class="test-people-label">考试科目</view>
+							<view class="fflex">二手车评估师</view>
+						</view>
+					</view>
+				</view>
+				<view class="note-box">
+					<view class="note-title ddflex">
+						<image class="note-title-icon" src="/static/images/ksgg.png"></image>
+						<view>考试公告</view>
+					</view>
+					<view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">2022年“技能+学历”双证教育班培训简章2022年“技能+学历”双证教育班培训简章2022年“技能+学历”双证教育班培训简章</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">2022年“技能+学历”双证教育班培训简章</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">2022年“技能+学历”双证教育班培训简章</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+					</view>
+				</view>
+				<!-- 注意事项 -->
+				<view class="note-box">
+					<view class="note-title ddflex">
+						<image class="note-title-icon" src="/static/images/zysx.png"></image>
+						<view>注意事项</view>
+					</view>
+					<view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">2022年“技能+学历”双证教育班培训简章2022年“技能+学历”双证教育班培训简章2022年“技能+学历”双证教育班培训简章</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+						<view class="note-item ddflex">
+							<view class="note-item-content">2022年“技能+学历”双证教育班培训简章</view>
+							<!-- <view class="note-item-date">2022-08-25</view> -->
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		
+		<Foot></Foot>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+			}
+		},
+		onReady() {},
+		methods: {
+		}
+	}
+
+</script>
+
+<style>
+	@import url('./scoreQuery.css');
+</style>

+ 342 - 0
pages/test/test.css

@@ -0,0 +1,342 @@
+.project{
+	height: 70px;
+	line-height: 70px;
+	background: #1AA1E6;
+	font-size: 24px;
+	color: #FFFFFF;
+	font-weight: bold;
+}
+.project-content{
+	margin: 38px 0;
+	justify-content: center;
+	align-items: stretch;
+}
+/* 考试 */
+.test-box{
+	width: 890px;
+	min-height: 812px;
+	background: #FFFFFF;
+	border-radius: 0px 0px 0px 0px;
+	opacity: 1;
+	border: 3px solid #FFFFFF;
+	position: relative;
+	padding: 30px;
+	box-sizing: border-box;
+}
+.test-box-title{
+	font-size: 18px;
+}
+.test-question-box{
+	margin-top: 30px;
+}
+.test-question{
+	font-size: 18px;
+}
+.short{
+	height: 300px;
+	border-radius: 10px;
+	margin-top: 20px;
+	border: 1px solid #C4C4C4;
+}
+.text-ans{
+	width: 100%;
+	height: 100%;
+	font-size: 16px;
+	color: #333;
+	padding: 20px;
+	box-sizing: border-box;
+}
+.placeholder{
+	color: #C4C4C4;
+}
+.test-question-answer{
+	margin-top: 20px;
+}
+.answer-item{
+	margin-top: 20px;
+	cursor: pointer;
+}
+.answer-checked{
+	width: 24px;
+	height: 24px;
+	background: #0BBE2F;
+	opacity: 1;
+	border: 2px solid #0BBE2F;
+	border-radius: 100%;
+	margin-right: 20px;
+}
+.answer-unchecked{
+	width: 24px;
+	height: 24px;
+	opacity: 1;
+	border: 2px solid #999999;
+	border-radius: 100%;
+	margin-right: 20px;
+}
+.answer-text{
+	font-size: 18px;
+}
+.test-btn-group{
+	position: absolute;
+	bottom: 40px;
+	right: 70px;
+}
+.test-btn{
+	width: 150px;
+	height: 42px;
+	line-height: 42px;
+	text-align: center;
+	background: #FFFFFF;
+	border-radius: 6px 6px 6px 6px;
+	opacity: 1;
+	border: 1px solid #707070;
+	margin-left: 60px;
+	cursor: pointer;
+}
+
+
+
+.test-info{
+	width: 280px;
+	flex-direction: column;
+	justify-content: space-between;
+	margin-left: 30px;
+}
+/* 考试信息 */
+.test-people{
+	width: 100%;
+	background-color: #FFFFFF;
+	padding: 12px 11px;
+	box-sizing: border-box;
+}
+.test-people image{
+	width: 80px;
+	height: 89px;
+	margin-right: 19px;
+}
+.test-people-info{
+	flex-direction: column;
+	justify-content: space-between;
+	font-size: 14px;
+	flex: 1;
+	align-items: flex-start;
+}
+.test-people-label{
+	color: #999999;
+	line-height: 36px;
+	margin-right: 8px;
+}
+/* 考试倒计时 */
+.test-date{
+	width: 100%;
+	background-color: #FFFFFF;
+	padding: 30px;
+	box-sizing: border-box;
+	margin-top: 20px;
+}
+.test-date-title{
+	text-align: center;
+	font-size: 12px;
+	font-family: Source Han Sans CN-Regular, Source Han Sans CN;
+	font-weight: 400;
+	color: #666666;
+}
+.test-date-group{
+	margin: 14px auto 0;
+	justify-content: center;
+}
+.test-date-item{
+	width: 35px;
+	height: 35px;
+	line-height: 35px;
+	background: #FF0000;
+	border-radius: 2px 2px 2px 2px;
+	color: #fff;
+	text-align: center;
+	font-size: 24px;
+}
+.test-date-symbol{
+	font-size: 24px;
+	font-family: Source Han Sans CN-Regular, Source Han Sans CN;
+	font-weight: 400;
+	color: #B7B7B7;
+	margin: 0 5px;
+}
+/* 答题卡 */
+.test-answer{
+	width: 100%;
+	background-color: #FFFFFF;
+	padding: 30px;
+	box-sizing: border-box;
+	margin-top: 20px;
+	position: relative;
+}
+.test-answer-title{
+	font-size: 18px;
+	font-family: Source Han Sans CN-Bold, Source Han Sans CN;
+	font-weight: bold;
+	color: #333333;
+	text-align: center;
+}
+.test-answer-info{
+	margin: 20px 0;
+	color: #B7B7B7;
+	font-size: 14px;
+	justify-content: center;
+}
+.test-answer-info-symbol{
+	width: 1px;
+	height: 14px;
+	background-color: #B7B7B7;
+	margin: 0 10px;
+}
+.test-answer-box{
+	flex-wrap: wrap;
+	padding-bottom: 30px;
+	border-bottom: 1px solid #EBEBEB;
+}
+.test-answer-item{
+	width: 34px;
+	height: 24px;
+	line-height: 24px;
+	background: #FFFFFF;
+	border-radius: 5px 5px 5px 5px;
+	opacity: 1;
+	border: 1px solid #999999;
+	color: #999999;
+	text-align: center;
+	font-size: 14px;
+	margin-right: 8px;
+	margin-bottom: 10px;
+	cursor: pointer;
+}
+.test-answer-item:nth-child(5n+5){
+	margin-right: 0px;
+}
+.test-answer-item-curActive{
+	border: 1px solid #333;
+	color: #333;
+}
+.test-answer-item-active{
+	border: 1px solid #0BBE2F;
+	color: #0BBE2F;
+}
+.test-answer-number{
+	justify-content: space-between;
+	font-size: 12px;
+	color: #999999;
+	margin-top: 10px;
+}
+.test-isanswer{
+	width: 15px;
+	height: 15px;
+	border-radius: 2px 2px 2px 2px;
+	opacity: 1;
+	border: 1px solid #0BBE2F;
+	margin-right: 10px;
+}
+.test-unanswer{
+	width: 15px;
+	height: 15px;
+	background: #FFFFFF;
+	border-radius: 2px 2px 2px 2px;
+	opacity: 1;
+	border: 1px solid #C7C7C7;
+	margin-right: 10px;
+}
+.submit-btn{
+	width: 220px;
+	height: 42px;
+	line-height: 42px;
+	background: #F45D44;
+	border-radius: 6px 6px 6px 6px;
+	opacity: 1;
+	color: #fff;
+	text-align: center;
+	font-size: 16px;
+	position: absolute;
+	bottom:40px;
+}
+
+/* 弹窗 */
+.popup-box{
+	width: 722px;
+	min-height: 326px;
+	background: #FFFFFF;
+	box-shadow: 0px 0px 10px 1px rgba(81,0,0,0.1);
+	border-radius: 6px 6px 6px 6px;
+	opacity: 1;
+	border: 3px solid #FFFFFF;
+}
+.popup-top{
+	height: 65px;
+	line-height: 65px;
+	padding: 0 25px 0 17px;
+	border-bottom: 1px solid #EBEBEB;
+	font-size: 14px;
+	justify-content: space-between;
+}
+.popup-top image{
+	width: 29px;
+	height: 29px;
+	cursor: pointer;
+}
+.popup-content{
+	text-align: center;
+	font-size: 16px;
+	margin-top: 55px;
+}
+.popup-bottom{
+	margin-top: 60px;
+	justify-content: center;
+}
+.popup-btn1{
+	width: 146px;
+	height: 42px;
+	line-height: 42px;
+	border-radius: 21px 21px 21px 21px;
+	opacity: 1;
+	border: 1px solid #999999;
+	text-align: center;
+	cursor: pointer;
+}
+.popup-btn2{
+	width: 146px;
+	height: 42px;
+	line-height: 42px;
+	border-radius: 21px 21px 21px 21px;
+	opacity: 1;
+	border: 1px solid #DF230F;
+	margin-left: 30px;
+	text-align: center;
+	color: #DF230F;
+	cursor: pointer;
+}
+/* 出分 */
+.chufen-title{
+	font-size: 24px;
+	font-family: Source Han Sans CN-Bold, Source Han Sans CN;
+	font-weight: bold;
+	color: #333333;
+}
+.chufen-number{
+	color: #F45D44;
+	font-size: 46px;
+	margin-top: 30px;
+}
+.popup-bottom-label{
+	font-size: 16px;
+	color: #999999;
+}
+.popup-bottom-value{
+	font-size: 24px;
+	color: #1AA1E6;
+	margin-top: 20px;
+}
+.line{
+	width: 1px;
+	height: 57px;
+	color: #DEDEDE;
+	background-color: #DEDEDE;
+	margin: 0 30px;
+}

+ 529 - 0
pages/test/test.vue

@@ -0,0 +1,529 @@
+<template>
+	<view>
+		<Headers></Headers>
+		<view class="project">
+			<view style="width: 1200px;margin: auto;">二手车评估师考试</view>
+		</view>
+		
+		<view class="project-content ddflex">
+			<!-- 考试区域 -->
+			<view class="test-box">
+				<view class="test-box-title">
+					<text style="font-weight: bold;margin-right: 10px;">考试题目</text>
+					<text>{{ cIndex + 1 }}</text><text style="color: #999999;">/{{questTotal}}</text>
+				</view>
+				
+				<view class="test-question-box">
+					<view class="test-question ddflex">
+						<view>{{ cIndex + 1 }}</view>
+						<view>【{{getQuestType()}}】</view>
+						<view>
+							<rich-text class="hh" :nodes="addTitleType(quest.title,quest.qtype)"></rich-text>
+						</view>
+					</view>
+					<!-- 简答题 -->
+					<view class="short" v-if="quest.qtype == 4 || quest.qtype == 5">
+						<textarea
+								v-model="quest.answerTxt"
+								maxlength="-1"
+								ref="inputText"
+								placeholder="在此输入答案"
+								placeholder-class="placeholder"
+								class="text-ans"
+								@click="intAnswer(qitem, idx)"
+							></textarea>
+					</view>
+					<view class="test-question-answer" v-else-if="quest.qtype == 1 || quest.qtype == 2 || quest.qtype == 3">
+						<view class="answer-item ddflex" v-for="(qitem, idx) in quest.questJson" :key="idx" @click="setAnswer(qitem, idx)">
+							<!-- answer-checked -->
+							<view :class="qitem.cssStr ? 'answer-checked' : 'answer-unchecked'"></view>
+							<view class="answer-text ddflex">
+								<view style="margin-right: 10px;">{{ qitem.num }} </view>
+								<rich-text class="hh" :nodes="qitem.title"></rich-text>
+							</view>
+						</view>
+					</view>
+				</view>
+				
+				<view style="height: 82px;width: 100%;"> </view>
+				<view class="test-btn-group ddflex">
+					<view v-if="cIndex != 0" class="test-btn" @click="prev()">上一题</view>
+					<view v-if="cIndex + 1 != questTotal" class="test-btn" @click="next()">下一题</view>
+				</view>
+			</view>
+			<!-- 答题卡区域 -->
+			<view class="test-info ddflex">
+				<view class="test-people ddflex">
+					<image></image>
+					<view class="test-people-info ddflex">
+						<view class="ddflex">
+							<view class="test-people-label">考生姓名</view>
+							<view class="fflex">李田</view>
+						</view>
+						<view class="ddflex">
+							<view class="test-people-label">准考证号</view>
+							<view class="fflex" style="word-break: break-all;">4512541244</view>
+						</view>
+						<view class="ddflex">
+							<view class="test-people-label">考试科目</view>
+							<view class="fflex">二手车评估师</view>
+						</view>
+					</view>
+				</view>
+				<view class="test-date">
+					<view class="test-date-title">距考试结束还有</view>
+					<view class="test-date-group ddflex">
+						<view class="test-date-item">{{times.hour}}</view>
+						<text class="test-date-symbol">:</text>
+						<view class="test-date-item">{{times.minutes}}</view>
+						<text class="test-date-symbol">:</text>
+						<view class="test-date-item">{{times.seconds}}</view>
+					</view>
+				</view>
+				<view class="test-answer fflex">
+					<view class="test-answer-title">答题卡</view>
+					<view class="test-answer-info ddflex">
+						<view class="">共 {{quests.length}} 题</view>
+						<view class="test-answer-info-symbol"></view>
+						<view class="">总计 100 分</view>
+					</view>
+					<view class="test-answer-box ddflex">
+						<view :class="'test-answer-item '+(cIndex == index?'test-answer-item-curActive':item.isSubmit?'test-answer-item-active':'')" v-for="item,index in quests"
+							@click="toQuestTip(index)">
+							{{index+1}}
+						</view>
+					</view>
+					<view class="test-answer-number ddflex">
+						<view class="ddflex">
+							<view class="test-isanswer"></view>
+							<view>已做 {{quests.filter(item=>{return item.isSubmit}).length}}</view>
+						</view>
+						<view class="ddflex">
+							<view class="test-unanswer"></view>
+							<view>未做 {{quests.filter(item=>{return !item.isSubmit}).length}}</view>
+						</view>
+					</view>
+					
+					<view style="height: 82px;"></view>
+					<view class="submit-btn" @click="open">交  卷</view>
+				</view>
+			</view>
+		</view>
+		
+		<uni-popup ref="popup" type="bottom" :is-mask-click='false'>
+			<view class="popup-box" v-if="state==1">
+				<view class="popup-top ddflex">
+					<view>您正在结束作答</view>
+					<image src="/static/images/close.png" @click="close()"></image>
+				</view>
+				<view class="popup-content">您已完成全部考题,是否确定交卷?</view>
+				<view class="popup-bottom ddflex">
+					<view class="popup-btn1" @click="close()">继续考试</view>
+					<view class="popup-btn2" @click="submit">确定交卷</view>
+				</view>
+			</view>
+			<view class="popup-box" v-if="state==2">
+				<view class="popup-top ddflex">
+					<view>考试结果</view>
+					<image src="/static/images/close.png" @click="close()"></image>
+				</view>
+				<view class="popup-content" style="margin-top: 23px;">
+					<view class="chufen-title">二手车评估师考试</view>
+					<view class="chufen-number">
+						84<text style="font-size: 18px;margin-left: 10px;">分</text>
+						<view style="font-size: 16px;">考试不合格</view>
+					</view>
+				</view>
+				<view class="popup-bottom ddflex" style="margin-top: 30px;margin-bottom: 60px;padding-left: 30px">
+					<view>
+						<view class="popup-bottom-label">总题数</view>
+						<view class="popup-bottom-value">23</view>
+					</view>
+					<view class="line"></view>
+					<view>
+						<view class="popup-bottom-label">考试用时</view>
+						<view class="popup-bottom-value">20:42:14</view>
+					</view>
+				</view>
+			</view>
+		</uni-popup>
+		
+		<Foot></Foot>
+	</view>
+</template>
+
+<script>
+	const app = getApp();
+	const req = require('../../utils/request.js');
+	const utils = require('../../utils/util.js');
+	export default {
+		data() {
+			return {
+				state:1,
+				
+				paperId: '', //考试题目
+				paperTitle: '', //考试标题
+				paperType: '', //1每日一练 2模拟试题 3大厂真题 5企业真题
+				
+				type: '', //标识类型 1试卷 2章节 3热门考点 4错题集 5高频错题
+				systems: {},
+				isMockExam: true, //是否是模拟考试
+				isShowTip: false, //是否展示温馨提示
+				isShowSheet: false, //
+				
+				paper: '', //试卷详情
+				time: 0, //允许做题的时间
+				times: 0, //做题时分秒倒计时
+				quest: '', //当前选中的题目
+				quests: [], //题目数据
+				questTotal: 0, //题目条数
+				cIndex: 0, //当前做题下标
+				
+				answerTxt: '', //填空题、简答题答案
+				isGoBack: false,
+				isShowView: false
+			}
+		},
+		onReady() {},
+		onLoad() {
+			this.getQuests()
+		},
+		methods: {
+			getQuestType() {
+				// <!-- 1单选 2多选 3 判断 4 填空 5 简答', -->
+				var text = '';
+				switch (this.quest.qtype) {
+					case 1:
+						text = '单选题';
+						break;
+					case 2:
+						text = '多选题';
+						break;
+					case 3:
+						text = '判断题';
+						break;
+					case 4:
+						text = '填空题';
+						break;
+					case 5:
+						text = '简答题';
+						break;
+					default:
+						break;
+				}
+				return text;
+			},
+					
+			stylesText(text){
+				return utils.preText(text);
+			},
+			
+			addTitleType(title, qtype) {
+				var stitle=this.stylesText(title);
+				return stitle;
+			},
+						
+			//获取考试对象
+			getPaper() {
+				var _ts = this;
+				req.getRequest(api.paper_detail + _ts.paperId, {}, res => {
+					if (res) {
+						if (res.time > 0 && _ts.paperType != 3 && _ts.paperType != 5) {
+							_ts.time = res.time * 60;
+							_ts.setTime();
+						}
+						_ts.paperType = res.paperType * 1;
+						_ts.paper = res;
+					}
+				});
+			},
+
+			getQuests(){
+				let _ts = this
+				req.getRequest('https://mock.apifox.cn/m1/2171629-0-default/api/paper/quest/init/2834',{},quests=>{
+					console.log(quests)
+					if (quests && quests.length > 0) {
+						_ts.questTotal = quests.length;
+						for (var k = 0; k < quests.length; k++) {
+							var quest = quests[k];
+							quest.eitype = _ts.etype;
+							quest.title = quest.title.replace(/<code class="(.*?)"/gi, '<code class="Java" ');
+						}
+						if (_ts.questTotal > 0) {
+							_ts.quest = _ts.setQuest(quests[0]);
+						}
+						_ts.quests = quests;
+					}
+				})
+			},
+			
+			//考试时间倒计时
+			setTime() {
+				var _ts = this;
+				var time = _ts.time;
+				if (time <= 0) {
+					//考试时间到,交卷
+					if (_ts.ptime) {
+						clearTimeout(_ts.ptime);
+					}
+					_ts.submitTest();
+					return;
+				}
+				var times = {};
+				times.hour = _ts.cut22(Math.floor(time / 3600));
+				var leave2 = time % 3600;
+				times.minutes = _ts.cut22(Math.floor(leave2 / 60));
+				var leave3 = leave2 % 60;
+				times.seconds = _ts.cut22(Math.round(leave3));
+				_ts.times = times;
+				_ts.ptime = setTimeout(function() {
+					_ts.time = time - 1;
+					_ts.setTime();
+				}, 1000);
+			}, //下次继续
+						
+			cut22(n) {
+				n = n.toString();
+				return n[1] ? n : '0' + n;
+			},
+						
+			//将答案和问题转成数组或对象
+			setQuest(quest) {
+				console.log('quest.iscv==', quest.iscv);
+				if (quest.iscv) {
+					return quest;
+				}
+				quest.iscv = true;
+				var answers = [];
+				var qjs = [];
+				try {
+					var qJsons = JSON.parse(quest.questJson);
+					if (quest.qtype == 1 || quest.qtype == 3) {
+						//'单选题'
+						answers = quest.answerJson ? [quest.answerJson] : [];
+					} else if (quest.qtype == 2) {
+						if (quest.answerJson) {
+							answers = JSON.parse(quest.answerJson);
+						}
+					}
+					for (var m = 0; m < qJsons.length; m++) {
+						var num = this.getNum(m);
+						qjs.push({
+							num: num,
+							title: qJsons[m],
+							cssStr: ''
+						});
+					}
+				} catch (e) {}
+				quest.answerJson = answers;
+				quest.questJson = qjs;
+				console.log('下一题中');
+				quest.answerTxt = '';
+				this.answerTxt = '';
+				return quest;
+			},
+						
+			getNum: function(ix) {
+				var keys = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N'];
+				return keys[ix];
+			},
+			intAnswer(item, idx) {
+				var _ts = this;
+				var qes = this.quest;
+				qes.isSubmit = true;
+				_ts.quest = qes;
+			},
+			setAnswer(item, idx) {
+				// <!-- 1单选 2多选 3 判断 4 填空 5 简答', -->
+				var _ts = this;
+				idx = idx + 1;
+				var qes = this.quest;
+				/*修改答案选中项*/
+				var sItems = qes.sItems;
+				if (qes.qtype == 2) {
+					var isflg = false;
+					if (sItems && sItems.length > 0) {
+						var cidx = sItems.indexOf(idx);
+						if (cidx > -1) {
+							sItems.splice(cidx, 1);
+							isflg = true;
+						}
+					} else {
+						sItems = [];
+					}
+					if (!isflg) {
+						sItems.push(idx);
+					}
+				} else if (qes.qtype == 1 || qes.qtype == 3) {
+					sItems = [idx];
+				}
+				qes.sItems = sItems.sort();
+				qes.isSubmit = true;
+				//修改Css
+				qes = _ts.setCss(qes);
+				_ts.quest = qes;
+				_ts.quests[_ts.cIndex] = qes;
+			},
+						
+			//设置页面选中样式
+			setCss(qes) {
+				var qjson = qes.questJson;
+				var answers = qes.answerJson; //答案
+				var sItems = qes.sItems;
+				if (!sItems) {
+					sItems = [];
+				}
+				for (var m = 0; m < qjson.length; m++) {
+					var qitem = qjson[m];
+					var cidx = sItems.indexOf(m + 1);
+					if (cidx > -1) {
+						qitem.cssStr = ' active';
+					} else {
+						qitem.cssStr = '';
+					}
+				}
+				qes.questJson = qjson;
+				qes.cssStr = ' active';
+				return qes;
+			},
+						
+			//上一题
+			prev() {
+				var _ts = this;
+				var cIndex = _ts.cIndex;
+				if (cIndex <= 0) {
+					return;
+				}
+				_ts.cIndex = cIndex - 1;
+				_ts.quest = _ts.setQuest(_ts.quests[_ts.cIndex]);
+			}, //下一题
+			next() {
+				var _ts = this;
+				var cIndex = _ts.cIndex;
+				if (cIndex >= _ts.questTotal - 1) {
+					return;
+				}
+				_ts.cIndex = cIndex + 1;
+				console.log('下一题');
+				_ts.quest = _ts.setQuest(_ts.quests[_ts.cIndex]);
+				console.log('下一题后');
+				console.log('_ts.quest==', _ts.quest);
+				console.log('_ts.quest.answerTxt==', _ts.quest.answerTxt);
+				_ts.$forceUpdate();
+				console.log('quests==', _ts.quests);
+			},
+						
+			toQuestTip(index) {
+				var _ts = this;
+				var _ts = this;
+				_ts.cIndex = index;
+				_ts.quest = _ts.setQuest(_ts.quests[_ts.cIndex]);
+				_ts.closeCeng();
+				// });
+			},
+						
+			//提交
+			submitQuest() {
+				var msg = '';
+				if (this.paperType == 2) {
+					if (this.times.hour > 0) {
+						msg = '距离考试结束还剩' + this.times.hour + '小时' + this.times.minutes + '分钟,确定要结束考试吗?';
+					} else {
+						if (this.times.minutes > 0) {
+							msg = '距离考试结束还剩' + this.times.minutes + '分钟,确定要结束考试吗?';
+						} else {
+							msg = '确定要交卷结束考试吗?';
+						}
+					}
+				} else {
+					msg = '确定要交卷结束做题吗?';
+				}
+						
+				this.$showModal({ title: '温馨提示', content: msg, cancelText: '继续作答', confirmText: '交卷' })
+					.then(res => {
+						this.submitTest();
+					})
+					.catch(err => {
+						// 点击取消按钮的操作
+					});
+			},
+						
+			async submitTest(){
+				if (!this.paper.isScore) {//手动阅卷
+				//订阅成绩通知
+					await requsetmessage.resultsTest().then(res => {});
+				}
+				this.submit();
+			},
+						
+						
+			//提交考试+答案
+			submit() {
+				uni.redirectTo({
+					url:'/pages/scoreQuery/scoreQuery'
+				})
+				return
+				var _ts = this;
+				if (_ts.ptime) {
+					clearTimeout(_ts.ptime);
+				}
+				var dataP = {
+					uniqueId: _ts.paperId,
+					uniqueType: _ts.type
+				};
+				//组装考试题目
+				dataP.questionList = this.quests.map(it => {
+					// <!-- 1单选 2多选 3 判断 4 填空 5 简答', -->
+					var data = {
+						id: it.id, //记录ID
+						paperQuestionId: it.pqId, //试卷题目ID
+						questionId: it.questId //题目ID
+					};
+					var answerJson = '';
+					if (it.qtype == 1 || it.qtype == 3) {
+						answerJson = it.sItems ? it.sItems.join('') : '';
+					} else if (it.qtype == 2) {
+						answerJson = it.sItems ? JSON.stringify(it.sItems) : '';
+					} else if (it.qtype == 4) {
+						var list = [];
+						list.push(it.answerTxt ? it.answerTxt : '');
+						answerJson = JSON.stringify(list);
+					} else if (it.qtype == 5) {
+						answerJson = it.answerTxt ? it.answerTxt : '';
+					}
+					data.answerJson = answerJson;
+					return data;
+				});
+				console.log(dataP);
+				req.postRequest(
+					api.complete_exam,
+					dataP,
+					res => {
+						if (!_ts.paper.isScore) {//手动阅卷
+							uni.redirectTo({
+								url: '/learn/marking/index?id=' + res.id
+							});
+						} else {//自动阅卷
+							uni.redirectTo({
+								url: '/learn/result/index?id=' + res.id
+							});
+						}
+					},
+					true
+				);
+			},
+			
+			open() {
+				this.$refs.popup.open('center')
+			},
+			close() {
+				this.$refs.popup.close()
+			},
+		}
+	}
+
+</script>
+
+<style>
+	@import url('./test.css');
+</style>

+ 470 - 0
static/css/main.css

@@ -0,0 +1,470 @@
+/* macin.css */
+.header {height: 40px;background: #444444;position: fixed;top: 0;left: 0;right: 0;z-index: 50;}
+.header-title{font-size: 14px;color: #fff;line-height: 40px;margin-left: 60px;}
+.header-title image{width: 230px;height: 50px;}
+.header .wrap{justify-content: space-between;}
+.placeholder-view{height: 40px;}
+.user{font-size: 13px;color: #fff;line-height: 52px;cursor: pointer;position: relative;}
+.user-img{width: 24px;height: 24px;border-radius: 50%;background: #ccc;font-size: 12px;color: #fff;text-align: center;line-height: 24px;margin-right: 8px;}
+.bico{width: 9px;height: 5px;margin-left: 6px;}
+.top-user{background: #332431;padding: 16px 0;}
+.userimg{width: 88px;height: 88px;border-radius: 50%;margin-right: 20px;}
+.username{font-size: 24px;color: #fff;font-weight: bold;}
+.rzimg{width: 40px;height: 15px;margin-left: 5px;}
+.user-mobile{font-size: 14px;color: rgba(255,255,255,.6);margin-top: 10px;}
+.user-opt{position: absolute;top: 52px;right: 0;width: 100px;padding: 0 10px;background: #fff;border-radius: 4px;box-shadow: 0 0 5px rgba(0,0,0,.3);display: none;}
+.user-opt::after{content: '';display: block;width: 0;height: 0;border: 5px solid transparent;border-top: none;border-bottom-color: #fff;position: absolute;right: 10px;top: -5px;}
+.user-opt .li{font-size: 14px;color: #666;padding: 5px 0;text-align: center;line-height: 30px;border-bottom: 1px solid #ebebeb;}
+.user-opt .li:last-child{border-bottom: none;}
+.user-opt .li:hover{color: var(--main);}
+.user:hover .user-opt{display: block;}
+/* 底部 */
+.footer{background: #444444;padding: 15px 0 15px;text-align: center;font-size: 12px;color: #fff;line-height: 24px;width:100%;position: fixed;bottom: 0;z-index: 2;}
+.footer a{color: #fff;margin-left: 5px;}
+.footer a:hover{color: #fff;}
+.foot-nav{justify-content: center;font-size: 12px;color: #c7c7c7;margin-bottom: 20px;}
+.foot-nav view{cursor: pointer;}
+.foot-nav text{font-family: '宋体';margin: 0 12px;}
+/* 内容 */
+.content{padding: 20px 0 90px;align-items: flex-start;}
+.left{width: 206px;background: #fff;padding: 20px 0 20px 22px;margin-right: 30px;}
+.left .li{height: 40px;font-size: 14px;color: #666;line-height: 40px;cursor: pointer;}
+.left .li.active{background: #FFF1EF;border-radius: 20px 0 0 20px;border-right: 3px solid var(--main);color: var(--main)}
+.left .li image{width: 16px;height: 16px;margin-right: 9px;margin-left: 20px;}
+.left-line{height: 1px;background-color: #F5F5F5;margin: 12px 0;}
+.left-tits{font-size: 14px;color: #000;font-weight: bold;padding-left: 20px;margin: 10px 0;}
+.left .lis{font-size: 14px;color: #000;font-weight: bold;line-height: 30px;padding-left: 20px;cursor: pointer;}
+.left .lis.active{background: #FFF1EF;border-radius: 20px 0 0 20px;border-right: 3px solid var(--main);color: var(--main);}
+.right{width: 942px;}
+.c-title{font-size: 16px;color: #333;padding: 5px 0 15px;}
+.c-back{margin-right: 20px;color: var(--main);font-size: 14px;}
+.c-back image{width: 15px;margin-right: 5px;}
+.c-box{background: #fff;min-height: 360px;}
+.c-bot{background: #fff;padding: 17px 28px;margin-top: 20px;}
+.c-btn{width: 80px;height: 32px; margin-right: 30rpx;  background: var(--main);border-radius: 4px;font-size: 14px;color: #fff;text-align: center;line-height: 32px;cursor: pointer;}
+/* 企业注册 */
+.qyzc{padding: 20px 30px 50px;}
+.c-tit{font-size: 16px;color: #000;font-weight: bold;}
+.c-form .li{margin-top: 25px;}
+.c-form .li .label{width:95px;text-align: right;font-size: 14px;color: #666;padding-right: 15px;}
+.c-ipt{font-size: 12px;color: #666;height: 30px;line-height: 30px;border: 1px solid #D8DCE6;border-radius: 4px;padding: 0 12px;}
+.c-placeholder{color: #909399;}
+.c-ipt-text{font-size: 14px;color: #666;height: 30px;line-height: 30px;padding: 0 12px;}
+.c-txa-text{font-size: 14px;color: #666;line-height: 30px;padding: 0 12px;}
+
+.com-upload-img{width: 96px;height: 96px;border: 1px dashed #C5C5C5;margin-right: 16px;}
+.imgboxs{flex-wrap: wrap;}
+.imgs{width: 96px;height: 96px;border: 1px dashed #C5C5C5;margin-right: 16px;position: relative;margin-bottom: 15px;}
+.upload-img{width: 100%;height: 100%;}
+.delete{position: absolute;top: 0;left: 0;right: 0;bottom: 0;background: rgba(0,0,0,.5);justify-content: center;display: none;}
+.delete image{width: 20px;height: 20px;cursor: pointer;margin: 38px auto 0;}
+.imgs:hover .delete{display: block;}
+.upload{width: 96px;height: 96px;border: 1px dashed #C5C5C5;border-radius: 4px;font-size: 12px;color: #606266;flex-direction: column;justify-content: center;margin-right: 16px;cursor: pointer;margin-bottom: 15px;}
+.upload image{width: 16px;height: 16px;margin: 0 auto 8px;}
+.com-upload{margin-bottom: 0;}
+.chang{margin-left: 19px;font-size: 14px;color: #666;}
+.chang checkbox{zoom: .5;margin-right: 4px;vertical-align: middle;}
+.c-line{height: 1px;background: #EBEBEB;margin: 40px 0;}
+.rz-tip{background: #fcf1eb;font-size: 12px;color: #FF6C17;padding: 8px 20px;margin-bottom: 20px;}
+.fail{background: #fbecea;color: var(--main);}
+.suc{background: #f2fdf2;color: #0f7f00;}
+/* 审核状态 */
+.qyzc-audit{padding: 80px 0 200px;text-align: center;}
+.qyzc-audit image{width: 60px;height: 60px;margin: 0 auto;}
+.audit-sta{font-size: 16px;color: #FF6C17;font-weight: bold;margin: 20px 0 10px;}
+.audit-tip{font-size: 12px;color: #999;}
+.edit-btn{width: 98px;height: 30px;border: 1px solid var(--main);border-radius: 2px;font-size: 14px;color: var(--main);text-align: center;line-height: 30px;margin: 30px auto 0;cursor: pointer;}
+/* 路线上报 */
+.ct-opt{justify-content: space-between;}
+.pil{width: 93px;height: 30px;border: 1px solid #DCDFE6;border-radius: 3px;font-size: 12px;color: #606266;text-align: center;line-height: 30px;cursor: pointer;}
+.pil:hover{color: var(--main);border-color: var(--main);}
+.c-textarea{padding: 10px 12px;height: 100px;border: 1px solid #D8DCE6;border-radius: 4px;font-size: 12px;color: #666;}
+.c-select{width: 190px;height: 30px;border: 1px solid #DCDFE6;border-radius: 4px;font-size: 12px;color: #666;padding: 0 12px;line-height: 30px;}
+.c-select .uni-input{padding: 0 !important;height: 30px !important;line-height: 30px !important;}
+.team-time{border: 1px solid #DCDFE6;padding: 0 12px;border: 1px solid #DCDFE6;border-radius: 4px;height: 30px;width: 320px;line-height: 30px;}
+.time-zhi{display: block;margin: 0 12px;font-size: 12px;color: #303133;}
+.datatime{width: 100%;text-align: left;font-size: 12px;color: #606266;}
+.sel-type{margin-left: 30px;font-size: 12px;color: #666;}
+.sel-type text{margin-right: 20px;}
+/* 投诉管理 */
+.tousu{padding: 30px 30px 25px;}
+.c-tab{border-bottom: 1px solid #EDEEF0;}
+.c-tab .li{font-size: 16px;color: #999;margin-right: 30px;position: relative;padding-bottom: 18px;}
+.c-tab .li.active{color: var(--main);}
+.c-tab .li.active::after{content: '';display: block;width: 32px;height: 3px;background: var(--main);position: absolute;bottom: 0;left: 50%;margin-left: -16px;}
+.ts-list .li{padding: 25px 0;border-bottom: 1px solid #EDEEF0;position: relative;}
+.ts-list .li:last-child{border-bottom: none;}
+.ts-l{width: 80%;}
+.ts-des{font-size: 16px;color: #333;line-height: 27px;}
+.ts-img{margin-top: 10px;}
+.ts-img image{width: 64px;height: 64px;margin-right: 8px;}
+.ts-source{font-size: 12px;color: #999;margin-top: 15px;}
+.ts-reply{margin-top: 24px;background: #F7F8FA;padding: 15px;}
+.ts-reply-des{font-size: 14px;color: #666;line-height: 20px;}
+.ts-reply-user{color: #000;font-weight: bold;}
+.ts-reply-user_type{height: 14px;border: 1px solid #1597E8;border-radius: 4px;font-size: 12px;color: #1597E8;padding: 0 4px;line-height: 14px;margin: 0 5px;}
+.ts-teply-time{font-size: 12px;color: #999;margin-top: 12px;}
+.reply-btn{width: 76px;height: 32px;background: var(--main);border-radius: 3px;font-size: 12px;color: #fff;text-align: center;line-height: 32px;position: absolute;top: 25px;right: 20px;}
+/* 招徕奖励 */
+.award-box{padding: 40px 30px 50px;}
+.add-btn{width: 100px;height: 32px;background: var(--main);border-radius: 3px;font-size: 12px;color: #fff;justify-content: center;}
+.add-btn image{width: 15px;height: 15px;margin-right: 7px;}
+.award-table{width: 100%;border: 1px solid #EBEEF5;border-collapse: collapse;margin-top: 25px;font-size: 12px;color: #606266;text-align: center;}
+.award-table th{background: #F5F7FA;font-size: 12px;color: #303133;font-weight: normal;height: 40px;padding: 0 10px;}
+.award-table td{line-height: 20px;padding: 20px 10px;}
+.award-opt{color: #409EFF;cursor: pointer;}
+/* 招徕奖励详情 */
+.step{padding: 30px 0 20px;min-height: initial;align-items: flex-start;}
+.step .li{width: 25%;text-align: center;font-size: 14px;color: #909399;position: relative;}
+.step .li::after{content: '';display: block;border-bottom: 1px dashed #D1D1D1;width: 150px;position: absolute;top: 14px;right: -75px;}
+.step .li:last-child::after{display: none;}
+.step .li view{font-size: 16px;color: #C0C4CC;margin: 8px 0 4px;}
+.step .li image{width: 28px;height: 28px;margin: 0 auto;}
+.step .li.ing view{color: #303133;}
+.step .li.end::after{background: #1A85FF;}
+.award-det{padding: 30px 30px 50px;margin-top: 20px;}
+.award-tit{font-size: 18px;color: #303133;font-weight: bold;}
+.award-info{flex-wrap: wrap;}
+.award-info .li{width: 50%;font-size: 16px;color: #303133;margin-top: 20px;}
+.award-info .li .label{width: 102px;color: #909399;}
+.bz-btn{color: #1A85FF;}
+.award-det .c-line{margin: 20px 0 0;}
+.mt55{margin-top: 55px;}
+.award-img{margin-top: 20px;}
+.award-img image{width: 64px;height: 64px;margin-right: 8px;}
+.pzbox{justify-content: center;flex-wrap: wrap;}
+.pzimg{width: 30px;height: 30px;margin: 5px;}
+/* 申报奖励 */
+.declare{padding: 30px 30px 50px;}
+.team-counts{width: 163px;height: 30px;border: 1px solid #E3E3E3;border-radius: 4px;}
+.jia{width: 40px;height: 30px;background: #E3E3E3;font-size: 30px;color: #A5A5A5;font-family: '宋体';text-align: center;line-height: 30px;cursor: pointer;}
+.team-count{width: 85px;height: 30px;font-size: 14px;color: #323233;text-align: center;line-height: 30px;}
+.single{width: 165px;height: 30px;border: 1px solid #E3E3E3;border-radius: 4px;padding: 0 12px;font-size: 12px;color: #909399;}
+.single text{margin-right: 10px;}
+.single input{font-size: 12px;color: #666;height: 30px;line-height: 30px;}
+/* 旅游线路产品上报 */
+.checkbox{zoom: .6;}
+.dai{color: #FF6C17;}
+.c-btns{min-width: 110px;width: 100%;font-size: 12px;color: #409EFF;justify-content: center;}
+.c-btns text{font-family: '宋体';color: #E8E8E8;margin: 0 10px;}
+.c-btns view{cursor: pointer;}
+.add-btn1{width: 124px;}
+/* 资源共享 */
+.resource-total{padding: 16px 30px;font-size: 16px;color: #666;min-height: initial;}
+.resource-list{margin-top: 16px;padding: 0 30px;}
+.resource-list .li{padding: 18px 0;border-bottom: 1px solid #EDEEF0;cursor: pointer;}
+.resource-list .li:last-child{border-bottom: none;}
+.resource-tit{font-size: 18px;color: #333;font-weight: bold;}
+.resource-info{font-size: 14px;color: #666;margin-top: 10px;}
+.download{width: 20px;height: 20px;}
+/* 分页 */
+.panigator {font-size: 14px;color: #666;justify-content: center;margin-top: 30px;}
+/* 需求广场 */
+.xq-box{padding: 0 0 50px;}
+.damand-tab{/* border-bottom: 1px solid #EDEEF0; */margin: 0 30px;padding-top: 15px;}
+.damand-tab .li{font-size: 16px;color: #999;position: relative;padding: 20px 0;margin-right: 40px;}
+.damand-tab .li.active{color: var(--main);}
+.damand-tab .li.active::after{content: '';display: block;width: 32px;height: 3px;background: var(--main);position: absolute;left: 50%;margin-left: -16px;bottom: 0;}
+.demand-list{padding: 0 30px;}
+.demand-list .li{padding: 22px 0;border-bottom: 1px solid #EDEEF0;cursor: pointer;}
+.demand-tit{font-size: 18px;color: #333;font-weight: bold;}
+.demand-time{font-size: 12px;color: #999;font-weight: normal;}
+.demand-user{font-size: 14px;color: #666;margin-top: 10px;}
+.demand-des{font-size: 12px;color: #999;margin-top: 15px;padding-right: 100px;}
+.demand-xinzi{margin-top: 15px;font-size: 14px;color: #FF6C17;}
+.dsta{border: 1px solid #fde2e2;font-size: 14px;color: #e63c3c;background: #fef1f1;font-weight: normal;padding: 0 5px;margin-right: 12px;border-radius: 2px;}
+.ding{background-color: #fdf6ec;border-color: #faecd8;color: #e6a23c;}
+.dend{background-color: #f0f9eb;border-color: #e1f3d8;color: #67c23a;}
+/* 资质申报 */
+.declare-list{padding: 0 30px;}
+.declare-list .li{padding: 22px 0;border-bottom: 1px solid #EDEEF0;cursor: pointer;}
+.declare-list .li:last-child{border-bottom: none;}
+.declare-tit{font-size: 18px;color: #333;font-weight: bold;}
+.declare-who{font-size: 14px;color: #666;margin-top: 10px;}
+.declare-des{font-size: 12px;color: #999;margin-top: 15px;line-height: 20px;}
+.declare-btn{width: 80px;height: 32px;background: var(--main);border-radius: 4px;font-size: 14px;color: #fff;text-align: center;line-height: 32px;}
+.declare-record{padding: 0 30px 50px;}
+/* 学习中心 */
+.learn-box{min-height: initial;padding: 0 30px 0;margin-bottom: 16px;}
+.learn-tits{font-size: 16px;color: #333;}
+.learn-tits image{width: 13px;height: 14px;margin-right: 8px;}
+.learn-list .li{border-bottom: 1px solid #EBEBEB;padding: 25px 0;}
+.learn-list .li:last-child{border-bottom: none;}
+.learn-img{width: 147px;height: 83px;border-radius: 5px;margin-right: 20px;}
+.learn-tit{font-size: 18px;color: #333;font-weight: bold;}
+.learn-time{font-size: 12px;color: #666;margin-top: 15px;}
+.learn-time text{font-family: '宋体';margin: 0 10px;}
+.learn-btn{width: 76px;height: 32px;background: linear-gradient(90deg, #FF5519 0%, #DF230F 100%);border-radius: 21px;font-size: 12px;color: #fff;text-align: center;line-height: 32px;}
+.li-t{border-bottom: 1px solid #EBEBEB;padding: 22px 0;}
+.ks-tit{font-size: 18px;color: #333;font-weight: bold;}
+.redo{font-size: 12px;color: #999;justify-content: center;margin-top: 10px;}
+.redo image{width: 10px;height: 10px;margin-right: 5px;}
+.percent{margin-top: 12px;font-size: 12px;color: #999;}
+.percent-cent{width: 438px;height: 8px;background: #F5F5F5;border-radius: 6px;position: relative;margin-right: 10px;}
+.percent-cent view{position: absolute;top: 0;left: 0;height: 8px;border-radius: 6px;background: #F8A31D;}
+.li-b{padding: 30px 50px;}
+.li-b .lis{width: 33.33%;text-align: center;}
+.lis-t{position: relative;width: 167px;height: 167px;margin: 0 auto;}
+.lis-t image{width: 100%;height: 100%;position: absolute;top: 0;left: 0;}
+.lis-text{font-size: 12px;color: #999;display: block;}
+.lis-cent{font-size: 32px;color: #F45D44;margin-top: 5px;}
+.lis-cent text{font-size: 14px;}
+.lis-tip{font-size: 12px;color: #999;}
+.lis-tc{position: relative;z-index: 2;padding-top: 50px;}
+/* 学习中心观看视频 */
+.zbtit{height: 82px;line-height: 82px;background: #333333;padding: 0 30px;}
+.zb-back{font-size: 16px;color: #fff;background: url(/static/images/back.png) no-repeat left center;padding-left: 27px;margin-right: 70px;}
+.zbtit text{font-size: 18px;color: #fff;font-weight: bold;vertical-align: middle;}
+.live{position: fixed;top: 134px;left: 0;bottom: 0;right: 0;background: #333;}
+.live-l{position: absolute;top: 0;left: 0;bottom: 0;width: 80%;}
+.live-c{position: absolute;top: 0;left: 0;bottom: 74px;right: 0;}
+.live-video{width: 100%;height: 100%;}
+.live-b{position: absolute;left: 0;bottom: 0;height: 74px;line-height: 74px;right: 0;padding: 0 30px 0 100px;font-size: 16px;color: #9b9b9b;justify-content: center;}
+.live-b a{color: rgba(255,255,255,.5);font-size: 16px;}
+.next{background: url(/static/images/next.png) no-repeat right center;padding-right: 23px;margin-left: 52px;}
+.prev{background: url(/static/images/prev.png) no-repeat left center;padding-left: 23px;}
+.kclive-r{position: absolute;top: 0;right: 0;width: 20%;bottom: 0;background: #2A2A2A;}
+.kctabs{background: #232323;}
+.kctabs a{display: block;height: 56px;line-height: 56px;font-size: 16px;color: #909090;text-align: center;}
+.kctabs a i{display: inline-block;width: 14px;height: 14px;margin-right: 5px;vertical-align: middle;}
+.kctabs a.active{color: #DF230F;}
+.kcjj i{background: url(/static/images/jjico.png) no-repeat center;}
+.kcdet{margin: 0 20px;border-bottom: 1px solid #454545;padding: 25px 0;}
+.kcdet h3{font-size: 20px;color: #fff;line-height: 34px;font-weight: normal;}
+.kcdet p{font-size: 12px;color: #fff;margin-top: 20px;}
+.kcdet p em{font-style: normal;margin: 0 12px;font-family: '宋体';}
+.kclive-con{position: absolute;top: 56px;right: 0;left: 0;bottom: 0;overflow-y: auto;padding-bottom: 30px;}
+.kctits{font-size: 18px;color: #fff;position: relative;padding-left: 10px;margin: 25px 20px 15px;}
+.kctits:before{content: '';display: block;width: 3px;height: 15px;border-radius: 3px;background: #DF230F;position: absolute;left: 0;top: 50%;transform: translateY(-50%);}
+.kclive-list{margin: 0 20px;}
+.kclive-list .li{line-height: 34px;color: #999;padding-left: 24px;background: url(/static/images/bfico1.png) no-repeat left center;text-overflow: ellipsis;white-space: nowrap;overflow: hidden;cursor: pointer;}
+.kclive-list .li:hover,.kclive-list .li.active{background-image: url(/static/images/bfico1_h.png);color: #DF230F;}
+
+/* 申报弹窗 */
+.ceng{position: fixed;top: 0;left: 0;right: 0;bottom: 0;z-index: 99;background: rgba(0,0,0,.3);}
+.popup{position: fixed;top: 50%;transform: translateY(-50%);left: 50%;width: 914px;margin-left: -457px;padding: 20px 30px 40px;background: #fff;z-index: 100;}
+.pop-tit{font-size: 16px;color: #333;}
+.pop-btn{justify-content: flex-end;margin-top: 35px;}
+.pop-cancel,.pop-submit{width: 78px;height: 30px;border-radius: 4px;font-size: 14px;text-align: center;line-height: 30px;cursor: pointer;}
+.pop-cancel{border: 1px solid #D1D1D1;color: #666;margin-right: 18px;}
+.pop-submit{border: 1px solid var(--main);background: var(--main);color: #fff;}
+.pop-con{flex-wrap: wrap;align-items: flex-start;margin-top: 20px;}
+.c-forms{flex-wrap: wrap;}
+.pop-con .li{width: 50%;}
+.popup-h{width: 600px;margin-left: -300px;}
+.pop-close{width: 32px;height: 32px;position: absolute;top: 10px;right: 10px;cursor: pointer;}
+.pop-textarea{width: 100%;height: 200px;box-sizing: border-box;font-size: 14px;color: #333;border: 1px solid #e9e9e9;border-radius: 5px;margin-top: 20px; padding: 15px;}
+/* 申报记录 */
+.record-filter{justify-content: space-between;}
+.record-filter .li{margin-top: 0;margin-left: 20px;}
+.record-filter .li .label{width: auto;}
+.inquire{width: 90px;height: 32px;background: var(--main);border-radius: 2px;font-size: 14px;color: #fff;text-align: center;line-height: 32px;margin: 0 10px 0 0;cursor: pointer;}
+.inquire-c{width: 60px;height: 32px;background: var(--main);border-radius: 2px;font-size: 14px;color: #fff;text-align: center;line-height: 32px;margin: 0 0 0 10px;cursor: pointer;}
+
+.reset{width: 60px;height: 30px;border: 1px solid #4A4A4A;border-radius: 2px;font-size: 14px;color: #343434;text-align: center;line-height: 32px;}
+/* 上报数据分析 */
+.sj-box{min-height: initial;}
+.sj-tit{font-size: 16px;color: #1D2129;font-weight: bold;padding: 20px;border-bottom: 1px solid #E9E9E9;}
+.sj-box-c{padding: 20px;height: 200px;}
+.sj-box1{min-height: initial;width: 460px;}
+.sj-box-b{justify-content: space-between;margin-top: 20px;}
+/* 考试中心 */
+.exam-list{/* margin-top: 20px; */padding: 0 30px;}
+.exam-list .li{padding: 20px 0;border-bottom: 1px solid #EBEBEB;cursor: pointer;}
+.ks-time{font-size: 12px;color: #999;margin-top: 10px;}
+.ks-status{font-size: 12px;color: #999;text-align: right;}
+.ks-status.ing{color: #f00;}
+/* .ks-day{justify-content: flex-end;color: #666;margin-top: 8px;}
+.ks-day view{width: 20px;height: 20px;background: var(--main);color: #fff;text-align: center;border-radius: 3px;line-height: 20px;}
+.ks-day text{display: block;margin: 0 3px;}
+.ks-day text:last-child{margin-right: 0;} */
+/* 试卷详情 */
+.sj-det{min-height: initial;padding: 30px;}
+.kst-tit{font-size: 18px;color: #333;font-weight: bold;text-align: center;border-bottom: 1px solid #EBEBEB;padding: 0 0 28px;margin-bottom: 30px;}
+.kst-info{justify-content: center;font-size: 12px;color: #999;}
+.kst-info text{color: #333;margin: 0 19px 0 0;}
+.sjms{margin: 30px auto 0;width: 120px;height: 30px;border: 1px solid var(--main);line-height: 30px;border-radius: 4px;font-size: 14px;color: var(--main);text-align: center;cursor: pointer;}
+.sjms:hover{background: var(--main);color: #fff;}
+.tx-det{min-height: initial;margin-top: 20px;padding: 30px;}
+.tx-info{margin-top: 40px;font-size: 14px;color: #666;}
+/* 考试页面 */
+.loca{height: 78px;padding: 0 30px;min-height: initial;}
+.back{font-size: 16px;color: #333;padding-left: 30px;background: url(/static/images/back1.png) no-repeat left center;}
+.juanzi{padding: 20px 0 0;align-items: flex-start;}
+.ztleft{width: 890px;margin-right: 30px;}
+.topic{padding: 25px 30px;background: #fff;border-radius: 6px 6px 0 0;box-shadow:0px 0px 10px rgba(81,0,0,0.1);}
+.sj-h3{font-size: 18px;color: #333;}
+.process-load{color: #999;margin-top: 18px;justify-content: space-between;}
+.process-load .process{width: 645px;height: 14px;background: #FFDDD1;border: 1px solid #ffded2;position: relative;border-radius: 8px;overflow: hidden;margin-top: 2px;}
+.process-load .process view{position: absolute;top: 0;left: 0;height: 14px;background: #F8A31D;border-radius: 8px;}
+.process-load text{color: #DF230F;font-size: 14px;}
+.sj-line{color: #707070;margin: 0 12px;}
+.exam{background: #fff;border-radius: 0 0 6px 6px;margin-top: 10px;box-shadow:0px 0px 10px rgba(81,0,0,0.1);}
+.question{background: #F5F5F5;padding: 25px 30px;font-size: 18px;color: #333;}
+.answer{margin-top: 20px;padding-bottom: 45px;}
+.answer .li{font-size: 18px;color: #333;padding: 10px 30px 10px 75px;background-image: url(/static/images/wei.png);background-position: 30px center;background-repeat: no-repeat;cursor: pointer;}
+.answer .li.sels{background-color: #F5F5F5;background-image: url(/static/images/sel.png);}
+.operate{/* position: fixed;bottom: 0;left: 50%;margin-left: -600px;box-shadow:0px 0px 10px rgba(81,0,0,0.1); */border-radius: 6px;width: 830px;background: #fff;height: 40px;line-height: 40px;z-index: 30;padding: 0 30px;justify-content: space-between;margin-top: 12px;}
+.operate button{color: #666;font-size: 16px;background: none;}
+.operate button:hover{color: #333;}
+.operate button[disabled]{background: none;color: #999;}
+.operate button[disabled]:hover{color: #999;}
+.ztright{width: 280px;min-height: initial;}
+.daojishi{padding: 22px 0;text-align: center;background: #f5f5f5;line-height: 21px;font-size: 12px;color: #666;}
+.daojishi view{font-size: 14px;color: #fff;width: 24px;height: 21px;border-radius: 2px;background: #DF230F;}
+.daojishi text{margin: 0 5px;}
+.ztrightc{padding: 30px;}
+.zt-tit{font-size: 18px;color: #333;border-bottom: 1px solid #EBEBEB;padding-bottom: 10px;position: relative;padding-left: 11px;}
+.zt-tit:before{content: '';display: block;width: 6px;height: 15px;border-radius: 3px;background: #DF230F;position: absolute;top: 5px;left: 0;}
+.zt-tits{color: #999;margin: 10px 0;}
+.dtka{flex-wrap: wrap;}
+.dtka .li{width: 32px;height: 22px;border: 1px solid #C7C7C7;border-radius: 5px;text-align: center;line-height: 22px;color: #999;margin: 0 12px 10px 0;cursor: pointer;}
+.dtka .li:nth-child(5n){margin-right: 0;}
+.dtka .li.ing{border-color: #707070;color: #333;}
+.dtka .li.correct{border-color: #0BBE2F;background: #0BBE2F;color: #fff;}
+.dtka .li.error{border-color: #DF230F;background: #DF230F;color: #fff;}
+.sta{border-top: 1px solid #EBEBEB;margin-top: 20px;padding-top: 11px;}
+.sta text{font-size: 12px;color: #999;margin-right: 20px;}
+.sta text:before{content: '';display: inline-block;width: 13px;height: 13px;border: 1px solid #C7C7C7;border-radius: 2px;margin-right: 4px;vertical-align: middle;}
+.sta text.sta-error:before{background: #DF230F;border-color: #DF230F;}
+.jiaojuan{margin: 30px auto 0;width: 200px;height: 40px;border: 1px solid var(--main);border-radius: 6px;text-align: center;line-height: 40px;font-size: 16px;color: #DF230F;cursor: pointer;}
+/* 成绩查询 */
+.gourl {width: 146px;height: 42px;background: var(--main); text-align: center;font-size: 16px;color: #fff;line-height: 42px;border-radius: 21px;margin: 30px auto 0;}
+.cj-list{padding: 0 30px;}
+.cj-list .li{padding: 23px 0;border-bottom: 1px solid #EBEBEB;clear: both;overflow: hidden;}
+.cj-list .li:last-child{border-bottom: none;}
+.cj-list .li .ztl{width: 620px;}
+.cj-tit{font-size: 18px;color: #333;text-overflow: ellipsis;white-space: nowrap;overflow: hidden;font-weight: bold;}
+.cj-bri{font-size: 12px;margin-top: 8px;}
+.cj-bri text{font-family: '宋体';font-style: normal;color: #707070;margin: 0 11px;}
+.cj-list .li .ztl:hover .cj-tit{color: var(--main);}
+.cj-list .li .ztr{align-items: flex-start;}
+.ckjx{display: block;width: 76px;height: 30px;border: 1px solid var(--main);border-radius: 4px;line-height: 30px;font-size: 12px;color: var(--main);text-align: center;}
+.ckjx:hover{background: #DF230F;color: #fff;}
+.ckbg{color: #999;margin-right: 20px;line-height: 32px;font-size: 12px;}
+.ckbg:hover{color: #333;}
+.ks-status{position: relative;}
+.kssta{display: block;font-size: 14px;color: #333;}
+.kssta-red{display: block;font-size: 14px;color: #DF230F;}
+.ks-sta{display: block;width: 78px;height: 68px;margin-left: 20px;}
+.day{font-size: 12px;color: #DF230F;margin-left: 20px;}
+.day .span{width: 25px;height: 37px;border-radius: 6px;line-height: 37px;text-align: center;background: #DF230F;font-size: 24px;color: #fff;margin-right: 4px;}
+.day .em{font-style: normal;margin-top: 22px;}
+
+
+/* 考试结果 */
+.result{margin: 20px 0;padding: 40px 0;text-align: center;background: #fff url(/static/images/jgbg.png) no-repeat top center;min-height: initial;}
+.yuejuan{padding: 40px 0 100px;text-align: center;font-size: 18px;color: #333;}
+.yuejuan image{display: block;margin: 0 auto 15px;width: 78px;height: 81px;}
+.suc-tit{text-align: center;margin-bottom: 20px;padding: 0 30px;}
+.suc-tit p{font-size: 24px;color: #333;font-weight: bold;}
+.suc-tit span{display: block;font-size: 12px;color: #999;margin-top: 10px;}
+.re-info{margin: 40px 0 55px;padding-left: 225px;}
+.re-info .li{float: left;margin-right: 38px;font-size: 18px;color: #333;position: relative; }
+.re-fen{background: url(/static/images/jgbg2.png) no-repeat;width: 189px;height: 189px;text-align: center;overflow: hidden;margin-top: 88px;}
+.re-fen em{font-style: normal;font-size: 14px;font-weight: normal;}
+.re-fen p{margin-top: 50px;font-size: 32px;color: #FF5519;font-weight: bold;}
+.re-fen span{display: block;font-size: 24px;color: #999;width: 103px;border-top: 1px solid #EBEBEB;margin: 5px auto 0;padding-top: 5px;}
+.re-info .li.spe .re-fen{background: url(/static/images/jgbg1.png) no-repeat;width: 276px;height: 276px;margin-top: 0;}
+.re-info .li.spe .re-fen p{margin-top: 95px;font-size: 43px;}
+.re-info .li.spe .re-fen p em{font-size: 18px;}
+.re-info .li.spe .re-fen span{font-size: 14px;border-top: none;padding-top: 0;}
+.re-fen-c{position: relative;z-index: 5;}
+.re-info .canvas11{position: absolute;left:38px;top:38px; display: block;z-index: 1;}
+.re-info .canvas22{position: absolute;left:30px;top:117px; display: block;z-index: 1;}
+.ti-count{margin-bottom: 80px;text-align: center;min-height: initial;}
+.ti-count span{display: block;font-size: 18px;color: #333;margin-bottom: 15px;}
+.ti-count table{width: 100%;border: 1px solid #F7F7F7;color: #333;}
+.ti-count table th{height: 48px;background: #F5F5F5;color: #999;}
+.ti-count table tr th:first-child,.ti-count table tr td:first-child{padding-left: 80px;}
+.ti-count table tr th:last-child,.ti-count table tr td:last-child{padding-right: 80px;}
+.ti-count table td{padding: 15px 0;}
+.goon,.confirm{display: inline-block;width: 144px;height: 40px;border-radius: 21px;line-height: 40px;font-size: 16px;color: #FF5519;border: 1px solid #FF5519;margin: 0 14px;}
+.confirm{border-color: #DF230F;color: #DF230F;}
+/* 学习记录 */
+.kclist{padding: 0 30px;}
+.kclist .li{padding: 20px 0;border-bottom: 1px solid #EBEBEB;clear: both;overflow: hidden;align-items: flex-start;}
+.kclist .li:last-child{border-bottom: none;}
+.kcimg{width: 176px;height: 99px;border-radius: 4px;margin-right: 20px;}
+.kcinfo{width: 520px;}
+.kcinfo h3{font-size: 18px;color: #333;text-overflow: ellipsis;white-space: nowrap;overflow: hidden;margin: 5px 0 2px;}
+.process-box{margin: 8px 0;}
+.process-box .process{width: 301px;height: 8px;border-radius: 4px;background: #F5F5F5;position: relative;margin-right: 4px;}
+.process-box .process view{position: absolute;left: 0;top: 0;background: #F8A31D;border-radius: 4px;height: 8px;}
+.process-box span{font-size: 12px;color: #999;line-height: 20px;}
+.kcinfo p{font-size: 12px;}
+.kcinfo p em{font-family: '宋体';font-style: normal;color: #707070;margin: 0 11px;}
+.tkbtn{width:146px;height:42px;background:linear-gradient(90deg,rgba(255,85,25,1) 0%,rgba(223,35,15,1) 100%);border-radius:21px;font-size: 16px;color: #fff;text-align: center;line-height: 42px;margin-top: 32px;display: block;}
+.kclist li a:hover h3{color: #DF230F;}
+.tkbtn:hover{background: #FF5519;}
+.xxwc{width: 100px;height: 100px;}
+/* 首页 */
+.gk-info{min-height: initial;padding: 40px 30px;}
+.gk-info .li{width: 25%;font-size: 26px;color: #1D2129;align-items: flex-start;}
+.gk-info .li image{width: 36px;height: 36px;margin-right: 9px;}
+.gk-info .li text{display: block;font-size: 12px;color: #4E5969;margin-bottom: 5px;}
+.sy-box{min-height: initial;margin-top: 20px;}
+.sye{height: 340px;}
+.idx-nav{justify-content: space-between;}
+.idx-nav .li{width: 461px;}
+.idx-nav .li image{width: 100%;height: 129px;}
+.hb-box{min-height: initial;margin-top: 20px;padding: 20px 15px;margin-bottom: 20px;}
+.sj-tits{font-size: 16px;color: #1D2129;font-weight: bold;}
+.sj-more{font-weight: normal;font-size: 14px;color: #999;}
+.hb-list{flex-wrap: wrap;}
+.hb-list .li{width: 260px;height: 50px;background: #F8F8F8;border-radius: 8px;margin: 20px 20px 0 0;padding: 15px;cursor: pointer;}
+.hb-list .li:nth-child(3n){margin-right: 0;}
+.hb-list .li image{width: 36px;height: 36px;margin-right: 10px;}
+.hb-tit{font-size: 16px;color: #333;}
+.hb-bri{font-size: 13px;color: #999;margin-top: 8px;}
+/* 人员管理 */
+.ry-box{padding: 30px;}
+.download-btn{font-size: 12px;color: var(--main);}
+.dr-btn{width: 54px;height: 30px;border: 1px solid var(--main);border-radius: 3px;font-size: 12px;color: var(--main);text-align: center;line-height: 30px;margin-left: 40px;}
+.c-picker{height: 30px;border: 1px solid #DCDFE6;border-radius: 4px;font-size: 12px;color: #666;padding: 0 12px;line-height: 30px;}
+/* 人员详情 */
+.xq-det{padding: 0 30px;}
+.xq-det-t{border-bottom: 1px solid #EDEEF0;padding: 30px 0 40px;}
+.xq-tit{font-size: 24px;color: #333;font-weight: bold;}
+.xq-time{font-size: 12px;color: #999;font-weight: normal;}
+.xq-res{font-size: 14px;color: #666;margin-top: 18px;}
+.xq-res view{margin-right: 55px;}
+.xq-des{padding: 30px 0 50px;font-size: 12px;color: #666;line-height: 20px;}
+.xq-bot{min-height: initial;padding: 30px;margin-top: 20px;}
+.xq-bot-tit{font-size: 16px;color: #333;font-weight: bold;}
+/* 申报记录 */
+.jl-det{padding: 0 30px 50px;}
+.jl-tit{font-size: 18px;color: #333;font-weight: bold;padding: 30px 0;border-bottom: 1px solid #EDEEF0;}
+.jl-info{flex-wrap: wrap;padding: 30px 0;}
+.jl-info .li{width: 50%;font-size: 16px;color: #303133;padding: 10px 0;}
+.jl-info .li .label{color: #909399;width: 100px;}
+.jl-tits{font-size: 18px;color: #333;font-weight: bold;margin-top: 50px;}
+.jl-file{margin-top: 20px;flex-wrap: wrap;}
+.jl-file image{width: 64px;height: 64px;margin: 0 10px 10px 0;}
+.c-pickers{width: 165px;}
+.c-pickers.uni-combox{height: 30px;line-height: 30px;padding: 0 12px !important;}
+.c-pickers.uni-combox .uni-input-input{font-size: 12px;}
+/* 发布需求 */
+.xq-pop{height: 600px;overflow-y: auto;}
+.fb-form .li{margin-top: 0;margin-right: 30px;}
+.fb-form .li .label{width: auto;}
+.xq-pop-con{height: 450px;}
+.xq-table td{padding: 0 10px;height: 50px;}
+.xq-pop .pop-btn{margin-top: 0}
+.add-xq{font-size: 14px;color: var(--main);}
+.jus-align{justify-content: center;}
+.dp-time{width: 375px;}
+.form-num{margin-top: 25px;}
+.form-num .label{font-size: 14px;color: #666;padding-right: 15px;}
+
+/* 人才交流 */
+.career-logo{width: 50px;height: 50px;border-radius: 5px;float: left;margin-right: 10px;}
+.career-logo image{width: 100%;height: 100%;}
+.career-detail{display: flex;justify-content: space-between;padding: 20px 10px;border-bottom: 1px solid #EDEEF0;}
+.career-detail:hover{background-color: #eeeeee;border-radius: 5px;}
+.career-detail:last-child{border-bottom: none;}
+.career-detail-title{font-weight: bold;}
+.career-detail-address{font-size: 14px;color: #666;margin: 5px 0;}
+.career-detail-salary{font-weight: bold;color: #1597E8;margin-right: 10px;}
+.career-tag{padding: 0px 10px;border: 1px solid #1597E8;color:#1597E8;border-radius: 5px;display:inline-block;font-size:10px;margin-left: 5px;}
+.pb20{padding-bottom: 20px;}

BIN
static/images/back.png


BIN
static/images/back1.png


BIN
static/images/back2.png


BIN
static/images/back3.png


BIN
static/images/bdico1.png


BIN
static/images/bdico2.png


BIN
static/images/bdico3.png


BIN
static/images/bfico1.png


BIN
static/images/bfico1_h.png


BIN
static/images/bg.png


BIN
static/images/bico.png


BIN
static/images/certificate_bottom_bg.png


BIN
static/images/certificate_top_bg.png


BIN
static/images/cjwt.png


BIN
static/images/close.png


BIN
static/images/close1.png


BIN
static/images/delete.png


BIN
static/images/download.png


BIN
static/images/empty.png


BIN
static/images/gou.png


BIN
static/images/guoqi.png


BIN
static/images/idxico1.png


BIN
static/images/idxico2.png


BIN
static/images/idxico3.png


BIN
static/images/idxico4.png


BIN
static/images/idxico5.png


BIN
static/images/ing.png


BIN
static/images/jgbg.png


BIN
static/images/jgbg1.png


BIN
static/images/jgbg2.png


BIN
static/images/jia.png


BIN
static/images/jjico.png


BIN
static/images/ksgg.png


BIN
static/images/loginBg.png


BIN
static/images/logo_home.png


BIN
static/images/navico0.png


BIN
static/images/navico0_h.png


BIN
static/images/navico1.png


BIN
static/images/navico10.png


BIN
static/images/navico10_h.png


BIN
static/images/navico11.png


BIN
static/images/navico11_h.png


BIN
static/images/navico12.png


BIN
static/images/navico12_h.png


BIN
static/images/navico1_h.png


BIN
static/images/navico2.png


BIN
static/images/navico2_h.png


BIN
static/images/navico3.png


BIN
static/images/navico3_h.png


BIN
static/images/navico4.png


BIN
static/images/navico4_h.png


BIN
static/images/navico5.png


BIN
static/images/navico5_h.png


BIN
static/images/navico6.png


BIN
static/images/navico6_h.png


BIN
static/images/navico7.png


BIN
static/images/navico7_h.png


BIN
static/images/navico8.png


BIN
static/images/navico8_h.png


BIN
static/images/navico9.png


BIN
static/images/navico9_h.png


BIN
static/images/next.png


BIN
static/images/note.png


Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff