Prechádzať zdrojové kódy

2022-09-21

1. 新建外围人员独立uniapp项目
2. 调整uniapp-reg项目的 注册逻辑及考试结果页展示
moccus 2 rokov pred
rodič
commit
6bbcce7e31
100 zmenil súbory, kde vykonal 67336 pridanie a 0 odobranie
  1. 20 0
      exam-06173-uni - reg/.hbuilderx/launch.json
  2. 74 0
      exam-06173-uni - reg/App.vue
  3. 21 0
      exam-06173-uni - reg/api/ability/login/wx.js
  4. 11 0
      exam-06173-uni - reg/api/ability/sms.js
  5. 9 0
      exam-06173-uni - reg/api/book.js
  6. 48 0
      exam-06173-uni - reg/api/course.js
  7. 28 0
      exam-06173-uni - reg/api/course/face.js
  8. 89 0
      exam-06173-uni - reg/api/exam.js
  9. 18 0
      exam-06173-uni - reg/api/notice.js
  10. 37 0
      exam-06173-uni - reg/api/paper.js
  11. 8 0
      exam-06173-uni - reg/api/paper/capture.js
  12. 9 0
      exam-06173-uni - reg/api/paper/exam.js
  13. 11 0
      exam-06173-uni - reg/api/points.js
  14. 18 0
      exam-06173-uni - reg/api/qu.js
  15. 27 0
      exam-06173-uni - reg/api/repo/repo.js
  16. 75 0
      exam-06173-uni - reg/api/repo/train.js
  17. 6 0
      exam-06173-uni - reg/api/sys/config/base.js
  18. 5 0
      exam-06173-uni - reg/api/sys/config/cos.js
  19. 5 0
      exam-06173-uni - reg/api/sys/config/oss.js
  20. 5 0
      exam-06173-uni - reg/api/sys/config/qiniu.js
  21. 5 0
      exam-06173-uni - reg/api/sys/config/upload.js
  22. 9 0
      exam-06173-uni - reg/api/sys/depart/depart.js
  23. 9 0
      exam-06173-uni - reg/api/sys/user/bind.js
  24. 11 0
      exam-06173-uni - reg/api/sys/user/user.js
  25. 73 0
      exam-06173-uni - reg/api/user.js
  26. 26 0
      exam-06173-uni - reg/common/config.js
  27. 28 0
      exam-06173-uni - reg/common/file-utils.js
  28. 86 0
      exam-06173-uni - reg/common/filters.js
  29. 97 0
      exam-06173-uni - reg/common/graceChecker.js
  30. 352 0
      exam-06173-uni - reg/common/html-parser.js
  31. 245 0
      exam-06173-uni - reg/common/permission.js
  32. 145 0
      exam-06173-uni - reg/common/request.js
  33. 258 0
      exam-06173-uni - reg/common/upload.js
  34. 46 0
      exam-06173-uni - reg/common/utils.js
  35. 28 0
      exam-06173-uni - reg/common/validate.js
  36. 558 0
      exam-06173-uni - reg/components/cmd-progress/cmd-progress.vue
  37. 185 0
      exam-06173-uni - reg/components/pay-dialog/index.vue
  38. 27 0
      exam-06173-uni - reg/components/u-parse/components/wxParseAudio.vue
  39. 86 0
      exam-06173-uni - reg/components/u-parse/components/wxParseImg.vue
  40. 107 0
      exam-06173-uni - reg/components/u-parse/components/wxParseTemplate0.vue
  41. 99 0
      exam-06173-uni - reg/components/u-parse/components/wxParseTemplate1.vue
  42. 97 0
      exam-06173-uni - reg/components/u-parse/components/wxParseTemplate10.vue
  43. 87 0
      exam-06173-uni - reg/components/u-parse/components/wxParseTemplate11.vue
  44. 98 0
      exam-06173-uni - reg/components/u-parse/components/wxParseTemplate2.vue
  45. 98 0
      exam-06173-uni - reg/components/u-parse/components/wxParseTemplate3.vue
  46. 98 0
      exam-06173-uni - reg/components/u-parse/components/wxParseTemplate4.vue
  47. 98 0
      exam-06173-uni - reg/components/u-parse/components/wxParseTemplate5.vue
  48. 98 0
      exam-06173-uni - reg/components/u-parse/components/wxParseTemplate6.vue
  49. 98 0
      exam-06173-uni - reg/components/u-parse/components/wxParseTemplate7.vue
  50. 98 0
      exam-06173-uni - reg/components/u-parse/components/wxParseTemplate8.vue
  51. 98 0
      exam-06173-uni - reg/components/u-parse/components/wxParseTemplate9.vue
  52. 15 0
      exam-06173-uni - reg/components/u-parse/components/wxParseVideo.vue
  53. 261 0
      exam-06173-uni - reg/components/u-parse/libs/html2json.js
  54. 156 0
      exam-06173-uni - reg/components/u-parse/libs/htmlparser.js
  55. 195 0
      exam-06173-uni - reg/components/u-parse/libs/wxDiscode.js
  56. 102 0
      exam-06173-uni - reg/components/u-parse/readme.md
  57. 232 0
      exam-06173-uni - reg/components/u-parse/u-parse.css
  58. 118 0
      exam-06173-uni - reg/components/u-parse/u-parse.vue
  59. 25 0
      exam-06173-uni - reg/components/uni-status-bar/uni-status-bar.vue
  60. 63 0
      exam-06173-uni - reg/components/yf-carsousel/yf-carsousel.vue
  61. 57 0
      exam-06173-uni - reg/components/yf-empty-view/yf-empty-view.vue
  62. 101 0
      exam-06173-uni - reg/components/yf-file-upload/yf-file-upload.vue
  63. 109 0
      exam-06173-uni - reg/components/yf-more-list/yf-more-list.vue
  64. 150 0
      exam-06173-uni - reg/components/yf-photo-take/yf-photo-take.vue
  65. 14140 0
      exam-06173-uni - reg/hybrid/html/build/pdf.js
  66. 1 0
      exam-06173-uni - reg/hybrid/html/build/pdf.js.map
  67. 47638 0
      exam-06173-uni - reg/hybrid/html/build/pdf.worker.js
  68. 1 0
      exam-06173-uni - reg/hybrid/html/build/pdf.worker.js.map
  69. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/78-EUC-H.bcmap
  70. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/78-EUC-V.bcmap
  71. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/78-H.bcmap
  72. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/78-RKSJ-H.bcmap
  73. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/78-RKSJ-V.bcmap
  74. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/78-V.bcmap
  75. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/78ms-RKSJ-H.bcmap
  76. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/78ms-RKSJ-V.bcmap
  77. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/83pv-RKSJ-H.bcmap
  78. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/90ms-RKSJ-H.bcmap
  79. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/90ms-RKSJ-V.bcmap
  80. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/90msp-RKSJ-H.bcmap
  81. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/90msp-RKSJ-V.bcmap
  82. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/90pv-RKSJ-H.bcmap
  83. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/90pv-RKSJ-V.bcmap
  84. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Add-H.bcmap
  85. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Add-RKSJ-H.bcmap
  86. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Add-RKSJ-V.bcmap
  87. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Add-V.bcmap
  88. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-0.bcmap
  89. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-1.bcmap
  90. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-2.bcmap
  91. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-3.bcmap
  92. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-4.bcmap
  93. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-5.bcmap
  94. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-6.bcmap
  95. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-UCS2.bcmap
  96. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-GB1-0.bcmap
  97. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-GB1-1.bcmap
  98. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-GB1-2.bcmap
  99. BIN
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-GB1-3.bcmap
  100. 0 0
      exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-GB1-4.bcmap

+ 20 - 0
exam-06173-uni - reg/.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": [{
+     	"app-plus" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"default" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"mp-weixin" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"type" : "uniCloud"
+     }
+    ]
+}

+ 74 - 0
exam-06173-uni - reg/App.vue

@@ -0,0 +1,74 @@
+<script>
+	import {
+		login
+	} from '@/api/user.js'
+	import md5 from 'js-md5'
+	export default {
+		onLaunch: function(options) {
+			if(options && options.query && options.query.user){
+				this.getUserInfo({
+					smsCode: "",
+					captchaKey: "",
+					captchaValue: "",
+					username: options.query.user,
+					password: "",
+					mark: ""
+				}).then(res => {
+					if(this.loginCallBack){
+						this.loginCallBack()
+					}
+				})
+			}
+		},
+		onShow: function() {
+
+		},
+		onHide: function() {
+
+		},
+		methods: {
+			getUserInfo(params) {
+				return new Promise((resolve, reject) => {
+					login({
+						...params,
+						mark: md5(params.username + 'gdnxfdexam321')
+					}).then(res => {
+						// 保存本地token
+						uni.setStorageSync('token', res.token);
+						resolve(res)
+					}).catch(err => {
+						reject(err)
+					})
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	/* uni.css - 通用组件、模板样式库,可以当作一套ui库应用 */
+	@import './style/uni.css';
+
+
+	/* 考试相关样式 */
+	@import './style/style.css';
+
+
+
+	/* 重写样式 */
+	.uni-load-more__text {
+		font-size: 14px !important;
+	}
+
+
+
+
+
+	.page-box {
+		padding: 20px;
+		font-size: 14px;
+		display: flex;
+		flex-direction: column;
+		height: 100vh;
+	}
+</style>

+ 21 - 0
exam-06173-uni - reg/api/ability/login/wx.js

@@ -0,0 +1,21 @@
+import request from '@/common/request.js'
+
+
+/**
+ * 调用微信登录
+ * @param id
+ * @returns {*}
+ */
+export function wxLogin(data) {
+  return request.post('/api/common/wx/login', data)
+}
+
+
+/**
+ * 获取微信登录的URL
+ * @param id
+ * @returns {*}
+ */
+export function apiGetWechatUrl(data) {
+  return request.post('/api/common/wx/get-url', data)
+}

+ 11 - 0
exam-06173-uni - reg/api/ability/sms.js

@@ -0,0 +1,11 @@
+import request from '@/common/request.js'
+
+
+/**
+ * 发送短信验证码
+ * @param id
+ * @returns {*}
+ */
+export function send(data) {
+  return request.post('/api/common/sms/send', data)
+}

+ 9 - 0
exam-06173-uni - reg/api/book.js

@@ -0,0 +1,9 @@
+import request from '@/common/request.js'
+
+/**
+ * 获取考试列表
+ * @param {Object} data
+ */
+export function bookPaging(data) {
+	return request.post('/api/user/wrong-book/paging', data);
+}

+ 48 - 0
exam-06173-uni - reg/api/course.js

@@ -0,0 +1,48 @@
+import request from '@/common/request.js'
+
+
+/**
+ * 获取考试列表
+ * @param {Object} data
+ */
+export function coursePaging(data) {
+	return request.post('/api/course/course/user-paging', data);
+}
+
+/**
+ * 获取考试详情
+ * @param {Object} id
+ */
+export function fetchDetail(id) {
+	return request.post('/api/course/course/detail', { id: id});
+}
+
+
+/**
+ * 课程文件列表
+ * @param {Object} id
+ */
+export function fetchLearnList(id) {
+	return request.post('/api/course/file/learn/list', { courseId: id});
+}
+
+
+/**
+ * 校验文件
+ * @param {Object} data
+ */
+export function apiCheckFile(data) {
+	return request.post('/api/course/file/check-file', data);
+}
+
+
+/**
+ * 获取基础详情
+ * @param {} id 
+ */
+export function simpleDetail(id) {
+	return request.post('/api/course/course/simple-detail', {id: id});
+}
+
+
+

+ 28 - 0
exam-06173-uni - reg/api/course/face.js

@@ -0,0 +1,28 @@
+import request from '@/common/request.js'
+
+/**
+ * 保存截图
+ * @param data
+ * @returns {Promise}
+ */
+export function saveCapture(data) {
+  return request.post('/api/course/face/save', data)
+}
+
+/**
+ * 校验人脸
+ * @param data
+ * @returns {Promise}
+ */
+export function checkFace(data) {
+  return request.post('/api/course/face/check', data)
+}
+
+/**
+ * 保存校验数据
+ * @param data
+ * @returns {Promise}
+ */
+export function saveCheck(data) {
+  return request.post('/api/course/face/save-check', data)
+}

+ 89 - 0
exam-06173-uni - reg/api/exam.js

@@ -0,0 +1,89 @@
+import request from '@/common/request.js'
+
+
+/**
+ * 获取考试列表
+ * @param {Object} data
+ */
+export function examPaging(data) {
+	return request.post('/api/exam/exam/online-paging', data);
+}
+
+/**
+ * 获取考试详情
+ * @param {Object} id
+ */
+export function examDetail(id) {
+	return request.post('/api/exam/exam/detail', { id: id});
+}
+
+/**
+ * 创建试卷
+ * @param {Object} id
+ */
+export function createPaper(data) {
+	return request.post('/api/paper/paper/create-paper', data);
+}
+
+/**
+ * 获取试卷详情
+ * @param {Object} id
+ */
+export function paperDetail(id) {
+	return request.post('/api/paper/paper/paper-detail', { id: id});
+}
+
+
+/**
+ * 试卷详情
+ * @param data
+ */
+export function paperResult(id) {
+	return request.post('/api/paper/paper/paper-result', { id: id});
+}
+
+/**
+ * 获取题目详情
+ * @param {Object} id
+ */
+export function paperQuDetail(paperId, quId) {
+	return request.post('/api/paper/paper/qu-detail', { paperId: paperId, quId: quId});
+}
+
+/**
+ * 填充答案
+ * @param {Object} id
+ */
+export function fillAnswer(data) {
+	return request.post('/api/paper/paper/fill-answer', data);
+}
+
+/**
+ * 交卷
+ * @param {Object} id
+ */
+export function handExam(data) {
+	return request.post('/api/paper/paper/hand-exam', data);
+}
+
+
+
+
+
+/**
+ * 检查是否有进行中的考试
+ * @returns {*}
+ */
+export function checkProcess() {
+  return request.post('/api/paper/paper/check-process', {})
+}
+
+
+/**
+ * 校验考试信息
+ * @param id
+ * @returns {*}
+ */
+export function checkInfo(id) {
+  return request.post('/api/exam/exam/check-info', { id: id })
+}

+ 18 - 0
exam-06173-uni - reg/api/notice.js

@@ -0,0 +1,18 @@
+import request from '@/common/request.js'
+
+
+/**
+ * 公告列表
+ * @param {Object} data
+ */
+export function noticePaging(data) {
+	return request.post('/api/sys/notice/paging', data);
+}
+
+/**
+ * 公告详情
+ * @param {Object} id
+ */
+export function noticeDetail(id) {
+	return request.post('/api/sys/notice/detail', { id: id});
+}

+ 37 - 0
exam-06173-uni - reg/api/paper.js

@@ -0,0 +1,37 @@
+import request from '@/common/request.js'
+
+
+/**
+ * 获取考试列表
+ * @param {Object} data
+ */
+export function totalPaging(data) {
+	return request.post('/api/user/exam/my-paging', data);
+}
+
+/**
+ * 获取考试详情
+ * @param {Object} id
+ */
+export function examDetail(id) {
+	return request.post('/api/exam/exam/detail', { id: id});
+}
+
+/**
+ * 获取考试列表
+ * @param {Object} data
+ */
+export function paperPaging(data) {
+	return request.post('/api/paper/paper/my-paging', data);
+}
+
+/**
+ * 获取考试列表
+ * @param {Object} data
+ */
+export function paperResult(id) {
+	return request.post('/api/paper/paper/paper-result', { id: id});
+}
+
+
+

+ 8 - 0
exam-06173-uni - reg/api/paper/capture.js

@@ -0,0 +1,8 @@
+import request from '@/common/request.js'
+/**
+ * 保存截图
+ * @param data
+ */
+export function saveCapture(data) {
+  return request.post('/api/paper/capture/save', data)
+}

+ 9 - 0
exam-06173-uni - reg/api/paper/exam.js

@@ -0,0 +1,9 @@
+import request from '@/common/request.js'
+
+/**
+ * 离开检查
+ * @param data
+ */
+export function leaveIncr(data) {
+  return request.post('/api/paper/paper/leave-incr', data)
+}

+ 11 - 0
exam-06173-uni - reg/api/points.js

@@ -0,0 +1,11 @@
+import request from '@/common/request.js'
+
+/**
+ * 积分日志
+ * @param {Object} data
+ */
+export function pointsPaging(data) {
+	return request.post('/api/user/points/my-paging', data);
+}
+
+

+ 18 - 0
exam-06173-uni - reg/api/qu.js

@@ -0,0 +1,18 @@
+import request from '@/common/request.js'
+
+/**
+ * 题库详情
+ * @param data
+ */
+export function fetchDetail(id) {
+  return request.post('/api/qu/qu/detail', { id: id })
+}
+
+/**
+ * 题库详情
+ * @param data
+ */
+export function fetchDetailForTrain(id) {
+  return request.post('/api/qu/qu/detail-for-train', { id: id })
+}
+

+ 27 - 0
exam-06173-uni - reg/api/repo/repo.js

@@ -0,0 +1,27 @@
+import request from '@/common/request.js'
+
+/**
+ * 题库列表
+ * @param {Object} data
+ */
+export function repoPaging(data) {
+	return request.post('/api/repo/user-paging', data);
+}
+
+
+/**
+ * 题库详情
+ * @param {Object} id
+ */
+export function repoDetail(id) {
+	return request.post('/api/repo/detail', {id: id});
+}
+
+
+/**
+ * 查找最新的训练
+ * @returns {*}
+ */
+export function checkProcess() {
+  return request.post('/api/repo/train/check', {})
+}

+ 75 - 0
exam-06173-uni - reg/api/repo/train.js

@@ -0,0 +1,75 @@
+import request from '@/common/request.js'
+/**
+ * 开始训练了
+ * @param mode
+ * @param repoId
+ * @param userId
+ * @returns {*}
+ */
+export function startTrain(mode, repoId, userId, clear) {
+  return request.post('/api/repo/train/start', { mode: mode, repoId: repoId, userId: userId, clear: clear })
+}
+
+/**
+ * 是否存在训练
+ * @param mode
+ * @param repoId
+ * @param userId
+ * @returns {*}
+ */
+export function hasTrain(mode, repoId, userId) {
+  return request.post('/api/repo/train/check', { mode: mode, repoId: repoId, userId: userId })
+}
+
+/**
+ * 查找答题卡
+ * @param mode
+ * @param repoId
+ * @param userId
+ * @returns {*}
+ */
+export function listCard(trainId) {
+  return request.post('/api/repo/train/card', { id: trainId })
+}
+
+
+/**
+ * 开始训练了
+ * @param mode
+ * @param repoId
+ * @param userId
+ * @returns {*}
+ */
+export function fillResult(data) {
+  return request.post('/api/repo/train/fill', data)
+}
+
+
+/**
+ * 手动结束训练
+ * @param trainId
+ * @returns {*}
+ */
+export function finishTrain(trainId) {
+  return request.post('/api/repo/train/finish', { id: trainId })
+}
+
+/**
+ * 查找训练题目详情
+ * @param trainId
+ * @param quId
+ * @returns {Promise}
+ */
+export function quDetail(trainId, quId) {
+  return request.post('/api/repo/train/qu-detail', { trainId: trainId, quId: quId })
+}
+
+/**
+ * 训练记录
+ * @param {Object} data
+ */
+export function trainPaging(data) {
+  return request.post('/api/repo/train/paging', data)
+}
+
+

+ 6 - 0
exam-06173-uni - reg/api/sys/config/base.js

@@ -0,0 +1,6 @@
+import request from '@/common/request.js'
+
+export function fetchDetail() {
+  return request.post('/api/sys/config/detail', { id: '1' })
+}
+

+ 5 - 0
exam-06173-uni - reg/api/sys/config/cos.js

@@ -0,0 +1,5 @@
+import request from '@/common/request'
+
+export function fetchToken() {
+  return request.post('/api/common/cos/token')
+}

+ 5 - 0
exam-06173-uni - reg/api/sys/config/oss.js

@@ -0,0 +1,5 @@
+import request from '@/common/request.js'
+
+export function fetchToken() {
+  return request.post('/api/common/oss/token')
+}

+ 5 - 0
exam-06173-uni - reg/api/sys/config/qiniu.js

@@ -0,0 +1,5 @@
+import request from '@/common/request.js'
+
+export function fetchToken() {
+  return request.post('/api/common/qiniu/token')
+}

+ 5 - 0
exam-06173-uni - reg/api/sys/config/upload.js

@@ -0,0 +1,5 @@
+import request from '@/common/request.js'
+
+export function fetchDetail() {
+  return request.post('/api/sys/config/upload/detail', { provider: '' })
+}

+ 9 - 0
exam-06173-uni - reg/api/sys/depart/depart.js

@@ -0,0 +1,9 @@
+import request from '@/common/request.js'
+
+export function fetchTree(data) {
+  return request.post('/api/sys/depart/tree', data)
+}
+
+export function fetchTreeSelect(data) {
+  return request.post('/api/sys/depart/tree-select', data)
+}

+ 9 - 0
exam-06173-uni - reg/api/sys/user/bind.js

@@ -0,0 +1,9 @@
+import request from '@/common/request.js'
+
+export function bindMobile(data) {
+  return request.post('/api/sys/user/bind/bind-mobile', data)
+}
+
+export function unBindMobile(data) {
+  return request.post('/api/sys/user/bind/unbind-mobile', data)
+}

+ 11 - 0
exam-06173-uni - reg/api/sys/user/user.js

@@ -0,0 +1,11 @@
+import request from '@/common/request.js'
+
+export function faceCheck(data) {
+  return request.post('/api/sys/user/face-check', data)
+}
+
+
+
+export function faceLogin(data) {
+  return request.post('/api/sys/user/face-login', data)
+}

+ 73 - 0
exam-06173-uni - reg/api/user.js

@@ -0,0 +1,73 @@
+import request from '@/common/request.js'
+
+/**
+ * 用户快速注册
+ * @param {Object} userName
+ * @param {Object} realName
+ */
+export function logout() {
+	return request.post('/api/sys/user/logout', {});
+}
+
+/**
+ * 用户快速注册
+ * @param {Object} userName
+ * @param {Object} realName
+ */
+export function info(token) {
+	return request.post('/api/sys/user/info', {token: token});
+}
+
+/**
+ * 修改用户资料
+ * @param {Object} data
+ */
+export function update(data) {
+	return request.post('/api/sys/user/update', data);
+}
+
+/**
+ * 用户登录
+ * @param {Object} data
+ */
+export function login(data) {
+	return request.post('/api/sys/user/login', data);
+}
+
+/**
+ * 用户注册
+ * @param {Object} data
+ */
+export function userReg(data) {
+	return request.post('/api/sys/user/reg', data);
+}
+
+
+/**
+ * 用户快速注册
+ * @param {Object} userName
+ * @param {Object} realName
+ */
+export function updatePass(data) {
+	return request.post('/api/sys/user/update-pass', data);
+}
+
+
+/**
+ * 手机号码登录
+ * @param {Object} data
+ */
+export function mobileLogin(data) {
+  return request.post('/api/sys/user/mobile-login', data)
+}
+
+/**
+ * 重置密码
+ * @param {Object} data
+ */
+export function resetPass(data) {
+  return request.post('/api/sys/user/reset-pass', data)
+}
+
+
+

+ 26 - 0
exam-06173-uni - reg/common/config.js

@@ -0,0 +1,26 @@
+let urls = {
+	api: '',
+	socket: ''
+}
+
+if(process.env.NODE_ENV === 'development'){
+    // 开发环境
+    // urls.api = 'http://localhost:8617'
+    // urls.socket = 'ws://localhost:8617'
+	urls.api = 'http://124.70.18.168:8617'
+	urls.socket = 'ws://124.70.18.168:8617'
+}else{
+    // t2预发布环境
+    // urls.api = 'https://t2-api.jeegen.com'
+    // urls.socket = 'wss://t2-api.jeegen.com'
+	
+	// 生产环境
+	urls.api = 'http://10.155.32.18:8617'
+	urls.socket = 'ws://10.155.32.18:8617'
+	
+	// 同域
+	// urls.api = ''
+	// urls.socket = ''
+}
+
+export default urls

+ 28 - 0
exam-06173-uni - reg/common/file-utils.js

@@ -0,0 +1,28 @@
+/**
+ * 生成随机文件名称
+ * 规则八位随机字符,加下划线连接时间戳
+ */
+export const buildDir = () => {
+  // 以日期作为目录
+  const date = new Date()
+  const dir = date.getFullYear() + '/' + (date.getMonth() + 1) + '/' + date.getDate()
+
+  function rx() {
+    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
+  }
+  return `${dir}/${date.getTime()}-${rx()}${rx()}`
+}
+
+/**
+ * 获取文件名并构建新的文件名称
+ * 必须包含后缀
+ */
+export const buildName = (name) => {
+	const index = name.lastIndexOf('.') + 1
+	const format = name.substring(
+		index,
+		name.length
+	)
+	return buildDir() + '.' + format
+}
+

+ 86 - 0
exam-06173-uni - reg/common/filters.js

@@ -0,0 +1,86 @@
+export function quTypeFilter(value) {
+  const map = {
+    '1': '单选题',
+    '2': '多选题',
+    '3': '判断题',
+    '4': '简答题'
+  }
+  return map[value]
+}
+
+export function examResultFilter(value) {
+  const map = {
+    '1': '合格',
+    '0': '不合格'
+  }
+  return map[value]
+}
+
+export function paperStateFilter(value) {
+  const map = {
+    '0': '考试中',
+    '1': '待阅卷',
+    '2': '已考完',
+    '3': '!已弃考'
+  }
+  return map[value]
+}
+
+export function examOpenType(value) {
+  const map = {
+    '1': '完全公开',
+    '2': '指定部门',
+    '3': '需要密码'
+  }
+  return map[value]
+}
+
+export function examStateFilter(value) {
+  const map = {
+    '0': '进行中',
+    '1': '已禁用',
+    '2': '待开始',
+    '3': '已结束'
+  }
+  return map[value]
+}
+
+export function quLevelFilter(value) {
+  const map = {
+    '1': '普通',
+    '2': '较难'
+  }
+  return map[value]
+}
+
+/**
+ * 处理富文本里的图片宽度自适应
+ * 1.去掉img标签里的style、width、height属性
+ * 2.img标签添加style属性:max-width:100%;height:auto
+ * 3.修改所有style里的width属性为max-width:100%
+ * 4.去掉<br/>标签
+ * @param html
+ * @returns {void|string|*}
+ */
+export function formatRichText (html) { //控制小程序中图片大小
+
+	if(!html){
+		return ''
+	}
+	
+	let newContent= html.replace(/<img[^>]*>/gi,function(match,capture){
+		match = match.replace(/style="[^"]+"/gi, '').replace(/style='[^']+'/gi, '');
+		match = match.replace(/width="[^"]+"/gi, '').replace(/width='[^']+'/gi, '');
+		match = match.replace(/height="[^"]+"/gi, '').replace(/height='[^']+'/gi, '');
+		return match;
+	});
+	newContent = newContent.replace(/style="[^"]+"/gi,function(match,capture){
+		match = match.replace(/width:[^;]+;/gi, 'max-width:100%;').replace(/width:[^;]+;/gi, 'max-width:100%;');
+		return match;
+	});
+	// newContent = newContent.replace(/<br[^>]*\/>/gi, '');
+	newContent = newContent.replace(/\<img/gi, '<img style="max-width:100%;height:auto;display:inline-block;margin:10rpx auto;"');
+	
+	return newContent;
+}	
+

+ 97 - 0
exam-06173-uni - reg/common/graceChecker.js

@@ -0,0 +1,97 @@
+/**
+数据验证(表单验证)
+来自 grace.hcoder.net 
+作者 hcoder 深海
+*/
+module.exports = {
+	error:'',
+	check : function (data, rule){
+		for(var i = 0; i < rule.length; i++){
+			if (!rule[i].checkType){return true;}
+			if (!rule[i].name) {return true;}
+			if (!rule[i].errorMsg) {return true;}
+			if (!data[rule[i].name]) {this.error = rule[i].errorMsg; return false;}
+			switch (rule[i].checkType){
+				case 'string':
+					var reg = new RegExp('^.{' + rule[i].checkRule + '}$');
+					if(!reg.test(data[rule[i].name])) {this.error = rule[i].errorMsg; return false;}
+				break;
+				case 'int':
+					var reg = new RegExp('^(-[1-9]|[1-9])[0-9]{' + rule[i].checkRule + '}$');
+					if(!reg.test(data[rule[i].name])) {this.error = rule[i].errorMsg; return false;}
+					break;
+				break;
+				case 'between':
+					if (!this.isNumber(data[rule[i].name])){
+						this.error = rule[i].errorMsg;
+						return false;
+					}
+					var minMax = rule[i].checkRule.split(',');
+					minMax[0] = Number(minMax[0]);
+					minMax[1] = Number(minMax[1]);
+					if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
+						this.error = rule[i].errorMsg;
+						return false;
+					}
+				break;
+				case 'betweenD':
+					var reg = /^-?[1-9][0-9]?$/;
+					if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
+					var minMax = rule[i].checkRule.split(',');
+					minMax[0] = Number(minMax[0]);
+					minMax[1] = Number(minMax[1]);
+					if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
+						this.error = rule[i].errorMsg;
+						return false;
+					}
+				break;
+				case 'betweenF': 
+					var reg = /^-?[0-9][0-9]?.+[0-9]+$/;
+					if (!reg.test(data[rule[i].name])){this.error = rule[i].errorMsg; return false;}
+					var minMax = rule[i].checkRule.split(',');
+					minMax[0] = Number(minMax[0]);
+					minMax[1] = Number(minMax[1]);
+					if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
+						this.error = rule[i].errorMsg;
+						return false;
+					}
+				break;
+				case 'same':
+					if (data[rule[i].name] != rule[i].checkRule) { this.error = rule[i].errorMsg; return false;}
+				break;
+				case 'notsame':
+					if (data[rule[i].name] == rule[i].checkRule) { this.error = rule[i].errorMsg; return false; }
+				break;
+				case 'email':
+					var reg = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
+					if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
+				break;
+				case 'phoneno':
+					var reg = /^1[0-9]{10,10}$/;
+					if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
+				break;
+				case 'zipcode':
+					var reg = /^[0-9]{6}$/;
+					if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
+				break;
+				case 'reg':
+					var reg = new RegExp(rule[i].checkRule);
+					if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
+				break;
+				case 'in':
+					if(rule[i].checkRule.indexOf(data[rule[i].name]) == -1){
+						this.error = rule[i].errorMsg; return false;
+					}
+				break;
+				case 'notnull':
+					if(data[rule[i].name] == null || data[rule[i].name].length < 1){this.error = rule[i].errorMsg; return false;}
+				break;
+			}
+		}
+		return true;
+	},
+	isNumber : function (checkVal){
+		var reg = /^-?[1-9][0-9]?.?[0-9]*$/;
+		return reg.test(checkVal);
+	}
+}

+ 352 - 0
exam-06173-uni - reg/common/html-parser.js

@@ -0,0 +1,352 @@
+/*
+ * HTML5 Parser By Sam Blowes
+ *
+ * Designed for HTML5 documents
+ *
+ * Original code by John Resig (ejohn.org)
+ * http://ejohn.org/blog/pure-javascript-html-parser/
+ * Original code by Erik Arvidsson, Mozilla Public License
+ * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
+ *
+ * ----------------------------------------------------------------------------
+ * License
+ * ----------------------------------------------------------------------------
+ *
+ * This code is triple licensed using Apache Software License 2.0,
+ * Mozilla Public License or GNU Public License
+ *
+ * ////////////////////////////////////////////////////////////////////////////
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.  You may obtain a copy
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ////////////////////////////////////////////////////////////////////////////
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is Simple HTML Parser.
+ *
+ * The Initial Developer of the Original Code is Erik Arvidsson.
+ * Portions created by Erik Arvidssson are Copyright (C) 2004. All Rights
+ * Reserved.
+ *
+ * ////////////////////////////////////////////////////////////////////////////
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * ----------------------------------------------------------------------------
+ * Usage
+ * ----------------------------------------------------------------------------
+ *
+ * // Use like so:
+ * HTMLParser(htmlString, {
+ *     start: function(tag, attrs, unary) {},
+ *     end: function(tag) {},
+ *     chars: function(text) {},
+ *     comment: function(text) {}
+ * });
+ *
+ * // or to get an XML string:
+ * HTMLtoXML(htmlString);
+ *
+ * // or to get an XML DOM Document
+ * HTMLtoDOM(htmlString);
+ *
+ * // or to inject into an existing document/DOM node
+ * HTMLtoDOM(htmlString, document);
+ * HTMLtoDOM(htmlString, document.body);
+ *
+ */
+// Regular Expressions for parsing tags and attributes
+var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
+var endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
+var attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; // Empty Elements - HTML 5
+
+var empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr'); // Block Elements - HTML 5
+// fixed by xxx 将 ins 标签从块级名单中移除
+
+var block = makeMap('a,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video'); // Inline Elements - HTML 5
+
+var inline = makeMap('abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'); // Elements that you can, intentionally, leave open
+// (and which close themselves)
+
+var closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'); // Attributes that have their values filled in disabled="disabled"
+
+var fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected'); // Special Elements (can contain anything)
+
+var special = makeMap('script,style');
+function HTMLParser(html, handler) {
+  var index;
+  var chars;
+  var match;
+  var stack = [];
+  var last = html;
+
+  stack.last = function () {
+    return this[this.length - 1];
+  };
+
+  while (html) {
+    chars = true; // Make sure we're not in a script or style element
+
+    if (!stack.last() || !special[stack.last()]) {
+      // Comment
+      if (html.indexOf('<!--') == 0) {
+        index = html.indexOf('-->');
+
+        if (index >= 0) {
+          if (handler.comment) {
+            handler.comment(html.substring(4, index));
+          }
+
+          html = html.substring(index + 3);
+          chars = false;
+        } // end tag
+
+      } else if (html.indexOf('</') == 0) {
+        match = html.match(endTag);
+
+        if (match) {
+          html = html.substring(match[0].length);
+          match[0].replace(endTag, parseEndTag);
+          chars = false;
+        } // start tag
+
+      } else if (html.indexOf('<') == 0) {
+        match = html.match(startTag);
+
+        if (match) {
+          html = html.substring(match[0].length);
+          match[0].replace(startTag, parseStartTag);
+          chars = false;
+        }
+      }
+
+      if (chars) {
+        index = html.indexOf('<');
+        var text = index < 0 ? html : html.substring(0, index);
+        html = index < 0 ? '' : html.substring(index);
+
+        if (handler.chars) {
+          handler.chars(text);
+        }
+      }
+    } else {
+      html = html.replace(new RegExp('([\\s\\S]*?)<\/' + stack.last() + '[^>]*>'), function (all, text) {
+        text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, '$1$2');
+
+        if (handler.chars) {
+          handler.chars(text);
+        }
+
+        return '';
+      });
+      parseEndTag('', stack.last());
+    }
+
+    if (html == last) {
+      throw 'Parse Error: ' + html;
+    }
+
+    last = html;
+  } // Clean up any remaining tags
+
+
+  parseEndTag();
+
+  function parseStartTag(tag, tagName, rest, unary) {
+    tagName = tagName.toLowerCase();
+
+    if (block[tagName]) {
+      while (stack.last() && inline[stack.last()]) {
+        parseEndTag('', stack.last());
+      }
+    }
+
+    if (closeSelf[tagName] && stack.last() == tagName) {
+      parseEndTag('', tagName);
+    }
+
+    unary = empty[tagName] || !!unary;
+
+    if (!unary) {
+      stack.push(tagName);
+    }
+
+    if (handler.start) {
+      var attrs = [];
+      rest.replace(attr, function (match, name) {
+        var value = arguments[2] ? arguments[2] : arguments[3] ? arguments[3] : arguments[4] ? arguments[4] : fillAttrs[name] ? name : '';
+        attrs.push({
+          name: name,
+          value: value,
+          escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') // "
+
+        });
+      });
+
+      if (handler.start) {
+        handler.start(tagName, attrs, unary);
+      }
+    }
+  }
+
+  function parseEndTag(tag, tagName) {
+    // If no tag name is provided, clean shop
+    if (!tagName) {
+      var pos = 0;
+    } // Find the closest opened tag of the same type
+    else {
+        for (var pos = stack.length - 1; pos >= 0; pos--) {
+          if (stack[pos] == tagName) {
+            break;
+          }
+        }
+      }
+
+    if (pos >= 0) {
+      // Close all the open elements, up the stack
+      for (var i = stack.length - 1; i >= pos; i--) {
+        if (handler.end) {
+          handler.end(stack[i]);
+        }
+      } // Remove the open elements from the stack
+
+
+      stack.length = pos;
+    }
+  }
+}
+
+function makeMap(str) {
+  var obj = {};
+  var items = str.split(',');
+
+  for (var i = 0; i < items.length; i++) {
+    obj[items[i]] = true;
+  }
+
+  return obj;
+}
+
+function removeDOCTYPE(html) {
+  return html.replace(/<\?xml.*\?>\n/, '').replace(/<!doctype.*>\n/, '').replace(/<!DOCTYPE.*>\n/, '');
+}
+
+function parseAttrs(attrs) {
+  return attrs.reduce(function (pre, attr) {
+    var value = attr.value;
+    var name = attr.name;
+
+    if (pre[name]) {
+			pre[name] = pre[name] + " " + value;
+    } else {
+			pre[name] = value;
+    }
+
+    return pre;
+  }, {});
+}
+
+function parseHtml(html) {
+  html = removeDOCTYPE(html);
+  var stacks = [];
+  var results = {
+    node: 'root',
+    children: []
+  };
+  HTMLParser(html, {
+    start: function start(tag, attrs, unary) {
+      var node = {
+        name: tag
+      };
+
+      if (attrs.length !== 0) {
+        node.attrs = parseAttrs(attrs);
+      }
+
+      if (unary) {
+        var parent = stacks[0] || results;
+
+        if (!parent.children) {
+          parent.children = [];
+        }
+
+        parent.children.push(node);
+      } else {
+        stacks.unshift(node);
+      }
+    },
+    end: function end(tag) {
+      var node = stacks.shift();
+      if (node.name !== tag) console.error('invalid state: mismatch end tag');
+
+      if (stacks.length === 0) {
+        results.children.push(node);
+      } else {
+        var parent = stacks[0];
+
+        if (!parent.children) {
+          parent.children = [];
+        }
+
+        parent.children.push(node);
+      }
+    },
+    chars: function chars(text) {
+      var node = {
+        type: 'text',
+        text: text
+      };
+
+      if (stacks.length === 0) {
+        results.children.push(node);
+      } else {
+        var parent = stacks[0];
+
+        if (!parent.children) {
+          parent.children = [];
+        }
+
+        parent.children.push(node);
+      }
+    },
+    comment: function comment(text) {
+      var node = {
+        node: 'comment',
+        text: text
+      };
+      var parent = stacks[0];
+
+      if (!parent.children) {
+        parent.children = [];
+      }
+
+      parent.children.push(node);
+    }
+  });
+  return results.children;
+}
+
+export default parseHtml;

+ 245 - 0
exam-06173-uni - reg/common/permission.js

@@ -0,0 +1,245 @@
+/// null = 未请求,1 = 已允许,0 = 拒绝|受限, 2 = 系统未开启
+
+var isIOS
+
+function album() {
+    var result = 0;
+    var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
+    var authStatus = PHPhotoLibrary.authorizationStatus();
+    if (authStatus === 0) {
+        result = null;
+    } else if (authStatus == 3) {
+        result = 1;
+    } else {
+        result = 0;
+    }
+    plus.ios.deleteObject(PHPhotoLibrary);
+    return result;
+}
+
+function camera() {
+    var result = 0;
+    var AVCaptureDevice = plus.ios.import("AVCaptureDevice");
+    var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');
+    if (authStatus === 0) {
+        result = null;
+    } else if (authStatus == 3) {
+        result = 1;
+    } else {
+        result = 0;
+    }
+    plus.ios.deleteObject(AVCaptureDevice);
+    return result;
+}
+
+function location() {
+    var result = 0;
+    var cllocationManger = plus.ios.import("CLLocationManager");
+    var enable = cllocationManger.locationServicesEnabled();
+    var status = cllocationManger.authorizationStatus();
+    if (!enable) {
+        result = 2;
+    } else if (status === 0) {
+        result = null;
+    } else if (status === 3 || status === 4) {
+        result = 1;
+    } else {
+        result = 0;
+    }
+    plus.ios.deleteObject(cllocationManger);
+    return result;
+}
+
+function push() {
+    var result = 0;
+    var UIApplication = plus.ios.import("UIApplication");
+    var app = UIApplication.sharedApplication();
+    var enabledTypes = 0;
+    if (app.currentUserNotificationSettings) {
+        var settings = app.currentUserNotificationSettings();
+        enabledTypes = settings.plusGetAttribute("types");
+        if (enabledTypes == 0) {
+            result = 0;
+            console.log("推送权限没有开启");
+        } else {
+            result = 1;
+            console.log("已经开启推送功能!")
+        }
+        plus.ios.deleteObject(settings);
+    } else {
+        enabledTypes = app.enabledRemoteNotificationTypes();
+        if (enabledTypes == 0) {
+            result = 3;
+            console.log("推送权限没有开启!");
+        } else {
+            result = 4;
+            console.log("已经开启推送功能!")
+        }
+    }
+    plus.ios.deleteObject(app);
+    plus.ios.deleteObject(UIApplication);
+    return result;
+}
+
+function contact() {
+    var result = 0;
+    var CNContactStore = plus.ios.import("CNContactStore");
+    var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
+    if (cnAuthStatus === 0) {
+        result = null;
+    } else if (cnAuthStatus == 3) {
+        result = 1;
+    } else {
+        result = 0;
+    }
+    plus.ios.deleteObject(CNContactStore);
+    return result;
+}
+
+function record() {
+    var result = null;
+    var avaudiosession = plus.ios.import("AVAudioSession");
+    var avaudio = avaudiosession.sharedInstance();
+    var status = avaudio.recordPermission();
+    console.log("permissionStatus:" + status);
+    if (status === 1970168948) {
+        result = null;
+    } else if (status === 1735552628) {
+        result = 1;
+    } else {
+        result = 0;
+    }
+    plus.ios.deleteObject(avaudiosession);
+    return result;
+}
+
+function calendar() {
+    var result = null;
+    var EKEventStore = plus.ios.import("EKEventStore");
+    var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
+    if (ekAuthStatus == 3) {
+        result = 1;
+        console.log("日历权限已经开启");
+    } else {
+        console.log("日历权限没有开启");
+    }
+    plus.ios.deleteObject(EKEventStore);
+    return result;
+}
+
+function memo() {
+    var result = null;
+    var EKEventStore = plus.ios.import("EKEventStore");
+    var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
+    if (ekAuthStatus == 3) {
+        result = 1;
+        console.log("备忘录权限已经开启");
+    } else {
+        console.log("备忘录权限没有开启");
+    }
+    plus.ios.deleteObject(EKEventStore);
+    return result;
+}
+
+
+function requestIOS(permissionID) {
+    return new Promise((resolve, reject) => {
+        switch (permissionID) {
+            case "push":
+                resolve(push());
+                break;
+            case "location":
+                resolve(location());
+                break;
+            case "record":
+                resolve(record());
+                break;
+            case "camera":
+                resolve(camera());
+                break;
+            case "album":
+                resolve(album());
+                break;
+            case "contact":
+                resolve(contact());
+                break;
+            case "calendar":
+                resolve(calendar());
+                break;
+            case "memo":
+                resolve(memo());
+                break;
+            default:
+                resolve(0);
+                break;
+        }
+    });
+}
+
+function requestAndroid(permissionID) {
+    return new Promise((resolve, reject) => {
+        plus.android.requestPermissions(
+            [permissionID],
+            function(resultObj) {
+                var result = 0;
+                for (var i = 0; i < resultObj.granted.length; i++) {
+                    var grantedPermission = resultObj.granted[i];
+                    console.log('已获取的权限:' + grantedPermission);
+                    result = 1
+                }
+                for (var i = 0; i < resultObj.deniedPresent.length; i++) {
+                    var deniedPresentPermission = resultObj.deniedPresent[i];
+                    console.log('拒绝本次申请的权限:' + deniedPresentPermission);
+                    result = 0
+                }
+                for (var i = 0; i < resultObj.deniedAlways.length; i++) {
+                    var deniedAlwaysPermission = resultObj.deniedAlways[i];
+                    console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
+                    result = -1
+                }
+                resolve(result);
+            },
+            function(error) {
+                console.log('result error: ' + error.message)
+                resolve({
+                    code: error.code,
+                    message: error.message
+                });
+            }
+        );
+    });
+}
+
+function gotoAppPermissionSetting() {
+    if (permission.isIOS) {
+        var UIApplication = plus.ios.import("UIApplication");
+        var application2 = UIApplication.sharedApplication();
+        var NSURL2 = plus.ios.import("NSURL");
+        var setting2 = NSURL2.URLWithString("app-settings:");
+        application2.openURL(setting2);
+        plus.ios.deleteObject(setting2);
+        plus.ios.deleteObject(NSURL2);
+        plus.ios.deleteObject(application2);
+    } else {
+        var Intent = plus.android.importClass("android.content.Intent");
+        var Settings = plus.android.importClass("android.provider.Settings");
+        var Uri = plus.android.importClass("android.net.Uri");
+        var mainActivity = plus.android.runtimeMainActivity();
+        var intent = new Intent();
+        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+        var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
+        intent.setData(uri);
+        mainActivity.startActivity(intent);
+    }
+}
+
+const permission = {
+    get isIOS(){
+        return typeof isIOS === 'boolean' ? isIOS : (isIOS = uni.getSystemInfoSync().platform === 'ios')
+    },
+    requestIOS: requestIOS,
+    requestAndroid: requestAndroid,
+    gotoAppSetting: gotoAppPermissionSetting
+}
+
+module.exports = permission

+ 145 - 0
exam-06173-uni - reg/common/request.js

@@ -0,0 +1,145 @@
+// API配置信息
+import urls from '../common/config.js'
+
+/**
+ * 构建完整请求URL
+ * @param {Object} path
+ */
+function buildUrl(path) {
+
+	// 完整接口地址返回
+	if (path.startsWith('http://') || path.startsWith('https://')) {
+		return path;
+	}
+
+	return urls.api + path;
+}
+
+/**
+ * 通用请求封装
+ * @param {Object} path
+ * @param {Object} data
+ */
+function postData(path, data) {
+
+	// 构建完整请求
+	const url = buildUrl(path)
+
+	return new Promise((resolve, reject) => {
+
+		uni.request({
+			url: url,
+			data: data,
+			method: "POST",
+			header: {
+				'content-type': "application/json",
+				'token': uni.getStorageSync("token")
+			},
+			success: function(res) {
+				// 错误500
+				if (res.statusCode == 500) {
+					uni.showToast({
+						title: '糟糕,服务器开小差了~',
+						icon: 'none',
+						duration: 5000
+					});
+					return;
+				}
+
+				// 404
+				if (res.statusCode == 404) {
+					uni.showToast({
+						title: '接口地址404,请联系管理员~',
+						icon: 'none',
+						duration: 5000
+					});
+					return;
+				}
+
+
+				// 成功才回调
+				if (res.data.code === 0) {
+					resolve(res.data.data);
+				} else {
+
+					// 后台错误信息
+					uni.showToast({
+						title: res.data.msg,
+						icon: 'none',
+						duration: 3000
+					});
+
+
+					if (res.data.code === 10010002) {
+						// 跳转到登录
+						uni.navigateTo({
+							url: '/pages/login/login'
+						});
+						return;
+					}
+
+					reject(res.data)
+
+				}
+			},
+			fail: function(e) {
+				uni.showToast({
+					title: '啊哦,与服务器失去连接了~',
+					icon: 'none',
+					duration: 10000
+				});
+			}
+		});
+	});
+}
+
+/**
+ * 文件上传
+ * @param {Object} url
+ * @param {Object} file
+ * @param {Object} data
+ */
+function uploadData(path, file, formData) {
+
+	// 构建完整请求地址
+	let url = buildUrl(path)
+	
+	
+	uni.showLoading({
+		title: '正在上传...'
+	})
+	
+	// 兼容chooseMedia
+	const filePath = file.path || file.tempFilePath
+	
+	return new Promise((resolve, reject) => {
+		uni.uploadFile({
+			url: url,
+			filePath: filePath,
+			name: 'file',			
+			header: {
+				'token': uni.getStorageSync("token")
+			},
+			formData: formData,
+			success: res => {
+				let data = {}
+				if (res.data) {
+					data = JSON.parse(res.data)
+				}
+				resolve(data);
+				uni.hideLoading()
+			},
+			fail: err => {
+				reject()
+				uni.hideLoading()
+			}
+		})
+	});
+}
+
+
+
+module.exports = {
+	post: postData,
+	upload: uploadData
+};

+ 258 - 0
exam-06173-uni - reg/common/upload.js

@@ -0,0 +1,258 @@
+import { buildDir } from '@/common/file-utils'
+import request from '@/common/request'
+import { fetchToken as ossToken } from '@/api/sys/config/oss'
+import { fetchToken as cosToken } from '@/api/sys/config/cos'
+import { fetchDetail as uploadDetail } from '@/api/sys/config/upload'
+import { fetchToken as qiuiuToken } from '@/api/sys/config/qiniu'
+
+/**
+ * 获取网站基本信息
+ */
+function fetchSite() {
+
+	return new Promise((resolve, reject) => {
+
+		uploadDetail().then(cfg => {
+			console.log('upload', cfg)
+			resolve(cfg)
+		}).catch(err => {
+			uni.showToast({
+				title: `获取系统基础设置失败: ${err} `,
+				icon: 'none',
+				duration: 5000
+			});
+			reject()
+		})
+
+	})
+
+}
+
+/**
+ * 文件上传入口
+ * @param file
+ * @param data
+ * @returns {Promise<unknown>}
+ */
+async function uploadFile(file) {
+
+	// 获取上传设置
+	let cfg = await fetchSite()
+	const provider = cfg.provider
+	
+	uni.showLoading({
+		title: '上传中..'
+	})
+	
+	return new Promise((resolve, reject) => {
+		// 本地文件上传
+		if (provider === 'local') {
+			request.upload('/api/common/file/upload', file).then(res => {
+				resolve(res.data.url)
+				uni.hideLoading()
+			}, err => {
+				reject(err)
+				uni.hideLoading()
+			})
+		}
+
+		// OSS文件上传
+		if (provider === 'oss') {
+			ossUpload(file).then(res => {
+				resolve(res)
+				uni.hideLoading()
+			}, err => {
+				reject(err)
+				uni.hideLoading()
+			})
+		}
+
+		// 七牛云文件上传
+		if (provider === 'qiniu') {
+			qiniuUpload(file).then(res => {
+				resolve(res)
+				uni.hideLoading()
+			}, err => {
+				reject(err)
+				uni.hideLoading()
+			})
+		}
+
+		// 腾讯云文件上传
+		if (provider === 'cos') {
+			cosUpload(file).then(res => {
+				resolve(res)
+				uni.hideLoading()
+			}, err => {
+				reject(err)
+				uni.hideLoading()
+			})
+		}
+	}).catch(err=>{
+		uni.hideLoading()
+		
+		uni.showToast({
+			title: `处理上传出现错误: ${err} `,
+			icon: 'none',
+			duration: 5000
+		});
+		
+	})
+}
+
+// OSS上传
+function ossUpload(file) {
+	return new Promise((resolve, reject) => {
+		// 获得上传令牌
+		ossToken().then(res => {
+			const conf = res
+			const dataObj = {
+				'policy': res.policy,
+				'OSSAccessKeyId': res.accessId,
+				'success_action_status': 200,
+				'signature': res.signature,
+				'key': buildDir() + getFileExt(file)
+			}
+
+			console.log('调用upload', dataObj)
+
+			// 调用
+			request.upload(conf.host, file, dataObj).then(() => {
+				// 保存截图
+				const url = conf.url + dataObj.key
+				console.log('上传后的地址', url)
+				resolve(url)
+			})
+
+
+
+		}).catch(err => {
+			uni.showToast({
+				title: `获取OSS令牌失败: ${err} `,
+				icon: 'none',
+				duration: 5000
+			});
+			reject(err)
+		})
+	})
+}
+
+/**
+ * 腾讯云文件上传
+ * @param file
+ * @returns {Promise<unknown>}
+ */
+function cosUpload(file) {
+	return new Promise((resolve, reject) => {
+		// 获得上传令牌
+		cosToken().then(res => {
+			const conf = res
+	
+			// 上传后文件目录
+			const key = buildDir() + getFileExt(file)
+	
+			// #ifdef MP-WEIXIN
+			var COS = require('cos-wx-sdk-v5');
+			const cos = new COS({
+				SecretId: res.tmpSecretId,
+				SecretKey: res.tmpSecretKey,
+				XCosSecurityToken: res.sessionToken
+			})
+			
+			cos.postObject({
+			    Bucket: conf.bucket, 
+			    Region: conf.region,  
+			    Key: key,
+				FilePath: file.path
+			}, function(err, data) {
+			    console.log(err || data);
+				const url = conf.url + key
+				resolve(url)
+			});
+			// #endif
+			
+			// #ifndef MP-WEIXIN
+			var COS = require('cos-js-sdk-v5');
+			const cos = new COS({
+				SecretId: res.tmpSecretId,
+				SecretKey: res.tmpSecretKey,
+				XCosSecurityToken: res.sessionToken
+			})
+			
+			cos.putObject({
+			    Bucket: conf.bucket, 
+			    Region: conf.region,  
+			    Key: key,
+				Body: file
+			}, function(err, data) {
+			    console.log(err || data);
+				const url = conf.url + key
+				resolve(url)
+			});
+			// #endif
+			
+		}).catch(err => {
+			uni.showToast({
+				title: `获取COS上传令牌失败: ${err} `,
+				icon: 'none',
+				duration: 5000
+			});
+			reject(err)
+		})
+	})
+}
+
+/**
+ * 七牛云文件上传
+ * @param file
+ * @returns {Promise<unknown>}
+ */
+function qiniuUpload(file) {
+	return new Promise((resolve, reject) => {
+		uploadDetail().then(res => {
+			const conf = JSON.parse(res.data)
+			// 获得上传Token
+			qiuiuToken().then(res => {
+				const dataObj = {
+					'token': res.token,
+					'key': buildDir() + getFileExt(file)
+				}
+
+				request.upload(conf.endpoint, file, dataObj).then(() => {
+					// 保存数据
+					const url = conf.url + dataObj.key
+					resolve(url)
+				})
+			}).catch(err => {
+				uni.showToast({
+					title: `获取七牛令牌失败: ${err} `,
+					icon: 'none',
+					duration: 5000
+				});
+				reject(err)
+			})
+		})
+	})
+}
+
+/**
+ * 获取文件后缀
+ * @param file
+ * @returns {string}
+ */
+function getFileExt(file) {
+
+	// 取文件名
+	let name = file.name || file.path || file.tempFilePath
+
+	// 获取文件后缀
+	const ext = name.split('.').pop()
+	if (ext != null && ext !== '') {
+		return '.' + ext.toLowerCase()
+	}
+	return ''
+}
+
+module.exports = {
+	uploadFile: uploadFile
+};

+ 46 - 0
exam-06173-uni - reg/common/utils.js

@@ -0,0 +1,46 @@
+/**
+ * 图片压缩方法,压缩base64格式图片
+ * @param {Object} base64
+ * @param {Object} w
+ */
+function compressImage(base64, w) {
+
+	return new Promise((resolve, reject) => {
+
+		var img = new Image();
+		var quality = 0.6; //压缩系数0-1之间
+		img.src = base64;
+		img.setAttribute("crossOrigin", 'Anonymous'); //url为外域时需要
+
+		img.onload = function() {
+
+			// 等比缩放
+			let width = img.width;
+			let height = img.height;
+			console.log('++++orginal w:' + width + ',h:' + height)
+			if (width > w) {
+				const rate = height / width
+				height = parseInt(w * rate)
+				width = w
+			}
+
+			var canvas = document.createElement("canvas");
+			var ctx = canvas.getContext("2d");
+			canvas.width = width;
+			canvas.height = height;
+			quality = 0.8;
+
+			console.log('++++compress w:' + width + ',h:' + height)
+
+			ctx.clearRect(0, 0, canvas.width, canvas.height);
+			ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
+			const base64 = canvas.toDataURL("image/jpeg", quality); //压缩语句
+			resolve(base64);
+		}
+
+	})
+}
+
+module.exports = {
+	compressImage: compressImage
+}

+ 28 - 0
exam-06173-uni - reg/common/validate.js

@@ -0,0 +1,28 @@
+/**
+ * @param {string} url
+ * @returns {Boolean}
+ */
+export function validURL(url) {
+  const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
+  return reg.test(url)
+}
+
+
+/**
+ * @param {string} email
+ * @returns {Boolean}
+ */
+export function validEmail(email) {
+  const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
+  return reg.test(email)
+}
+
+/**
+ * 校验是否是手机号码
+ * @param mobile
+ * @returns {boolean}
+ */
+export function isMobile(mobile) {
+  const regx = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
+  return regx.test(mobile)
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 558 - 0
exam-06173-uni - reg/components/cmd-progress/cmd-progress.vue


+ 185 - 0
exam-06173-uni - reg/components/pay-dialog/index.vue

@@ -0,0 +1,185 @@
+<template>
+
+	<view class="content">
+		<view>
+			<view style="padding: 20px;">
+				<view style="font-size: 16px; padding-bottom: 10px;">选择支付方式</view>
+				<template v-for="item in payList">
+					<view v-if="item.enabled" :key="item.name" style="margin-bottom: 10px;">
+						<button type="default" v-if="item.name === 'alipay'" @click="tradePay(item.name)">支付宝支付</button>
+						<button type="primary" v-if="item.name === 'wechat'" @click="tradePay(item.name)">微信支付</button>
+					</view>
+				</template>
+			</view>
+		</view>
+	</view>
+
+</template>
+
+<script>
+	import { payConfig } from '@/api/ability/pay/config'
+	import { tradeJs } from '@/api/ability/pay/wechat'
+	import { alipayTrade } from '@/api/ability/pay/alipay'
+	import { checkOrder } from '@/api/order/order'
+
+	export default {
+
+		name: 'PayDialog',
+		props: {
+			orderId: String
+		},
+		data() {
+			return {
+
+				// 支付方式
+				payList: [],
+				dialogVisible: false,
+				// 选择支付方式
+				prepay: true,
+				// 微信支付
+				payMethod: '',
+				// 支付宝相关
+				aliForm: '',
+				socket: false
+			}
+		},
+
+		created() {
+			
+			// 查找支付方式
+			payConfig().then(res => {
+				this.payList = res
+			})
+		},
+
+		methods: {
+
+			tradePay(name) {
+				// 当前支付方式
+				this.payMethod = name
+
+				if (name === 'wechat') {
+					this.wechatPay()
+				}
+
+				if (name === 'alipay') {
+					this.alipayPay()
+				}
+			},
+
+			// 微信支付
+			wechatPay() {
+
+				let that = this
+
+				// 获取当前用户信息
+				uni.login({
+					provider: 'weixin',
+					success: (user) => {
+						console.log(user)
+						// 获得JSAPI支付信息
+						tradeJs({
+							id: that.orderId,
+							code: user.code
+						}).then(res => {
+							console.log('trade', res)
+							this.callWechatPay(res)
+						}).catch(() => {
+							uni.hideLoading()
+						})
+
+					},
+					fail: () => {
+						uni.showToast({
+							title: "微信登录授权失败",
+							icon: "none"
+						});
+					}
+				})
+			},
+
+			callWechatPay(data) {
+
+				let that = this
+
+				uni.hideLoading()
+
+				// 仅作为示例,非真实参数信息。
+				uni.requestPayment({
+					provider: 'wxpay',
+					timeStamp: data.timeStamp,
+					nonceStr: data.nonceStr,
+					package: data.package,
+					signType: 'RSA',
+					paySign: data.paySign,
+					success: function(res) {
+						console.log('success:' + JSON.stringify(res));
+						uni.showToast({
+							title: "恭喜,支付成功!",
+							icon: "none"
+						});
+						
+						that.$emit('success')
+
+					},
+					fail: function(err) {
+						console.log('fail:' + JSON.stringify(err));
+					}
+				});
+
+			},
+
+
+
+			// 支付宝支付
+			alipayPay() {
+			
+				uni.showToast({
+					title: '抱歉,移动端暂不支持此支付方式!',
+					icon: "none"
+				})
+			},
+
+			// 检查订单是否成功
+			checkState() {
+				checkOrder(this.orderId).then(res => {
+					const data = res.data
+
+					// 校验订单状态
+					if (data.orderState === 2) {
+						this.$message.success('支付成功!')
+						setTimeout(() => {
+							window.location.reload()
+						}, 2000)
+					} else {
+						this.$message.warning('订单尚未支付成功,请稍后刷新..')
+					}
+				})
+			},
+
+			handleClose() {
+				this.$emit('update:visible', false)
+				this.$emit('close')
+			},
+
+			changePay() {
+				this.prepay = true
+				this.payMethod = ''
+				this.weQr = null
+				this.aliForm = ''
+			},
+
+			// 支付结果回调
+			onMessage(msg) {
+				if (msg === 'success' && this.socket) {
+					this.socket = false
+					this.$message.success('支付成功!')
+					setTimeout(() => {
+						window.location.reload()
+					}, 2000)
+				}
+			}
+
+		}
+	}
+</script>

+ 27 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseAudio.vue

@@ -0,0 +1,27 @@
+<template>
+  <!--增加audio标签支持-->
+  <audio
+    :id="node.attr.id"
+    :class="node.classStr"
+    :style="node.styleStr"
+    :src="node.attr.src"
+    :loop="node.attr.loop"
+    :poster="node.attr.poster"
+    :name="node.attr.name"
+    :author="node.attr.author"
+    controls></audio>
+</template>
+
+<script>
+export default {
+  name: 'wxParseAudio',
+  props: {
+    node: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+};
+</script>

+ 86 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseImg.vue

@@ -0,0 +1,86 @@
+<template>
+  <image
+    :mode="node.attr.mode"
+    :lazy-load="node.attr.lazyLoad"
+    :class="node.classStr"
+    :style="newStyleStr || node.styleStr"
+    :data-src="node.attr.src"
+    :src="node.attr.src"
+    @tap="wxParseImgTap"
+    @load="wxParseImgLoad"
+    />
+</template>
+
+<script>
+export default {
+  name: 'wxParseImg',
+  data() {
+    return {
+      newStyleStr: '',
+      preview: true,
+    };
+  },
+  props: {
+    node: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  methods: {
+    wxParseImgTap(e) {
+      if (!this.preview) return;
+      const { src } = e.currentTarget.dataset;
+      if (!src) return;
+      let parent = this.$parent;
+      while(!parent.preview || typeof parent.preview !== 'function') {// TODO 遍历获取父节点执行方法
+      	parent = parent.$parent;
+      }
+      parent.preview(src, e);
+    },
+    // 图片视觉宽高计算函数区
+    wxParseImgLoad(e) {
+      const { src } = e.currentTarget.dataset;
+      if (!src) return;
+      const { width, height } = e.mp.detail;
+      const recal = this.wxAutoImageCal(width, height);
+      const { imageheight, imageWidth } = recal;
+      const { padding, mode } = this.node.attr;
+      const { styleStr } = this.node;
+      const imageHeightStyle = mode === 'widthFix' ? '' : `height: ${imageheight}px;`;
+      this.newStyleStr = `${styleStr}; ${imageHeightStyle}; width: ${imageWidth}px; padding: 0 ${+padding}px;`;
+    },
+    // 计算视觉优先的图片宽高
+    wxAutoImageCal(originalWidth, originalHeight) {
+      // 获取图片的原始长宽
+      const { padding } = this.node.attr;
+      const windowWidth = this.node.$screen.width - (2 * padding);
+      const results = {};
+
+      if (originalWidth < 60 || originalHeight < 60) {
+        const { src } = this.node.attr;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.removeImageUrl(src);
+        this.preview = false;
+      }
+
+      // 判断按照那种方式进行缩放
+      if (originalWidth > windowWidth) {
+        // 在图片width大于手机屏幕width时候
+        results.imageWidth = windowWidth;
+        results.imageheight = windowWidth * (originalHeight / originalWidth);
+      } else {
+        // 否则展示原来的数据
+        results.imageWidth = originalWidth;
+        results.imageheight = originalHeight;
+      }
+
+      return results;
+    },
+  },
+};
+</script>

+ 107 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseTemplate0.vue

@@ -0,0 +1,107 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--table类型-->
+			<block v-else-if="node.tag == 'table'">
+				<view :class="node.classStr" class="table" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate1';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate0',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;// TODO currentTarget才有dataset
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {// TODO 遍历获取父节点执行方法
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 99 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseTemplate1.vue

@@ -0,0 +1,99 @@
+<template>
+	<view :class="(node.tag == 'li' ? node.classStr : (node.node==='text'?'text':''))">
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<!-- <view :class="node.classStr" :style="node.styleStr"> -->
+				<view :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate2';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate1',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 97 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseTemplate10.vue

@@ -0,0 +1,97 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate11';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate10',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 87 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseTemplate11.vue

@@ -0,0 +1,87 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<!--button类型-->
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					{{node.text}}
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					{{node.text}}
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					{{node.text}}
+				</view>
+			</block>
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate11',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseTemplate2.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate3';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate2',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseTemplate3.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate4';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate3',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseTemplate4.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate5';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate4',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseTemplate5.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate6';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate5',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseTemplate6.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate7';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate6',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseTemplate7.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate8';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate7',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseTemplate8.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate9';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate8',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseTemplate9.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate10';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate9',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 15 - 0
exam-06173-uni - reg/components/u-parse/components/wxParseVideo.vue

@@ -0,0 +1,15 @@
+<template>
+  <!--增加video标签支持,并循环添加-->
+  <view :class="node.classStr" :style="node.styleStr">
+    <video :class="node.classStr" class="video-video" :src="node.attr.src"></video>
+  </view>
+</template>
+
+<script>
+export default {
+  name: 'wxParseVideo',
+  props: {
+    node: {},
+  },
+};
+</script>

+ 261 - 0
exam-06173-uni - reg/components/u-parse/libs/html2json.js

@@ -0,0 +1,261 @@
+/**
+ * html2Json 改造来自: https://github.com/Jxck/html2json
+ *
+ *
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ *               垂直微信小程序开发交流社区
+ *
+ * github地址: https://github.com/icindy/wxParse
+ *
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */
+
+import wxDiscode from './wxDiscode';
+import HTMLParser from './htmlparser';
+
+function makeMap(str) {
+  const obj = {};
+  const items = str.split(',');
+  for (let i = 0; i < items.length; i += 1) obj[items[i]] = true;
+  return obj;
+}
+
+// Block Elements - HTML 5
+const block = makeMap('br,code,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video');
+
+// Inline Elements - HTML 5
+const inline = makeMap('a,abbr,acronym,applet,b,basefont,bdo,big,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var');
+
+// Elements that you can, intentionally, leave open
+// (and which close themselves)
+const closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
+
+function removeDOCTYPE(html) {
+  const isDocument = /<body.*>([^]*)<\/body>/.test(html);
+  return isDocument ? RegExp.$1 : html;
+}
+
+function trimHtml(html) {
+  return html
+    .replace(/<!--.*?-->/gi, '')
+    .replace(/\/\*.*?\*\//gi, '')
+    .replace(/[ ]+</gi, '<')
+    .replace(/<script[^]*<\/script>/gi, '')
+    .replace(/<style[^]*<\/style>/gi, '');
+}
+
+function getScreenInfo() {
+  const screen = {};
+  wx.getSystemInfo({
+    success: (res) => {
+      screen.width = res.windowWidth;
+      screen.height = res.windowHeight;
+    },
+  });
+  return screen;
+}
+
+function html2json(html, customHandler, imageProp, host) {
+  // 处理字符串
+  html = removeDOCTYPE(html);
+  html = trimHtml(html);
+  html = wxDiscode.strDiscode(html);
+  // 生成node节点
+  const bufArray = [];
+  const results = {
+    nodes: [],
+    imageUrls: [],
+  };
+
+	const screen = getScreenInfo();
+  function Node(tag) {
+    this.node = 'element';
+    this.tag = tag;
+		
+		this.$screen = screen;
+  }
+
+  HTMLParser(html, {
+    start(tag, attrs, unary) {
+      // node for this element
+      const node = new Node(tag);
+
+      if (bufArray.length !== 0) {
+        const parent = bufArray[0];
+        if (parent.nodes === undefined) {
+          parent.nodes = [];
+        }
+      }
+
+      if (block[tag]) {
+        node.tagType = 'block';
+      } else if (inline[tag]) {
+        node.tagType = 'inline';
+      } else if (closeSelf[tag]) {
+        node.tagType = 'closeSelf';
+      }
+
+      node.attr = attrs.reduce((pre, attr) => {
+        const { name } = attr;
+        let { value } = attr;
+        if (name === 'class') {
+          node.classStr = value;
+        }
+        // has multi attibutes
+        // make it array of attribute
+        if (name === 'style') {
+          node.styleStr = value;
+        }
+        if (value.match(/ /)) {
+          value = value.split(' ');
+        }
+
+        // if attr already exists
+        // merge it
+        if (pre[name]) {
+          if (Array.isArray(pre[name])) {
+            // already array, push to last
+            pre[name].push(value);
+          } else {
+            // single value, make it array
+            pre[name] = [pre[name], value];
+          }
+        } else {
+          // not exist, put it
+          pre[name] = value;
+        }
+
+        return pre;
+      }, {});
+
+      // 优化样式相关属性
+      if (node.classStr) {
+        node.classStr += ` ${node.tag}`;
+      } else {
+        node.classStr = node.tag;
+      }
+      if (node.tagType === 'inline') {
+        node.classStr += ' inline';
+      }
+
+      // 对img添加额外数据
+      if (node.tag === 'img') {
+        let imgUrl = node.attr.src;
+        imgUrl = wxDiscode.urlToHttpUrl(imgUrl, imageProp.domain);
+        Object.assign(node.attr, imageProp, {
+          src: imgUrl || '',
+        });
+        if (imgUrl) {
+          results.imageUrls.push(imgUrl);
+        }
+      }
+
+      // 处理a标签属性
+      if (node.tag === 'a') {
+        node.attr.href = node.attr.href || '';
+      }
+
+      // 处理font标签样式属性
+      if (node.tag === 'font') {
+        const fontSize = [
+          'x-small',
+          'small',
+          'medium',
+          'large',
+          'x-large',
+          'xx-large',
+          '-webkit-xxx-large',
+        ];
+        const styleAttrs = {
+          color: 'color',
+          face: 'font-family',
+          size: 'font-size',
+        };
+        if (!node.styleStr) node.styleStr = '';
+        Object.keys(styleAttrs).forEach((key) => {
+          if (node.attr[key]) {
+            const value = key === 'size' ? fontSize[node.attr[key] - 1] : node.attr[key];
+            node.styleStr += `${styleAttrs[key]}: ${value};`;
+          }
+        });
+      }
+
+      // 临时记录source资源
+      if (node.tag === 'source') {
+        results.source = node.attr.src;
+      }
+
+      if (customHandler.start) {
+        customHandler.start(node, results);
+      }
+
+      if (unary) {
+        // if this tag doesn't have end tag
+        // like <img src="hoge.png"/>
+        // add to parents
+        const parent = bufArray[0] || results;
+        if (parent.nodes === undefined) {
+          parent.nodes = [];
+        }
+        parent.nodes.push(node);
+      } else {
+        bufArray.unshift(node);
+      }
+    },
+    end(tag) {
+      // merge into parent tag
+      const node = bufArray.shift();
+      if (node.tag !== tag) {
+        console.error('invalid state: mismatch end tag');
+      }
+
+      // 当有缓存source资源时于于video补上src资源
+      if (node.tag === 'video' && results.source) {
+        node.attr.src = results.source;
+        delete results.source;
+      }
+
+      if (customHandler.end) {
+        customHandler.end(node, results);
+      }
+
+      if (bufArray.length === 0) {
+        results.nodes.push(node);
+      } else {
+        const parent = bufArray[0];
+        if (!parent.nodes) {
+          parent.nodes = [];
+        }
+        parent.nodes.push(node);
+      }
+    },
+    chars(text) {
+      if (!text.trim()) return;
+
+      const node = {
+        node: 'text',
+        text,
+      };
+
+      if (customHandler.chars) {
+        customHandler.chars(node, results);
+      }
+
+      if (bufArray.length === 0) {
+        results.nodes.push(node);
+      } else {
+        const parent = bufArray[0];
+        if (parent.nodes === undefined) {
+          parent.nodes = [];
+        }
+        parent.nodes.push(node);
+      }
+    },
+  });
+
+  return results;
+}
+
+export default html2json;

+ 156 - 0
exam-06173-uni - reg/components/u-parse/libs/htmlparser.js

@@ -0,0 +1,156 @@
+/**
+ *
+ * htmlParser改造自: https://github.com/blowsie/Pure-JavaScript-HTML5-Parser
+ *
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ *               垂直微信小程序开发交流社区
+ *
+ * github地址: https://github.com/icindy/wxParse
+ *
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */
+// Regular Expressions for parsing tags and attributes
+
+const startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z0-9_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
+const endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
+const attr = /([a-zA-Z0-9_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
+
+function makeMap(str) {
+  const obj = {};
+  const items = str.split(',');
+  for (let i = 0; i < items.length; i += 1) obj[items[i]] = true;
+  return obj;
+}
+
+// Empty Elements - HTML 5
+const empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr');
+
+// Block Elements - HTML 5
+const block = makeMap('address,code,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video');
+
+// Inline Elements - HTML 5
+const inline = makeMap('a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var');
+
+// Elements that you can, intentionally, leave open
+// (and which close themselves)
+const closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
+
+// Attributes that have their values filled in disabled="disabled"
+const fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected');
+
+function HTMLParser(html, handler) {
+  let index;
+  let chars;
+  let match;
+  let last = html;
+  const stack = [];
+
+  stack.last = () => stack[stack.length - 1];
+
+  function parseEndTag(tag, tagName) {
+    // If no tag name is provided, clean shop
+    let pos;
+    if (!tagName) {
+      pos = 0;
+    } else {
+      // Find the closest opened tag of the same type
+      tagName = tagName.toLowerCase();
+      for (pos = stack.length - 1; pos >= 0; pos -= 1) {
+        if (stack[pos] === tagName) break;
+      }
+    }
+    if (pos >= 0) {
+      // Close all the open elements, up the stack
+      for (let i = stack.length - 1; i >= pos; i -= 1) {
+        if (handler.end) handler.end(stack[i]);
+      }
+
+      // Remove the open elements from the stack
+      stack.length = pos;
+    }
+  }
+
+  function parseStartTag(tag, tagName, rest, unary) {
+    tagName = tagName.toLowerCase();
+
+    if (block[tagName]) {
+      while (stack.last() && inline[stack.last()]) {
+        parseEndTag('', stack.last());
+      }
+    }
+
+    if (closeSelf[tagName] && stack.last() === tagName) {
+      parseEndTag('', tagName);
+    }
+
+    unary = empty[tagName] || !!unary;
+
+    if (!unary) stack.push(tagName);
+
+    if (handler.start) {
+      const attrs = [];
+
+      rest.replace(attr, function genAttr(matches, name) {
+        const value = arguments[2] || arguments[3] || arguments[4] || (fillAttrs[name] ? name : '');
+
+        attrs.push({
+          name,
+          value,
+          escaped: value.replace(/(^|[^\\])"/g, '$1\\"'), // "
+        });
+      });
+
+      if (handler.start) {
+        handler.start(tagName, attrs, unary);
+      }
+    }
+  }
+
+  while (html) {
+    chars = true;
+
+    if (html.indexOf('</') === 0) {
+      match = html.match(endTag);
+
+      if (match) {
+        html = html.substring(match[0].length);
+        match[0].replace(endTag, parseEndTag);
+        chars = false;
+      }
+
+      // start tag
+    } else if (html.indexOf('<') === 0) {
+      match = html.match(startTag);
+
+      if (match) {
+        html = html.substring(match[0].length);
+        match[0].replace(startTag, parseStartTag);
+        chars = false;
+      }
+    }
+
+    if (chars) {
+      index = html.indexOf('<');
+      let text = '';
+      while (index === 0) {
+        text += '<';
+        html = html.substring(1);
+        index = html.indexOf('<');
+      }
+      text += index < 0 ? html : html.substring(0, index);
+      html = index < 0 ? '' : html.substring(index);
+
+      if (handler.chars) handler.chars(text);
+    }
+
+    if (html === last) throw new Error(`Parse Error: ${html}`);
+    last = html;
+  }
+
+  // Clean up any remaining tags
+  parseEndTag();
+}
+
+export default HTMLParser;

+ 195 - 0
exam-06173-uni - reg/components/u-parse/libs/wxDiscode.js

@@ -0,0 +1,195 @@
+// HTML 支持的数学符号
+function strNumDiscode(str) {
+  str = str.replace(/&forall;/g, '∀');
+  str = str.replace(/&part;/g, '∂');
+  str = str.replace(/&exist;/g, '∃');
+  str = str.replace(/&empty;/g, '∅');
+  str = str.replace(/&nabla;/g, '∇');
+  str = str.replace(/&isin;/g, '∈');
+  str = str.replace(/&notin;/g, '∉');
+  str = str.replace(/&ni;/g, '∋');
+  str = str.replace(/&prod;/g, '∏');
+  str = str.replace(/&sum;/g, '∑');
+  str = str.replace(/&minus;/g, '−');
+  str = str.replace(/&lowast;/g, '∗');
+  str = str.replace(/&radic;/g, '√');
+  str = str.replace(/&prop;/g, '∝');
+  str = str.replace(/&infin;/g, '∞');
+  str = str.replace(/&ang;/g, '∠');
+  str = str.replace(/&and;/g, '∧');
+  str = str.replace(/&or;/g, '∨');
+  str = str.replace(/&cap;/g, '∩');
+  str = str.replace(/&cup;/g, '∪');
+  str = str.replace(/&int;/g, '∫');
+  str = str.replace(/&there4;/g, '∴');
+  str = str.replace(/&sim;/g, '∼');
+  str = str.replace(/&cong;/g, '≅');
+  str = str.replace(/&asymp;/g, '≈');
+  str = str.replace(/&ne;/g, '≠');
+  str = str.replace(/&le;/g, '≤');
+  str = str.replace(/&ge;/g, '≥');
+  str = str.replace(/&sub;/g, '⊂');
+  str = str.replace(/&sup;/g, '⊃');
+  str = str.replace(/&nsub;/g, '⊄');
+  str = str.replace(/&sube;/g, '⊆');
+  str = str.replace(/&supe;/g, '⊇');
+  str = str.replace(/&oplus;/g, '⊕');
+  str = str.replace(/&otimes;/g, '⊗');
+  str = str.replace(/&perp;/g, '⊥');
+  str = str.replace(/&sdot;/g, '⋅');
+  return str;
+}
+
+// HTML 支持的希腊字母
+function strGreeceDiscode(str) {
+  str = str.replace(/&Alpha;/g, 'Α');
+  str = str.replace(/&Beta;/g, 'Β');
+  str = str.replace(/&Gamma;/g, 'Γ');
+  str = str.replace(/&Delta;/g, 'Δ');
+  str = str.replace(/&Epsilon;/g, 'Ε');
+  str = str.replace(/&Zeta;/g, 'Ζ');
+  str = str.replace(/&Eta;/g, 'Η');
+  str = str.replace(/&Theta;/g, 'Θ');
+  str = str.replace(/&Iota;/g, 'Ι');
+  str = str.replace(/&Kappa;/g, 'Κ');
+  str = str.replace(/&Lambda;/g, 'Λ');
+  str = str.replace(/&Mu;/g, 'Μ');
+  str = str.replace(/&Nu;/g, 'Ν');
+  str = str.replace(/&Xi;/g, 'Ν');
+  str = str.replace(/&Omicron;/g, 'Ο');
+  str = str.replace(/&Pi;/g, 'Π');
+  str = str.replace(/&Rho;/g, 'Ρ');
+  str = str.replace(/&Sigma;/g, 'Σ');
+  str = str.replace(/&Tau;/g, 'Τ');
+  str = str.replace(/&Upsilon;/g, 'Υ');
+  str = str.replace(/&Phi;/g, 'Φ');
+  str = str.replace(/&Chi;/g, 'Χ');
+  str = str.replace(/&Psi;/g, 'Ψ');
+  str = str.replace(/&Omega;/g, 'Ω');
+
+  str = str.replace(/&alpha;/g, 'α');
+  str = str.replace(/&beta;/g, 'β');
+  str = str.replace(/&gamma;/g, 'γ');
+  str = str.replace(/&delta;/g, 'δ');
+  str = str.replace(/&epsilon;/g, 'ε');
+  str = str.replace(/&zeta;/g, 'ζ');
+  str = str.replace(/&eta;/g, 'η');
+  str = str.replace(/&theta;/g, 'θ');
+  str = str.replace(/&iota;/g, 'ι');
+  str = str.replace(/&kappa;/g, 'κ');
+  str = str.replace(/&lambda;/g, 'λ');
+  str = str.replace(/&mu;/g, 'μ');
+  str = str.replace(/&nu;/g, 'ν');
+  str = str.replace(/&xi;/g, 'ξ');
+  str = str.replace(/&omicron;/g, 'ο');
+  str = str.replace(/&pi;/g, 'π');
+  str = str.replace(/&rho;/g, 'ρ');
+  str = str.replace(/&sigmaf;/g, 'ς');
+  str = str.replace(/&sigma;/g, 'σ');
+  str = str.replace(/&tau;/g, 'τ');
+  str = str.replace(/&upsilon;/g, 'υ');
+  str = str.replace(/&phi;/g, 'φ');
+  str = str.replace(/&chi;/g, 'χ');
+  str = str.replace(/&psi;/g, 'ψ');
+  str = str.replace(/&omega;/g, 'ω');
+  str = str.replace(/&thetasym;/g, 'ϑ');
+  str = str.replace(/&upsih;/g, 'ϒ');
+  str = str.replace(/&piv;/g, 'ϖ');
+  str = str.replace(/&middot;/g, '·');
+  return str;
+}
+
+function strcharacterDiscode(str) {
+  // 加入常用解析
+  str = str.replace(/&nbsp;/g, ' ');
+  str = str.replace(/&ensp;/g, ' ');
+  str = str.replace(/&emsp;/g, ' ');
+  str = str.replace(/&quot;/g, "'");
+  str = str.replace(/&amp;/g, '&');
+  str = str.replace(/&lt;/g, '<');
+  str = str.replace(/&gt;/g, '>');
+  str = str.replace(/&#8226;/g, '•');
+
+  return str;
+}
+
+// HTML 支持的其他实体
+function strOtherDiscode(str) {
+  str = str.replace(/&OElig;/g, 'Œ');
+  str = str.replace(/&oelig;/g, 'œ');
+  str = str.replace(/&Scaron;/g, 'Š');
+  str = str.replace(/&scaron;/g, 'š');
+  str = str.replace(/&Yuml;/g, 'Ÿ');
+  str = str.replace(/&fnof;/g, 'ƒ');
+  str = str.replace(/&circ;/g, 'ˆ');
+  str = str.replace(/&tilde;/g, '˜');
+  str = str.replace(/&ensp;/g, '');
+  str = str.replace(/&emsp;/g, '');
+  str = str.replace(/&thinsp;/g, '');
+  str = str.replace(/&zwnj;/g, '');
+  str = str.replace(/&zwj;/g, '');
+  str = str.replace(/&lrm;/g, '');
+  str = str.replace(/&rlm;/g, '');
+  str = str.replace(/&ndash;/g, '–');
+  str = str.replace(/&mdash;/g, '—');
+  str = str.replace(/&lsquo;/g, '‘');
+  str = str.replace(/&rsquo;/g, '’');
+  str = str.replace(/&sbquo;/g, '‚');
+  str = str.replace(/&ldquo;/g, '“');
+  str = str.replace(/&rdquo;/g, '”');
+  str = str.replace(/&bdquo;/g, '„');
+  str = str.replace(/&dagger;/g, '†');
+  str = str.replace(/&Dagger;/g, '‡');
+  str = str.replace(/&bull;/g, '•');
+  str = str.replace(/&hellip;/g, '…');
+  str = str.replace(/&permil;/g, '‰');
+  str = str.replace(/&prime;/g, '′');
+  str = str.replace(/&Prime;/g, '″');
+  str = str.replace(/&lsaquo;/g, '‹');
+  str = str.replace(/&rsaquo;/g, '›');
+  str = str.replace(/&oline;/g, '‾');
+  str = str.replace(/&euro;/g, '€');
+  str = str.replace(/&trade;/g, '™');
+
+  str = str.replace(/&larr;/g, '←');
+  str = str.replace(/&uarr;/g, '↑');
+  str = str.replace(/&rarr;/g, '→');
+  str = str.replace(/&darr;/g, '↓');
+  str = str.replace(/&harr;/g, '↔');
+  str = str.replace(/&crarr;/g, '↵');
+  str = str.replace(/&lceil;/g, '⌈');
+  str = str.replace(/&rceil;/g, '⌉');
+
+  str = str.replace(/&lfloor;/g, '⌊');
+  str = str.replace(/&rfloor;/g, '⌋');
+  str = str.replace(/&loz;/g, '◊');
+  str = str.replace(/&spades;/g, '♠');
+  str = str.replace(/&clubs;/g, '♣');
+  str = str.replace(/&hearts;/g, '♥');
+
+  str = str.replace(/&diams;/g, '♦');
+  str = str.replace(/&#39;/g, "'");
+  return str;
+}
+
+function strDiscode(str) {
+  str = strNumDiscode(str);
+  str = strGreeceDiscode(str);
+  str = strcharacterDiscode(str);
+  str = strOtherDiscode(str);
+  return str;
+}
+
+function urlToHttpUrl(url, domain) {
+  if (/^\/\//.test(url)) {
+    return `https:${url}`;
+  } else if (/^\//.test(url)) {
+    return `https://${domain}${url}`;
+  }
+  return url;
+}
+
+export default {
+  strDiscode,
+  urlToHttpUrl,
+};

+ 102 - 0
exam-06173-uni - reg/components/u-parse/readme.md

@@ -0,0 +1,102 @@
+## uParse 适用于 uni-app/mpvue 的富文本解析组件
+
+> 支持 Html、Markdown 解析,Fork自: [mpvue-wxParse](https://github.com/F-loat/mpvue-wxParse)
+
+
+## 属性
+
+| 名称             | 类型          | 默认值        | 描述               |
+| -----------------|--------------- | ------------- | ----------------  |
+| loading          | Boolean        | false         | 数据加载状态       |
+| className        | String         | —             | 自定义 class 名称  |
+| content          | String         | —             | 渲染内容           |
+| noData           | String         | 数据不能为空   | 空数据时的渲染展示  |
+| startHandler     | Function       | 见源码         | 自定义 parser 函数 |
+| endHandler       | Function       | null          | 自定义 parser 函数 |
+| charsHandler     | Function       | null          | 自定义 parser 函数 |
+| imageProp        | Object         | 见下文        | 图片相关参数        |
+
+### 自定义 parser 函数具体介绍
+
+* 传入的参数为当前节点 `node` 对象及解析结果 `results` 对象,例如 `startHandler(node, results)`
+* 无需返回值,通过对传入的参数直接操作来完成需要的改动
+* 自定义函数会在原解析函数处理之后执行
+
+### imageProp 对象具体属性
+
+| 名称              | 类型           | 默认值        | 描述                |
+| -----------------|--------------- | ------------- | ------------------ |
+| mode             | String         | 'aspectFit'   | 图片裁剪、缩放的模式 |
+| padding          | Number         | 0             | 图片内边距          |
+| lazyLoad         | Boolean        | false         | 图片懒加载          |
+| domain           | String         | ''            | 图片服务域名        |
+
+## 事件
+
+| 名称             | 参数              | 描述              |
+| -----------------|----------------- | ----------------  |
+| preview          | 图片地址,原始事件 | 预览图片时触发     |
+| navigate         | 链接地址,原始事件 | 点击链接时触发     |
+
+## 基本使用方法
+
+
+``` vue
+<template>
+  <div>
+    <u-parse :content="article" @preview="preview" @navigate="navigate" />
+  </div>
+</template>
+
+<script>
+import uParse from '@/components/u-parse/u-parse.vue'
+
+export default {
+  components: {
+    uParse
+  },
+  data () {
+    return {
+      article: '<div>我是HTML代码</div>'
+    }
+  },
+  methods: {
+    preview(src, e) {
+      // do something
+    },
+    navigate(href, e) {
+      // do something
+    }
+  }
+}
+</script>
+
+<style>
+@import url("@/components/u-parse/u-parse.css");
+</style>
+```
+
+
+## 渲染 Markdown
+
+> 先将 markdown 转换为 html 即可
+
+```
+npm install marked
+```
+
+``` js
+import marked from 'marked'
+import uParse from '@/components/u-parse/u-parse.vue'
+
+export default {
+  components: {
+    uParse
+  },
+  data () {
+    return {
+      article: marked(`#hello, markdown!`)
+    }
+  }
+}
+```

+ 232 - 0
exam-06173-uni - reg/components/u-parse/u-parse.css

@@ -0,0 +1,232 @@
+/**
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ *         垂直微信小程序开发交流社区
+ *
+ * github地址: https://github.com/icindy/wxParse
+ *
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */
+
+.wxParse {
+  width: 100%;
+  font-family: Helvetica, sans-serif;
+  font-size: 30upx;
+  color: #666;
+  line-height: 1.8;
+}
+
+.wxParse view {
+  word-break: hyphenate;
+}
+
+.wxParse .inline {
+  display: inline;
+  margin: 0;
+  padding: 0;
+}
+
+.wxParse .div {
+  margin: 0;
+  padding: 0;
+}
+
+.wxParse .h1 .text {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+.wxParse .h2 .text {
+  font-size: 1.5em;
+  margin: 0.83em 0;
+}
+.wxParse .h3 .text {
+  font-size: 1.17em;
+  margin: 1em 0;
+}
+.wxParse .h4 .text {
+  margin: 1.33em 0;
+}
+.wxParse .h5 .text {
+  font-size: 0.83em;
+  margin: 1.67em 0;
+}
+.wxParse .h6 .text {
+  font-size: 0.67em;
+  margin: 2.33em 0;
+}
+
+.wxParse .h1 .text,
+.wxParse .h2 .text,
+.wxParse .h3 .text,
+.wxParse .h4 .text,
+.wxParse .h5 .text,
+.wxParse .h6 .text,
+.wxParse .b,
+.wxParse .strong {
+  font-weight: bolder;
+}
+
+
+.wxParse .p {
+  margin: 1em 0;
+}
+
+.wxParse .i,
+.wxParse .cite,
+.wxParse .em,
+.wxParse .var,
+.wxParse .address {
+  font-style: italic;
+}
+
+.wxParse .pre,
+.wxParse .tt,
+.wxParse .code,
+.wxParse .kbd,
+.wxParse .samp {
+  font-family: monospace;
+}
+.wxParse .pre {
+  overflow: auto;
+  background: #f5f5f5;
+  padding: 16upx;
+  white-space: pre;
+  margin: 1em 0upx;
+}
+.wxParse .code {
+  display: inline;
+  background: #f5f5f5;
+}
+
+.wxParse .big {
+  font-size: 1.17em;
+}
+
+.wxParse .small,
+.wxParse .sub,
+.wxParse .sup {
+  font-size: 0.83em;
+}
+
+.wxParse .sub {
+  vertical-align: sub;
+}
+.wxParse .sup {
+  vertical-align: super;
+}
+
+.wxParse .s,
+.wxParse .strike,
+.wxParse .del {
+  text-decoration: line-through;
+}
+
+.wxParse .strong,
+.wxParse .s {
+  display: inline;
+}
+
+.wxParse .a {
+  color: deepskyblue;
+}
+
+.wxParse .video {
+  text-align: center;
+  margin: 22upx 0;
+}
+
+.wxParse .video-video {
+  width: 100%;
+}
+
+.wxParse .img {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  max-width: 100%;
+  overflow: hidden;
+}
+
+.wxParse .blockquote {
+  margin: 10upx 0;
+  padding: 22upx 0 22upx 22upx;
+  font-family: Courier, Calibri, "宋体";
+  background: #f5f5f5;
+  border-left: 6upx solid #dbdbdb;
+}
+.wxParse .blockquote .p {
+  margin: 0;
+}
+
+.wxParse .ul, .wxParse .ol {
+  display: block;
+  margin: 1em 0;
+  padding-left: 33upx;
+}
+.wxParse .ol {
+  list-style-type: disc;
+}
+.wxParse .ol {
+  list-style-type: decimal;
+}
+.wxParse .ol>weixin-parse-template,.wxParse .ul>weixin-parse-template {
+  display: list-item;
+  align-items: baseline;
+  text-align: match-parent;
+}
+
+.wxParse .ol>.li,.wxParse .ul>.li {
+  display: list-item;
+  align-items: baseline;
+  text-align: match-parent;
+}
+.wxParse .ul .ul, .wxParse .ol .ul {
+  list-style-type: circle;
+}
+.wxParse .ol .ol .ul, .wxParse .ol .ul .ul, .wxParse .ul .ol .ul, .wxParse .ul .ul .ul {
+    list-style-type: square;
+}
+
+.wxParse .u {
+  text-decoration: underline;
+}
+.wxParse .hide {
+  display: none;
+}
+.wxParse .del {
+  display: inline;
+}
+.wxParse .figure {
+  overflow: hidden;
+}
+
+.wxParse .table {
+  width: 100%;
+}
+.wxParse .thead, .wxParse .tfoot, .wxParse .tr {
+  display: flex;
+  flex-direction: row;
+}
+.wxParse .tr {
+  width:100%;
+  display: flex;
+  border-right: 2upx solid #e0e0e0;
+  border-bottom: 2upx solid #e0e0e0;
+}
+.wxParse .th,
+.wxParse .td {
+  display: flex;
+  width: 1276upx;
+  overflow: auto;
+  flex: 1;
+  padding: 11upx;
+  border-left: 2upx solid #e0e0e0;
+}
+.wxParse .td:last {
+  border-top: 2upx solid #e0e0e0;
+}
+.wxParse .th {
+  background: #f0f0f0;
+  border-top: 2upx solid #e0e0e0;
+}

+ 118 - 0
exam-06173-uni - reg/components/u-parse/u-parse.vue

@@ -0,0 +1,118 @@
+<!--**
+ * forked from:https://github.com/F-loat/mpvue-wxParse
+ *
+ * github地址: https://github.com/dcloudio/uParse
+ *
+ * for: uni-app框架下 富文本解析
+ */-->
+
+<template>
+<!--基础元素-->
+<div class="wxParse" :class="className" v-if="!loading">
+  <block v-for="(node,index) of nodes" :key="index">
+    <wxParseTemplate :node="node" />
+  </block>
+</div>
+</template>
+
+<script>
+import HtmlToJson from './libs/html2json';
+import wxParseTemplate from './components/wxParseTemplate0';
+
+export default {
+  name: 'wxParse',
+  props: {
+    loading: {
+      type: Boolean,
+      default: false,
+    },
+    className: {
+      type: String,
+      default: '',
+    },
+    content: {
+      type: String,
+      default: '',
+    },
+    noData: {
+      type: String,
+      default: '<div style="color: red;">数据不能为空</div>',
+    },
+    startHandler: {
+      type: Function,
+      default() {
+        return (node) => {
+          node.attr.class = null;
+          node.attr.style = null;
+        };
+      },
+    },
+    endHandler: {
+      type: Function,
+      default: null,
+    },
+    charsHandler: {
+      type: Function,
+      default: null,
+    },
+    imageProp: {
+      type: Object,
+      default() {
+        return {
+          mode: 'aspectFit',
+          padding: 0,
+          lazyLoad: false,
+          domain: '',
+        };
+      },
+    },
+  },
+  components: {
+    wxParseTemplate,
+  },
+  data() {
+    return {
+      imageUrls: [],
+    };
+  },
+  computed: {
+    nodes() {
+      const {
+        content,
+        noData,
+        imageProp,
+        startHandler,
+        endHandler,
+        charsHandler,
+      } = this;
+      const parseData = content || noData;
+      const customHandler = {
+        start: startHandler,
+        end: endHandler,
+        chars: charsHandler,
+      };
+      const results = HtmlToJson(parseData, customHandler, imageProp, this);
+      this.imageUrls = results.imageUrls;
+      console.log(results)
+      return results.nodes;
+    },
+  },
+  methods: {
+    navigate(href, $event) {
+      this.$emit('navigate', href, $event);
+    },
+    preview(src, $event) {
+      if (!this.imageUrls.length) return;
+      wx.previewImage({
+        current: src,
+        urls: this.imageUrls,
+      });
+      this.$emit('preview', src, $event);
+    },
+    removeImageUrl(src) {
+      const { imageUrls } = this;
+      imageUrls.splice(imageUrls.indexOf(src), 1);
+    },
+  },
+};
+</script>

+ 25 - 0
exam-06173-uni - reg/components/uni-status-bar/uni-status-bar.vue

@@ -0,0 +1,25 @@
+<template>
+	<view :style="{ height: statusBarHeight }" class="uni-status-bar">
+		<slot />
+	</view>
+</template>
+
+<script>
+	var statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px'
+	export default {
+		name: 'UniStatusBar',
+		data() {
+			return {
+				statusBarHeight: statusBarHeight
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.uni-status-bar {
+		width: 750rpx;
+		height: 20px;
+		// height: var(--status-bar-height);
+	}
+</style>

+ 63 - 0
exam-06173-uni - reg/components/yf-carsousel/yf-carsousel.vue

@@ -0,0 +1,63 @@
+<template>
+	
+		<swiper 
+		:interval="3000" 
+		:duration="1000" 
+		:indicator-dots="true" 
+		:current="current" @change="swiperTab" 
+		:autoplay="true"
+		:circular="true"
+		class="swiper"
+		>
+			<swiper-item v-for="(item,index) in dataList" :key="index">
+				<image :src="item.url" class="swiper-img" mode="aspectFill"></image>
+			</swiper-item>
+		</swiper>
+</template>
+
+<script>
+	export default {
+		name: "yf-carsousel",
+		props:{
+			imgList: {
+				type: Array,
+				default() {
+					return []
+				}
+			}
+		},
+		data() {
+			return {
+				current: 0,
+				dataList: []
+			}
+		},
+		watch: {
+			imgList: {
+				handler(val) {
+					console.log('watch....', val)
+					this.dataList = val
+				},
+				deep: true
+			}
+		},
+		mounted() {
+			this.dataList = this.imgList
+		},
+		methods: {
+			swiperTab(e) {
+				var that = this;
+				this.current = Number(e.target.current);
+			}
+		}
+	}
+</script>
+
+<style>
+	
+	.swiper, .swiper-img {
+		width: 100vw;
+		height: 45vw;
+	}
+	
+</style>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 57 - 0
exam-06173-uni - reg/components/yf-empty-view/yf-empty-view.vue


+ 101 - 0
exam-06173-uni - reg/components/yf-file-upload/yf-file-upload.vue

@@ -0,0 +1,101 @@
+<template>
+  
+  <view>
+  	<view>
+  		<image v-if="fileUrl" :src="fileUrl" mode="widthFix" style="width: 120px;"></image>
+  	</view>
+  
+  	<view v-if="fileUrl">
+  		<button size="mini" type="warn" @click="clearUpload()">清除</button>
+  	</view>
+  
+  	<view v-else>
+  		<button size="mini" type="primary" @click="doUpload()">上传</button>
+  	</view>
+  </view>
+  
+  
+</template>
+
+<script>
+import { uploadFile } from '@/common/upload.js'
+
+export default {
+  name: 'yf-file-upload',
+  props: {
+    value: String,
+    accept: {
+      type: String,
+      default: '*'
+    },
+    tips: String,
+    listType: {
+      type: String,
+      default: 'picture'
+    }
+  },
+  data() {
+    return {
+      fileUrl: '',
+	  showProgress: false,
+	  percent: 0
+    }
+  },
+
+  watch: {
+    // 检测查询变化
+    value: {
+      handler() {
+        this.fillValue()
+      }
+    },
+
+    // 检测查询变化
+    fileUrl: {
+      handler(val) {
+        this.$emit('input', val)
+      }
+    }
+  },
+  mounted() {
+    
+  },
+
+  created() {
+    this.fillValue()
+  },
+
+  methods: {
+	  
+
+
+    fillValue() {
+      this.fileUrl = this.value
+    },
+	
+	// 执行上传操作
+	doUpload() {
+	
+		let that = this
+	
+		uni.chooseImage({
+			count: 1,
+			sizeType: ['copressed'],
+			success(res) {
+				uploadFile(res.tempFiles[0]).then(resUrl=>{
+					console.log('上传结果', resUrl)
+					that.$emit('input', resUrl)
+					that.showProgress = false
+				})
+			}
+		})
+	},
+	
+	// 清理上传
+	clearUpload() {
+		this.$emit('input', '')
+	}
+
+  }
+}
+</script>

+ 109 - 0
exam-06173-uni - reg/components/yf-more-list/yf-more-list.vue

@@ -0,0 +1,109 @@
+<template>
+	<view :id="id">
+
+		<uni-list>
+			<template v-for="(item,index) in dataList">
+				<slot name="item" v-bind:data="item"></slot>
+			</template>
+		</uni-list>
+
+		<yf-empty-view :isShow="more==='noMore' && query.current==1 && dataList.length==0"></yf-empty-view>
+		<uni-load-more v-if="dataList.length > 0 " :status="more" :contentText="contentText"></uni-load-more>
+
+	</view>
+</template>
+
+<script>
+	import request from '@/common/request.js'
+
+	export default {
+		name: 'yf-more-list',
+		components: {},
+		props: {
+			url: String, // 页面地址
+			params: Object
+		},
+		data() {
+			return {
+				id: new Date().getTime(),
+				contentText: {
+					contentdown: "上拉显示更多",
+					contentrefresh: "正在加载...",
+					contentnomore: "没有更多数据了..."
+				},
+				loading: false,
+				more: 'more',
+				query: {
+					current: 1,
+					size: 10,
+					params: {
+						
+					}
+				},
+				dataList: []
+			}
+		},
+		watch: {
+			params: {
+				handler(val) {
+					this.query.params = val
+					this.initData()
+				},
+				deep: true
+			}
+		},
+
+		mounted() {
+			this.id = new Date().getTime()
+			this.query.params = this.params
+			this.loadData()
+		},
+
+
+		methods: {
+
+			initData() {
+				this.more = 'more'
+				this.query.current = 1
+				this.dataList = []
+				this.loadData();
+			},
+
+
+			loadData() {
+				
+
+				// 避免重复加载
+				if (this.more === 'loading' || this.more == 'noMore') {
+					return;
+				}
+
+				this.more = 'loading'
+				// 加载数据
+				request.post(this.url, this.query).then(res => {
+					
+					// 清空列表
+					if (this.query.current === 1) {
+						this.dataList = []
+					}
+
+					// 追加数据
+					this.dataList = this.dataList.concat(res.records)
+					
+					console.log(this.dataList)
+					if (this.query.current >= res.pages) {
+						this.more = 'noMore'
+					} else {
+						this.more = 'more'
+						this.query.current += 1
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style>
+
+
+</style>

+ 150 - 0
exam-06173-uni - reg/components/yf-photo-take/yf-photo-take.vue

@@ -0,0 +1,150 @@
+<template>
+	<view>
+		<button  type="primary" @tap="takePhoto">拍照人脸识别</button>
+	</view>
+</template>
+
+<script>
+	import { pathToBase64, base64ToPath } from 'image-tools'
+	export default {
+		name: 'yf-photo-take',
+		props:{
+			value: String,
+			base64: String
+		},
+		data() {
+			return {
+				photo: '',
+				photoBase64: ''
+			}
+		},
+		watch:{
+			value: {
+				handler(val){
+					if(!val){
+						this.photo = ''
+						this.photoBase64 = ''
+					}
+				}
+			},
+			
+			photo: {
+				handler(val){
+					this.$emit('input', val)
+					this.$emit('update:base64', this.photoBase64)
+				}
+			}
+		},
+
+		methods: {
+
+			// 拍照选图
+			takePhoto(){
+				
+				// #ifdef MP-WEIXIN
+				this.mediaChoose()
+				// #endif
+				
+				// #ifndef MP-WEIXIN
+				this.imageChoose()
+				// #endif
+			},
+		
+		
+			// 压缩和处理图片
+			compressImage(url){
+				
+				let that = this
+				
+				uni.showLoading({
+					title: '正在处理图片..'
+				})
+				
+				// #ifndef H5
+				uni.compressImage({
+				  src: url,
+				  width: '500px',
+				  height: 'auto',
+				  quality: 90,
+				  success: res => {
+					console.log('uni-压缩:', res.tempFilePath)
+					url = res.tempFilePath
+					// 转换base64
+					pathToBase64(url).then(img => {
+						// 去除png文件头
+						that.photoBase64 = img.replace(/^data:image\/\w+;base64,/, "");
+						that.photo = url
+						uni.hideLoading()
+					}).catch(error => {
+						console.error(error)
+						uni.hideLoading()
+					})
+				  }
+				})
+				// #endif
+				
+				
+				// #ifdef H5
+				pathToBase64(url).then(img => {
+					// H5压缩base64
+					that.$utils.compressImage(img, 500).then(psd=>{
+						// 去除png文件头
+						that.photoBase64 = psd.replace(/^data:image\/\w+;base64,/, "");
+						that.photo = url
+						uni.hideLoading()
+					})
+				}).catch(error => {
+					console.error(error)
+					uni.hideLoading()
+				})
+				// #endif
+			},
+		
+			
+			
+			// 小程序平台选择图片及压缩
+			mediaChoose(){
+				
+				let that = this
+				
+				uni.chooseMedia({
+				  count: 1,
+				  mediaType: ['image'],
+				  sourceType: ['camera'],
+				  maxDuration: 30,
+				  camera: 'front',
+				  success(res) {
+					  
+					let url = ''
+					  
+					if(res.tempFilePaths){
+						url = res.tempFilePaths[0]
+					}else{
+						url = res.tempFiles[0].tempFilePath
+					}
+					
+					that.compressImage(url);
+					
+				  }
+				})
+			},
+			
+			// H5平台选择图片和压缩
+			imageChoose(){
+				
+				let that = this
+				
+				uni.chooseImage({
+				  	count: 1,
+				    sizeType: ['original', 'compressed'],
+				    sourceType: ['camera'], //这要注意,camera掉拍照,album是打开手机相册
+				    success: (res)=> {
+						let url = res.tempFilePaths[0]
+						that.compressImage(url);
+				    }
+				});
+			}
+			
+		}
+	}
+</script>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 14140 - 0
exam-06173-uni - reg/hybrid/html/build/pdf.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 0
exam-06173-uni - reg/hybrid/html/build/pdf.js.map


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 47638 - 0
exam-06173-uni - reg/hybrid/html/build/pdf.worker.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 0
exam-06173-uni - reg/hybrid/html/build/pdf.worker.js.map


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/78-EUC-H.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/78-EUC-V.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/78-H.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/78-RKSJ-H.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/78-RKSJ-V.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/78-V.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/78ms-RKSJ-H.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/78ms-RKSJ-V.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/83pv-RKSJ-H.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/90ms-RKSJ-H.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/90ms-RKSJ-V.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/90msp-RKSJ-H.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/90msp-RKSJ-V.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/90pv-RKSJ-H.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/90pv-RKSJ-V.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Add-H.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Add-RKSJ-H.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Add-RKSJ-V.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Add-V.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-0.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-1.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-2.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-3.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-4.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-5.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-6.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-CNS1-UCS2.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-GB1-0.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-GB1-1.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-GB1-2.bcmap


BIN
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-GB1-3.bcmap


+ 0 - 0
exam-06173-uni - reg/hybrid/html/web/cmaps/Adobe-GB1-4.bcmap


Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov