HarmonyOS Next“说书人”项目 单机版 实践案例

前段时间开发了一个软件,取名为“说书人”,后由于备案暂时没有通过,于是删除了联网功能,重新做了一个单机版,这里对于单机版的开发实践案例进行一个发出,希望能帮助到大家

文章最后给出了AtomGit仓库地址

pages/Data 目录

此目录下存储了项目中会使用到的数据

AppData.ets

此处存储了应用的版本号信息

export interface appAloneDataTem {appName: string,appVersion: string,appLogin: boolean
}export let appAloneData: appAloneDataTem = {appName: '说书人',appVersion: 'V 1.0.0',appLogin: false
}PersistentStorage.persistProp('appData', appAloneData)复制

bookData.ets

此处存储了书本信息

export interface bookDataTemplate{bookID: number,bookName: string,bookBrief: string,// bookHead: string,bookLabel: string[],// 发布状态:真为公有,假为私有releaseState: boolean,createUserID: number,createUserName: string,createUserOpen: boolean,haveRoleID: string[],chapterIndex: string
}export let bookData: bookDataTemplate = {bookID: 0,bookName: '',bookBrief: '简介',// bookHead: "",bookLabel: [],releaseState: false,createUserID: 0,createUserName: '未知用户',createUserOpen: true,haveRoleID: [],chapterIndex: "0",
}export let bookDataList: bookDataTemplate[] = [{bookID: 0,bookName: '开幕',bookBrief: '《说书人》的第一幕',// bookHead: "",bookLabel: [],releaseState: false,createUserID: 0,createUserName: '未知用户',createUserOpen: true,haveRoleID: [],chapterIndex: "0",}
]PersistentStorage.persistProp('bookData', bookData)
PersistentStorage.persistProp('bookDataList', bookDataList)复制

frameData.ets

此处存储了项目所需要使用到的一些设置信息,以及公有的组件

import router from '@ohos.router';// 画面设置
export interface frame{typefaceSize: number,backGround: ResourceColor,
}export let frameDataSet: frame = {typefaceSize: 16,backGround: "#ffffff",
}// 颜色加法
export let ThisPagefontColor: ResourceColor ='#' +setTenSix(frameDataSet.backGround.toString().slice(1,3)) +setTenSix(frameDataSet.backGround.toString().slice(3,5)) +setTenSix(frameDataSet.backGround.toString().slice(5,7))// 十进制转十六进制
function setTenSix(Color: string){let colorData = (255 - parseInt('0x' + Color.toString()))return colorData <= 15 ? '0' + colorData.toString(16) : colorData.toString(16)
}PersistentStorage.persistProp('frame', frameDataSet)PersistentStorage.persistProp('fontColor', ThisPagefontColor)@Component
export struct frameData {@StorageProp('frame')  frameData: frame = frameDataSet@StorageProp('fontColor') ThisColor: ResourceColor = ThisPagefontColorbuild() {Text('Back').fontColor(this.ThisColor).fontSize(this.frameData.typefaceSize + 6).onClick(() => {router.back()})}
}复制
readBookCharpter.ets

此处存储了章节信息

// 章节信息
export interface readBookCharpterTemplate{// 章节IDarticleID: number,// 章节索引chapterIndex: string,// 章节内容dialogueList: string,// 造物者之IDcreateUserID: string,// 归属之书ascriptionBookID: number,
}export let readBookCharpterData: readBookCharpterTemplate = {articleID: 0,chapterIndex: "1-1",dialogueList: "",createUserID: "",ascriptionBookID: 0
}export let readBookCharpterDataList: readBookCharpterTemplate[] = [{articleID: 0,chapterIndex: "1-1",dialogueList: "left|官方001|大家好!,left|官方001|欢迎使用《说书人》APP,它是一款面向角色编写剧本的软件 ,left|官方001|你可以在这款软件中定义角色,为多个角色之间编写剧本,还可以编写角色的关系网,查看角色的时间线等等... ,left|官方001|虽然在“还可以”之后的功能都还没实现就是了 ,left|官方001|截止编写本幕为止,软件只完成了基本功能,还有相当多不完善的地方,都会在为了慢慢解决的 ,left|官方001|十分感谢您对《说书人》的使用,如果使用过程中存在什么意见或建议,可以添加客服QQ提出 ,left|官方001|客服QQ: 1827650871",createUserID: "",ascriptionBookID: 0}
]PersistentStorage.persistProp('readBookCharpterData', readBookCharpterData)
PersistentStorage.persistProp('readBookCharpterDataList', readBookCharpterDataList)复制

roleData.ets

此处存储了角色会使用的数据


export interface roleCustom{name: string,value: string
}export interface roleDataTemplate{roleID: number,roleName: string,roleAge: string,roleGender: string,roleBrief: string,roleHead: string,roleLabel: string[],roleCustom: roleCustom[],// 发布状态:真为公有,假为私有releaseState: boolean,// 创造他的用户createUserID: number,createUserName: string,// 用户是否公开createUserOpen: boolean,// 有关系的角色和出现过的书籍relevantRoleID: string[],relevantBookID: string[]
}export let roleData: roleDataTemplate = {roleID: 0,roleName: '',roleAge: '0',roleGender: '',roleBrief: '简介',roleHead: "",roleLabel: [],roleCustom: [],releaseState: false,createUserID: 0,createUserName: "未知用户",createUserOpen: true,relevantRoleID: [],relevantBookID: []
}export let roleDataList: roleDataTemplate[] = [{roleID: 0,roleName: '官方001',roleAge: '18',roleGender: '男',roleBrief: '一个勤劳的打工人',roleHead: "",roleLabel: [],roleCustom: [],releaseState: false,createUserID: 0,createUserName: "未知用户",createUserOpen: true,relevantRoleID: [],relevantBookID: []},
]PersistentStorage.persistProp('roleData', roleData)
PersistentStorage.persistProp('roleDataList', roleDataList)复制
inspirationTem.ets
export interface inspirationTem {inspirationID: number,inspirationTitle: string,inspirationMain: string
}export let inspirationData: inspirationTem = {inspirationID: 0,inspirationTitle: '标题',inspirationMain: '正文'
}export let inspirationDataList: inspirationTem[] = [{inspirationID: 0,inspirationTitle: '标题',inspirationMain: '正文'}
]PersistentStorage.persistProp('inspirationData', inspirationData)
PersistentStorage.persistProp('inspirationDataList', inspirationDataList)复制

以上,便是整个应用所使用的数据信息,使用持久化存储将数据存储在本地

接下来,便是主要页面

pages/index.ets

import router from '@ohos.router'
import { frame, frameDataSet,ThisPagefontColor } from './Data/frameData'
import { userOwnData, userOwn } from './Data/userData'import promptAction from '@ohos.promptAction';@Entry
@Component
struct Index {@StorageProp('frame') frameData: frame = frameDataSet@StorageProp('fontColor') ThisColor: ResourceColor = ThisPagefontColor@StorageLink('userOwnData') userOwn: userOwnData = userOwn@State indexTime: number = 0onPageShow(): void {promptAction.showToast({message: "欢迎使用说书人"})this.indexTime = setTimeout(() => {router.clear()router.replaceUrl({"url":"pages/Main/userSpace","params": {"goPageIndex" : 0}})promptAction.showToast({message: '登陆成功!'})}, 3000)}build() {Flex({justifyContent: FlexAlign.Center}){}.width('100%').height('100%').backgroundImage($r('app.media.fengmian')).backgroundImageSize(ImageSize.Cover).backgroundColor(this.frameData.backGround).expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM]).onClick(() => {clearTimeout(this.indexTime)router.clear()router.replaceUrl({"url":"pages/Main/userSpace","params": {"goPageIndex" : 0}})promptAction.showToast({message: '登陆成功!'})})}
}复制

pages/loginPOP.ets

import { frame, frameDataSet,ThisPagefontColor, frameData } from './Data/frameData'
import router from '@ohos.router';@CustomDialog
export default struct agreePage {agreePage: CustomDialogControlleronCancel: () => void = () => {}onJUJUE: () => void = () => {}@StorageProp('frame') frameData: frame = frameDataSet@StorageProp('fontColor') ThisColor: ResourceColor = ThisPagefontColorbuild() {/* 用户名和需要修改的参数都由外部传递此处只涉及数据修改任务*/Flex(){Column({space: 16}){Row(){Text('《用户协议》与《隐私政策》提示').fontSize(this.frameData.typefaceSize + 4).fontColor(this.ThisColor)}.width('100%').justifyContent(FlexAlign.Center).padding({top: 24,left: 24})Scroll(){Column({ space: 12 }){Text(`
您需要阅读并同意隐私政策和用户协议后,才能使用《说书人》软件。如果您不同意,很遗憾我们无法为您提供相关服务。`).fontColor(this.ThisColor).fontSize(this.frameData.typefaceSize + 2)Flex({wrap: FlexWrap.Wrap}){Text('您可以点击阅读').fontColor(this.ThisColor).fontSize(this.frameData.typefaceSize + 2)Text(`《用户协议》`).fontColor(`#4a90e2`).fontSize(this.frameData.typefaceSize + 2).onClick(() => {router.pushUrl({url: "pages/agreement/userAgreememt"})this.agreePage.close()})Text(`与`).fontColor(this.ThisColor).fontSize(this.frameData.typefaceSize + 2)Text(`《隐私政策》`).fontColor(`#4a90e2`).fontSize(this.frameData.typefaceSize + 2).onClick(() => {router.pushUrl({url: "pages/agreement/privacyAgreement"})this.agreePage.close()})Text(`了解相关信息。`).fontColor(this.ThisColor).fontSize(this.frameData.typefaceSize + 2)Text(`如您同意,请点击“同意”开始接受我们的服务。`).fontColor(this.ThisColor).fontSize(this.frameData.typefaceSize + 2)}.width('100%')}.padding({left: 24,right: 24})}.edgeEffect(EdgeEffect.Spring)Row(){Button('同意 ').type(ButtonType.Normal).backgroundColor(this.frameData.backGround).fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor).border({width: {left: 1,right: 1,bottom: 1},color: '#f4f6f5'}).width('50%').onClick(() => {this.onCancel()this.agreePage.close()})Button('拒绝').type(ButtonType.Normal).backgroundColor(this.frameData.backGround).fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor).border({width: {left: 1,right: 1,bottom: 1},color: '#f4f6f5'}).width('50%').onClick(() => {this.onJUJUE()this.agreePage.close()})}}}.backgroundColor(this.frameData.backGround)}
}复制

pages/Main

以下是Main目录中的文件,此处存储了主要界面

userSpace.ets

import { frame, frameDataSet, ThisPagefontColor } from '../Data/frameData'import scriptInterface from './mainPage/scriptPage'
import RelationshipPage from './mainPage/relationshipPage'@Entry
@Component
struct UserSpace {@StorageProp('frame') frameData: frame = frameDataSet@StorageProp('fontColor') ThisColor: ResourceColor = ThisPagefontColorbuild() {Flex(){Tabs(){TabContent(){scriptInterface()}.tabBar('首页')TabContent(){RelationshipPage()}.tabBar('灵感')}.barPosition(BarPosition.End)}.backgroundColor(this.frameData.backGround)}
}复制

pages/Main/mainPage/scriptPage.ets

import { frame, frameDataSet,ThisPagefontColor } from '../../Data/frameData'
import { router } from '@kit.ArkUI'
import { roleDataList, roleDataTemplate, } from '../../Data/roleData'import { standardCudeImage } from '../../template/textImgTemplate'
import { bookDataList, bookDataTemplate } from '../../Data/bookData'
import { it } from '@ohos/hypium'@Entry
@Component
export default struct scriptInterface {@StorageProp('frame') frameData: frame = frameDataSet@StorageProp('fontColor') ThisColor: ResourceColor = ThisPagefontColor@StorageProp('roleDataList') roleDataList: roleDataTemplate[]  = roleDataList@StorageProp('bookDataList') bookDataList: bookDataTemplate[] = bookDataList@State openSet: boolean = false@State ThisText: string = ''@State sw:number = 0@State sh:number = 0build() {Flex(){Stack({alignContent: Alignment.Top}){Column(){Row(){TextInput({placeholder: "搜索"}).width('90%').textAlign(TextAlign.Center).onChange(value => {this.ThisText = value})Text('+').fontSize(32).width(50).textAlign(TextAlign.Center)}.width('100%').justifyContent(FlexAlign.SpaceBetween).onClick(() => {this.openSet = !this.openSet})Tabs(){// 角色TabContent(){Scroll(){Column({ space: 16 }){ForEach(this.roleDataList, (item: roleDataTemplate, index) => {if (item.roleName.includes(this.ThisText) || item.roleID.toString().includes(this.ThisText)) {// 角色模板Row({space: 16}){Text(`${item.roleName}`).fontSize(16).width(90).height(120).borderRadius(16).backgroundColor(this.frameData.backGround).border({width: 1}).borderRadius(16).textOverflow({overflow: TextOverflow.Ellipsis}).padding(16).textAlign(TextAlign.Center)Column({ space: 6 }){Row(){Text(`${item.roleName}`).fontSize(this.frameData.typefaceSize + 4).fontColor(this.ThisColor).fontWeight(600)}Row(){Text(`${item.roleBrief}`).fontSize(this.frameData.typefaceSize - 2).fontColor(this.ThisColor).maxLines(2).textOverflow({overflow: TextOverflow.Ellipsis})}.width('70%')Row(){ForEach(item.roleLabel, (item: string) => {Text(`/ ${item} /`).fontSize(this.frameData.typefaceSize - 4).fontColor(this.ThisColor).fontWeight(200)})}}.width('100%').alignItems(HorizontalAlign.Start)}.onClick(() => {router.pushUrl({"url": "pages/userSystem/userDetailed","params": {"roleID": item.roleID}})})}})}}.height('100%').align(Alignment.Top).edgeEffect(EdgeEffect.Spring).padding({top: 12,bottom: 64})}.tabBar('角色')// 剧本TabContent(){Scroll(){// 剧本列表Column({ space: 16 }){ForEach(this.bookDataList, (item: bookDataTemplate, index) => {if (item.bookName.includes(this.ThisText) || item.bookID.toString().includes(this.ThisText)) {// 剧本模板Row({space: 16}){Column({ space: 6 }){Row(){Text(item.bookName).fontSize(this.frameData.typefaceSize + 4).fontColor(this.ThisColor).fontWeight(600)}.width('70%').justifyContent(FlexAlign.End)Row(){Text(item.bookBrief).fontSize(this.frameData.typefaceSize - 2).fontColor(this.ThisColor).maxLines(2).textOverflow({overflow: TextOverflow.Ellipsis}).textAlign(TextAlign.End)}.width('70%').justifyContent(FlexAlign.End)Row(){/* 感觉很酷的一串代码 */ForEach(item.bookLabel, (item: string) => {Text(`/ ${item} /`).fontSize(this.frameData.typefaceSize - 4).fontColor(this.ThisColor).fontWeight(200).textAlign(TextAlign.End)})}.width('70%').justifyContent(FlexAlign.End)}.alignItems(HorizontalAlign.Start)standardCudeImage(`${item.bookName}`, this.frameData.backGround, this.ThisColor)}.onClick(() => {router.pushUrl({url: "pages/scriptSystem/scriptDetailed",params: {"bookID": item.bookID,"collection": false}})})}})}}.height('100%').align(Alignment.Top).edgeEffect(EdgeEffect.Spring).padding({top: 12,bottom: 64})}.tabBar('剧本')}.barPosition(BarPosition.Start)}.padding({left: 24,right: 24,}).align(Alignment.Top).alignItems(HorizontalAlign.Start)// 阴影Column(){}.width('100%').height('100%').backgroundColor(Color.Black).opacity(.6).visibility(this.openSet ? Visibility.Visible : Visibility.None).onClick(() => {this.openSet = false})// 角色剧本动态Column(){Row(){Text('角色').fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor)}.width(160).justifyContent(FlexAlign.Center).padding({left: 24,right: 24,top: 16,bottom: 16}).border({width: {bottom: 1}}).onClick(() => {router.pushUrl({"url": "pages/CreatePage/userCreate"})this.openSet = false})Row(){Text('剧本').fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor)}.width(160).justifyContent(FlexAlign.Center).padding({left: 24,right: 24,top: 16,bottom: 16}).border({width: {bottom: 1}}).onClick(() => {router.pushUrl({"url": "pages/CreatePage/scriptCreate"})this.openSet = false})}.border({ width: 1 }).borderRadius(2).position({x: this.sw / 2 - 16,y: 36}).backgroundColor(Color.White).visibility(this.openSet ? Visibility.Visible : Visibility.None)}}.backgroundColor(this.frameData.backGround).onAreaChange((oldValue: Area, newValue: Area) => {this.sw = new Number(newValue.width).valueOf();this.sh = new Number(newValue.height).valueOf();});}
}复制

pages/Main/mainPage/relationshipPage

import { frame, frameDataSet,ThisPagefontColor } from '../../Data/frameData'
import { inspirationTem, inspirationData, inspirationDataList } from '../../Data/inspirationData'
import { promptAction } from '@kit.ArkUI'@Entry
@Component
export default struct RelationshipPage {@StorageProp('frame') frameData: frame = frameDataSet@StorageProp('fontColor') ThisColor: ResourceColor = ThisPagefontColor@StorageLink('inspirationData') inspirationData: inspirationTem = inspirationData@StorageLink('inspirationDataList') inspirationDataList: inspirationTem[] = inspirationDataList@State index: number = 0build() {Flex({justifyContent: FlexAlign.Center,wrap: FlexWrap.Wrap}){Column(){// 标题Row(){Text('灵感图谱').fontSize(this.frameData.typefaceSize + 6).fontColor(this.ThisColor).letterSpacing(6)}.padding({top: 12, bottom: 12}).width('100%').justifyContent(FlexAlign.Center).border({width: {bottom: 2}})// 正文Column(){Row(){TextInput({ placeholder: "标题", text: this.inspirationDataList[this.index].inspirationTitle }).fontWeight(600).fontSize(this.frameData.typefaceSize + 14).placeholderFont({size: this.frameData.typefaceSize + 14}).fontColor(this.ThisColor).maxLength(16).showUnderline(true).onChange(value => {this.inspirationDataList[this.index].inspirationTitle = value})}.padding(24)Scroll(){Column(){TextArea({placeholder: '在此输入内容', text: this.inspirationDataList[this.index].inspirationMain}).backgroundColor(this.frameData.backGround).borderRadius(12).height('100%').maxLength(600).border({width: 1}).fontSize(this.frameData.typefaceSize + 2).onChange(value => {this.inspirationDataList[this.index].inspirationMain = value})}.padding({left: 24, right: 24})}.edgeEffect(EdgeEffect.Spring).height('70%').width('100%').align(Alignment.Top)}.width('100%').alignItems(HorizontalAlign.Start)// 按钮Row(){Button('上一篇').fontSize(this.frameData.typefaceSize + 6).fontColor(this.ThisColor).backgroundColor(this.frameData.backGround).layoutWeight(1).onClick(() => {if (this.index != 0) {this.index -= 1} else {promptAction.showToast({message: "已到达第一篇"})}})Button('下一篇').fontSize(this.frameData.typefaceSize + 6).fontColor(this.ThisColor).backgroundColor(this.frameData.backGround).layoutWeight(1).onClick(() => {if (this.index == this.inspirationDataList.length - 1) {if (this.inspirationDataList[this.index].inspirationTitle != '标题' ||this.inspirationDataList[this.index].inspirationMain != '正文') {this.inspirationDataList.push({inspirationID: this.index,inspirationTitle: '标题',inspirationMain: '正文'})this.index ++} else {promptAction.showToast({message: "已到达最后一篇"})}} else {this.index ++}})}.height('10%').width('100%').justifyContent(FlexAlign.SpaceBetween)}}}
}复制

pages/userSystem/

以下是pages/userSystem/中的内容,存储了角色系统

userDetailed.ets

import { frame, frameDataSet,ThisPagefontColor, frameData } from '../Data/frameData'
import { roleDataTemplate, roleData, roleDataList } from '../Data/roleData'
import { promptAction, router } from '@kit.ArkUI'
import { standardCudeImage } from '../template/textImgTemplate'@Extend(Text) function textCare(size: number){.fontColor('#3c3f41').backgroundColor('#e0dcda').fontSize(size).fontWeight(300).padding({left: 8,right: 8,top: 5,bottom: 5}).borderRadius(12).opacity(.8)
}@Entry
@Component
struct UserDetailed {aboutToAppear(): void {let params = router.getParams() as Record<string, number>let roleID = params['roleID']for (let item of this.roleDataList) {if (item.roleID == roleID) {this.roleData = itembreak}}}@StorageProp('frame') frameData: frame = frameDataSet@StorageProp('fontColor') ThisColor: ResourceColor = ThisPagefontColor@StorageProp('roleDataList') roleDataList: roleDataTemplate[] = roleDataList@State roleData: roleDataTemplate = roleData@State openText: boolean = falsebuild() {Flex({wrap: FlexWrap.Wrap}){Column({ space: 24 }){// 标题Row(){Row(){Text('Back').fontColor(this.ThisColor).fontSize(this.frameData.typefaceSize + 6).onClick(() => {router.back()}).width(100)}Text(this.roleData.roleName).fontSize(this.frameData.typefaceSize + 8).fontColor(this.ThisColor)Text('').width(100).textAlign(TextAlign.End)}.width('100%').justifyContent(FlexAlign.SpaceBetween)Scroll(){Column({ space: 24 }){Row({space: 16}){Text(this.roleData.roleName).fontSize(24).width(120).height(120).borderRadius(60).backgroundColor(this.frameData.backGround).border({width: 1}).textOverflow({overflow: TextOverflow.Ellipsis}).padding(2).textAlign(TextAlign.Center).letterSpacing(3)Column({ space: 9 }){// 书名Row(){Text(this.roleData.roleName).fontSize(this.frameData.typefaceSize + 6).fontColor(this.ThisColor).fontWeight(600)}// IDRow(){Text(String(this.roleData.roleID)).fontSize(this.frameData.typefaceSize - 4).fontColor(Color.Gray).fontWeight(400)}// 标签Row({ space: 6 }){ForEach(this.roleData.roleLabel, (item: string) => {Text(item).textCare(this.frameData.typefaceSize - 3)})}}.width('100%').alignItems(HorizontalAlign.Start).height(120)}// 简介Column({ space: 12 }){Text('简介').fontSize(this.frameData.typefaceSize + 4).fontColor(this.ThisColor).fontWeight(600)Row(){Text(this.roleData.roleBrief).maxLines(this.openText ? 999 : 4).textOverflow({overflow: this.openText ? TextOverflow.None : TextOverflow.Ellipsis }).fontSize(this.frameData.typefaceSize).fontColor(this.ThisColor)}.width('100%')Row(){Text(this.openText ? '收起' : '展开').fontSize(this.frameData.typefaceSize - 2).fontColor(this.ThisColor).fontWeight(300).onClick(() => {this.openText = !this.openText})}.width('100%')}.width('100%').alignItems(HorizontalAlign.Start)}.alignItems(HorizontalAlign.Start).height('100%')}.edgeEffect(EdgeEffect.Spring).height('87%')// 目录开始阅读收藏Row(){Text('').width(50)Text('解锁详细档案').fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor).onClick(() => {router.pushUrl({"url": "pages/userSystem/userPages/userArchives","params": {"roleID": this.roleData.roleID}})})Text('').width(50)}.width('100%').justifyContent(FlexAlign.SpaceBetween).alignItems(VerticalAlign.Center).border({width: {top: 2}}).padding({top: 16})}.padding({top: 16,left: 24,right: 24,bottom: 16})}.height('100%')}
}复制

pages/userSystem/userPages

import { frame, frameDataSet,ThisPagefontColor, frameData } from '../../Data/frameData'
import { roleDataTemplate, roleData, roleDataList, roleCustom } from '../../Data/roleData'
import { standardCudeImage } from '../../template/textImgTemplate'
import router from '@ohos.router';@Entry
@Component
struct UserArchives {aboutToAppear(): void {let params = router.getParams() as Record<string, number>let roleID = params['roleID']for (let item of this.roleDataList) {if (item.roleID == roleID) {this.roleData = itembreak}}}@StorageProp('frame') frameData: frame = frameDataSet@StorageProp('fontColor') ThisColor: ResourceColor = ThisPagefontColor@StorageProp('roleDataList') roleDataList: roleDataTemplate[] = roleDataList@State roleData: roleDataTemplate = roleData@State sw: number = 0@State sh: number = 0build() {Flex(){Scroll(){Column({ space: 12 }){// 标题Row(){frameData().width(50)Text(this.roleData.roleName).fontSize(this.frameData.typefaceSize + 8).fontColor(this.ThisColor)Text('详细档案').width(50).fontSize(this.frameData.typefaceSize + 6).fontColor(this.ThisColor)}.width('100%').justifyContent(FlexAlign.SpaceBetween).border({width: {bottom: 2}}).padding({top: 16,left: 24,right: 24,bottom: 16})Column({ space: 24 }){Stack(){Column({ space: 12 }){Row(){Text('姓名:').fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor)Text(this.roleData.roleName).fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor)}.width('100%').justifyContent(FlexAlign.SpaceBetween).margin({top: 42}).padding({left: 16,right: 16,top: 16,bottom: 6}).border({width: {bottom: 1}})Row(){Text('性别:').fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor)Text(this.roleData.roleGender).fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor)}.width('100%').justifyContent(FlexAlign.SpaceBetween).padding({left: 16,right: 16,top: 16,bottom: 6}).border({width: {bottom: 1}})Row(){Text('年龄:').fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor)Text(this.roleData.roleAge).fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor)}.width('100%').justifyContent(FlexAlign.SpaceBetween).padding({left: 16,right: 16,top: 16,bottom: 6}).border({width: {bottom: 1}})ForEach(this.roleData.roleCustom, (item: roleCustom, index) => {Row(){Text(`${item.name}: `).fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor)Text(`${item.value}`).fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor)}.width('100%').justifyContent(FlexAlign.SpaceBetween).padding({left: 16,right: 16,top: 16,bottom: 6}).border({width: {bottom: 1}})})Row(){Text('简介:').fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor)Text(`${this.roleData.roleBrief}`).fontSize(this.frameData.typefaceSize - 2).fontColor(this.ThisColor).width('70%').textAlign(TextAlign.End)}.width('100%').justifyContent(FlexAlign.SpaceBetween).padding({left: 16,right: 16,top: 16,bottom: 6}).border({width: {bottom: 1}})}.border({width: 1}).borderRadius(16).padding(16)Text(this.roleData.roleName).fontSize(18).width(90).height(90).borderRadius(45).backgroundColor(this.frameData.backGround).border({width: 1}).textOverflow({overflow: TextOverflow.Ellipsis}).padding(2).textAlign(TextAlign.Center).letterSpacing(3).position({x: this.sw / 2 - 64,y: -46})}.margin({top: 46})}.alignItems(HorizontalAlign.Center).padding({left: 24,right: 24,top: 10,bottom: 10})}}.edgeEffect(EdgeEffect.Spring)}.onAreaChange((oldValue: Area, newValue: Area) => {this.sw = new Number(newValue.width).valueOf();this.sh = new Number(newValue.height).valueOf();});}
}复制

pages/scriptSystem/

以下是pages/scriptSystem/中的内容,存储了剧本系统

import { frame, frameDataSet,ThisPagefontColor, frameData } from '../Data/frameData'
import router from '@ohos.router'
import { bookDataTemplate, bookData, bookDataList } from '../Data/bookData'
import { standardCudeImage } from '../template/textImgTemplate'@Extend(Text) function textCare(size: number){.fontColor('#3c3f41').backgroundColor('#e0dcda').fontSize(size).fontWeight(300).padding({left: 8,right: 8,top: 5,bottom: 5}).borderRadius(12).opacity(.8)
}@Entry
@Component
struct ScriptDetailed {aboutToAppear(): void {let params = router.getParams() as Record<string, number>let bookID = params['bookID']for (let i = 0; i < this.bookDataList.length; i++) {if (this.bookDataList[i].bookID == bookID) {this.bookData = this.bookDataList[i]break}}}@StorageProp('frame') frameData: frame = frameDataSet@StorageProp('fontColor') ThisColor: ResourceColor = ThisPagefontColor@StorageProp('bookDataList') bookDataList: bookDataTemplate[] = bookDataList@State bookData: bookDataTemplate = bookData@State openText: boolean = falsebuild() {Flex({wrap: FlexWrap.Wrap}){Column({ space: 24 }){// 标题Row(){Row(){frameData()}.width(50)Text(this.bookData.bookName).fontSize(this.frameData.typefaceSize + 8).fontColor(this.ThisColor).maxLines(1)Row(){Text('')}.width(50).justifyContent(FlexAlign.Start)}.width('100%').justifyContent(FlexAlign.SpaceBetween)Scroll(){Column({ space: 24 }){// 封面标题作者标签IDRow({space: 16}){standardCudeImage(this.bookData.bookName, this.frameData.backGround, this.ThisColor)Column({ space: 9 }){// 书名Row(){Text(this.bookData.bookName).fontSize(this.frameData.typefaceSize + 6).fontColor(this.ThisColor).fontWeight(600)}// IDRow(){Text(this.bookData.bookID.toString()).fontSize(this.frameData.typefaceSize - 4).fontColor(Color.Gray).fontWeight(400)}// 标签Row({ space: 6 }){ForEach(this.bookData.bookLabel, (item: string) => {Text(item).textCare(this.frameData.typefaceSize - 3)})}}.width('100%').alignItems(HorizontalAlign.Start).height(120)}// 简介Column({ space: 12 }){Text('简介').fontSize(this.frameData.typefaceSize + 4).fontColor(this.ThisColor).fontWeight(600)Row(){Text(this.bookData.bookBrief).maxLines(this.openText ? 999 : 4).textOverflow({overflow: this.openText ? TextOverflow.None : TextOverflow.Ellipsis }).fontSize(this.frameData.typefaceSize).fontColor(this.ThisColor)}.width('100%')Row(){Text(this.openText ? '收起' : '展开').fontSize(this.frameData.typefaceSize - 2).fontColor(this.ThisColor).fontWeight(300).onClick(() => {this.openText = !this.openText})}.width('100%')}.width('100%').alignItems(HorizontalAlign.Start)}.alignItems(HorizontalAlign.Start).height('100%')}.edgeEffect(EdgeEffect.Spring).height('87%')// 目录开始阅读收藏Row(){Text('').fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor).width(100)Text('开始阅读').fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor).onClick(() => {router.pushUrl({"url": "pages/scriptSystem/scriptPages/scriptRead","params": {"bookID": this.bookData.bookID,"chapterIndex": 1,}})})Text('').fontSize(this.frameData.typefaceSize + 2).fontColor(this.ThisColor).width(100)}.width('100%').justifyContent(FlexAlign.SpaceBetween).alignItems(VerticalAlign.Center).border({width: {top: 2}}).padding({top: 16})}.padding({top: 16,left: 24,right: 24,bottom: 16})}.height('100%')}
}复制

pages/scriptSystem/scriptPages/scriptRead.ets

import { frame, frameDataSet,ThisPagefontColor, frameData } from '../../Data/frameData'
import { readBookCharpterTemplate, readBookCharpterDataList, readBookCharpterData } from '../../Data/readBookChapterData'
import { smallImage } from '../../template/textImgTemplate'
import { delPage } from './popUp/del'
import { editTextPage } from './popUp/editText'import router from '@ohos.router';
import promptAction from '@ohos.promptAction'
import { roleDataTemplate } from '../../Data/roleData'@Extend(Text) function textCare(size: number){.padding({left: 12,right: 12,top: 16,bottom: 12}).fontSize(size).fontColor(Color.Black)
}@Entry
@Component
struct ScriptRead {// 删除文字delPageOpen: CustomDialogController = new CustomDialogController({builder: delPage({onCancel: (value: boolean) => {if (value) {this.dialogueListNew.splice(this.delIndex, 1)this.displayList[this.displayIndex] = false}}})})// 添加文字editTextPageOpen: CustomDialogController = new CustomDialogController({builder: editTextPage({onCancel: (careValue: number ,text: string ,returnRole: roleDataTemplate, newData: boolean) => {let textValue: string = ''for (let i = 0; i < text.length; i++) {if (text[i] == ','){textValue += ','} else if (text[i] == '|') {textValue += '/'} else {textValue += text[i]}}let dialogue: string[] = []/* 如果是旁白,就不需要角色昵称 */if (careValue != 2){if (careValue == 1) {dialogue[0] = 'left'} else if(careValue == 3) {dialogue[0] = 'right'}dialogue[1] = returnRole.roleName} else {dialogue[0] = 'pb'dialogue[1] = 'pb'}dialogue[2] = textValuethis.dialogueListNew.push(dialogue)this.displayList.push(true)this.scorllData.scrollBy(0, 10000)}}),})scorllData: Scroller = new Scroller()@StorageProp('frame') frameData: frame = frameDataSet@StorageProp('fontColor') ThisColor: ResourceColor = ThisPagefontColor@StorageLink('readBookCharpterDataList') readBookList: readBookCharpterTemplate[] = []@State index: number = 1@State bookLength: number = 0@State dialogueList: string[] = []@State dialogueListNew: string[][] = []@State displayList: boolean[] = []@State displayIndex: number = 1@State delIndex: number = 0@State readBook: readBookCharpterTemplate = readBookCharpterData@Builder leftUser(roleName: string, roleText: string){// 左侧角色Column({ space: 4 }){Row({ space: 12 }){smallImage(roleName, this.frameData.backGround, this.ThisColor)Text(`${roleName}`).fontColor(this.ThisColor).fontSize(this.frameData.typefaceSize)}Row(){Text(`${roleText}`).fontColor(this.ThisColor).fontSize(this.frameData.typefaceSize - 2)}.border({width: 1}).borderRadius({topRight: 12,bottomLeft: 12,bottomRight: 12}).backgroundColor(this.frameData.backGround).padding({top: 8,bottom: 8,left: 12,right: 12}).margin({left: '12%'})}.width('70%').alignItems(HorizontalAlign.Start)}@Builder rightUser(roleName: string, roleText: string){// 右侧角色Column({ space: 4 }){Row({ space: 12 }){Text(`${roleName}`).fontColor(this.ThisColor).fontSize(this.frameData.typefaceSize)smallImage(roleName, this.frameData.backGround, this.ThisColor)}.width('100%').justifyContent(FlexAlign.End)Row(){Row(){Text(`${roleText}`).fontColor(this.ThisColor).fontSize(this.frameData.typefaceSize - 2)}.border({width: 1}).borderRadius({topLeft: 12,bottomLeft: 12,bottomRight: 12}).backgroundColor(this.frameData.backGround).padding({top: 8,bottom: 8,left: 12,right: 12}).margin({right: '12%'})}.width('80%').justifyContent(FlexAlign.End)}.width('100%').alignItems(HorizontalAlign.End)}@Builder narratorUser(roleText: string){// 旁白Column({ space: 4 }){Row(){Text(`${roleText}`).fontColor(this.ThisColor).fontSize(this.frameData.typefaceSize - 2).textAlign(TextAlign.Center)}.border({width: 1}).borderRadius(12).padding(12).margin({top: 8,}).justifyContent(FlexAlign.Center)}.padding({left: 24,right: 24}).width('100%')}aboutToAppear(): void {let params = router.getParams() as Record<string, number>let bookID = params['bookID']let readIndex = params['chapterIndex']for (let index = 0; index < this.readBookList.length; index++) {if (this.readBookList[index].ascriptionBookID == bookID) {this.readBook = this.readBookList[index]break}}this.dialogueList = this.readBook.dialogueList.split(',')for (let item of this.dialogueList) {let read = item.split('|')this.dialogueListNew.push([read[0], read[1], read[2]])}}onPageHide(): void {this.saveData()}saveData() {let readList: string[] = []this.readBook.dialogueList = ''for (let item of this.dialogueListNew) {readList.push(item.join('|'))}for (let item of readList) {this.readBook.dialogueList += item + ','}for (let index = 0; index < this.readBookList.length; index ++) {if (this.readBookList[index].articleID == this.readBook.articleID) {this.readBookList[index] = this.readBook}}promptAction.showToast({message: "保存成功!"})}build() {Flex(){Column(){// 标题Row(){frameData().width(50)Text(`第${this.index}幕`).fontSize(this.frameData.typefaceSize + 8).fontColor(this.ThisColor)Text('').textAlign(TextAlign.End).width(50)}.width('100%').justifyContent(FlexAlign.SpaceBetween).border({width: {bottom: 2}}).padding({top: 16,left: 24,right: 24,bottom: 16})Scroll(this.scorllData){Column({ space: 12 }){ForEach(this.dialogueListNew, (item: string[], index) => {Row(){if (item[0] == 'left') {this.leftUser(item[1], item[2])} else if (item[0] == 'right') {this.rightUser(item[1], item[2])} else if (item[0] == 'pb') {this.narratorUser(item[2])}}.onClick(() => {this.delIndex = indexthis.delPageOpen.open()})})}.alignItems(HorizontalAlign.Start).padding({left: 24,right: 24,top: 16,bottom: 16}).width('100%').alignItems(HorizontalAlign.Start)}.align(Alignment.Top).edgeEffect(EdgeEffect.Spring).height('86%').onClick(() => {this.displayList[this.displayIndex++] = true})Row(){Text('').textCare(this.frameData.typefaceSize + 2).width(100)Text('编辑文本').textCare(this.frameData.typefaceSize + 2).onClick(() => {this.editTextPageOpen.open()})Text('保存').textCare(this.frameData.typefaceSize + 2).onClick(() => {this.saveData()}).width(100).textAlign(TextAlign.End)}.width('100%').justifyContent(FlexAlign.SpaceBetween).border({width: {top: 2}})}.height('100%')}}
}复制

以上便是"说书人"项目中部分重要代码的分享,由于字数限制,不能全部上传,完整代码已经上传AtomGit,大家可以进行下载

master · 说书人_单机版 · AtomGit

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

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

相关文章

HTML新特性|01 音频视频

音频 1、Audio (音频) HTML5提供了播放音频文件的标准 2、control(控制器) control 属性供添加播放、暂停和音量控件 3、标签: <audio> 定义声音 <source> 规定多媒体资源,可以是多个<!DOCTYPE html> <html lang"en"> <head><…

像素的访问和算术运算

【欢迎关注编码小哥&#xff0c;学习更多实用的编程方法和技巧】 一、常用的访问像素的方法 1、使用at()方法 // 灰度图 cv::Mat grayImage; for (int y 0; y < grayImage.rows; y) {for (int x 0; x < grayImage.cols; x) {uchar pixel grayImage.at<uchar>…

【深度学习】卷积网络代码实战ResNet

ResNet (Residual Network) 是由微软研究院的何凯明等人在2015年提出的一种深度卷积神经网络结构。ResNet的设计目标是解决深层网络训练中的梯度消失和梯度爆炸问题&#xff0c;进一步提高网络的表现。下面是一个ResNet模型实现&#xff0c;使用PyTorch框架来展示如何实现基本的…

js的讲解

Proxy 是 ES6&#xff08;ECMAScript 2015&#xff09;中引入的一个新的内置对象&#xff0c;用于定义某些操作的自定义行为&#xff08;如属性查找、赋值、枚举、函数调用等&#xff09;。Proxy 可以被看作是一个拦截器&#xff0c;它拦截并自定义对象上的基本操作。通过创建一…

雷电「模拟器」v9 最新清爽去广

前言 雷电模拟器9是基于安卓9内核开发的全新版本模拟器 安装环境 [名称]&#xff1a;雷电「模拟器」 [大小]&#xff1a;579MB [版本]&#xff1a;9.1.34 [语言]&#xff1a;简体中文 [安装环境]&#xff1a;Windows 通过网盘分享的文件&#xff1a;雷电模拟器 链接:…

大模型 API 接入初探

文章目录 大模型 API 接入初探一、使用大模型 API 的前置步骤&#xff08;一&#xff09;注册账户与获取凭证&#xff08;二&#xff09;理解 API 文档 二、三个常用 API&#xff08;一&#xff09;列出模型&#xff08;二&#xff09;FIM 补全&#xff08;三&#xff09;对话补…

ACPI PM Timer

ACPI PM Timer 概述&#xff1a; ACPI PM Timer是一个非常简单的计时器&#xff0c;它以 3.579545 MHz 运行&#xff0c;在计数器溢出时生成系统控制中断&#xff08;SCI&#xff09;。它精度较低&#xff0c;建议使用其他定时器&#xff0c;如HPET或APIC定时器。 检测ACPI P…

力扣--LCR 188.买卖芯片的最佳时机

题目 数组 prices 记录了某芯片近期的交易价格&#xff0c;其中 prices[i] 表示的 i 天该芯片的价格。你只能选择 某一天 买入芯片&#xff0c;并选择在 未来的某一个不同的日子 卖出该芯片。请设计一个算法计算并返回你从这笔交易中能获取的最大利润。 如果你不能获取任何利…

工业相机基本参数

分辨率&#xff08;Resolution&#xff09; 定义&#xff1a;分辨率指的是相机图像的像素数&#xff0c;通常以 宽度 x 高度 的形式表示&#xff0c;如 1920x1080 或 2592x1944。作用&#xff1a;分辨率越高&#xff0c;相机可以捕捉到更多的细节。高分辨率相机适用于需要精确…

实时在线翻译谷歌插件

Real - time Translation插件的安装 1、下载插件并解压 2、打开谷歌浏览器&#xff0c;在地址栏输入 “chrome://extensions/” 进入扩展程序页面. 3、开启页面右上角的 “开发者模式”. 4、点击 “加载已解压的扩展程序” 按钮&#xff0c;选择之前解压的文件夹&#xff0c;点…

torch.sparse_csc_tensor

torch.sparse_csc_tensor 以CSC格式构建一个稀疏张量。CSC格式的稀疏张量乘法运算通常比 COO 格式的稀疏张量更快。 CSC格式&#xff08;Compressed Sparse Column Format&#xff09;是一种存储稀疏矩阵的常用格式&#xff0c;它通过三个数组来表示稀疏矩阵&#xff1a; 非零…

C++ 设计模式:原型模式(Prototype Pattern)

链接&#xff1a;C 设计模式 链接&#xff1a;C 设计模式 - 工厂方法 链接&#xff1a;C 设计模式 - 抽象工厂 链接&#xff1a;C 设计模式 - 建造者模式 原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;它允许一个对象通过复制现有对象来…

C语言中的贪心算法

贪心算法&#xff08;Greedy Algorithm&#xff09;是一种在每一步选择中都采取当前最优解的算法&#xff0c;希望通过局部最优解的选择&#xff0c;最终得到全局最优解。它常用于解决最优化问题&#xff0c;如最小生成树、最短路径等。本文将从理论到实践&#xff0c;逐步引导…

区块链:概念与应用场景

一、区块链的定义 区块链是一种分布式账本技术&#xff0c;它以去中心化的方式存储数据&#xff0c;通过密码学保证数据的安全性和不可篡改性。 &#xff08;一&#xff09;分布式账本 账本结构&#xff1a;区块链可以看作是一个由多个节点共同维护的账本。这个账本是由一系列…

[数据集][图像分类]常见鱼类分类数据集2w张8类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;7554&#xff08;剩余1w多为测试集&#xff09; 分类类别数&#xff1a;…

uniapp开发小程序内嵌h5页面,video视频两边有细小黑色边框

1.问题如图 2.原因分析 是否为设置上述属性呢&#xff1f; 设置了&#xff0c;但是仍然有黑边。经过选中页面元素分析后&#xff0c;判断video元素本身就有这种特点&#xff0c;就是视频资源无法完全铺满元素容器。 3.解决方案

pod生命周期和pod的优雅终止

pod优雅终止 概念&#xff1a;当一个pod需要被终止时&#xff0c;系统会给予一定的时间窗口让pod内的应用程序完成正在处理的任务并安全地关闭&#xff0c;而不是立即强制终止。这样可以避免因突然终止而导致的数据丢失或服务中断 1. 发送终止信号&#xff1a; 当一个 pod 被…

Android 13 Launcher3 移除桌面抽屉入口

com.android.launcher3.taskbar.TaskbarView.updateHotseatItems // 移除任务栏抽屉入口 // if (mAllAppsButton != null) { // int index = Utilities.isRtl(getResources()) ? 0 : getChildCount(); // addView(mAllAppsButton, index)…

深度学习任务中的 `ulimit` 设置优化指南

深度学习任务中的 ulimit 设置优化指南 1. 什么是 ulimit&#xff1f;2. 深度学习任务中的关键 ulimit 设置2.1 max locked memory&#xff08;-l&#xff09;2.2 open files&#xff08;-n&#xff09;2.3 core file size&#xff08;-c&#xff09;2.4 stack size&#xff08…

【SpringMVC】SpringMVC 快速入门

通常&#xff0c;Web 应用的工作流程如下&#xff1a; 用户通过浏览器访问前端页面&#xff1b; 前端页面通过异步请求向后端服务器发送数据&#xff1b; 后端采用“表现层-业务层-数据层”三层架构进行开发&#xff1a; 表现层接收页面请求将请求参数传递给业务层业务层访问…