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><…

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

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

雷电「模拟器」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;对话补…

实时在线翻译谷歌插件

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

[数据集][图像分类]常见鱼类分类数据集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.解决方案

【SpringMVC】SpringMVC 快速入门

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

OpenGL变换矩阵和输入控制

在前面的文章当中我们已经成功播放了动画&#xff0c;让我们的角色动了起来&#xff0c;这一切变得比较有意思了起来。不过我们发现&#xff0c;角色虽然说是动了起来&#xff0c;不过只是在不停地原地踏步而已&#xff0c;而且我们也没有办法通过键盘来控制这个角色来进行移动…

【Spring MVC 核心机制】核心组件和工作流程解析

在 Web 应用开发中&#xff0c;处理用户请求的逻辑常常会涉及到路径匹配、请求分发、视图渲染等多个环节。Spring MVC 作为一款强大的 Web 框架&#xff0c;将这些复杂的操作高度抽象化&#xff0c;通过组件协作简化了开发者的工作。 无论是处理表单请求、生成动态页面&#x…

Verilog 过程赋值

关键词&#xff1a;阻塞赋值&#xff0c;非阻塞赋值&#xff0c;并行 过程性赋值是在 initial 或 always 语句块里的赋值&#xff0c;赋值对象是寄存器、整数、实数等类型。 这些变量在被赋值后&#xff0c;其值将保持不变&#xff0c;直到重新被赋予新值。 连续性赋值总是处…

[并发与并行] python如何构建并发管道处理多阶段任务?

文章目录 1. 背景&目标2. show me the code3.知识点4. 总结 1. 背景&目标 背景&#xff1a;一个任务可分为多个阶段(各个阶段非CPU密集型任务&#xff0c;而是属于IO密集型任务)&#xff0c;希望每个阶段能够交给各自的线程去执行。 目标&#xff1a;构建支持多并发的…

07 基于OpenAMP的核间通信方案

引言 ZYNQ7020有两个CPU核心&#xff0c;这两个核心可以采用SMP或AMP方式进行调度&#xff0c;当采用AMP方式进行调度时核0和核1可以运行不同的操作系统&#xff0c;如核0运行Linux系统&#xff0c;提供有些复杂的用户交互工作&#xff0c;核1运行实时操作系统&#xff0c;对设…

7.若依参数设置、通知公告、日志管理

参数设置 对系统中的参数进行动态维护。 关闭验证码校验功能 打开页面注册功能 需要修改前端页面代码 通知公告 促进组织内部信息传递 若依只提供了一个半成品&#xff0c;只实现了管理员可以添加通知公告。 日志管理 追踪用户行为和系统运行状况。 登录日志 和操作日志…

基于Docker+模拟器的Appium自动化测试(二)

模拟器的设置 打开“夜神模拟器”的系统设置&#xff0c;切换到“手机与网络”页&#xff0c;选中网络设置下的“开启网络连接”和“开启网络桥接模式”复选框&#xff0c;而后选择“静态IP”单选框&#xff0c;在IP地址中输入“192.168.0.105”&#xff0c;网关等内容不再赘述…

大数据技术-Hadoop(三)Mapreduce的介绍与使用

目录 一、概念和定义 二、WordCount案例 1、WordCountMapper 2、WordCountReducer 3、WordCountDriver 三、序列化 1、为什么序列化 2、为什么不用Java的序列化 3、Hadoop序列化特点&#xff1a; 4、自定义bean对象实现序列化接口&#xff08;Writable&#xff09; 4…

【数据仓库】SparkSQL数仓实践

文章目录 集成hive metastoreSQL测试spark-sql 语法SQL执行流程两种数仓架构的选择hive on spark数仓配置经验 spark-sql没有元数据管理功能&#xff0c;只有sql 到RDD的解释翻译功能&#xff0c;所以需要和hive的metastore服务集成在一起使用。 集成hive metastore 在spark安…

基本算法——回归

本节将通过分析能源效率数据集&#xff08;Tsanas和Xifara&#xff0c;2012&#xff09;学习基本的回归算法。我们将基 于建筑的结构特点&#xff08;比如表面、墙体与屋顶面积、高度、紧凑度&#xff09;研究它们的加热与冷却负载要 求。研究者使用一个模拟器设计了12种不…

V-Express - 一款针对人像视频生成的开源软件

V-Express是腾讯AI Lab开发的一款针对人像视频生成的开源软件。它旨在通过条件性丢弃&#xff08;Conditional Dropout&#xff09;技术&#xff0c;实现渐进式训练&#xff0c;以改善使用单一图像生成人像视频时的控制信号平衡问题。 在生成过程中&#xff0c;不同的控制信号&…

Java与SQL Server数据库连接的实践与要点

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;Java和SQL Server数据库交互是企业级应用开发中的重要环节。本文详细探讨了使用Java通过JDBC连接到SQL Server数据库的过程&#xff0c;包括加载驱动、建立连接、执行SQL语句、处理异常、资源管理、事务处理和连…