哪些网站可以做网站/百度seo点击软件

哪些网站可以做网站,百度seo点击软件,汉中专业网站建设服务,施工企业费用预算的编制的内容包括代码仓地址,大家记得点个star IbestKnowTeach: 百得知识库基于鸿蒙NEXT稳定版实现的一款企业级开发项目案例。 本案例涉及到多个鸿蒙相关技术知识点: 1、布局 2、配置文件 3、组件的封装和使用 4、路由的使用 5、请求响应拦截器的封装 6、位置服务 7、三…

代码仓地址,大家记得点个star

IbestKnowTeach: 百得知识库基于鸿蒙NEXT稳定版实现的一款企业级开发项目案例。 本案例涉及到多个鸿蒙相关技术知识点: 1、布局 2、配置文件 3、组件的封装和使用 4、路由的使用 5、请求响应拦截器的封装 6、位置服务 7、三方库的使用和封装 8、头像上传 9、应用软件更新等https://gitee.com/xt1314520/IbestKnowTeach

我的页面开发

设计图

需求分析

华为账号登录功能开发(需要真机)

注意:这个功能需要真机,所以东林在gitee代码仓里面的代码是普通账号密码登录得,没有使用华为账号登录

我们之前封装的响应拦截器里面有判断,根据接口返回的状态码判断是否有权限,如果没有权限会跳转到登录页面

我们也可以点击我的页面头像区域可以到登录页面

1、登录界面整体布局

从上到下的整体布局所以我们使用Column进行包裹组件,整体可以拆分出五块区域

2、刨去华为账号登录的代码
import { CommonConstant } from '../contants/CommonConstant';
import { router } from '@kit.ArkUI';
import { RouterConstant } from '../contants/RouterConstant';@Entry@Componentstruct LoginPage {// 多选框状态@State multiSelectStatus: boolean = falsebuild() {Column() {Column({ space: 15 }) {Image($r('app.media.app_icon')).width($r('app.float.common_width_big')).aspectRatio(1).borderRadius(15)Text($r('app.string.application_name')).fontSize($r('app.float.common_font_size_huge')).fontWeight(FontWeight.Medium)Text($r('app.string.app_description')).fontSize($r('app.float.common_font_size_small')).fontColor($r('app.color.common_gray'))// 用户协议和隐私协议Row() {Checkbox().select($$this.multiSelectStatus).width(18).selectedColor("#FA6D1D")Text() {Span("已阅读并同意")Span(" 用户协议 ").fontColor(Color.Black).onClick(() => {router.pushUrl({ url: RouterConstant.PAGE_USER_POLICY })})Span("和")Span(" 隐私政策 ").fontColor(Color.Black).onClick(() => {router.pushUrl({ url: RouterConstant.PAGE_PRIVACY_POLICY })})}.fontSize($r('app.float.common_font_size_small')).fontColor($r('app.color.common_gray'))}}.height('50%')}.padding($r('app.float.common_padding')).height(CommonConstant.HEIGHT_FULL).width(CommonConstant.WIDTH_FULL).justifyContent(FlexAlign.Center).backgroundImage($r('app.media.background')).backgroundImageSize({ width: CommonConstant.WIDTH_FULL, height: CommonConstant.HEIGHT_FULL }).expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])}}

3、集成华为账号登录

参考东林的鸿蒙应用开发-高级课里面有个章节叫华为账号服务

大概分为以下几个步骤

1、在AGC上创建项目和应用

2、本地创建应用工程

3、本地生成签名文件

4、将签名放在AGC上生成证书

5、复制Client_ID放在本地项目中

6、本地完成签名

import { LoginWithHuaweiIDButton, loginComponentManager } from '@kit.AccountKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { CommonConstant } from '../contants/CommonConstant';
import { router } from '@kit.ArkUI';
import { RouterConstant } from '../contants/RouterConstant';
import { authentication } from '@kit.AccountKit';
import { util } from '@kit.ArkTS';
import { Logger } from '../utils/Logger';
import { showToast } from '../utils/Toast';
import userApi from '../api/UserApi';
import { PreferencesUtil } from '../utils/PreferencesUtil';@Entry@Componentstruct LoginPage {// 多选框状态@State multiSelectStatus: boolean = false// 构造LoginWithHuaweiIDButton组件的控制器controller: loginComponentManager.LoginWithHuaweiIDButtonController =new loginComponentManager.LoginWithHuaweiIDButtonController().onClickLoginWithHuaweiIDButton((error: BusinessError, response: loginComponentManager.HuaweiIDCredential) => {// 判断是否勾选用户协议和隐私政策if (!this.multiSelectStatus) {showToast('请勾选用户协议和隐私政策')return}if (error) {Logger.error(`Failed to onClickLoginWithHuaweiIDButton. Code: ${error.code}, message: ${error.message}`);showToast('华为账号登录失败')return;}// 登录成功if (response) {Logger.info('Succeeded in getting response.')// 创建授权请求,并设置参数const authRequest = new authentication.HuaweiIDProvider().createAuthorizationWithHuaweiIDRequest();// 获取头像昵称需要传如下scopeauthRequest.scopes = ['profile'];// 用户是否需要登录授权,该值为true且用户未登录或未授权时,会拉起用户登录或授权页面authRequest.forceAuthorization = true;// 用于防跨站点请求伪造authRequest.state = util.generateRandomUUID();// 执行授权请求try {const controller = new authentication.AuthenticationController(getContext(this));controller.executeRequest(authRequest).then((data) => {const authorizationWithHuaweiIDResponse = data as authentication.AuthorizationWithHuaweiIDResponse;const state = authorizationWithHuaweiIDResponse.state;if (state != undefined && authRequest.state != state) {Logger.error(`Failed to authorize. The state is different, response state: ${state}`);showToast('华为账号登录失败')return;}Logger.info('Succeeded in authentication.');const authorizationWithHuaweiIDCredential = authorizationWithHuaweiIDResponse.data!;// 头像const avatarUri = authorizationWithHuaweiIDCredential.avatarUri;// 昵称const nickName = authorizationWithHuaweiIDCredential.nickName;// 唯一idconst unionID = authorizationWithHuaweiIDCredential.unionID;// 登录接口login(unionID, nickName, avatarUri)}).catch((err: BusinessError) => {showToast('华为账号登录失败')Logger.error(`Failed to auth. Code: ${err.code}, message: ${err.message}`);});} catch (error) {showToast('华为账号登录失败')Logger.error(`Failed to auth. Code: ${error.code}, message: ${error.message}`);}}});build() {Column() {Column({ space: 15 }) {Image($r('app.media.app_icon')).width($r('app.float.common_width_big')).aspectRatio(1).borderRadius(15)Text($r('app.string.application_name')).fontSize($r('app.float.common_font_size_huge')).fontWeight(FontWeight.Medium)Text($r('app.string.app_description')).fontSize($r('app.float.common_font_size_small')).fontColor($r('app.color.common_gray'))// 用户协议和隐私协议Row() {Checkbox().select($$this.multiSelectStatus).width(18).selectedColor("#FA6D1D")Text() {Span("已阅读并同意")Span(" 用户协议 ").fontColor(Color.Black).onClick(() => {router.pushUrl({ url: RouterConstant.PAGE_USER_POLICY })})Span("和")Span(" 隐私政策 ").fontColor(Color.Black).onClick(() => {router.pushUrl({ url: RouterConstant.PAGE_PRIVACY_POLICY })})}.fontSize($r('app.float.common_font_size_small')).fontColor($r('app.color.common_gray'))}}.height('50%')Column() {LoginWithHuaweiIDButton({params: {// LoginWithHuaweiIDButton支持的样式style: loginComponentManager.Style.BUTTON_RED,// 账号登录按钮在登录过程中展示加载态extraStyle: {buttonStyle: new loginComponentManager.ButtonStyle().loadingStyle({show: true})},// LoginWithHuaweiIDButton的边框圆角半径borderRadius: 24,// LoginWithHuaweiIDButton支持的登录类型loginType: loginComponentManager.LoginType.ID,// LoginWithHuaweiIDButton支持按钮的样式跟随系统深浅色模式切换supportDarkMode: true,// verifyPhoneNumber:如果华为账号用户在过去90天内未进行短信验证,是否拉起Account Kit提供的短信验证码页面verifyPhoneNumber: true,},controller: this.controller,})}.width('80%').height(40)}.padding($r('app.float.common_padding')).height(CommonConstant.HEIGHT_FULL).width(CommonConstant.WIDTH_FULL).justifyContent(FlexAlign.Center).backgroundImage($r('app.media.background')).backgroundImageSize({ width: CommonConstant.WIDTH_FULL, height: CommonConstant.HEIGHT_FULL }).expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])}
}/*** 登录* @param unionID* @param nickname* @param avatarUri*/
async function login(unionID?: string, nickname?: string, avatarUri?: string) {if (!nickname) {nickname = '小得'}if (!avatarUri) {avatarUri ='https://upfile-drcn.platform.hicloud.com/DT4ISbQduGIF5Gz5g_Z9yg.PCj5oenfVYPRaeJp1REFEyac5ctfyoz-bD3L3k5cJTIDkrfDyewIkQaOAEoTWdgIxA_sJ0DD5RITPB85tfWAF7oquqQ6AvE4Jt8dIRUoyic4djriMA.112968985.jpg'}// 调用服务端登录const token = await userApi.userLogin({ unionId: unionID, nickname: nickname, avatarUri: avatarUri });// 如果token存在if (token) {AppStorage.setOrCreate(CommonConstant.TOKEN_NAME, token)PreferencesUtil.savaData(CommonConstant.PREFERENCES_NAME, CommonConstant.TOKEN_NAME, token)// 获取用户信息const userInfo = await userApi.getUserInfo();if (!userInfo) {showToast(CommonConstant.DEFAULT_LOGIN_ERROR)}// 存放用户数据AppStorage.setOrCreate(CommonConstant.USER_INFO, userInfo)PreferencesUtil.savaData(CommonConstant.PREFERENCES_NAME, CommonConstant.USER_INFO, JSON.stringify(userInfo))// 登录成功showToast('登录成功')// 回到首页router.pushUrl({url: RouterConstant.PAGE_INDEX, params: {"currentIndex": 0}})} else {showToast(CommonConstant.DEFAULT_LOGIN_ERROR)}
}

4、隐私和用户协议页面

新建两个Page页面,然后在resources/rawfile下面新建两个html文件

页面里面使用Web组件来包裹html文件

import { webview } from '@kit.ArkWeb'
import { CommonConstant } from '../contants/CommonConstant'@Entry@Componentstruct PolicyPage {webViewController: webview.WebviewController = new webview.WebviewControllerbuild() {Navigation() {Web({src: $rawfile("PrivacyPolicy.html"),controller: this.webViewController})}.height(CommonConstant.HEIGHT_FULL).width(CommonConstant.WIDTH_FULL).title($r('app.string.privacy_policy')).titleMode(NavigationTitleMode.Mini).mode(NavigationMode.Stack).expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])}}

import { webview } from '@kit.ArkWeb'
import { CommonConstant } from '../contants/CommonConstant'@Entry@Componentstruct UserPolicyPage {webViewController: webview.WebviewController = new webview.WebviewControllerbuild() {Navigation() {Web({src: $rawfile("UserPolicy.html"),controller: this.webViewController})}.height(CommonConstant.HEIGHT_FULL).width(CommonConstant.WIDTH_FULL).title($r('app.string.user_policy')).titleMode(NavigationTitleMode.Mini).mode(NavigationMode.Stack).expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])}}
5、编写用户接口方法
import http from '../request/Request'
import { LoginParam, UserInfo, UserNicknameUpdateParam } from './UserApi.type'/*** 用户接口*/
class UserApi {/*** 登录接口*/userLogin = (data: LoginParam): Promise<string> => {return http.post('/v1/user/login', data)}/*** 获取用户信息*/getUserInfo = (): Promise<UserInfo> => {return http.get('/v1/user/info')}/*** 修改用户昵称*/editNickname = (data: UserNicknameUpdateParam) => {return http.post('/v1/user/editNickname', data)}
}const userApi = new UserApi();export default userApi as UserApi;
/*** 登录接口的传参*/
export interface LoginParam {/*** 华为账号id*/unionId?: string/*** 昵称*/nickname?: string/*** 头像*/avatarUri?: string
}/*** 用户信息*/
export interface UserInfo {/*** 用户id*/id: number/*** 华为账号id*/unionId: string/*** 昵称*/nickname: string/*** 头像*/avatarUri: string}/*** 修改用户昵称接口入参*/
export interface UserNicknameUpdateParam {/*** 昵称*/nickname: string
}

我的页面整体布局

设计图

需求分析

封装组件
1、标题组件
import { CommonConstant } from '../contants/CommonConstant'@Componentexport struct TitleComponent {// 标题@Link title: stringbuild() {Row() {Text(this.title).fontSize($r('app.float.common_font_size_huge')).fontWeight(FontWeight.Medium)}.width(CommonConstant.WIDTH_FULL).margin({ top: 10, bottom: 20 })}}
2、导航组件
import { CommonConstant } from '../contants/CommonConstant'
import { FunctionBarData } from '../models/FunctionBarData'
import { router } from '@kit.ArkUI'
import { PreferencesUtil } from '../utils/PreferencesUtil'
import { RouterConstant } from '../contants/RouterConstant'
import { IBestButton, IBestDialog, IBestDialogUtil } from '@ibestservices/ibest-ui'
import feedbackInfoApi from '../api/FeedbackInfoApi'
import { showToast } from '../utils/Toast'
import { ApplicationCheckUtil } from '../utils/ApplicationCheckUtil'@Component@Entryexport struct FunctionBarComponent {@State functionBarData: FunctionBarData = {icon: '',text: '',router: '',eventType: ''}// 反馈信息@State inputValue: string = ''@State formInputError: boolean = false@State dialogVisible: boolean = false@BuilderformInputContain() {Column() {TextInput({ 'placeholder': '请输入反馈意见,长度不能超过255字符' }).fontSize(14).placeholderFont({ size: 14 }).onChange((value) => {this.inputValue = value;this.formInputError = false})if (this.formInputError) {Text('反馈意见不能为空').width(CommonConstant.WIDTH_FULL).textAlign(TextAlign.Start).margin({top: 5,left: 5}).fontColor(Color.Red).fontSize($r('app.float.common_font_size_small')).transition({ type: TransitionType.Insert, opacity: 1 }).transition({ type: TransitionType.Delete, opacity: 0 })}}.width('90%').margin({ top: 15, bottom: 15 })}build() {Row() {IBestDialog({visible: $dialogVisible,title: "反馈意见",showCancelButton: true,defaultBuilder: (): void => this.formInputContain(),beforeClose: async (action) => {if (action === 'cancel') {return true}const valueLength = this.inputValue.trim().length;this.formInputError = !valueLength;if (!this.formInputError) {// 添加反馈内容await feedbackInfoApi.addFeedbackContent({ content: this.inputValue })// 更新用户个人信息showToast('添加反馈意见成功')this.inputValue = ''return true}return !this.formInputError}})Row({ space: 10 }) {if (this.functionBarData.icon != '') {Image(this.functionBarData.icon).width(30).aspectRatio(1)}Text(this.functionBarData.text).fontSize($r('app.float.common_font_size_medium')).fontWeight(FontWeight.Normal)}Image($r('app.media.icon_arrow')).width(15).aspectRatio(1)}.width(CommonConstant.WIDTH_FULL).height($r('app.float.common_height_small')).backgroundColor($r('app.color.common_white')).padding(10).justifyContent(FlexAlign.SpaceBetween).borderRadius(5).onClick(() => {if (this.functionBarData.router) {router.pushUrl({ url: this.functionBarData.router })} else if (this.functionBarData.eventType === 'logout') {// 退出登录logout()} else if (this.functionBarData.eventType === 'feedback') {// 点击反馈this.dialogVisible = true} else if (this.functionBarData.eventType === 'checkAppUpdate') {// 检查更新ApplicationCheckUtil.checkAppUpdate()}})}
}/*** 退出登录*/
function logout() {IBestDialogUtil.open({title: "提示",message: "是否确认退出登录?",showCancelButton: true,onConfirm: async () => {// 清除登录的缓存数据,userInfo有订阅者删不掉,所以重新赋值空的给userInfoAppStorage.setOrCreate(CommonConstant.USER_INFO, {nickname: '',unionId: '',avatarUri: '',id: 0})AppStorage.delete(CommonConstant.TOKEN_NAME)await PreferencesUtil.delAllData(CommonConstant.PREFERENCES_NAME, CommonConstant.TOKEN_NAME)await PreferencesUtil.delAllData(CommonConstant.PREFERENCES_NAME, CommonConstant.USER_INFO)router.clear()// 路由到我的页面router.replaceUrl({url: RouterConstant.PAGE_INDEX, params: {"currentIndex": 3}})}})
}

头像上传

1、编写工具类
import { common } from '@kit.AbilityKit';
import fs from '@ohos.file.fs';
import request from '@ohos.request';
import { BusinessError } from '@ohos.base';
import { picker } from '@kit.CoreFileKit';
import { Logger } from './Logger';
import { FileData } from '../models/FileData';let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir
let cacheDir = context.cacheDirexport class FileUtil {/*** 判断文件是否存在*/static isExist(fileName: string, fileSuffix: string) {// 判断文件是否存在,存在就删除let path = filesDir + '/' + fileName + '.' + fileSuffix;if (fs.accessSync(path)) {fs.unlinkSync(path);}}/*** 下载文件*/static downloadFile(fileName: string, fileSuffix: string, fileUrl: string): Promise<boolean> {return new Promise<boolean>((resolve, reject) => {// 判断文件是否已存在FileUtil.isExist(fileName, fileSuffix)request.downloadFile(context, {url: fileUrl,filePath: filesDir + '/' + fileName + '.' + fileSuffix}).then((downloadTask: request.DownloadTask) => {downloadTask.on('complete', () => {resolve(true)})}).catch((err: BusinessError) => {console.error(`Invoke downloadTask failed, code is ${err.code}, message is ${err.message}`);reject(err)});})}/*** 选择图片*/static selectImage(): Promise<string> {return new Promise<string>((resolve, reject) => {try {let photoSelectOptions = new picker.PhotoSelectOptions();photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;photoSelectOptions.maxSelectNumber = 1;let photoPicker = new picker.PhotoViewPicker(context);photoPicker.select(photoSelectOptions).then((photoSelectResult: picker.PhotoSelectResult) => {resolve(photoSelectResult.photoUris[0])}).catch((err: BusinessError) => {reject(err)});} catch (error) {let err: BusinessError = error as BusinessError;console.error('PhotoViewPicker failed with err: ' + JSON.stringify(err));reject(err)}})}/*** 将uri截取转换成固定类型*/static convertFile(uri: string): FileData {// 将uri分割成字符串数组const array: string[] = uri.split('/');// 获取用户文件全名const fileFullName = array[array.length-1]// 获取文件名字里面.最后出现的索引位置let index = fileFullName.lastIndexOf(".");// 获取文件后缀名const fileSuffix = fileFullName.substring(index + 1)// 获取文件名const fileName = fileFullName.substring(0, index)// 封装文件数据const fileData: FileData = { fileFullName: fileFullName, fileSuffix: fileSuffix, fileName: fileName }return fileData}/*** 将用户文件转换成缓存目录*/static copyUserFileToCache(uri: string, fileData: FileData): Promise<boolean> {return new Promise<boolean>((resolve, reject) => {// 缓存目录let cachePath = cacheDir + '/' + fileData.fileFullNametry {let files = fs.openSync(uri, fs.OpenMode.READ_ONLY)fs.copyFileSync(files.fd, cachePath)resolve(true)} catch (error) {let err: BusinessError = error as BusinessError;Logger.error('Error copying file:' + JSON.stringify(err))reject(err)}})}
}

2、修改头像
/*** 修改头像*/
async editAvatar() {try {// 头像上传const uri = await FileUtil.selectImage()if (!uri) {showToast("选择图片失败")return}// 将uri截取转换成固定类型const fileData = FileUtil.convertFile(uri)// 将用户文件转换成缓存目录const data = await FileUtil.copyUserFileToCache(uri, fileData)if (!data) {showToast("修改头像失败")return}// 上传文件await this.uploadImage(fileData)} catch (error) {showToast("修改头像失败")}}

3、上传头像
/*** 上传图片*/async uploadImage(fileData: FileData) {let files: Array<request.File> = [// uri前缀internal://cache 对应cacheDir目录{filename: fileData.fileFullName,name: 'file', // 文件上传的keyuri: 'internal://cache/' + fileData.fileFullName,type: fileData.fileSuffix}]let uploadConfig: request.UploadConfig = {url: 'http://118.31.50.145:9003/v1/user/editAvatar',header: {"Authorization": AppStorage.get<string>("token")},method: 'POST',files: files,data: []}// 打开上传进度弹窗this.dialog.open()// 发送请求const response = await request.uploadFile(context, uploadConfig)// 监听上传进度response.on("progress", async (val, size) => {Logger.info("头像上传进度:", `${val / size * 100}%`)emitter.emit({ eventId: 100 }, { data: { process: `上传进度: ${(val / size * 100).toFixed(0)}%` } })if (val === size) {this.dialog.close()showToast('头像上传成功')// 获取用户信息const userInfo = await userApi.getUserInfo();this.userInfo = userInfo// 存放用户数据AppStorage.setOrCreate(CommonConstant.USER_INFO, userInfo)PreferencesUtil.savaData(CommonConstant.PREFERENCES_NAME, CommonConstant.USER_INFO,JSON.stringify(userInfo))}})}
4、自定义上传进度弹窗
// 自定义上传进度弹窗
dialog: CustomDialogController = new CustomDialogController({builder: ProgressDialog({ message: `上传进度: 0%` }),customStyle: true,alignment: DialogAlignment.Center
})

import { emitter } from '@kit.BasicServicesKit'@CustomDialogexport struct ProgressDialog {@State message: string = ''controller: CustomDialogControlleraboutToAppear(): void {emitter.on({ eventId: 100 }, (res) => {this.message = res.data!["process"]})}build() {Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {LoadingProgress().width(30).height(30).color($r('app.color.common_white'))if (this.message) {Text(this.message).fontSize((14)).fontColor($r('app.color.common_white'))}}.width($r('app.float.common_width_huge')).height($r('app.float.common_height_small')).padding(10).backgroundColor('rgba(0,0,0,0.5)').borderRadius(8)}}

Emitter具有同一进程不同线程间,或同一进程同一线程内,发送和处理事件的能力

Emitter用于同一进程内相同线程或不同线程间的事件处理,事件异步执行。使用时需要先订阅一个事件,然后发布该事件,发布完成后Emitter会将已发布的事件分发给订阅者,订阅者就会执行该事件订阅时设置的回调方法。当不需要订阅该事件时应及时取消订阅释放Emitter资源。

官方文档地址:

文档中心

检查更新

应用市场更新功能为开发者提供版本检测、显示更新提醒功能。开发者使用应用市场更新功能可以提醒用户及时更新到最新版本。

当应用启动完成或用户在应用中主动检查应用新版本时,开发者可以通过本服务,来查询应用是否有可更新的版本。如果存在可更新版本,您可以通过本服务为用户显示更新提醒。

  1. 应用调用检查更新接口。
  2. 升级服务API返回是否有新版本。
  3. 调用显示升级对话框接口。
  4. 升级服务API向应用返回显示结果。

import { updateManager } from '@kit.StoreKit';
import type { common } from '@kit.AbilityKit';
import { Logger } from './Logger';
import { showToast } from './Toast';let context: common.UIAbilityContext = getContext() as common.UIAbilityContext;export class ApplicationCheckUtil {/*** 检测新版本*/static async checkAppUpdate() {try {const checkResult = await updateManager.checkAppUpdate(context);if (checkResult.updateAvailable === 0) {showToast('当前应用版本已经是最新');return;}// 存在新版本,显示更新对话框const resultCode = await updateManager.showUpdateDialog(context);if (resultCode === 1) {showToast("检查更新失败,请稍后重试,或者在我的界面直接点击反馈将信息反馈给开发者")return}} catch (error) {Logger.error('TAG', `检查更新出错: code is ${error.code}, message is ${error.message}`);showToast("检查更新失败,请稍后重试,或者在我的界面直接点击反馈将信息反馈给开发者")}}
}

退出登录

/*** 退出登录*/
function logout() {IBestDialogUtil.open({title: "提示",message: "是否确认退出登录?",showCancelButton: true,onConfirm: async () => {// 清除登录的缓存数据,userInfo有订阅者删不掉,所以重新赋值空的给userInfoAppStorage.setOrCreate(CommonConstant.USER_INFO, {nickname: '',unionId: '',avatarUri: '',id: 0})AppStorage.delete(CommonConstant.TOKEN_NAME)await PreferencesUtil.delAllData(CommonConstant.PREFERENCES_NAME, CommonConstant.TOKEN_NAME)await PreferencesUtil.delAllData(CommonConstant.PREFERENCES_NAME, CommonConstant.USER_INFO)router.clear()// 路由到我的页面router.replaceUrl({url: RouterConstant.PAGE_INDEX, params: {"currentIndex": 3}})}})
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/73851.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

免密登录远程服务器shell脚本

一、脚本代码 #!/bin/bash #提示用户输入用户i名和ip地址 read -p "请输入远程服务器的用户名: " hname read -p "请输入远程服务器的IP地址: " fip read -p "请输入远程服务器的远程端口:" sdk #检查是否配置了免密登录 function sfmm(){ …

《C#上位机开发从门外到门内》3-2::Modbus数据采集系统

文章目录 **1. 项目概述****1.1 项目背景****1.2 项目目标****1.3 技术栈** **2. 系统架构设计****2.1 系统架构图****2.2 模块功能** **3. 数据采集模块实现****3.1 Modbus协议简介****3.2 数据采集流程****3.3 代码实现** **4. 数据存储模块实现****4.1 数据库设计****4.2 数…

Carto 无尽旅图 for Mac v1.0.7.6 (51528)冒险解谜游戏 支持M、Intel芯片

游戏介绍 《Carto》源于英文"Cartographer"&#xff08;制图师&#xff09;&#xff0c;卡朵不慎坠入未知世界。这里蜿蜒曲折&#xff0c;地形丰富。作为制图师卡朵&#xff0c;你将用你自己的神秘力量&#xff0c;操纵地图颠覆世界&#xff0c;将其翻转、拼合。当世…

【Linux】:自定义协议(应用层)

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家带来应用层自定义协议相关的知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通…

【C++】二叉树和堆的链式结构

本篇博客给大家带来的是用C语言来实现堆链式结构和二叉树的实现&#xff01; &#x1f41f;&#x1f41f;文章专栏&#xff1a;数据结构 &#x1f680;&#x1f680;若有问题评论区下讨论&#xff0c;我会及时回答 ❤❤欢迎大家点赞、收藏、分享&#xff01; 今日思想&#xff…

八股学习-JUC java并发编程

本文仅供个人学习使用&#xff0c;参考资料&#xff1a;JMM&#xff08;Java 内存模型&#xff09;详解 | JavaGuide 线程基础概念 用户线程&#xff1a;由用户空间程序管理和调度的线程&#xff0c;运行在用户空间。 内核线程&#xff1a;由操作系统内核管理和调度的线程&…

遗传算法+四模型+双向网络!GA-CNN-BiLSTM-Attention系列四模型多变量时序预测

遗传算法四模型双向网络&#xff01;GA-CNN-BiLSTM-Attention系列四模型多变量时序预测 目录 遗传算法四模型双向网络&#xff01;GA-CNN-BiLSTM-Attention系列四模型多变量时序预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 基于GA-CNN-BiLSTM-Attention、CNN-BiL…

【新能源汽车“心脏”赋能:三电系统研发、测试与应用匹配的恒压恒流源技术秘籍】

新能源汽车“心脏”赋能&#xff1a;三电系统研发、测试与应用匹配的恒压恒流源技术秘籍 在新能源汽车蓬勃发展的浪潮中&#xff0c;三电系统&#xff08;电池、电机、电控&#xff09;无疑是其核心驱动力。而恒压源与恒流源&#xff0c;作为电源管理的关键要素&#xff0c;在…

在线JSON格式校验工具站

在线JSON校验格式化工具&#xff08;Be JSON&#xff09;在线,JSON,JSON 校验,格式化,xml转json 工具,在线工具,json视图,可视化,程序,服务器,域名注册,正则表达式,测试,在线json格式化工具,json 格式化,json格式化工具,json字符串格式化,json 在线查看器,json在线,json 在线验…

图片黑白处理软件推荐

图片黑白二值化是一款小巧实用的图片处理软件&#xff0c;软件大小仅268K。 它的操作极其简单&#xff0c;用户只需将需要处理的图片直接拖入软件&#xff0c;就能实现图片漂白效果。 从原图和处理后的图片对比来看&#xff0c;效果显著。这种图片漂白处理在打印时能节省墨水&a…

【AI知识】常见的优化器及其原理:梯度下降、动量梯度下降、AdaGrad、RMSProp、Adam、AdamW

常见的优化器 梯度下降&#xff08;Gradient Descent, GD&#xff09;局部最小值、全局最小值和鞍点凸函数和非凸函数动量梯度下降&#xff08;Momentum&#xff09;自适应学习率优化器AdaGrad&#xff08;Adaptive Gradient Algorithm&#xff09;​RMSProp&#xff08;Root M…

1.5.5 掌握Scala内建控制结构 - 异常处理

本次实战聚焦于Scala内建控制结构中的异常处理机制。通过具体案例演示了如何使用try-catch-finally结构来处理程序运行中可能出现的异常情况。在try块中调用可能抛出异常的方法&#xff0c;catch块则根据不同异常类型进行捕获并处理&#xff0c;finally块则无论是否发生异常都会…

齿轮热处理学习笔记分享

对于一个做冷加工的人来说&#xff0c;热处理是一个神秘的话题&#xff0c;但是一点都不去了解的话&#xff0c;工作也无法进行。所以抽点时间来学习一下齿轮热处理相关的内容&#xff0c;做成笔记分享给爱学习的小伙伴们&#xff0c;文章较长&#xff0c;需要一些耐心去阅读&a…

Linux中vscode编程,小白入门喂饭级教程

确保Ubuntu联网 因为后面安装VScode需要从互联网下载。 安装GCC 在桌面空白处右键->打开终端 执行命令&#xff1a;gcc -v 在最后一行可以看到gcc version 7.5.0 如果提示Command ‘gcc’ not found&#xff0c;就查一下如何安装gcc&#xff0c;先把gcc安装好。 安装VS…

蓝桥杯真题——洛谷Day13 找规律(修建灌木)、字符串(乘法表)、队列(球票)

目录 找规律 P8781 [蓝桥杯 2022 省 B] 修剪灌木 字符串 P8723 [蓝桥杯 2020 省 AB3] 乘法表 队列 P8641 [蓝桥杯 2016 国 C] 赢球票 找规律 P8781 [蓝桥杯 2022 省 B] 修剪灌木 思路&#xff1a;对某个特定的点来说有向前和向后的情况&#xff0c;即有向前再返回到该位置…

matrix-breakout-2-morpheus 靶机----练习攻略 【仅获取shell】

【此练习仅做到反弹shell】 1.靶机下载地址 https://download.vulnhub.com/matrix-breakout/matrix-breakout-2-morpheus.ova 2. 打开靶机&#xff0c;kali使用nmap扫描同C段的主机 找到靶机ip 确保靶机和kali网卡均为NAT模式 先查看kali的ip nmap 192.168.182.1/24 …

Flutter中Align的使用说明

又失业了&#xff0c;作为一个高龄Android程序员今年找工作真难呀。现在Flutter是必需技能了&#xff0c;所以最近在自学。所用书籍叫《Flutter实战》&#xff0c;如下 如今已看了100多页&#xff0c;发现这本书写得……有点赶吧&#xff0c;好几处讲得不清不楚&#xff0c;而关…

用ASCII字符转化图片

代码 from PIL import Image# 定义 ASCII 字符集&#xff0c;从最暗到最亮 ASCII_CHARS "%#*-:. "def resize_image(image, new_width100):width, height image.sizeratio height / widthnew_height int(new_width * ratio)resized_image image.resize((new_wi…

详解Sympy:符号计算利器

Sympy是一个专注于符号数学计算的数学工具&#xff0c;使得用户可以轻松地进行复杂的符号运算&#xff0c;如求解方程、求导数、积分、级数展开、矩阵运算等。其中比较流行的深度学习框架pytorch的用到了Sympy,主要用于将模型的计算图转换为符号化表达式&#xff0c;以便进行分…

高频SQL 50 题(持续更新)

SQL的编写与运用 0. 写在前面 最近学习了数据库系统概论&#xff0c;其中涉及到了关于SQL语句的编写&#xff0c;感觉理论知识不足以让我掌握相关的编写方式&#xff0c;因此选择刷力扣上的题目进行复习巩固。 时间不是很多&#xff0c;可能不会经常更新&#xff0c;有时间写…