当前位置: 首页 > news >正文

seo网站优化专员c2c平台的产品类型

seo网站优化专员,c2c平台的产品类型,做展示型网站多少钱,重庆网络学院官网文章目录 开源预约挂号平台 - 从0到上线演示地址源码地址可以学到的技术前端技术后端技术部署上线开发工具其他技术业务功能 项目讲解前端创建项目 - 安装PNPM - 使用VSCODE - 安装插件首页顶部与底部 - 封装组建 - 使用scss左右布局中间内容部分路由 - vue-routerBANNER- 走马… 文章目录 开源预约挂号平台 - 从0到上线演示地址源码地址可以学到的技术前端技术后端技术部署上线开发工具其他技术业务功能 项目讲解前端创建项目 - 安装PNPM - 使用VSCODE - 安装插件首页顶部与底部 - 封装组建 - 使用scss左右布局中间内容部分路由 - vue-routerBANNER- 走马灯效果 - 使用elementplus搜索区 - 自动填充组建 - 深度选择器AXIOS发起请求筛选区表格部分与分页 - 使用TypeScript类型筛选区与首页表格父子组件传参 医院部分使用 Pinia仓库科室滑动效果 登录模块自定义表单验证验证码功能Token功能 挂号功能挂号列表动画功能卡片印章样式 订单详情实名认证前端上传图片功能 就诊人管理级联选择器路由鉴权与Nprogress加载进度条 后端框架图创建表业务表字段表 配置表数据初始化 - BRP.COM.InitREST接口 - BRP.COM.REST.Api统一入口统一错误处理 - BRP.COM.SafeRunORM映射的使用JWT功能后端处理上传文件 部署部署云华为云创建服务器流程阿里云创建服务器流程 在安装LinuxCentos系统中安装数据库创建数据库创建命名空间创建Application三库分离创建灾备数据库备份数据库恢复数据库将数据库加入MIRROR部署NGINX打包前端文件跨越问题处理使用Git进行版本控制上传Github **创造价值分享学习一起成长相伴前行欢迎大家提出意见共同交流。** 开源预约挂号平台 - 从0到上线 项目缩写名称BRP - Booking Registration Platform 演示地址 预约挂号平台 源码地址 前端源码 - https://github.com/yaoxin521123/brp-app-web.git后端源码 - https://github.com/yaoxin521123/brp-iris.git 可以学到的技术 前端技术 Vue3ViteTypeScriptvue-routerPiniaelementplusAXIOSscss 后端技术 IRIS2023REST统一入口统一错误处理ORMJWT自研框架后端处理上传文件 部署上线 华为云Centos7.9Ngnix创建独立命名空间创建独立数据库创建独立Applicaion三库分离打包前端文件跨域问题创建灾备服务器备份数据库恢复数据库将数据库加入MIRROR 开发工具 vscodeIRIS2023 其他技术 SVG矢量图使用路由鉴权封装全局组件HTTP上传图片使用Git进行版本控制上传Github 业务功能 手机登录扫码二维码登录微信支付预约挂号医院详情预约通知实名认证挂号订单就诊人管理 项目讲解 由于篇幅有限以下为重点功能讲解可参考项目源码对比观看。 前端 创建项目 - 安装PNPM - 使用VSCODE - 安装插件 先安装node.js与npm。 下载地址https://nodejs.cn/download/ 下一步安装即可。 C:\Users\hpnode -v v16.14.0C:\Users\hpnpm -v 8.3.1打开cmd安装pnpm。 npm install -g pnpm注网络不好可以替换镜像地址。 获取当前配置的镜像地址 pnpm get registry设置新的镜像地址 pnpm set registry https://registry.npm.taobao.org在任意路径下打开cmd创建vue3项目。依次填写名称 - brp-app-webVueTypeScript。 E:\vuepnpm create vite ../.pnpm-store/v3/tmp/dlx-13224 | 1 ../.pnpm-store/v3/tmp/dlx-13224 | Progress: resolved 1, reused 0, downloaded 1, added 1, done √ Project name: ... brp-app-web Select a framework : Vue Seiect a variant : TypeScript使用vscode打开项目在terminl中输入pnpm run dev即可启动项目。 vscode推荐使用v3插件如下 Element UI Snippets - v0.7.2Prettier - Code formatter - v10.1.0TypeScript Vue Plugin (Volar) - v1.8.26Wink Snippets - v1.0.5 在main.ts文件中引入必要的依赖包 import { createApp } from vue; import /style/reset.scss; import App from /App.vue; import router from /router; import ElementPlus from element-plus; import element-plus/dist/index.css; //ts-ignore import zhCn from element-plus/dist/locale/zh-cn.mjs; import pinia from /store; const app createApp(App); app.use(router); app.use(ElementPlus, {locale: zhCn, }); app.use(pinia); app.mount(#app);首页 首页分为顶部底部中间内容部分BANNER区搜索区筛选区表格分页右侧。 顶部与底部 - 封装组建 - 使用scss左右布局 将顶部与底部封装为全局组件。 将全局组件引入到main.ts中 ... import HosptialTop from /components/hospital_top/index.vue; import HosptialBottom from /components/hospital_bottom/index.vue; ... const app createApp(App); app.component(HosptialTop, HosptialTop); app.component(HosptialBottom, HosptialBottom); app.mount(#app);注再使用ts中有代码提示报错运行时没有报错可以使用//ts-ignore忽略。 在App.vue中引入全局组件该文件为入口文件。 布局分部为头部中部底部中间部用于内容切换路由跳转等。 templatediv classcontainerHosptialTop /div classcontentrouter-view/router-view/divHosptialBottom /Login //div /template实现头部与底部左右布局以头部scss样式举例。 注使用scss前需要先安装scss 在项目目录中使用cmd执行pnpm i scss命令即可。 先让top浮动 display: flex;居中 justify-content: center;并在位置固定position: fix;层级在最上z-index: 999;在content中让left与right浮动起来在左右两侧justify-content: space-between;其余为宽高大小居中等属性。 注后面的前端界面中有大量左右布局均为此方式后面不再赘述。 style scoped langscss .top {position: fix;z-index: 999;width: 100%;height: 70px;background: #fff;display: flex;justify-content: center;.content {width: 1200px;height: 70px;background: white;display: flex;justify-content: space-between;.left {display: flex;justify-content: center;align-items: center;img {width: 70px;height: 50px;margin-right: 10px;}p {font-size: 20px;color: #55a6fe;}}.right {display: flex;justify-content: center;align-items: center;font-size: 14px;color: #ccc;.help {margin-right: 10px;}}} } /style中间内容部分 路由 - vue-router 中间内容部分需要使用路由来切换页面首先创建文件router/index.ts编写路由。 注使用vue-router时需要在项目目录中打开cmd执行命令pnpm i vue-router安装路由。 createRouter为创建路由配置方法。scrollBehavior()方法每次路由跳转滚动条自动回到顶部。component: () import(/pages/home/index.vue),懒加载路由import中文件为路由的路径。 import { createRouter, createWebHistory } from vue-router; export default createRouter({history: createWebHistory(),routes: [{path: /home,component: () import(/pages/home/index.vue),meta: {title: 首页,},},],scrollBehavior() {return {left: 0,top: 0,};}, });在main.ts中引入路由。 ... import router from /router; ... app.use(router); ...设置好路由后在地址栏就可以输入路由名称进行路由跳转。 http://119.3.235.244/homehttp://119.3.235.244/hospital BANNER- 走马灯效果 - 使用elementplus 创建组件pages - carousel - index.vue 。 使用组件el-carousel循环4次设置img图片即可。 el-carousel height350pxel-carousel-item v-foritem in 4 :keyitemimg src/assets/images/web-banner-1.png alt //el-carousel-item/el-carousel搜索区 - 自动填充组建 - 深度选择器 创建组件pages - search - index.vue。 使用组件el-autocomplete :fetch-suggestionsfetchData为搜索时防抖的触发方法根据输入内容进行后台查询。 el-autocompleteclearableplaceholder请输入医院名称v-modelhosname:fetch-suggestionsfetchData:trigger-on-focusfalseselectgoDetail/由于搜索组件的宽度为深层样式所以这里使用 ::v-deep()修改组件内部的样式。 注如果去掉scoped关键字则样式为全局样式。 style scoped langscss .search {width: 100%;height: 50px;display: flex;justify-content: center;align-items: center;margin: 10px 0px;::v-deep(.el-input__wrapper) {width: 600px;margin-right: 10px;} } /styleAXIOS发起请求 创建文件utils - request.ts编写代码如下。 注需要安装axios库pnpm i axios。 利用axios.create方法创建一个axios实例可以设置基础路径、超时的时间的设置。利用axios请求、响应拦截器功能请求拦截器一般可以在请求头中携带公共的参数token响应拦截器,可以简化服务器返回的数据处理http网络错误。对外暴露axios。 import axios from axios; import { ElMessage } from element-plus; import userUserStore from /store/modules/user;const request axios.create({//baseURL: import.meta.env.VITE_API_BASE_URL,baseURL: /api,timeout: 5000, });request.interceptors.request.use((config) {let userStore userUserStore();if (userStore.userInfo.token) {config.headers.token userStore.userInfo.token;}return config; });request.interceptors.response.use((response) {return response.data;},(error) {let status error.response.status;console.log(status);switch (status) {case 404:ElMessage({type: error,message: error.message,});break;case 500 | 501 | 502 | 503 | 504 | 505:ElMessage({type: error,message: 服务器挂了,});break;case 401:ElMessage({type: error,message: 参数有误,});break;}return Promise.reject(new Error(error.message));} );export default request; 筛选区 pages - home - level - index.vue与pages - home - region- index.vue 筛选静态 代码为ulli样式浮动使用flex按照比例划分区域。等级占0.5份其他占9份并增加鼠标滑过样式。将筛选区封装为组件使用。 .content {display: flex;.left {margin-right: 10px;flex: 0.5;}.hospital {flex: 9;display: flex;li {margin-right: 10px;.active {color: #55a6fe;}}li:hover {color: #55a6fe;cursor: pointer;}}}表格部分与分页 - 使用TypeScript类型 表格显示内容为后端接口返回的数据。首先定义接口返回数据类型。api - home - type.ts 注表格的样式与绑定数据不再赘述参考elementUI官方即可。 ResponseData - 定义首页模块ts数据类型Hospital - 代表已有的医院数据的ts类型Content - 存储全部已有医院的数组类型HospitalResponseData - 获取已有医院接口返回的数据ts类型 export interface ResponseData {code: number;message: string;ok: boolean; } export interface Hospital {id: string;createTime: string;updateTime: string;isDeleted: number;params: {hostypeString: string;fullAddress: string;};hoscode: string;hosname: string;hostype: string;provinceCode: string;cityCode: string;districtCode: string;address: string;logoData: string;intro: string;route: string;status: number;bookingRule: {cycle: number;releaseTime: string;stopTime: string;quitDay: number;quitTime: string;rule: string[];}; } export type Content Hospital[];export interface HospitalResponseData extends ResponseData {data: {content: Content;pageable: {sort: {sorted: boolean;unsorted: boolean;empty: boolean;};pageNumber: number;pageSize: number;offset: number;paged: boolean;unpaged: boolean;};totalPages: number;totalElements: number;last: boolean;first: boolean;sort: {sorted: boolean;unsorted: boolean;empty: boolean;};numberOfElements: number;size: number;number: number;empty: boolean;}; }引入数据类型定义接口方法并暴露reqHospital。api - home - index.ts 通过枚举管理首页模块的接口地址 import request from /utils/request; import type {HospitalResponseData, } from ./type; enum API {HOSPITAL_URL /hosp/hospital/, } export const reqHospital (page: number,limit: number,hostype ,districtCode ) request.getany, HospitalResponseData(API.HOSPITAL_URL ${page}/${limit}?hostype${hostype}districtCode${districtCode});在首页中发起请求获取数据。page.index.vue onMounted - 页面加载完毕时回调的钩子。getHospitalInfo - 获取已有的医院的数据 script setup langts ... onMounted(() {getHospitalInfo(); }); const getHospitalInfo async () {let result: HospitalResponseData await reqHospital(pageNo.value,pageSize.value,hosType.value,districtCode.value);if (result.code 200) {hasHospitalArr.value result.data.content;total.value result.data.totalElements;} }; ... /script点击分页时需要触发对应的回调方法 el-paginationclasspaginationv-model:current-pagepageNov-model:page-sizepageSize:page-sizes[10, 20, 30, 40]:backgroundtruelayoutprev, pager, next, jumper,-,sizes,total:totaltotalcurrent-changecurrentChangesize-changesizeChange/sizeChange - 分页器下拉菜单发生变化的时候会触发currentChange - 分页器页码发生变化时候回调 const currentChange () {getHospitalInfo(); };const sizeChange () {pageNo.value 1;getHospitalInfo(); };筛选区与首页表格父子组件传参 给筛选区组件添加自定义回调方法。 !-- 等级子组件 --Level getLevelgetLevel /!--地区 --Region getRegiongetRegion /在父组件编写回调方法 组件自定义事件:获取儿子给父组件传递过来的等级参数子组件自定义事件获取子组件传递过来的地区参数 const getLevel (level: string) {hosType.value level;getHospitalInfo(); }; const getRegion (region: string) {districtCode.value region;getHospitalInfo(); };在子组件接受参数并触发回调方法通知父组件父组件拿到参数可以根据参数做后台筛选。 点击不同区域按钮回调给父组件传递区域的参数 const changeLevel (level: string) {regionFlag.value level;$emit(getRegion, level); };let $emit defineEmits([getRegion]);医院部分 使用 Pinia仓库 由于hospital路由的多个二级路由需要获取点击医院的信息。所以使用Pinia仓库进行数据缓存。把获得信息提供给多个二级路由使用这样就可以不用每个页面再次获取医院信息。创建 Pinia仓库。store - modules - hospitalDetail.ts 注使用pinia前需要先安装pnpm i pinia useDetailStore为定义的全局数据。state - 表示返回的数据。actions - 触发的回调方法给state中数据赋值。 import { defineStore } from pinia; import { reqHospitalDetail, reqHospitalDeparment } from /api/hospital; import type {HospitalDetailData,HospitalDetail, } from /api/hospital/type; import { DetailState } from /store/modules/interface; const useDetailStore defineStore(Detail, {state: (): DetailState {return {hospitalInfo: {} as HospitalDetail,};},actions: {async getHospital(hoscode: string) {let result: HospitalDetailData await reqHospitalDetail(hoscode);if (result.code 200) {this.hospitalInfo result.data;}},},getters: {}, });export default useDetailStore; hospital - index.vue中使用 pinia 组件挂载完毕通知pinia仓库发请求获取医院详情的数据存储仓库当中。 ... import { useRouter, useRoute } from vue-router; import { onMounted } from vue; import useDetailStore from /store/modules/hospitalDetail; let detailStore useDetailStore(); let $router useRouter(); let $route useRoute();onMounted(() {detailStore.getHospital($route.query.hoscode as string); }); 其他hospital二级路由拿到数据后获取展示即可。\pages\hospital\detail\index.vue 引入医院详情仓库的数据 script setup langts import useDetailStore from /store/modules/hospitalDetail; let hospitalStore useDetailStore(); /script科室滑动效果 展示为左右两个部分左侧为科室总称右侧为改科室的子科室。 deparment - 放置每一个医院的科室的数据deparmentInfo - 用一个div代表:大科室与小科室每一个大的科室下小科室 div classdeparmentdiv classleftNavulliclickchaneIndex(index):class{ active: index currentIndex }v-for(deparment, index) in hospitalStore.deparmentArr:keydeparment.depcode{{ deparment.depname }}/li/ul/divdiv classdeparmentInfodivclassshowDeparmentv-fordeparment in hospitalStore.deparmentArr:keydeparment.depcodeh1 classcur stylepadding: 10px;{{ deparment.depname }}/h1ulliclickshowLogin(item)v-foritem in deparment.children:keyitem.depcode{{ item.depname }}/li/ul/div/div/div左侧大的科室点击的事件 点击导航获取右侧科室(大的科室H1标题)滚动到对应科室的位置behavior: smooth, 过渡动画效果block: start, 滚动到位置 默认起始位置 let currentIndex refnumber(0); const chaneIndex (index: number) {currentIndex.value index;let allH1 document.querySelectorAll(.cur);allH1[currentIndex.value].scrollIntoView({behavior: smooth,block: start,}); };滑动样式 ::-webkit-scrollbar { display: none;}隐藏滚动条flex-direction: column;浮动布局为列布局 .deparment {width: 100%;height: 500px;display: flex;margin-top: 20px;.leftNav {width: 80px;height: 100%;ul {width: 100%;height: 100%;background: rgb(248, 248, 248);display: flex;flex-direction: column;li {flex: 1;text-align: center;color: #7f7f7f;font-size: 14px;line-height: 40px;.active {border-left: 1px solid red;color: red;background: white;}}}}.deparmentInfo {flex: 1;margin-left: 20px;height: 100%;overflow: auto;::-webkit-scrollbar {display: none;}.showDeparment {h1 {background-color: rgb(248, 248, 248);color: #7f7f7f;}ul {display: flex;flex-wrap: wrap;li {color: #7f7f7f;width: 33%;line-height: 30px;}}}}}登录模块 登录为全局组件包含手机号登录微信扫码登录表单验证等功能。 自定义表单验证 自定义校验规则:手机号码自定义校验规则验证码自定义校验规则 const validatorPhone (_: any, value: any, callback: any) {const reg /^1[3-9]\d{9}$/;if (reg.test(value)) {callback();} else {callback(new Error(请输入正确的号码格式));} }; const validatorCode (_: any, value: any, callback: any) {if (/^\d{6}$/.test(value)) {callback();} else {callback(new Error(请输入正确的验证码格式));} }; const rules {phone: [{ trigger: blur, validator: validatorPhone }],code: [{ trigger: blur, validator: validatorCode }], };验证码功能 将验证码功能封装为组件\components\countdown\index.vue time - 倒计时的事件watch - 监听父组件传递过来props数据变化timer - 开启定时器$emit(getFlag,false);通知父组件倒计时模式结束let $emit defineEmits([getFlag]);接受父组件传递过来的props-flag用于控制计数器组件显示与隐藏的 templatedivspan获取验证码({{ time }}s)/span/div /templatescript setup langts import { ref, watch } from vue; let props defineProps([flag]); let time refnumber(5); watch(() props.flag,() {let timer setInterval(() {time.value--;if (time.value 0) {$emit(getFlag, false);clearInterval(timer);}}, 1000);},{immediate: true,} ); let $emit defineEmits([getFlag]); /script登录组件中引入验证码组件 Countdown v-ifflag :flagflag getFlaggetFlag /点击验证码按钮时触发事件 getFlag - 计数器子组件绑定的自定义事件。当倒计时为零的时候通知父组件倒计时组件隐藏getCode - 获取验证码按钮的回调 const getCode async () {flag.value true;try {await userStore.getCode(loginParams.phone);loginParams.code userStore.code;} catch (error) {ElMessage({type: error,message: (error as Error).message,});} };const getFlag (val: boolean) {flag.value val; };Token功能 登录成功后将token存户到pinia。 await userStore.userLogin(loginParams);调用userStore方法 const login async () {await form.value.validate();console.log(form.value.validate());try {await userStore.userLogin(loginParams);userStore.visiable false;let redirect $route.query.redirect;if (redirect) {$router.push(redirect as string);} else {$router.push(/home);}} catch (error) {ElMessage({type: error,message: (error as Error).message,});} };SET_TOKEN(JSON.stringify(this.userInfo));本地存储localStorage持久化存储用户信息。 async userLogin(loginData: LoginData) {let result: UserLoginResponseData await reqUserLogin(loginData);if (result.code 200) {this.userInfo result.data;SET_TOKEN(JSON.stringify(this.userInfo));return ok;} else {return Promise.reject(new Error(result.message));}},export const SET_TOKEN (userInfo:string){localStorage.setItem(USERINFO,userInfo); }在axios中进行拦截请求头每次携带localStorage中的token信息 config请求拦截器回调注入的对象(配置对象),配置对象的身上最终要的一件事情headers属性 request.interceptors.request.use((config) {let userStore useUserStore();if (userStore.userInfo.token) {config.headers.token userStore.userInfo.token;}return config; });挂号功能 注这里显示了为什么要将登录注册为全局组件因为项目分为两个部分一个部分是不用登录可展示的部分另一部分是登录之后的功能。挂号就是必须要登录之后才展示的功能。 挂号列表动画功能 \pages\hospital\register\register_step1.vue文件中样式 cur: item.workDate workTime.workDate,根据条件添加cur属性有cur属性代表当前点击元素从而进行放大。 divclassitemclickchangeTime(item):class{active: item.status -1 || item.availableNumber -1,cur: item.workDate workTime.workDate,}v-foritem in workData.bookingScheduleList:keyitemtransform: scale(1.1);动画放大了1.1倍 .container {width: 100%;display: flex;margin: 30px 0px;.item {flex: 1;width: 100%;border: 1px solid skyblue;margin: 0px 5px;color: #7f7f7f;transition: all 0.5s;.active {border: 1px solid #ccc;.top1 {background: #ccc;}}.cur {transform: scale(1.1);}.top1 {background: #e8f2ff;height: 30px;width: 100%;text-align: center;line-height: 30px;}.bottom {width: 100%;height: 60px;text-align: center;line-height: 60px;}}}卡片印章样式 将就诊人封装为单独的组件。components\visitor\visitor.vue 给印章添加transition标签并声明名称为confirm templatediv classvisitor ...div classbottomp证件类型{{ user.param?.certificatesTypeString }}/pp证件号码{{ user.certificatesNo }}/pp用户性别{{ user.sex 0 ? 女生 : 男士 }}/pp出生日期{{ user.birthdate }}/pp手机号码{{ user.phone }}/pp婚姻状况{{ user.isMarry 0 ? 未婚 : 已婚 }}/pp详细地址{{ user.address }}/ptransition nameconfirmdiv classconfirm v-ifindex currentIndex已选择/div/transition/div/div /template编写样式 position: absolute;绝对定位border-radius: 50%;圆角50% opacity: 0.5;透明度0.5transform: rotate(35deg); 印章旋转角度.confirm-enter-from.confirm.enter-active .confirm-enter-to 出入动画持续动画时间。 .bottom {position: relative;padding: 0px 10px;p {line-height: 40px;}.confirm {position: absolute;width: 200px;height: 200px;color: red;border-radius: 50%;border: 1px dashed red;text-align: center;line-height: 200px;left: 15%;top: 15%;opacity: 0.5;transform: rotate(35deg);font-weight: 900;}.confirm-enter-from {transform: scale(1);}.confirm.enter-active {transform: all 0.3s;}.confirm-enter-to {transform: scale(1.2);}}订单详情 订单详情根据路由是否带参数决定显示详细界面还是列表界面。pages\user\order\allOrder\index.vuepages\user\order\detail\index.vue 实名认证 业务逻辑在第一次登录时需要先实名认证认证后该界面显示认证结果。 前端上传图片功能 pages\user\certification\index.vue中使用el-upload控件 :action“/api/oss/file/fileUpload?fileHostuserAuahuserId${userInfo.id}” 该属性表示选择图片后上传的后端服务器地址。 el-uploadrefuploadlist-typepicture-card:limit1:on-exceedexceedhandler:on-successsuccesshandler:on-previewhandlePictureCardPreview:on-removehandleRemove:action/api/oss/file/fileUpload?fileHostuserAuahuserId${userInfo.id}imgstylewidth: 100%; height: 100%src\assets\images\auth_example.pngalt//el-upload编写ts方法 exceedhandler - 超出数量的钩子successhandler - 图品上传成功的钩子handlePictureCardPreview - 照片墙预览的钩子handleRemove - 删除图片的钩子 注预览图片的地址为后端上传成功后返回的地址。 const exceedhandler () {ElMessage({type: error,message: 图片只能上传一张图片,}); }; const successhandler (response: any) {form.value.clearValidate(certificatesUrl);params.certificatesUrl response.data;console.log(params.certificatesUrl); }; const handlePictureCardPreview () {//触发预览的钩子的时候对话框显示dialogVisible.value true; }; const handleRemove () {params.certificatesUrl ; };就诊人管理 就诊人管理主要是针对患者的增删改查功能。 级联选择器 使用el-cascader级联选择器 el-cascader :propsprops v-modeluserParams.addressSelected stylewidth: 100% /在ts中引入级联选择器配置 lazyLoad(node: any, resolve: any) - 加载级联选择器数据方法resolve(showData); - 注入组件需要展示的数据id: item.value, - 每次回传id查询下一级的选择列表。 import type { CascaderProps } from element-plus;const props: CascaderProps {lazy: true,async lazyLoad(node: any, resolve: any) {let result: any await reqCity(node.data.id || 86);let showData result.data.map((item: any) {return {id: item.value,label: item.name,value: item.value,leaf: !item.hasChildren,};});resolve(showData);}, };路由鉴权与Nprogress加载进度条 路由鉴权:就是路由能不能被访问到权限设置-全局守卫完成let whiteList - 存储用户未登录可以访问路由得路径router.beforeEach((to, from, next) - 前置守卫Nprogress.start();访问路由组件的之前,进度条开始动document.title 大姚挂号平台-${to.meta.title}; 动态设置网页左上角的标题 let token userStore.userInfo.token;判断是否有tokenrouter.afterEach((to, from) - 后置路由Nprogress.done(); - 访问路由组件成功,进度条消息 import router from ./router; import Nprogress from nprogress; import useUserStore from /store/modules/user; import pinia from /store let userStore useUserStore(pinia); import nprogress/nprogress.css let whiteList [/home, /hospital/register, /hospital/detail, /hospital/notice, /hospital/close, /hospital/search]; router.beforeEach((to, from, next) {Nprogress.start();document.title 大姚挂号平台-${to.meta.title};let token userStore.userInfo.token;if (token) {next();} else {if (whiteList.includes(to.path)) {next();} else {userStore.visiable true;next({ path: /home, query: { redirect: to.fullPath } })}}});router.afterEach((to, from) {Nprogress.done(); })后端 框架图 注后端架构在《浅谈一下个人基于IRIS后端业务开发框架的理解》此博文中详细阐述所以不再赘述。 创建表 业务表 用户表 - BRP.BS.Account预约表 - BRP.BS.BookingSchedule医生表 - BRP.BS.Doctor挂号表 - BRP.BS.Doctor就诊人表 - BRP.BS.Patient 字段表 区域表 - BRP.CT.Region订单状态表 - BRP.CT.OrderStatus医院级别表 - BRP.CT.Level医院表 - BRP.CT.Hospital科室表 - BRP.CT.Department城市表 - BRP.CT.City证件类型表 - BRP.CT.CertificatesType 配置表 配置表 - BRP.CT.Config 所有表的关键字和父类如下 %JSON.Adaptor - 用于导入导出json数据BRP.COM.Map - ORM映射类 Class BRP.CT.Hospital Extends (%Persistent, %JSON.Adaptor, BRP.COM.Map) [ ClassType persistent, Inheritance left, ProcedureBlock, SqlRowIdName id ]注字段就不一一列举了可下源代码自行导入。 数据初始化 - BRP.COM.Init 所有表创建完后进行初始化数据。将文件放入数据文件指定目录。 执行方法w ##class(BRP.COM.Init).InitRegion(/brp/)即可。 Class BRP.COM.Init Extends %RegisteredObject {/// w ##class(BRP.COM.Init).InitRegion(/brp/) ClassMethod Init(path) {tsd ..InitRegion(path _ region.txt)d ..InitLevel(path _ level.txt)d ..InitHospital(path _ hospital.txt)d ..InitDepartment(path _ department.txt)d ..InitBookingSchedule()d ..InitDocotr(path _ doctor.txt)d ..InitPatient(path _ patient.txt)d ..InitOrderStatus()d ..InitCertificatesType(path _ certificatesType.txt)d ..InitCity(path _ city.txt)d ..InitCitySecond()b ;alltcq $$$OK }/// 初始化区域数据 /// w ##class(BRP.COM.Init).InitRegion(/brp/region.txt) ClassMethod InitRegion(path) {tss json {}.%FromJSONFile(path)s iter json.%GetIterator()while (iter.%GetNext(.key, .val)){s id ##class(Util.GenerateClassUtils).SaveJson2Entity(val, BRP.CT.Region)w 生成id _ id,!}b ;22tcq $$$OK } ... }REST接口 - BRP.COM.REST.Api CONTENTTYPE - 接口返回数据格式CHARSET - 编码类型REST接口有GETPOSTPUTDELETE请求方法。$g(%request.Data(districtCode, 1)) - 为路径中的Query参数。s content %request.Content - 为获取POST请求参数内容。 Class BRP.COM.REST.Api Extends %CSP.REST {Parameter CONTENTTYPE application/json;Parameter CHARSET utf-8;/// http://119.3.235.244:52773/api/hosp/hospital/1/10 /// w ##class(BRP.COM.REST.Api).QueryHospitalByPage(1,10) ClassMethod QueryHospitalByPage(page, limit) As %Status {s pDistrictCode $g(%request.Data(districtCode, 1))s pHostype $g(%request.Data(hostype,1 )) s json ##class(BRP.COM.SafeRun).Execute(BRP.API.Hospital, Query, pHostype, pDistrictCode)s json ##class(BRP.COM.SafeRun).ReturnResultPage(json, page, limit)w jsonq $$$OK }/// http://119.3.235.244:52773/api/cmn/dict/findByDictCode/HosType /// w ##class(BRP.COM.REST.Api).QueryRegion(HosType) ClassMethod QueryRegion(dictCode) As %Status {if (dictCode HosType) {s json ##class(BRP.COM.SafeRun).Execute(BRP.API.Level, Query)} elseif (dictCode CertificatesType) {s json ##class(BRP.COM.SafeRun).Execute(BRP.API.CertificatesType, Query)} else {s json ##class(BRP.COM.SafeRun).Execute(BRP.API.Region, Query)}w jsonq $$$OK }.../// Url顺序区别参数多的放到下方否则执行不到对应的路径 XData UrlMap { Routes Route Url/cmn/dict/findByDictCode/:dictCode MethodGET CallQueryRegion/ Route Url/hosp/hospital/department/:hoscode MethodGET CallQueryDepartment/ Route Url/hosp/hospital/getSchedule/:scheduleId MethodGET CallGetDoctorDataById/ Route Url/hosp/hospital/findByHosname/:hosname MethodGET CallQueryHospital/ Route Url/hosp/hospital/:page/:limit MethodGET CallQueryHospitalByPage/ Route Url/hosp/hospital/:hoscode MethodGET CallGetHospitalData/ Route Url/sms/send/:phone MethodGET CallGetCaptcha/ Route Url/user/login MethodPOST CallLogin/ Route Url/hosp/hospital/auth/getBookingScheduleRule/:page/:limit/:hoscode/:depcode MethodGET CallQueryBookingSchedule/ Route Url/hosp/hospital/auth/findScheduleList/:hoscode/:depcode/:workDate MethodGET CallQueryDoctor/ Route Url/user/patient/auth/findAll MethodGET CallQueryPatient/ Route Url/order/orderInfo/auth/submitOrder/:hoscode/:scheduleId/:patientId MethodPOST CallSubmitOrder/ Route Url/order/orderInfo/auth/getOrderInfo/:id MethodGET CallGetOrderDataById/ Route Url/order/orderInfo/auth/cancelOrder/:id MethodGET CallCancelOrder/ Route Url/order/orderInfo/auth/:page/:limit MethodGET CallQueryOrder/ Route Url/order/orderInfo/auth/getStatusList MethodGET CallQueryOrderStatus/ Route Url/user/patient/auth/save MethodPOST CallSavePatient/ Route Url/user/patient/auth/update MethodPUT CallSavePatient/ Route Url/user/patient/auth/remove/:id MethodDELETE CallDeletePatient/ Route Url/cmn/dict/findByParentId/:parentId MethodGET CallQueryCity/ Route Url/user/auth/getUserInfo MethodGET CallGetUserInfo/ Route Url/oss/file/fileUpload MethodPOST CallUploadFile/ Route Url/user/auth/userAuah MethodPOST CallUserAuah//Routes }}统一入口统一错误处理 - BRP.COM.SafeRun 注统一入口统一错误处理在《通用的异常处理程序机制与处理返回值方案》此博文中详细阐述所以不再赘述。 Class BRP.COM.SafeRun Extends (%RegisteredObject, BRP.COM.Base) {/// desc统一入口网关方便统一操作日志错误等。 ClassMethod Gateway() {s pClassName $g(%request.Data(ClassName, 1))s pMethodName $g(%request.Data(MethodName,1 )) s params ..GetMethodParams(pClassName, pMethodName) s ^yx(Gateway) $lb(pClassName,pMethodName,params)q ..Execute(pClassName, pMethodName, params) }/// desc所有程序中错误军抛出异常统一处理 /// w ##class(IMP.Common.SafeRun).Execute(IMP.Perms.Biz, QueryRole) ClassMethod Execute(pClassName, pMethodName, pParams...) {s $ecode try{d ..GetInfo()#; 判断方法是否有参数没有参数不用串pParams否则报错。if (##class(BRP.UTIL.Class).GetParamsList(pClassName, pMethodName) ){s result $classmethod(pClassName, pMethodName)} else {s result $classmethod(pClassName, pMethodName, pParams...)}} catch e {locktro:($tl 0)if (e.%IsA(BRP.COM.Exception.SessionException)){ret ..Session2Json()} s data e.Datas:$lv(data) data $$Format^%qcr(data, 1)s msg e.Name _ e.Location _ * _ data _ $zes ret $$LOG^%ETN(msg)#; SQL异常if (e.%IsA(BRP.COM.Exception.SqlException)){s msg e.AsSystemError()ret ..Failure2Json(msg)} elseif (e.%IsA(%Exception.SystemException)){ // 系统异常ret ..Failure2Json($ze )} elseif (e.%IsA(BRP.COM.Exception.ErrorException)){ // 通用错误异常ret ..Failure2Json(msg)} elseif (e.%IsA(%Exception.StatusException)){ // Status错误异常s msg e.DisplayString()ret ..Failure2Json(msg)} elseif (e.%IsA(BRP.COM.Exception.WarningException)){ // 警告信息s msg e.AsSystemError()ret ..Warning2Json(msg)} else { // 其他兜底异常if (msg ){s msg $ze} ret ..Failure2Json(msg)}}ret ..ReturnResult(result) }ClassMethod HandleToken(token) {throw:(token ) $$$WarningException(token异常, 请先登录)s ret ##class(Util.Jwt).VerifyJwt(token)q ret }} ORM映射的使用 注ORM映射的使用在《只需要改造一下实体类以后再也不用写SQL了》此博文中详细阐述所以不再赘述。 以查询区域Rest接口演示后端框架与ORM的使用 在BRP.BL.QUERY.Region中编写查询区域数组的方法。 BRP.CT.Region - 为区域实体表。Query方法为封装的ORM映射返回的列表方法可直接返回数组。 Class BRP.BL.QUERY.Region Extends %RegisteredObject {ClassMethod Query() {q ##class(BRP.CT.Region).Query() }}BRPzw ##class(BRP.BL.QUERY.Region).Query() [{id:17,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:东城区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110101},{id:18,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:西城区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110102},{id:19,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:朝阳区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110105},{id:20,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:丰台区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110106},{id:21,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:石景山区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110107},{id:22,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:海淀区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110108},{id:23,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:门头沟区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110109},{id:24,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:房山区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110111},{id:25,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:通州区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110112},{id:26,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:顺义区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110113},{id:27,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:昌平区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110114},{id:28,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:大兴区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110115},{id:29,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:怀柔区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110116},{id:30,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:平谷区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110117},{id:31,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:密云区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110118},{id:32,createTime:2020-06-23 15:48:57,dictCode:null,hasChildren:false,isDeleted:0,name:延庆区,param:null,parentId:110100,updateTime:2020-06-23 15:52:57,value:110119}] ; DYNAMIC ARRAY 在BRP.API.Region继承BRP.BL.QUERY.Region并重写Query()并返回。 ##super() - 调用父同名方法 Class BRP.API.Region Extends BRP.BL.QUERY.Region {/// zw ##class(BRP.API.Region).Query() ClassMethod Query() {q ##super() }} 使用统一入口调用接口方法如下 s json ##class(BRP.COM.SafeRun).Execute(BRP.API.Level, Query)在Rest中定义方法 ClassMethod QueryRegion(dictCode) As %Status {s json ##class(BRP.COM.SafeRun).Execute(BRP.API.Region, Query)w jsonq $$$OK }在XData路由中定义路径与方法请求方式。 XData UrlMap { Routes Route Url/cmn/dict/findByDictCode/:dictCode MethodGET CallQueryRegion/ /Routes }在浏览器中输入接口路径 http://119.3.235.244:52773/api/cmn/dict/findByDictCode/1JWT功能 注JWT功能在《基于M实现的JWT解决方案》此博文中详细阐述所以不再赘述。 登录成功后生成JWT并将JWT保存到用户表或临时Global用于后续对比。 ClassMethod Login(phone , pCaptcha ) {s captchaData ^BRP(Login, GetCaptcha, phone)s captcha $lg(captchaData, 1)throw:(captcha pCaptcha) $$$LoginException(验证码错误)s id $o(^BRP.BS.AccountI(Phone, phone, ))if id {s obj ##class(BRP.BS.Account).%New()} else {s obj ##class(BRP.BS.Account).%OpenId(id)} s jwt ##class(Util.Jwt).GenerateJwt()s obj.name phones obj.phone phones obj.token jwts sc obj.%Save()throw:($$$ISERR(sc)) $$$LoginException($system.Status.GetErrorText(sc))s obj {}s obj.name phones obj.token jwtq obj }前端携带登录成功后生成的TOKEN后端在必要的接口中进行判断。 s token $g(%request.CgiEnvs(HTTP_TOKEN))获取头信息中的TOKEN。HandleToken为验证token是否合法。 ClassMethod QueryDoctor(hoscode, depcode, workDate) As %Status {s token $g(%request.CgiEnvs(HTTP_TOKEN))s json ##class(BRP.COM.SafeRun).Execute(BRP.COM.SafeRun, HandleToken, token)if ({}.%FromJSON(json).code 0) {w json} else{s json ##class(BRP.COM.SafeRun).Execute(BRP.API.Doctor, Query, hoscode, depcode, workDate)w json}q $$$OK }如果未携带TOKEN会提示请先登录。 携带TOKEN并成功数据返回正常数据。 后端处理上传文件 后端处理上传文件功能对应前端HTTP上传图片功能。 定义后端REST上传文件接口与路由。 s binaryStream $g(%request.MimeData(file, 1))获取前端上传的文件流 Route Url/oss/file/fileUpload MethodPOST CallUploadFile/ClassMethod UploadFile() As %Status {s binaryStream $g(%request.MimeData(file, 1))s userId $g(%request.Data(userId,1 )) s json ##class(BRP.COM.SafeRun).Execute(BRP.API.Amount, UploadFile, userId , binaryStream)w jsonq $$$OK }实现将文件保存到本地并返回可显示的http图片路径。 ClassMethod UploadFile(userId, binaryStream) {s del \s path C:\InterSystems\IRISHealth2023\CSP\brp\picif $$$isUNIX {s del /s path /isc/iris/csp/brp/pic}s bool ##class(%File).CreateDirectoryChain(path, .return)s fileName $zstrip($zdt($now(), 8, , 3), *EN) _ .pngs fullFileName path _ del _ fileName#dim fileBinaryStream as %Stream.FileBinary ##class(%Stream.FileBinary).%New()s sc fileBinaryStream.LinkToFile(fullFileName)$$$ThrowOnError(sc)s sc fileBinaryStream.CopyFromAndSave(binaryStream)$$$ThrowOnError(sc)s obj ##class(BRP.BS.Account).%OpenId(userId)s obj.certificatesPhysicalUrl fullFileNames sc obj.%Save()$$$ThrowOnError(sc)q http://119.3.235.244:52773/csp/brp/pic/ _ fileName }前端进行预览即可。 部署 部署云 云服务器选择使用华为云与阿里云。 华为云创建服务器流程 首先注册华为云帐号并登录 华为云地址https://activity.huaweicloud.com/ 如果提示已注册过则选择直接开通华为云。 选择服务器2核4G1个月免费体验点击立即体验 如果没有实名认证先扫码实名认证 选择合适的服务器区域与操作系统这里选择了CentOS7.9点击立即购买 去支付即可。 点击返回HECS云服务器。 点击重置密码该密码为登录云服务器密码。之后就可以通过配置Xshell访问云服务器了。 阿里云创建服务器流程 首先注册登录阿里云选择云服务器。 地址https://www.aliyun.com/ 点击免费试用。 选择产品配置与操作系统。点击立即试用。 之后会提示创建成功。点击前往控制台。 创建成功点击远程连接。 点击重置密码会后就可以试用Xshell登录了。 在安装LinuxCentos系统中安装数据库 在ISC官网点击下载连接此时会让你登录帐号如果没有请先注册。 选择社区版。 3.选择IRIS并选择操作系统与版本最后点击下载。 下载完成后将文件上传到云服务器。在跟目录新建文件夹/isc 执行如下命令解压安装包 cd /isc tar -zxvf IRISHealth-2021.1.3.389.0.22951-lnxrhx64.tar.gz cd到解压的目录 cd /isc/IRISHealth-2021.1.3.389.0.22951-lnxrhx64执行命令 ./irisinstall最后会提示安装完成即可。 安装完数据库后需要修改云服务器安全组开放端口。 安全组点击配置规则 添加规则添加如下端口 51773,52773,1972,80,8088,2188。 配置完后端口就可以通过studio访问云库与云portal了。 创建数据库 打开portal 系统 配置 本地数据库点击创建数据库 创建BRP-DATA数据库用于保存Global与BRP-SRC数据库用于保存例程。下一步到完成即可。 创建完城后如下 创建命名空间 在 系统 配置 命名空间 中点击新建命名空间。填写如下 命名空间为BRPGlobal数据库为BRP-DATARoutine数据库为BRP-SRC 点击保存后该命名空间创建成功 创建Application 系统 安全管理 Web 应用程序点击新建应用程序填写如下 名称/api描述预约挂号接口命名空间BRP启用REST分派类BRP.COM.REST.Api 保存成功后rest接口可通过http访问。 Application中的/api路径会自动追加到定义的路由路径中。 如果HTTP接口返回403是因为UnknownUser权限不足重新分配权限。 三库分离 根据创建数据库操作分别创建BRP-CFBRP-BSBRP-CT数据库。 BRP-CF配置数据库BRP-CT字典数据库BRP-BS业务数据库 在系统 配置 命名空间选在BRP命名空间选择Global映射。增加如下映射。 BRP.BS*开头的Global映射到BRP-BS库中BRP.CF*开头的Global映射到BRP-BS库中BRP.CT*开头的Global映射到BRP-BS库中 在系统 Global中验证三库分离是否成功。 选择Databse查看对应的Global数据是否值并且Global节点是否映射正确。 创建灾备数据库 分别为华为云服务器与阿里云服务器启用ISCAgent服务。 systemctl start ISCAgentsystemctl status ISCAgentsystemctl enable ISCAgent [roothecs-210841 ~]# systemctl start ISCAgent [roothecs-210841 ~]# systemctl status ISCAgent ● ISCAgent.service - InterSystems AgentLoaded: loaded (/etc/systemd/system/ISCAgent.service; enabled; vendor preset: disabled)Active: active (running) since Mon 2023-12-25 20:40:46 CST; 13h agoMain PID: 18214 (ISCAgent)CGroup: /system.slice/ISCAgent.service├─18214 /usr/local/etc/irissys/ISCAgent├─18215 /usr/local/etc/irissys/ISCAgent├─20695 /usr/local/etc/irissys/ISCAgent└─20697 /usr/local/etc/irissys/ISCAgent [roothecs-210841 ~]# systemctl enable ISCAgent 启用后进入portal配置 - 镜像设置- 创建镜像才菜单可以使用了在DB华为云上创建镜像。 填写如下信息 镜像名称244DB不要使用SSL/TLS使用仲裁程序填写地址XXX.XXX.XXX.XXX端口号默认2188填写超级服务器地址XXX.XXX.XXX.XXX 成功后系统 - 镜像监视器显示如下图 在阿里云MIRROR上点击 系统 配置 将镜像加入为故障转移。 镜像名称 244DB代理地址为华为云地址端口默认实例名称IRIS 下一步 - 保存 回到华为云DB上查看镜像监视器发现镜像成功 回到阿里云上查看镜像监视器发现已同步成功 备份数据库 在DB上执行如下命令进行数据库备份然后在MIRROR上进行数据恢复。 %SYSd ^BACKUP1) Backup 2) Restore ALL 3) Restore Selected or Renamed Directories 4) Edit/Display List of Directories for Backups 5) Abort Backup 6) Display Backup volume information 7) Monitor progress of backup or restoreOption? 1*** The time is: 2023-12-26 10:14:36 ***InterSystems IRIS Backup Utility-------------------------- What kind of backup:1. Full backup of all in-use blocks2. Incremental since last backup3. Cumulative incremental since last full backup4. Exit the backup program 1 y?? Type the number of the function you wantWhat kind of backup:1. Full backup of all in-use blocks2. Incremental since last backup3. Cumulative incremental since last full backup4. Exit the backup program 1 1 Specify output device (type STOP to exit) Device: /isc/FullDBList_user.cbk /isc/setmirror.cbk Backing up to device: /isc/FullDBList_user.cbk /isc/setmirror.cbk Description: backupdbBacking up the following directories:/isc/iris/mgr//isc/iris/mgr/HSCUSTOM//isc/iris/mgr/brpbs//isc/iris/mgr/brpcf//isc/iris/mgr/brpct//isc/iris/mgr/brpdata//isc/iris/mgr/brpsrc//isc/iris/mgr/hslib//isc/iris/mgr/hssys//isc/iris/mgr/irisaudit//isc/iris/mgr/user/Start the Backup (y/n)? y 备份成功后将备份文件发送到MIRROR服务器上。 scp 本地cbk路径要发送的服务器地址。输入MIRROR服务器密码等待传送数据即可。 scp /isc/setmirror.cbk root123.57.246.161:/isc Enter passphrase for key /root/.ssh/id_rsa: root123.57.246.161s password: setmirror.cbk 恢复数据库 在阿里云MIRROR服务器上执行如下命令进行数据库恢复。 %SYSdo ^DBREST Cache DBREST UtilityRestore database directories from a backup archiveRestore: 1. All directories2. Selected and/or renamed directories3. Display backup volume information4. Exit the restore program1 2Do you want to set switch 10 so that other processes will be prevented from running during the restore? Yes yesSpecify input file for volume 1 of backup 1(Type STOP to exit) Device: /isc/setmirror.cbkThis backup volume was created by:IRIS for UNIX (Red Hat Enterprise Linux for x86-64) 2021.1.3The volume label contains:Volume number 1Volume backup DEC 25 2023 09:43PM FullPrevious backup Last FULL backup Description /isc/setmirror.cbkBuffer Count 0Mirror name 244DBFailover Member HECS-210841/IRIS Is this the backup you want to start restoring? Yes yes This backup was made on the other mirror member. Limit restore to mirrored databases? noFor each database included in the backup file, you can:-- press RETURN to restore it to its original directory;-- type X, then press RETURN to skip it and not restore it at all.-- type a different directory name. It will be restored to the directoryyou specify. (If you specify a directory that already contains a database, the data it contains will be lost)./isc/iris/mgr/ /isc/iris/mgr/HSCUSTOM/ /isc/iris/mgr/brpbs/ /isc/iris/mgr/brpcf/ /isc/iris/mgr/brpct/ /isc/iris/mgr/brpdata/ /isc/iris/mgr/brpsrc/ /isc/iris/mgr/hslib/ /isc/iris/mgr/hssys/ /isc/iris/mgr/irisaudit/ /isc/iris/mgr/user/ Do you want to change this list of directories? No Restore will overwrite the data in the old database. Confirm Restore? No yes***Restoring /isc/iris/mgr/ at 09:36:09 13107 blocks restored in 0.4 seconds for this pass, 13107 total restored.***Restoring /isc/iris/mgr/HSCUSTOM/ at 09:36:10 1397 blocks restored in 0.1 seconds for this pass, 1397 total restored....***Restoring /isc/iris/mgr/user/ at 09:36:45 1 blocks restored in 0.0 seconds for this pass, 79 total restored.Specify input file for volume 1 of backup following DEC 25 2023 09:43PM(Type STOP to exit) Device: Do you have any more backups to restore? Yes no Mounting /isc/iris/mgr//isc/iris/mgr/ ... (Mounted)Mounting /isc/iris/mgr/HSCUSTOM//isc/iris/mgr/HSCUSTOM/ ... (Mounted) ...Mounting /isc/iris/mgr/user//isc/iris/mgr/user/ ... (Mounted)Restoring a directory restores the globals in it only up to the date of the backup. If you have been journaling, you can apply journal entries to restore any changes that have been made in the globals since the backup was made.What journal entries do you wish to apply?1. All entries for the directories that you restored2. All entries for all directories3. Selected directories and globals4. No entriesApply: 1 1We know something about where journaling was at the time of the backup: 0: offset 198000 in /isc/iris/mgr/journal/MIRROR-244DB-20231225.003Are journal files created by this IRIS instance and located in their original paths? (Uses journal.log to locate journals)? enter Yes or No, please Are journal files created by this IRIS instance and located in their original paths? (Uses journal.log to locate journals)? yes The earliest journal entry since the backup was made is at offset 198000 in /isc/iris/mgr/journal/MIRROR-244DB-20231225.003Do you want to start from that location? Yes Yes /isc/iris/mgr/journal/MIRROR-244DB-20231225.003 is NOT in journal history log /isc/iris/mgr/journal.log You might have specified a wrong journal history log[Not restored]%SYS 恢复成功后查看MIRROR 数据Global恢复成功。 将数据库加入MIRROR 在系统 - 配置 - 本地数据库点击添加到镜像选择MIRROR的数据库添加即可。 部署NGINX 在官网下载nginx包 下载完成后上传到云服务器。运行命令解压。 tar -zxvf nginx-1.24.0.tar.gz解压后执行./configurem配置命令发现有很多not found 安装依赖。 yum install gcc-c yum install -y pcre pcre-devel yum install -y zlib zlib-devel yum install -y openssl openssl-devel make make install安装成功进入/usr/local/nginx查看文件是否存在conf、sbin、html文件夹若存在则安装成功 打包前端文件 在brp-web-app项目的termina中执行打包命令pnpm run build。会生成的打包文件dist。 将dist文件放入到云服务器nginx的html目录中 执行命令./nginx启动。若/usr/local/nginx/logs中error.log无报错则表示启动成功。 跨越问题处理 启动nginx后发现无法访问后台接口提示404或CORS跨越错误。需要做出如下修改 在前端文件vite.config.ts中增加如下配置 表示前端需要代理的跨域后端的接口。/api表示路径中包含此路径代表是需要代理的请求。 import { defineConfig } from vite; import vue from vitejs/plugin-vue; import path from path; // https://vitejs.dev/config/ export default defineConfig({...server: {proxy: {/api: {target: http://119.3.235.244:52773/,changeOrigin: true,},},}, }); 在\utils\request.ts中增加如下配置 此配置代表会为后端请求自动增加/api路径。 const request axios.create({baseURL: /api,timeout: 5000, });在ngnix的conf路径下nginx.conf做出如下修改 location /api 表示在ngnix中为此路径字段替换为http://119.3.235.244:52773进行转发。 注此处的/api与http://119.3.235.244:52773后边均不带/写成/api/与http://119.3.235.244:52773/则代理失败。需要与前端文件的vite配置路径一一对应。 server {listen 80;server_name localhost;client_header_buffer_size 1M;large_client_header_buffers 4 1M;#charset koi8-r;#access_log logs/host.access.log main;location / {root html;try_files $uri $uri/ /index.html last;index index.html index.htm;client_max_body_size 100M;}location /api {proxy_pass http://119.3.235.244:52773;break;}}重新启用./nginx -s quit ./nginx*查看跨越问题是否解决。 使用Git进行版本控制 注Git详细使用可以查看《Git使用大全》 在项目目录创建Git仓库 添加并提交。 上传Github 在git上生成token 在Github上创建仓库brp-app-web选择公开仓库。 用小乌龟Push到GitHub远程仓库。 输入账号密码再次输入帐号密码使用刚生成的Token。 查看文件是否推送成功 创造价值分享学习一起成长相伴前行欢迎大家提出意见共同交流。
http://www.lakalapos1.cn/news/33489/

相关文章:

  • 西安哪家网站建设好django网站开发
  • 大学网站建设管理办法wordpress hook列表
  • wordpress手机网站模板公司做网页要多少钱
  • 昌都网站建设响应式网站和平时网站的区别
  • 番禺高端网站建设公司武进网站建设基本流程
  • 网站用的什么字体设计WordPress网站远程访问
  • 公司请人做的网站打不开厦门APP开发网站开发公司
  • 杭州软件开发公司网站计算机培训班
  • 医药网站模板专业企业网站制作
  • 关键词优化排名易下拉排名网站快速排名优化
  • 第三方微信网站建设怎么搭建国外网络
  • 什么不属于网站推广软件安装字体到wordpress
  • 广州网站建设哪家比较好网站转化率是什么意思
  • 做流量任务的试用网站网站设计的论坛
  • 网站建设话语潍坊网站建设自助建站平台
  • 陕西省建设执业资格注册中心网站站长之家收录查询
  • 东莞东坑网站建设wordpress是英文的怎么办
  • 洛阳高端网站建设全国做网站的公司有哪些
  • 国内做免费视频网站外面网站怎么做的
  • 响应式企业网站开发所用的平台学做网站论坛视频下载
  • 科技企业网站建设模板营销网络建设将给三夫户外带来哪些有益的影响?
  • 网站建设的前期准备用jsp源码做网站
  • 中国建设银行数据管理部网站敦煌网介绍
  • 招聘网站怎么做市场品牌网站建设联系方式
  • wordpress如何删除主题如何做网站结构优化
  • 那个网站做外贸最好公司做网站有意义么
  • 做网站都需要什么wordpress多个置顶
  • 福州论坛建站模板建设网站上海市
  • 外文网站建站新闻类网站怎么建设
  • 遵化手机网站设计陕西建省级执法人才库