/// declare namespace tools { export interface Entity { } export interface Result { code?: number | string, desc?: string, data?: T | T[] } export interface UpyunResult { code: number, message?: string, time: number, url: string } export interface CheckQrResult extends Entity { /** * 课程ID */ courseId: number, /** * 课程名称 */ courseName: string, /** * 考试记录DataID */ examRecordDataId: number, /** * 考生ID */ examStudentId: number, /** * 考试试题大题号 */ questionMainNumber: number, /** * 考试试题题序 */ questionOrder: number, /** * 登录信息key */ key: string, /** * 登录信息token */ token: string, subNumber: number, } export interface SignResult extends Entity { accessUrl: string, formUrl: string, fsType: string, uploadUrl: string, formParams: object, signIdentifier: string } export interface NotifyResult extends Entity { filePath: string, result: boolean } export interface AudioAnswer extends Entity { examRecordDataId: number, mainNumber: number, order: number, studentAnswer: string, subNumber: string } } interface ApiConfigOption { ver: number, versionName: string, baseUrl: string } interface RequestOption { url: string, parameter: any } type TokenValidCallback = () => void; interface API { configOption: ApiConfigOption version(): string setTokenValidCallback(callback: TokenValidCallback): void checkQrcode(secret: string): Promise getPaperStruct(examRecordDataId: number) : Promise getSign(examRecordDataId: number, examStudentId: number, order: number, fileMd5: string, suffix: string) : Promise uploadFile(filePath: string, formParams: object, uploadUrl: string) : Promise notifyServer(examRecordDataId: number, examStudentId: number, order: number, filePath: string, transferFileType: string) : Promise getNotifyResult(acknowledgeId: string) : Promise getUploadedAudioAnswerList(examRecordDataId: number) : Promise getRequest(option: RequestOption, auth: boolean): Promise postRequest(option: RequestOption, auth: boolean): Promise } export class Api implements API { //ecs.qmth.com.cn:8878 //http://192.168.10.39:8003 //https://ecs.qmth.com.cn:8878 //ecs-test.qmth.com.cn //http://ecs-dev.qmth.com.cn //'https://org0.ea100.com.cn' //https://ecs-test.ea100.com.cn https://ecs-test.ea100.com.cn configOption: ApiConfigOption = { ver: 1, versionName: 'v1.0.0', baseUrl: 'http://192.168.10.41:8003' } private key: string = '' private token: string = '' private tokenValidCallback: TokenValidCallback = () => {} version(): string { return this.configOption.versionName } init(config: ApiConfigOption) { this.configOption = config } initBaseUrl(baseUrl: string) { this.configOption.baseUrl = baseUrl.replace(':443', '') console.log("initBaseUri:" + this.configOption.baseUrl) } /** * 授权成功后配置 * @param {number} uid * @param {string} token * @param {number} partitionId */ configAuthorize(key: string, token: string) { this.key = key this.token = token } setTokenValidCallback(callback: TokenValidCallback): void { this.tokenValidCallback = callback } checkQrcode(secret: string): Promise { const that = this return new Promise((resolve, reject) => { return this.postRequest({ url: '/api/ecs_oe_student/examControl/checkQrCode', parameter: { qrCode: secret } }, false).then(res => { console.log('then') if (res.key && res.token) { that.configAuthorize(res.key, res.token) // model transformer var result = { courseId: res.courseId, courseName: res.courseName, examRecordDataId: res.examRecordDataId, examStudentId: res.examStudentId, questionMainNumber: res.questionMainNumber, questionOrder: res.questionOrder, subNumber: res.subNumber } resolve((result as tools.CheckQrResult)) } else { reject('二维码已失效') } }, error => { reject(error) }).catch( exceptions => { reject(exceptions) }) }) } getPaperStruct(examRecordDataId: number) : Promise { return new Promise((resovle, reject) => { return this.getRequest({ url: '/api/ecs_oe_student/examRecordPaperStruct/getExamRecordPaperStruct', parameter: { examRecordDataId: examRecordDataId } }).then( res => { resovle(res) }, error => { reject(error) }).catch( exceptions => { reject(exceptions) }) }) } getSign(examRecordDataId: number, examStudentId: number, order: number, fileMd5: string, suffix: string) : Promise { return new Promise((resolve, reject) => { return this.postRequest({ url: '/api/ecs_oe_student/examControl/yunSignature', parameter: { examRecordDataId: examRecordDataId, examStudentId: examStudentId, order: order, fileMd5: fileMd5, fileSuffix: suffix } }).then(res => { var result = { accessUrl: res.accessUrl, formUrl: res.formUrl, fsType: res.fsType, uploadUrl: res.uploadUrl, formParams: res.formParams, signIdentifier: res.signIdentifier, } resolve(result) }, error => { reject(error) }) }) } uploadFile(filePath: string, formParams: object, uploadUrl: string) : Promise { return new Promise(function (resolve, reject) { wx.uploadFile({ url: uploadUrl, filePath: filePath, name: 'file', formData: formParams, success: res => { resolve(res) }, fail: error => { if (error.errMsg == 'uploadFile:fail url not in domain list') { reject('请点击右上角"•••"按钮开启调试模式') } else { reject(error.errMsg) } } }) }) } notifyServer(examRecordDataId: number, examStudentId: number, order: number, filePath: string, transferFileType: string) : Promise { return new Promise((resovle, reject) => { return this.postRequest({ url: '/api/ecs_oe_student/examControl/saveUploadedFile', parameter: { examRecordDataId: examRecordDataId, examStudentId: examStudentId, order: order, filePath: filePath, transferFileType: transferFileType } }).then( res => { resovle(res) }, error => { console.log('===================') reject(error) }).catch( exceptions => { console.log('===================') reject(exceptions) }) }) } getNotifyResult(acknowledgeId: string) : Promise { return new Promise((resovle, reject) => { return this.postRequest({ url: '/api/ecs_oe_student/examControl/getUploadedFileAcknowledgeStatus', parameter: { acknowledgeId: acknowledgeId } }).then( res => { resovle(res) }, error => { reject(error) }).catch( exceptions => { reject(exceptions) }) }) } getUploadedAudioAnswerList(examRecordDataId: number) : Promise { return new Promise((resolve, reject) => { return this.postRequest({ url: '/api/ecs_oe_student/examControl/getUploadedAudioAnswerList', parameter: { examRecordDataId: examRecordDataId } }).then( res => { resolve(res as tools.AudioAnswer[]) }, error => { reject(error) }).catch(e => { reject(e) }) }) } getRequest(option: RequestOption, auth: boolean = true): Promise { const that = this const header = auth ? { 'Content-Type': 'application/x-www-form-urlencoded', key: that.key, token: that.token } : { 'Content-Type': 'application/x-www-form-urlencoded', } return new Promise(function (resolve, reject) { wx.request({ url: that.configOption.baseUrl + option.url, method: 'GET', header: header, data: option.parameter, success: res => { console.log("request success", res); if (that.isTokenInValidCode(res.statusCode)) { reject('token失效') // token失效 if (that.tokenValidCallback) { that.tokenValidCallback() } } else if (res.statusCode !== 200) { reject((res.data as tools.Result).desc) } else { resolve(res.data) } }, fail: function (res) { console.log("request fail", res); if (res.errMsg == 'request:fail url not in domain list') { reject('请点击右上角"•••"按钮开启调试模式') } else if (res.errMsg == 'request:fail ') { reject("网络请求失败"); } else { reject(res.errMsg); } } }) }) } postRequest(option: RequestOption, auth: boolean = true): Promise { const that = this const header = auth ? { 'Content-Type': 'application/x-www-form-urlencoded', key: that.key, token: that.token } : { 'Content-Type': 'application/x-www-form-urlencoded', } console.log(that.configOption.baseUrl + option.url); console.log(option) return new Promise(function (resolve, reject) { wx.request({ url: that.configOption.baseUrl + option.url, method: 'POST', header: header, data: option.parameter, success: res => { console.log("request success", res); if (that.isTokenInValidCode(res.statusCode)) { reject('token失效') // token失效 if (that.tokenValidCallback) { that.tokenValidCallback() } } else if (res.statusCode == 503) { //接口限流,自动重试 that._postRequest(option, auth, 0, resolve, reject) } else if (res.statusCode !== 200) { reject((res.data as tools.Result).desc) } else { resolve(res.data) } }, fail: function (res) { console.log("request fail", res); if (res.errMsg == 'request:fail url not in domain list') { reject('请点击右上角"•••"按钮开启调试模式') } else if (res.errMsg == 'request:fail ') { reject("网络请求失败"); } else { reject(res.errMsg); } } }) }) } _postRequest(option: RequestOption, auth: boolean = true, retry: number = 0, resolve: (value?: any | PromiseLike) => void, reject: (reason?: any) => void) { const that = this const header = auth ? { 'Content-Type': 'application/x-www-form-urlencoded', key: that.key, token: that.token } : { 'Content-Type': 'application/x-www-form-urlencoded', } console.log(option) if (retry > 0) { console.log('正在重试'+retry) } wx.request({ url: that.configOption.baseUrl + option.url, method: 'POST', header: header, data: option.parameter, success: res => { console.log("request success", res); if (that.isTokenInValidCode(res.statusCode)) { reject('token失效') // token失效 if (that.tokenValidCallback) { that.tokenValidCallback() } } else if (res.statusCode == 503) { //接口限流,自动重试 if (retry < 10) { console.log('200ms重试') setTimeout(() => { that._postRequest(option, auth, retry+1, resolve, reject) }, 200); } else { reject('服务器繁忙,请稍后重试!') } } else if (res.statusCode !== 200) { reject((res.data as tools.Result).desc) } else { resolve(res.data) } }, fail: function (res) { console.log("request fail", res); if (res.errMsg == 'request:fail url not in domain list') { reject('请点击右上角"•••"按钮开启调试模式') } else if (res.errMsg == 'request:fail ') { reject("网络请求失败"); } else { reject(res.errMsg); } } }) } private isTokenInValidCode(code: number) : boolean { return code === 401 || code === 403 } }