從0到1:多醫院陪診小程序開發筆記(上)

概要設計

醫院陪診預約小程序:隨著移動互聯網的普及,越來越多的醫院陪診服務開始向線上轉型, 傳統的預約方式往往效率低下,用戶需耗費大量時間進行電話預約或現場排隊,陪診服務預約小程序集多種服務于一體,可以提高服務效率、提升用戶體驗。 用戶可以瀏覽不同醫院的位置、陪診項目和陪診時間,用戶可以選擇日期、時間段和人數,然后進行預約。

功能規劃

本項目前后端完整代碼包括公告通知,用戶預約,簽到核銷, 管理者可以自定義預約要填寫的內容,比如姓名、性別、年齡、診療科室、手機號等,后臺預約管理,后臺預約名單管理和導出Excel,后臺設置預約時段和人數上線,后臺管理最新通知公告,后臺用戶管理,后臺醫院管理,醫院管理員設定等功能。

在這里插入圖片描述

數據庫設計

MeetModel.DB_STRUCTURE = {_pid: 'string|true',MEET_ID: 'string|true',MEET_ADMIN_ID: 'string|true|comment=添加的管理員',MEET_TITLE: 'string|true|comment=標題',MEET_UNIT_ID: 'string|false',MEET_UNIT_NAME: 'string|false',MEET_JOIN_FORMS: 'array|true|default=[]|comment=表單字段設置',MEET_DAYS: 'array|true|default=[]|comment=最近一次修改保存的可用日期',MEET_CATE_ID: 'string|true|comment=分類編號',MEET_CATE_NAME: 'string|true|comment=分類冗余', MEET_FORMS: 'array|true|default=[]',MEET_OBJ: 'object|true|default={}',  MEET_CANCEL_SET: 'int|true|default=1|comment=取消設置 0=不允,1=允許,2=僅開始前可取消',MEET_STATUS: 'int|true|default=1|comment=狀態 0=未啟用,1=使用中,9=停止預約,10=已關閉',MEET_ORDER: 'int|true|default=9999',MEET_VOUCH: 'int|true|default=0',MEET_QR: 'string|false', MEET_ADD_TIME: 'int|true',MEET_EDIT_TIME: 'int|true',MEET_ADD_IP: 'string|false',MEET_EDIT_IP: 'string|false',
};JoinModel.DB_STRUCTURE = {_pid: 'string|true',JOIN_ID: 'string|true',JOIN_UNIT_ID: 'string|false',JOIN_UNIT_NAME: 'string|false',JOIN_EDIT_ADMIN_ID: 'string|false|comment=最近修改的管理員ID',JOIN_EDIT_ADMIN_NAME: 'string|false|comment=最近修改的管理員名',JOIN_EDIT_ADMIN_TIME: 'int|true|default=0|comment=管理員最近修改的時間',JOIN_EDIT_ADMIN_STATUS: 'int|false|comment=最近管理員修改為的狀態 ',JOIN_IS_ADMIN: 'int|true|default=0|comment=是否管理員添加 0/1',JOIN_CODE: 'string|true|comment=核驗碼15位',JOIN_IS_CHECKIN: 'int|true|default=0|comment=是否核銷 0/1 ',JOIN_CHECKIN_TIME: 'int|true|default=0',JOIN_USER_ID: 'string|true|comment=用戶ID',JOIN_MEET_ID: 'string|true|comment=預約PK',JOIN_MEET_CATE_ID: 'string|true',JOIN_MEET_CATE_NAME: 'string|true',JOIN_MEET_TITLE: 'string|true|comment=項目',JOIN_MEET_DAY: 'string|true|comment=日期',JOIN_MEET_TIME_START: 'string|true|comment=時段開始',JOIN_MEET_TIME_END: 'string|true|comment=時段結束',JOIN_MEET_TIME_MARK: 'string|true|comment=時段標識',JOIN_COMPLETE_END_TIME: 'string|false|comment=完整結束時間',JOIN_START_TIME: 'int|true|comment=開始時間戳',JOIN_FORMS: 'array|true|default=[]|comment=表單',/* title:mark:type:val:*/JOIN_OBJ: 'object|true|default={}',JOIN_STATUS: 'int|true|default=1|comment=狀態 1=預約成功,10=已取消, 99=系統取消',JOIN_REASON: 'string|false|comment=審核拒絕或者取消理由',JOIN_ADD_TIME: 'int|true',JOIN_EDIT_TIME: 'int|true',JOIN_ADD_IP: 'string|false',JOIN_EDIT_IP: 'string|false',
};

核心實現

class MeetService extends BaseProjectService {constructor() {super();this._log = new LogUtil(projectConfig.MEET_LOG_LEVEL);}/*** 拋出異常* @param {*} msg * @param {*} code */AppError(msg) {this._log.error(msg);super.AppError(msg);}_meetLog(meet, func = '', msg = '') {let str = '';str = `[MEET=${meet.MEET_TITLE}][${func}] ${msg}`;this._log.debug(str);}/** 統一獲取Meet(某天) */async getMeetOneDay(meetId, day, where, fields = '*') {let meet = await MeetModel.getOne(where, fields);if (!meet) return meet;meet.MEET_DAYS_SET = await this.getDaysSet(meetId, day, day);return meet;}/** 獲取日期設置 */async getDaysSet(meetId, startDay, endDay = null) {let where = {DAY_MEET_ID: meetId}if (startDay && endDay && endDay == startDay)where.day = startDay;else if (startDay && endDay)where.day = ['between', startDay, endDay];else if (!startDay && endDay)where.day = ['<=', endDay];else if (startDay && !endDay)where.day = ['>=', startDay];let orderBy = {'day': 'asc'}let list = await DayModel.getAllBig(where, 'day,dayDesc,times', orderBy, 1000);for (let k = 0; k < list.length; k++) {delete list[k]._id;}return list;}// 按時段統計某時段報名情況async statJoinCnt(meetId, timeMark) {let whereDay = {DAY_MEET_ID: meetId,day: this.getDayByTimeMark(timeMark)};let day = await DayModel.getOne(whereDay, 'times');if (!day) return;let whereJoin = {JOIN_MEET_TIME_MARK: timeMark,JOIN_MEET_ID: meetId};let ret = await JoinModel.groupCount(whereJoin, 'JOIN_STATUS');let stat = { //統計數據succCnt: ret['JOIN_STATUS_1'] || 0, //1=預約成功,cancelCnt: ret['JOIN_STATUS_10'] || 0, //10=已取消, adminCancelCnt: ret['JOIN_STATUS_99'] || 0, //99=后臺取消};let times = day.times;for (let j in times) {if (times[j].mark === timeMark) {let data = {['times.' + j + '.stat']: stat}await DayModel.edit(whereDay, data);return;}}}// 預約前檢測async beforeJoin(userId, meetId, timeMark) {await this.checkMeetRules(userId, meetId, timeMark);} // 根據日期獲取其所在天設置getDaySetByDay(meet, day) {for (let k = 0; k < meet.MEET_DAYS_SET.length; k++) {if (meet.MEET_DAYS_SET[k].day == day)return dataUtil.deepClone(meet.MEET_DAYS_SET[k]);}return null;}// 根據時段標識獲取其所在天 getDayByTimeMark(timeMark) {return timeMark.substr(1, 4) + '-' + timeMark.substr(5, 2) + '-' + timeMark.substr(7, 2);}// 根據時段標識獲取其所在天設置getDaySetByTimeMark(meet, timeMark) {let day = this.getDayByTimeMark(timeMark);for (let k = 0; k < meet.MEET_DAYS_SET.length; k++) {if (meet.MEET_DAYS_SET[k].day == day)return dataUtil.deepClone(meet.MEET_DAYS_SET[k]);}return null;}// 根據時段標識獲取其所在時段設置getTimeSetByTimeMark(meet, timeMark) {let day = this.getDayByTimeMark(timeMark);for (let k = 0; k < meet.MEET_DAYS_SET.length; k++) {if (meet.MEET_DAYS_SET[k].day != day) continue;for (let j in meet.MEET_DAYS_SET[k].times) {if (meet.MEET_DAYS_SET[k].times[j].mark == timeMark)return dataUtil.deepClone(meet.MEET_DAYS_SET[k].times[j]);}}return null;}// 預約時段人數和狀態控制校驗async checkMeetTimeControll(meet, timeMark, meetPeopleCnt = 1) {if (!meet) this.AppError('預約時段設置錯誤, 預約項目不存在');let daySet = this.getDaySetByTimeMark(meet, timeMark); // 當天設置let timeSet = this.getTimeSetByTimeMark(meet, timeMark); // 預約時段設置if (!daySet || !timeSet) this.AppError('預約時段設置錯誤day&time');let statusDesc = timeSet.status == 1 ? '開啟' : '關閉';let limitDesc = '';if (timeSet.isLimit) {limitDesc = '人數上限MAX=' + timeSet.limit;} elselimitDesc = '人數不限制NO';this._meetLog(meet, `------------------------------`);this._meetLog(meet, `#預約時段控制,預約日期=<${daySet.day}>`, `預約時段=[${timeSet.start}-${timeSet.end}],狀態=${statusDesc}, ${limitDesc} 當前預約成功人數=${timeSet.stat.succCnt}`);if (timeSet.status == 0) this.AppError('該時段預約已經關閉,請選擇其他');// 時段總人數限制if (timeSet.isLimit) {if (timeSet.stat.succCnt >= timeSet.limit) {this.AppError('該時段預約人員已滿,請選擇其他');}let maxCnt = timeSet.limit - timeSet.stat.succCnt;if (maxCnt < meetPeopleCnt) {this.AppError('本時段最多還可以預約' + (maxCnt) + '人,您當前提交了' + meetPeopleCnt + '人,請調整后再提交');}}}/** 報名規則校驗 */async checkMeetRules(userId, meetId, timeMark, formsList = null) {// 預約時段是否存在let meetWhere = {_id: meetId};let day = this.getDayByTimeMark(timeMark);let meet = await this.getMeetOneDay(meetId, day, meetWhere);if (!meet) {this.AppError('預約時段選擇錯誤,請重新選擇');}// 預約時段人數和狀態控制校驗let meetPeopleCnt = formsList ? formsList.length : 1;await this.checkMeetTimeControll(meet, timeMark, meetPeopleCnt);// 截止規則  await this.checkMeetEndSet(meet, timeMark);// 針對用戶的次數限制await this.checkMeetLimitSet(userId, meet, timeMark, meetPeopleCnt);}// 預約次數限制校驗async checkMeetLimitSet(userId, meet, timeMark, nowCnt) {if (!meet) this.AppError('預約次數規則錯誤, 預約項目不存在');let meetId = meet._id;let daySet = this.getDaySetByTimeMark(meet, timeMark); // 當天設置let timeSet = this.getTimeSetByTimeMark(meet, timeMark); // 預約時段設置this._meetLog(meet, `------------------------------`);this._meetLog(meet, `#預約次數規則,預約日期=<${daySet.day}>`, `預約時段=[${timeSet.start}~${timeSet.end}]`);let where = {JOIN_MEET_ID: meetId,JOIN_MEET_TIME_MARK: timeMark,JOIN_USER_ID: userId,JOIN_STATUS: JoinModel.STATUS.SUCC}let cnt = await JoinModel.count(where);let maxCnt = projectConfig.MEET_MAX_JOIN_CNT;this._meetLog(meet, `預約次數規則,mode=本時段可預約${maxCnt}次`, `當前已預約=${cnt}次`);if (cnt >= maxCnt)this.AppError(`您本時段已經預約,不能繼續預約`);}// 預約截止設置校驗async checkMeetEndSet(meet, timeMark) {if (!meet) this.AppError('預約截止規則錯誤, 預約項目不存在');this._meetLog(meet, `------------------------------`);let daySet = this.getDaySetByTimeMark(meet, timeMark); // 當天設置let timeSet = this.getTimeSetByTimeMark(meet, timeMark); // 預約時段設置this._meetLog(meet, `#預約截止規則,預約日期=<${daySet.day}>`, `預約時段=[${timeSet.start}-${timeSet.end}]`);let nowTime = timeUtil.time('Y-M-D h:m:s');/*let startTime = daySet.day + ' ' + timeSet.start + ':00';this._meetLog(meet, `預約開始規則,mode=<時段過期判定>`, `預約開始時段=${startTime},當前時段=${nowTime}`);if (nowTime > startTime) {this.AppError('該時段已開始,無法預約,請選擇其他');}*/let endTime = daySet.day + ' ' + timeSet.end + ':59';this._meetLog(meet, `預約開始規則,mode=<時段過期判定>`, `預約結束時段=${endTime},當前時段=${nowTime}`);if (nowTime > endTime) {this.AppError('該時段已結束,無法預約,請選擇其他');}}/**  預約詳情 */async viewMeet(meetId) {let fields = '*';let where = {_id: meetId,MEET_STATUS: ['in', [MeetModel.STATUS.COMM, MeetModel.STATUS.OVER]]}let meet = await MeetModel.getOne(where, fields);if (!meet) return null;let getDaysSet = [];meet.MEET_DAYS_SET = await this.getDaysSet(meetId, timeUtil.time('Y-M-D')); //今天及以后let daysSet = meet.MEET_DAYS_SET;let now = timeUtil.time('Y-M-D');for (let k = 0; k < daysSet.length; k++) {let dayNode = daysSet[k];if (dayNode.day < now) continue; // 排除過期let getTimes = [];for (let j in dayNode.times) {let timeNode = dayNode.times[j];// 排除狀態關閉的時段if (timeNode.status != 1) continue;// 判斷數量是否已滿if (timeNode.isLimit && timeNode.stat.succCnt >= timeNode.limit)timeNode.error = '預約已滿';// 截止規則if (!timeNode.error) {try {await this.checkMeetEndSet(meet, timeNode.mark);} catch (ex) {if (ex.name == 'AppError')timeNode.error = '預約結束';elsethrow ex;}}getTimes.push(timeNode);}dayNode.times = getTimes;getDaysSet.push(dayNode);}// 只返回需要的字段let ret = {};ret.MEET_DAYS_SET = getDaysSet;ret.MEET_QR = meet.MEET_QR;ret.MEET_TITLE = meet.MEET_TITLE;ret.MEET_CATE_NAME = meet.MEET_CATE_NAME;ret.MEET_OBJ = meet.MEET_OBJ;ret.MEET_UNIT_NAME = meet.MEET_UNIT_NAME;return ret;}/**  預約前獲取關鍵信息 */async detailForJoin(userId, meetId, timeMark) {let fields = 'MEET_DAYS_SET,MEET_JOIN_FORMS, MEET_TITLE';let where = {_id: meetId,MEET_STATUS: ['in', [MeetModel.STATUS.COMM, MeetModel.STATUS.OVER]]}let day = this.getDayByTimeMark(timeMark);let meet = await this.getMeetOneDay(meetId, day, where, fields);if (!meet) return null;let dayDesc = timeUtil.fmtDateCHN(this.getDaySetByTimeMark(meet, timeMark).day);let timeSet = this.getTimeSetByTimeMark(meet, timeMark);let timeDesc = timeSet.start + '~' + timeSet.end;meet.dayDesc = dayDesc + ' ' + timeDesc;// 取出本人最近一次本時段填寫表單let whereMy = {JOIN_USER_ID: userId,}let orderByMy = {JOIN_ADD_TIME: 'desc'}let joinMy = await JoinModel.getOne(whereMy, 'JOIN_FORMS', orderByMy);if (joinMy)meet.myForms = joinMy.JOIN_FORMS;elsemeet.myForms = [];return meet;}/** 按天獲取預約項目 */async getMeetListByDay(unit, day) {let where = {'meet.MEET_STATUS': ['in', [MeetModel.STATUS.COMM, MeetModel.STATUS.OVER]],'day': day,DAY_UNIT_NAME: unit,};let orderBy = {'MEET_ORDER': 'asc','MEET_ADD_TIME': 'desc'};let fields = 'meet.MEET_UNIT_NAME,meet.MEET_ORDER,meet.MEET_ADD_TIME,meet.MEET_TITLE,meet.MEET_DAYS_SET,meet.MEET_OBJ.cover, DAY_MEET_ID, day, times';let joinParams = {from: MeetModel.CL,localField: 'DAY_MEET_ID',foreignField: '_id',as: 'meet',};let list = await DayModel.getListJoin(joinParams, where, fields, orderBy, 1, 100, false);list = list.list;let retList = [];for (let k = 0; k < list.length; k++) {let usefulTimes = [];for (let j in list[k].times) {if (list[k].times[j].status != 1) continue;usefulTimes.push(list[k].times[j]);}if (usefulTimes.length == 0) continue;let node = {};node.timeDesc = usefulTimes.length > 1 ? usefulTimes.length + '個時段' : usefulTimes[0].start;node.title = list[k].meet.MEET_TITLE;node.pic = list[k].meet.MEET_OBJ.cover;node._id = list[k].DAY_MEET_ID;retList.push(node);}return retList;}/** 獲取從某天開始可預約的日期 */async getHasDaysFromDay(unit, day) {console.log(unit)let where = {DAY_UNIT_NAME: unit,day: ['>=', day],};let fields = 'DAY_UNIT_NAME,times,day';let list = await DayModel.getAllBig(where, fields);let retList = [];for (let k = 0; k < list.length; k++) {for (let n in list[k].times) {if (list[k].times[n].status == 1) {retList.push(list[k].day);break;}}} console.log(retList)return retList;}/** 取得預約分頁列表 */async getMeetList({unit,search, // 搜索條件sortType, // 搜索菜單sortVal, // 搜索菜單orderBy, // 排序 cateId, //分類查詢條件page,size,isTotal = true,oldTotal}) {orderBy = orderBy || {'MEET_ORDER': 'asc','MEET_ADD_TIME': 'desc'};let fields = 'MEET_UNIT_NAME,MEET_TITLE,MEET_OBJ,MEET_DAYS,MEET_CATE_NAME,MEET_CATE_ID';let where = {};where.and = {MEET_UNIT_NAME: unit,_pid: this.getProjectId() //復雜的查詢在此處標注PID};if (cateId && cateId !== '0') where.and.MEET_CATE_ID = cateId;where.and.MEET_STATUS = ['in', [MeetModel.STATUS.COMM, MeetModel.STATUS.OVER]]; // 狀態  if (util.isDefined(search) && search) {where.or = [{ MEET_TITLE: ['like', search] },];} else if (sortType && util.isDefined(sortVal)) {// 搜索菜單switch (sortType) {case 'sort': {orderBy = this.fmtOrderBySort(sortVal, 'NEWS_ADD_TIME');break;}case 'cateId': {if (sortVal) where.and.MEET_CATE_ID = String(sortVal);break;}}}let result = await MeetModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);return result;}/** 取消我的預約 只有成功可以取消 */async cancelMyJoin(userId, joinId) {let where = {JOIN_USER_ID: userId,_id: joinId,JOIN_IS_CHECKIN: 0, // 核銷不能取消JOIN_STATUS: JoinModel.STATUS.SUCC};let join = await JoinModel.getOne(where);if (!join) {this.AppError('未找到可取消的預約記錄');}// 取消規則判定let whereMeet = {_id: join.JOIN_MEET_ID,MEET_STATUS: ['in', [MeetModel.STATUS.COMM, MeetModel.STATUS.OVER]]}let meet = await this.getMeetOneDay(join.JOIN_MEET_ID, join.JOIN_MEET_DAY, whereMeet);if (!meet) this.AppError('預約項目不存在或者已關閉');let daySet = this.getDaySetByTimeMark(meet, join.JOIN_MEET_TIME_MARK);let timeSet = this.getTimeSetByTimeMark(meet, join.JOIN_MEET_TIME_MARK);if (!timeSet) this.AppError('被取消的時段不存在');if (meet.MEET_CANCEL_SET == 0)this.AppError('該預約不能取消');let startT = daySet.day + ' ' + timeSet.start + ':00';let startTime = timeUtil.time2Timestamp(startT);let now = timeUtil.time();if (meet.MEET_CANCEL_SET == 2 && now > startTime)this.AppError('該預約時段已經開始,無法取消');// TODO 已過期不能取消await JoinModel.del(where);// 統計this.statJoinCnt(join.JOIN_MEET_ID, join.JOIN_MEET_TIME_MARK);}/** 取得我的預約詳情 */async getMyJoinDetail(userId, joinId) {let fields = 'JOIN_UNIT_NAME,JOIN_COMPLETE_END_TIME,JOIN_IS_CHECKIN,JOIN_CHECKIN_TIME,JOIN_REASON,JOIN_MEET_ID,JOIN_MEET_TITLE,JOIN_MEET_DAY,JOIN_MEET_TIME_START,JOIN_MEET_TIME_END,JOIN_STATUS,JOIN_ADD_TIME,JOIN_CODE,JOIN_FORMS';let where = {_id: joinId,JOIN_USER_ID: userId};return await JoinModel.getOne(where, fields);}/** 取得我的預約分頁列表 */async getMyJoinList(userId, {search, // 搜索條件sortType, // 搜索菜單sortVal, // 搜索菜單orderBy, // 排序 page,size,isTotal = true,oldTotal}) {orderBy = orderBy || {//	'JOIN_MEET_DAY': 'desc',//	'JOIN_MEET_TIME_START': 'desc','JOIN_ADD_TIME': 'desc'};let fields = 'JOIN_UNIT_NAME,JOIN_COMPLETE_END_TIME,JOIN_IS_CHECKIN,JOIN_REASON,JOIN_MEET_ID,JOIN_MEET_TITLE,JOIN_MEET_DAY,JOIN_MEET_TIME_START,JOIN_MEET_TIME_END,JOIN_STATUS,JOIN_ADD_TIME,JOIN_OBJ';let where = {JOIN_USER_ID: userId};//where.MEET_STATUS = ['in', [MeetModel.STATUS.COMM, MeetModel.STATUS.OVER]]; // 狀態  if (util.isDefined(search) && search) {where['JOIN_MEET_TITLE'] = {$regex: '.*' + search,$options: 'i'};} else if (sortType) {// 搜索菜單switch (sortType) {case 'cateId': {if (sortVal) where.JOIN_MEET_CATE_ID = String(sortVal);break;}case 'all': { //所有 break;}case 'use': { //可用未過期where.JOIN_STATUS = JoinModel.STATUS.SUCC;where.JOIN_COMPLETE_END_TIME = ['>=', timeUtil.time('Y-M-D h:m')];break;}case 'check': { //已核銷where.JOIN_STATUS = JoinModel.STATUS.SUCC;where.JOIN_IS_CHECKIN = 1;break;}case 'timeout': { //已過期未核銷where.JOIN_STATUS = JoinModel.STATUS.SUCC;where.JOIN_IS_CHECKIN = 0;where.JOIN_COMPLETE_END_TIME = ['<', timeUtil.time('Y-M-D h:m')];break;}case 'succ': { //預約成功where.JOIN_STATUS = JoinModel.STATUS.SUCC;//where.JOIN_MEET_DAY = ['>=', timeUtil.time('Y-M-D h:m')];//where.JOIN_MEET_TIME_START = ['>=', timeUtil.time('h:m')];break;}case 'cancel': { //已取消where.JOIN_STATUS = ['in', [JoinModel.STATUS.CANCEL, JoinModel.STATUS.ADMIN_CANCEL]];break;}}}let result = await JoinModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);return result;}/** 取得我的某日預約列表 */async getMyJoinSomeday(userId, day) {let fields = 'JOIN_IS_CHECKIN,JOIN_MEET_ID,JOIN_MEET_TITLE,JOIN_MEET_DAY,JOIN_MEET_TIME_START,JOIN_MEET_TIME_END,JOIN_STATUS,JOIN_ADD_TIME';let where = {JOIN_USER_ID: userId,JOIN_MEET_DAY: day};//where.MEET_STATUS = ['in', [MeetModel.STATUS.COMM, MeetModel.STATUS.OVER]]; // 狀態  let orderBy = {'JOIN_MEET_TIME_START': 'asc','JOIN_ADD_TIME': 'desc'}return await JoinModel.getAll(where, fields, orderBy);}
}

UI設計

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

后臺管理系統設計

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

git下載

github下載

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85463.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85463.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85463.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

定時任務:springboot集成xxl-job-core(二)

定時任務實現方式&#xff1a; 存在的問題&#xff1a; xxl-job的原理&#xff1a; 可以根據服務器的個數進行動態分片&#xff0c;每臺服務器分到的處理數據是不一樣的。 1. 多臺機器動態注冊 多臺機器同時配置了調度器xxl-job-admin之后&#xff0c;執行器那里會有多個注…

Unity使用Lua框架和C#框架開發游戲的區別

在Unity中使用Lua框架和C#框架開發游戲有顯著的區別&#xff0c;主要體現在性能、開發效率、熱更新能力、維護成本等方面。 1. 語言類型與設計目標 維度LuaC#類型動態類型、解釋型腳本語言靜態類型、編譯型面向對象語言設計初衷輕量級嵌入、配置和擴展宿主程序通用開發&#…

高精度文檔解析利器:Mistral OCR 全面解析與技術應用

目錄 &#x1f680; 高精度文檔解析利器&#xff1a;Mistral OCR 全面解析與技術應用 一、什么是 Mistral OCR&#xff1f; 二、Mistral OCR 的核心特點 ? 1. 支持復雜文檔結構解析 ? 2. 高識別精度 ? 3. 與 AI 系統深度集成 ? 4. 可擴展性與容錯能力 三、技術原理…

騰訊云開發者社區文章內容提取免費API接口教程

接口簡介&#xff1a; 提取指定騰訊云開發者社區文章內容。本接口僅做內容提取&#xff0c;未經作者授權請勿轉載。 請求地址&#xff1a; https://cn.apihz.cn/api/caiji/tencent.php 請求方式&#xff1a; POST或GET。 請求參數&#xff1a; 【名稱】【參數】【必填】【說…

【項目】在線OJ(負載均衡式)

目錄 一、項目目標 二、開發環境 1.技術棧 2.開發環境 三、項目樹 目錄結構 功能邏輯 編寫思路 四、編碼 1.complie_server 服務功能 代碼藍圖 開發編譯功能 日志功能 ?編輯 測試編譯模塊 開發運行功能 設置運行限制 jsoncpp 編寫CR 如何生成唯一文件名 …

【后端高階面經:架構篇】50、數據存儲架構:如何改善系統的數據存儲能力?

一、數據存儲架構設計核心原則 (一)分層存儲架構:讓數據各得其所 根據數據訪問頻率和價值,將數據劃分為熱、溫、冷三層,匹配不同存儲介質,實現性能與成本的平衡。 熱數據層:訪問頻率>100次/秒。采用Redis集群存儲高頻訪問數據(如用戶登錄態、實時交易數據),配合…

B1、進度匯報(— 25/05/31)

本文檔匯總了各成員在 2025 年 5 月 11 日 ~ 5 月 31 日完成的工作。我們遇到了進度問題&#xff08;收工后需反思&#xff09;&#xff1a; 本學期第十四周&#xff08;05/19 ~ 05/25&#xff09;有相當多課程需要提交實驗結果或上臺展示。本學期第十六周&#xff08;06/02 ~…

每天總結一個html標簽——a標簽

文章目錄 一、定義與使用說明二、支持的屬性三、支持的事件四、默認樣式五、常見用法1. 文本鏈接2. 圖片鏈接3. 導航欄 在前端開發中&#xff0c;a標簽&#xff08;錨點標簽&#xff09;是最常用的HTML標簽之一&#xff0c;主要用于創建超鏈接&#xff0c;實現頁面間的跳轉或下…

云服務器突發宕機或無響應怎么辦

當云服務器突發宕機或無響應時&#xff0c;需快速定位問題并恢復服務。以下是分步驟的解決方案&#xff1a; 1. 初步確認問題 檢查網絡連接 本地網絡是否正常&#xff1f;嘗試 ping 其他網站 排除本地問題。 使用 ping <服務器IP> 或 traceroute <IP> 測試網絡連通…

動態IP與區塊鏈:重構網絡信任的底層革命

在數字經濟蓬勃發展的今天&#xff0c;網絡安全與數據隱私正面臨前所未有的挑戰。動態IP技術與區塊鏈的深度融合&#xff0c;正在構建一個去中心化、高可信的網絡基礎設施&#xff0c;為Web3.0時代的到來奠定基礎。 一、技術碰撞&#xff1a;動態IP與區塊鏈的天然契合 動態I…

從0開始學vue:vue3和vue2的關系

一、版本演進關系1. 繼承關系2. 版本生命周期 二、核心差異對比三、關鍵演進方向1. Composition API2. 性能優化 四、遷移策略1. 兼容構建模式2. 關鍵破壞性變更 五、生態演進1. 官方庫升級2. 構建工具鏈 六、選型建議1. 新項目2. 現有項目 七、未來展望 一、版本演進關系 1. …

Vue 核心技術與實戰智慧商城項目Day08-10

溫馨提示&#xff1a;這個黑馬的視頻在b占可以找到&#xff0c;里面有完整的教學過程 然后這個項目有完整的代碼&#xff0c;我已經上傳了&#xff0c;如果審核成功大家就可以看了&#xff0c;但是需要審核多久我也不是很確定 1.項目演示 2. 項目收獲 3. 創建項目 4. 調整初始化…

AR/MR實時光照陰影開發教程

一、效果演示 1、PICO4 Ultra MR 發光的球 2、AR實時光照 二、實現原理 PICO4 Ultra MR開發時&#xff0c;通過空間網格能力掃描周圍環境&#xff0c;然后將掃描到的環境網格材質替換為一個透明材質并停止掃描&#xff1b;基于Google ARCore XR Plugin和ARFoundation進行安卓手…

【Python訓練營打卡】day42 @浙大疏錦行

DAY 42 Grad-CAM與Hook函數 知識點回顧 1. 回調函數 2. lambda函數 3. hook函數的模塊鉤子和張量鉤子 4. Grad-CAM的示例 作業&#xff1a;理解下今天的代碼即可 Grad-CAM 在深度學習中&#xff0c;我們經常需要查看或修改模型中間層的輸出或梯度。然而&#xff0c;標準的…

創建ipv6 only和ipv6+ip4的k8s集群的注意事項

關鍵字 : CNI calico vxlan flannel ipv6-only ipv6ipv4 在搭建ipv6-only或ipv6ipv4的k8s集群時&#xff0c;在worker節點加入集群后&#xff0c;發現worker節點上的CNI啟動失敗。 以下是calico的啟動失敗情況 : kubectl get pod -A輸出如下 : NAMESPACE NAME …

鴻蒙OSUniApp離線優先數據同步實戰:打造無縫銜接的鴻蒙應用體驗#三方框架 #Uniapp

UniApp離線優先數據同步實戰&#xff1a;打造無縫銜接的鴻蒙應用體驗 最近在開發一個面向鴻蒙生態的UniApp應用時&#xff0c;遇到了一個有趣的挑戰&#xff1a;如何在網絡不穩定的情況下保證數據的實時性和可用性。經過一番探索和實踐&#xff0c;我們最終實現了一套行之有效…

day 43

應用cnn對kaggle上的圖像數據集進行練習 數據集地址&#xff1a;Cat and Dog import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pyplot as plt im…

Spring Boot 如何實現定時任務

Spring Boot 如何實現定時任務 在現代的微服務架構中&#xff0c;定時任務是一個常見的需求。無論是數據定時同步、定時清理緩存&#xff0c;還是定時發送通知&#xff0c;Spring Boot 提供了非常強大且靈活的定時任務支持。本文將詳細介紹如何在 Spring Boot 中實現定時任務&…

“粽”覽全局:分布式系統架構與實踐深度解析(端午特別版)

第一部分&#xff1a;引言——技術世界的“端午”第二部分&#xff1a;分布式系統概述——粽子節點初探第三部分&#xff1a;核心技術詳解——技術“粽子”大解構 粽葉篇&#xff1a;通信協議糯米篇&#xff1a;一致性算法餡料篇&#xff1a;任務調度與計算包扎篇&#xff1a;系…

AppTrace 視角下 App 一鍵拉起:提升應用轉化率的高效方案?

官網地址&#xff1a;AppTrace - 專業的移動應用推廣追蹤平臺 在大規模開展 App 推廣、用戶召回、廣告投放、邀請傳播等活動時&#xff0c;高效的深度鏈接方案至關重要。它不僅能縮短用戶路徑&#xff0c;帶來無縫、流暢的跳轉體驗&#xff0c;更核心的是通過參數傳遞打通 web…