# sxdx
**Repository Path**: hanweiwn/sydx
## Basic Information
- **Project Name**: sxdx
- **Description**: 石油大学
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-06-08
- **Last Updated**: 2026-06-18
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## 鸿蒙开发
软件最重要的事什么?
```
不要关注API(别人写好给我用的组件),不重复造轮子。
关注流程,关注思想。关注设计模式,关注算法。
我知道一个软件是怎么写出来的(写的细节完全可以参考AI)。
```
鸿蒙的项目我会从头到尾开发。最后一天:答辩。
**你们需要答辩和提交产出物。**
(演示你们做的项目,和回答问题。和提交相关文档(模版))
6.9任务:
数据库给我装上
测试sql语句
从git下载我的代码,在你的电脑上跑起来。
把我的代码,改一改。
### 今天任务:
分小组(不超过5个。项目立项:关于鸿蒙的什么项目)。
明天早上提交:小组名单和项目名称。我做的项目是 医院挂号系统。
DevEco Studio安装
把我的代码跑一边,看看出来是什么样子的。
### 环境:
笔记工具
```
通过网盘分享的文件:typora-setup-x64.exe
链接: https://pan.baidu.com/s/1WBHVw0B_OrYp5GwQ6DKmgQ?pwd=evsv 提取码: evsv 复制这段内容后打开百度网盘手机App,操作更方便哦
```
前端开发:
```
DevEco Studio (自己去下载)(今天就下载)
https://developer.huawei.com/consumer/cn/download/
是鸿蒙的开发的IDE。一路next,建议:不要装在有中文,有空格的目录下。
(注意:如果你过去的电脑装过nodejs,要看版本是否大于18.如果小于18.请删除掉。删的比较干净)
鸿蒙默认装的就是nodejs18版本。
```
后端服务
一路next
```
jdk java开发环境工具包
通过网盘分享的文件:jdk-17.0.12_windows-x64_bin.exe
链接: https://pan.baidu.com/s/1DWb6QQ1w2ve3i0RNFVyu0g?pwd=fqcc 提取码: fqcc 复制这段内容后打开百度网盘手机App,操作更方便哦 版本需要大于等于17.
后端开发:
idea: java的集成开发平台
通过网盘分享的文件:
链接: https://pan.baidu.com/s/13vCMgYVDYJygRvUkVy40ug?pwd=nncz 提取码: nncz 复制这段内容后打开百度网盘手机 App,操作更方便哦
```
数据库
一路next
```
通过网盘分享的文件:mysql-8.0.21-winx64.zip
链接: https://pan.baidu.com/s/1X31H7osZKYRRy_GZnocUIg?pwd=76ab 提取码: 76ab 复制这段内容后打开百度网盘手机App,操作更方便哦
数据库链接的终端。用它能很方便的操作数据库。
通过网盘分享的文件:Navicat170.rar
链接: https://pan.baidu.com/s/1acruVrVXrVPElKVcWmAPrg?pwd=ytw8 提取码: ytw8 复制这段内容后打开百度网盘手机App,操作更方便哦
```
### Mysql安装:
解压
\1. 将刚才下载下来的压缩包解压到相应盘符
我这里是解压到 D:/soft 中

\2. 在 mysql-8.0.xx 文件夹下创建 my.ini 文件
\3. 编辑刚新建的 my.ini 文件
```
[mysqld]
# 设置3306端口
port=3306
# 设置mysql的安装目录,切记此处一定要用双斜杠\\,单斜杠这里会出错。
basedir=D:\\soft\\mysql-8.0.21-winx64
# 设置mysql数据库的数据的存放目录
datadir=D:\\soft\\mysql-8.0.21-winx64\\data
# 允许最大连接数
max_connections=1000
# 允许连接失败的次数。这是为了防止有人从该主机试图攻击数据库系统
max_connect_errors=10
# 服务端使用的字符集默认为UTF8
character-set-server=utf8
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
# 默认使用“mysql_native_password”插件认证
default_authentication_plugin=mysql_native_password
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8
[client]
# 设置mysql客户端连接服务端时默认使用的端口
port=3306
default-character-set=utf8
```
安装
剩下操作都是在 cmd 中完成的,需要以管理员身份打开 cmd 窗口。
1. 打开 cmd 。

2. 切换目录。
3. 安装 mysql 。
在打开的MySQL的bin目录中,输入命令:mysqld --initialize --console ,完成MySQL的初始化。
```
mysqld --initialize --console
```

4. 创建服务。
初始化MySQL后,输入命令:mysqld --install,完成MySQL服务的安装。
```
mysqld --install
```

如果执行后提示,mysql已经存在,输入以下命令删除原有服务。
```
sc delete mysql
```
5. 启动服务。
```
net start mysql
```
6. 登录。
```
mysql -u root -p
```
7. 修改密码。
```
ALTER USER 'root'@'localhost' IDENTIFIED BY 'ilovelaohan';
```
其中 ilovelaohan是你的新密码。
## 鸿蒙
```
https://developer.huawei.com/consumer/cn/training/result?courseType=5
官方的学习地址
学完之后就可以考一个鸿蒙的初级开发认证。 官网考试。免费考。官网报名,在线考试。
```
### DevEco Studio

### ArkTS语法
```ts
//此处可以写arkts语法
// 基础变量和类型
// let username:string = 'zsf' //声明一个变量 名称为username 类型为string 值为'zsf'
// let age:number = 18
// let sex:boolean = true
// console.log('username is ',username)
// console.log('age is ',age)
// console.log('sex is ',sex)
//数组
// let students:string[] = ['张三丰','刘德华','张曼玉']
// console.log('stutents is ',students);
// console.log('第二个学生是',students[1]);
// 函数
// function printstar(){
// console.log('星星');
// console.log('星星');
// console.log('星星');
// }
// printstar()
// printstar()
// printstar()
//带参数的函数
// function buy(price:number,count:number){
// let result = price*count
// return result
// }
// let result = buy(58,3)
// console.log('results is ',result);
//箭头函数应该是今后用的最多的 属于函数的简写
//let 函数名 = ()=>{函数体}
// let buy2 = ()=>{
// console.log('这是一个箭头函数被调用了');
// }
// buy2()
//对象
//作用:描述一个物体的特征和行为
// 必须通过interface接口进行约定结构和类型
//定义接口
//今后使用它作为一个数据的载体,或者是传输的对象
//数据从数据库来,传递给前端,就要用这个
// interface Person{
// name:string
// age:number
// weight:number
// }
// //基于接口,定义对象
// let xiaoren:Person={
// name:'秦桧',
// age: 39,
// weight:380
// }
// let daren:Person={
// name:'岳飞',
// age: 2000,
// weight:160
// }
// console.log('xiaorenis',xiaoren.name,xiaoren.age,xiaoren.weight);
// console.log('daren',daren.name,daren.age,daren.weight);
//对象是可以有用方法的
// interface Person{
// eat:()=>void
// drink:(what:string)=>void
// }
// let xiaoren:Person={
// eat:():void=>{
// console.log('小人吃石头');
// },
// drink:(what:string):void=>{
// console.log('小人喝',what);
// }
// }
// xiaoren.eat()
// xiaoren.drink('雪碧')
//联合类型
//灵活的类型,存储不同的类型
// let judge:number|string = 100
// judge = 'zsf'
// console.log('judge',judge);
// judge = 250
// console.log('judge',judge);
// //枚举类型
// 变量的值就必须在一定的范围内
//你们数据库性别用 char(2) varchara(2) enum bit
//男 女
enum Sex{
man = '男',
woman = '女'
}
let yousex:Sex = Sex.man
console.log('you sex is',yousex);
```
### ArkUI界面开发
#### 第一个
```typescript
@Entry //标记当前组件为入口组件,是一个页面的起点
@Component //标记是一个自定义组件,是一个可以复用的UI单元
struct test1 {
build() { //组件描述ui的方法,内部使用声明式语法进行描述
//子组件 一个build 只能有一个根节点
Column(){
Text('石油大学饭一般').fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Green)
}.width('100%').height('100%')
}
}
```
新建模拟器

如果你的

```
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-emulator-faqs#section214296171615
```
#### 界面2
```ts
@Entry //标记当前组件为入口组件,是一个页面的起点
@Component //标记是一个自定义组件,是一个可以复用的UI单元
struct test1 {
//当这个值被改变的时候 会自动出发ui界面的改变
@State message:string = '石油大学的饭好吃的很'
build() { //组件描述ui的方法,内部使用声明式语法进行描述
//子组件 一个build 只能有一个根节点
Column(){
Text(this.message).fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Green)
Button('点我改变').onClick(()=>{
this.message = '石油大学的🍚一点都不好吃'
})
}.width('100%').height('100%')
}
}
```
#### 界面3

```ts
@Entry
@Component
struct test2 {
build() {
Column(){ //build下面只能有一个根节点
Text('小说介绍').backgroundColor(Color.Gray).width('100%')
.fontSize(20).height(40)
.fontWeight(900) //100-900之间的数字 加粗700 默认是400
Row(){
Text('都市').height(30).width('25%').backgroundColor(Color.Yellow)
Text('情感').height(30).width('25%').backgroundColor(Color.Blue)
Text('神话').height(30).width('25%').backgroundColor(Color.Brown)
Text('白领').height(30).width('25%').backgroundColor(Color.Orange)
}
}.width('100%')
.backgroundColor(Color.Pink)
}
}
```
#### 界面4

```ts
@Entry
@Component
struct test3 {
build() {
Column(){
Text('石油大学的饭太好了').height(40).fontSize(24)
.fontWeight(FontWeight.Bold)
.width('100%')
Text('石油大学的饭在一个风和日丽的下午,我们哦度吃了,非常好吃。石油大学的饭在一个风和日丽的下午,我们哦度吃了,非常好吃。石油大学的饭在一个风和日丽的下午,我们哦度吃了,非常好吃。石油大学的饭在一个风和日丽的下午,我们哦度吃了,非常好吃。')
.lineHeight(24).textOverflow({
overflow: TextOverflow.Ellipsis
}).maxLines(2)
Row(){
Text('置顶 ').fontColor('#0275fe')
Text('凤凰网 ').fontColor('#a1a1a1')
Text('9876评论 ').fontColor('#b1a1a2')
}.width('100%').margin({top:5,left:5})
}.width('100%')
}
}
```
#### 界面5

```ts
@Entry
@Component
struct test3 {
build() {
Column(){
Image('https://news-bos.cdn.bcebos.com/mvideo/log-news.png')
.width('50%').margin({bottom:10})
Text('石油大学的饭太好了').height(40).fontSize(24)
.fontWeight(FontWeight.Bold)
.width('100%')
Text('石油大学的饭在一个风和日丽的下午,我们哦度吃了,非常好吃。石油大学的饭在一个风和日丽的下午,我们哦度吃了,非常好吃。石油大学的饭在一个风和日丽的下午,我们哦度吃了,非常好吃。石油大学的饭在一个风和日丽的下午,我们哦度吃了,非常好吃。')
.lineHeight(24).textOverflow({
overflow: TextOverflow.Ellipsis
}).maxLines(2)
Row(){
Text('置顶 ').fontColor('#0275fe')
Text('凤凰网 ').fontColor('#a1a1a1')
Text('9876评论 ').fontColor('#b1a1a2')
}.width('100%').margin({top:5,left:5})
Row(){
Image($r('app.media.11'))
.width('100%').height('15%')
}.margin({top:10})
}.width('100%')
}
}
```
#### 图片
使用图片有三种方式:
1:网络图片
```
Image('https://news-bos.cdn.bcebos.com/mvideo/log-news.png')
.width('50%').margin({bottom:10})
```
2:本地文件夹图片
不推荐,因为不能够跨设备
```
Image('images/1.jpg')
.width('50%').margin({bottom:10})
```
3:本地media图片
图片必须放在resources/base/media目录下,这是推荐的方式,能够支持跨设备
```
Image($r('app.media.11'))
.width('100%').height('15%')
```
4:svg
矢量图,可以任意放大缩小,不失真,还可以更改颜色。
来源
```
https://developer.huawei.com/consumer/cn/design/harmonyos-icon/
https://www.iconfont.cn/
```
#### 登录
```ts
@Entry
@Component
struct Index {
build() {
Column({space:15}){
Image($r('app.media.huawei')).width(60)
TextInput({
placeholder:'请输入用户名'
})
TextInput({
placeholder:'请输入密码'
})
Button('登录').width('100%')
Row({space:20}){
Image($r('app.media.zfb_tab_me')).width(20)
.fillColor(Color.Red)
Text('前往注册')
Image($r('app.media.ic_more')).width(20)
.fillColor(Color.Green)
Text('忘记密码')
}
}.padding(20)
}
}
```
#### 边距:
margin: 外边距
padding: 内边距
```ts
@Entry
@Component
struct Index {
build() {
Column({space:15}){
Image($r('app.media.huawei')).width(60)
Text('石油医院挂号系统').fontSize(28).fontWeight(900)
TextInput({
placeholder:'请输入用户名'
})
TextInput({
placeholder:'请输入密码'
})
Button('登录').width('100%')
Row(){
Image($r('app.media.zfb_tab_me')).width(20)
.fillColor(Color.Red).margin({right:10})
Text('前往注册')
.margin({right:50})
Image($r('app.media.ic_more')).width(20)
.fillColor(Color.Green)
Text('忘记密码').margin({left:10})
}
}.padding(20)
}
}
```
#### 线性布局

```
@Entry
@Component
struct test4 {
build() {
//线性布局就能够自动适配适应你设备的大小
Column(){
Text().width(200).height(100).backgroundColor(Color.Pink).border({width:2})
Text().width(200).height(100).backgroundColor(Color.Yellow).border({width:2})
Text().width(200).height(100).backgroundColor(Color.Green).border({width:2})
Text().width(200).height(100).backgroundColor(Color.Orange).border({width:2})
}.width('100%')
.height('100%')
// .alignItems(HorizontalAlign.End) //最右边
// .alignItems(HorizontalAlign.Start) //最左边
.alignItems(HorizontalAlign.Center) //最左边
// .justifyContent(FlexAlign.SpaceAround) //间隙环绕 1 1 1 1
// .justifyContent(FlexAlign.SpaceBetween) //间隙环绕 0.5 1 1 1 0.5
// .justifyContent(FlexAlign.Start) // 主轴 用了线性布局将来是可以跨设备的
.justifyContent(FlexAlign.End) // 底部
.justifyContent(FlexAlign.Center) // 中间
}
}
```

```
@Entry
@Component
struct test4 {
build() {
//线性布局就能够自动适配适应你设备的大小
Row(){
Text().width(60).height(100).backgroundColor(Color.Pink).border({width:2})
Text().width(60).height(100).backgroundColor(Color.Yellow).border({width:2})
Text().width(60).height(100).backgroundColor(Color.Green).border({width:2})
Text().width(60).height(100).backgroundColor(Color.Orange).border({width:2})
}.width('100%')
.height('100%')
.justifyContent(FlexAlign.SpaceAround)
.alignItems(VerticalAlign.Center)
}
}
```
##### 个人中心

```ts
@Entry
@Component
struct my {
build() {
//上下两部分
//上面 左边箭头 个人中心 右边 更多的图标
//下面 个人的详细信息 挂号信息
Column(){
Row(){
Image($r('app.media.ic_arrow_left')).width(30)
Text('个人中心')
Image($r('app.media.ic_more')).width(24)
}.width('100%')
.backgroundColor('#ccc')
.height(40)
.justifyContent(FlexAlign.SpaceBetween)
.padding({left:10,right:10})
Column(){
Text('将来你的个人信息').margin({top:10})
}.backgroundColor(Color.White).width('100%').height('100%')
}.width('100%')
.height('100%')
.backgroundColor('#ccc')
.expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])
}
}
```
#### 自适应伸缩布局
设置layoutWeight属性的子元素与兄弟元素会按照权重进行分配主轴的剩余空间。

```ts
@Entry
@Component
struct test5 {
build() {
Column(){
Row(){
Text('左侧').backgroundColor(Color.Gray).height(40).layoutWeight(1)
Text('右侧').backgroundColor(Color.Brown).height(40).width(80)
}.width(300)
.height(40).backgroundColor('#fff')
Row(){
Text('左侧').backgroundColor(Color.Gray).height(40).layoutWeight(1)
Text('中间').backgroundColor(Color.Orange).height(40).layoutWeight(2)
Text('右侧').backgroundColor(Color.Brown).height(40).layoutWeight(3)
}.width(300)
.height(40).backgroundColor('#fff').margin({top:20})
}.width('100%')
.height('100%')
}
}
```
#### 弹性布局

```ts
@Entry
@Component
struct test6 {
build() {
Column(){
Text('专业选择').fontSize(30).fontWeight(700)
Flex({wrap:FlexWrap.Wrap}){ //弹性布局
Text('石油').margin(5).padding(10).backgroundColor('#f1f1f1')
Text('管道').margin(5).padding(10).backgroundColor('#f1f1f1')
Text('爆破').margin(5).padding(10).backgroundColor('#f1f1f1')
Text('化工').margin(5).padding(10).backgroundColor('#f1f1f1')
Text('物理').margin(5).padding(10).backgroundColor('#f1f1f1')
Text('信息科学').margin(5).padding(10).backgroundColor('#f1f1f1')
Text('化工').margin(5).padding(10).backgroundColor('#f1f1f1')
Text('物理').margin(5).padding(10).backgroundColor('#f1f1f1')
Text('信息科学').margin(5).padding(10).backgroundColor('#f1f1f1')
}
}.width('100%').height('100%')
}
}
```
#### 绝对定位
可以实现层叠效果,对整个手机屏幕的x,y轴而言。
右上角数字

```ts
@Entry
@Component
struct test7 {
build() {
Column(){
Image($r('app.media.bz_msg')).width(50)
Text('8').fontColor(Color.Red).fontWeight(FontWeight.Bold)
.fontSize(30)
.position({
x:195,
y: -15
})
}.width('100%').height('100%')
}
}
```
#### 层叠布局
比绝对定位要方便,根据当前容器元素的位置而言。

```
@Entry
@Component
struct test8 {
build() {
Column(){
Stack({
alignContent: Alignment.Center
}){
Text('老大').backgroundColor(Color.Yellow).width(250).height(250)
Text('老二').backgroundColor(Color.Blue).width(150).height(150)
Text('老三').backgroundColor(Color.Green).width(50).height(50)
}
}.width('100%').height('100%')
}
}
```

```
@Entry
@Component
struct test10 {
build() {
Column(){
Stack({
alignContent:Alignment.TopEnd
}){
Image($r('app.media.bz_msg')).width(50)
Text('8').fontColor(Color.Red).fontWeight(FontWeight.Bold)
.fontSize(30)
.margin({top:-12,right:-8})
}
}.width('100%').height('100%')
}
}
```
### 事件
#### 计数器

```
@Entry
@Component
struct test11 {
@State count:number = 0
build() {
Row(){
Button("-").onClick(()=>{
this.count--
})
Text(this.count.toString()).margin(10)
Button("+").onClick(()=>{
this.count++
})
}
}
}
```
#### 购物车

```
@Entry
@Component
struct carts {
@State count:number = 1
@State price:number = 21.40
build() {
Column(){
//产品 购物车的内容
Row({space:5}){
Image($r('app.media.product1')).width(100).borderRadius(8)
//文字
Column({space: 6}){
Text('冲销量100W好吃饭').lineHeight(20).fontSize(14)
Text('一折折扣商品').lineHeight(20).fontSize(12).fontColor('#7f7f7f')
Row({space:30}){
Text('¥'+this.price)
Row({space:10}){
Text('-').width(22).height(22).textAlign(TextAlign.Center)
.border({width:1,color:'#e1e1e1',radius: {topRight:5,bottomRight:5}})
.onClick(()=>{
this.count--
})
Text(this.count.toString())
Text('+').width(22).height(22).textAlign(TextAlign.Center)
.fontWeight(700)
.border({width:1,color:'#e1e1e1',radius: {topRight:5,bottomRight:5}})
.onClick(()=>{
this.count++
})
}
}
}.alignItems(HorizontalAlign.Start)
.width('80%').margin({left:10})
}.width('100%').height(100)
//结算
Row(){
Column(){
Text(`已选择${this.count}件商品`)
Text('合计:'+(this.count*this.price).toFixed(2))
}
}.width('100%').height(700)
}.width('100%').height('100%')
.backgroundColor('#f3f3f3')
}
}
```
### 新闻列表

```
@Entry
@Component
struct test12 {
@State news:string[] = [
'石油大学的饭吃出来金砖',
'石油大学的饭吃出来金条',
'石油大学的饭特表好吃',
'今天天气真正好',
'黄蓉来到桃花岛',
'石油大学的饭吃出来金砖'
]
build() {
Column(){
ForEach(this.news,(item:string,index:number)=>{
Text(index+item).fontSize(24).fontWeight(700)
.padding(8)
.width('100%')
})
}.width('100%').height('100%')
}
}
```
#### 新闻列表2
数据是从后端传过来的,前后段的交互数据总是json。10年前总是xml。
不管你后端是Java,Python,.Net。Go还是任何其他语言(把数据封装成对象)-----后端需要把数据打成json给前端
------数据交互的载体就是JSON--------------
前端:不管你是vue,react,html,鸿蒙还是大屏终端。拿到的就是JSON。(拿到JSON后,可能需要转换为自己的对象)
不管是百度地图,短信接口,身份证验证三要素。DeepSeek大模型交互的数据接口都是JSON。
#### JSON
就是个文本。
```
{
'username':'zsf',
'password':'000000',
'sex':'female'
}
[
{
'username':'zsf',
'password':'000000',
'sex':'female'
},
{
'username':'zsf',
'password':'000000',
'sex':'female'
},
{
'username':'zsf',
'password':'000000',
'sex':'female'
}
]
```

```
//将来数据可能来自于后台
//接口和对象
interface News{
title:string,
createTime:string
}
@Entry
@Component
struct test13 {
@State message:string = '我不测测'
//声明一个包含了所有数据的载体
@State news:News[]=[
{
title:'石油大学于明天食堂全部免费开发,随便吃',
createTime:'2026-06-09 12:21:21'
},{
title:'石油大学于明天商店全部免费开发,随便吃',
createTime:'2026-06-09 12:21:21'
},{
title:'石油大学于明天教室全部免费开发,随便吃',
createTime:'2026-06-09 12:21:21'
}
]
build() {
Column(){
Column(){
ForEach(this.news,(item:News,index:number)=>{
Text(item.title)
.width('100%').fontSize(15).fontColor('#303030')
.lineHeight(20)
Text(item.createTime).fontSize(12)
.fontColor(Color.Gray)
.margin({top:10})
})
}.margin({left:5})
}.width('100%').height('100%')
}
}
```
### 药品管理
#### 多列的布局方式

```
@Entry
@Component
struct medic {
build() {
Column(){
//标题
Row(){
Text('便民药品').fontSize(20)
.fontWeight(FontWeight.Bold)
}
//商品列表要有一个循环,而且能够向下拖动
List(){ //列表组件 能够向上向下拖动
ForEach(Array.from({length:10}),()=>{
ListItem(){
Column(){
Text('hello').height(40).width('100%')
.backgroundColor('#ccc').borderRadius(12).padding(6)
}.width('90%').margin({top:5})
}
})
}.listDirection(Axis.Vertical)
.lanes(2) //2列
.width('100%')
.padding(8)
.layoutWeight(1)
}.width('100%')
.height('100%')
.backgroundColor('#ffffff')
}
}
```
#### 便民药品1
```
@Entry
@Component
struct medic {
build() {
Column(){
//标题
Row(){
Text('便民药品').fontSize(20)
.fontWeight(FontWeight.Bold)
}
//商品列表要有一个循环,而且能够向下拖动
List(){ //列表组件 能够向上向下拖动
ForEach(Array.from({length:10}),()=>{
ListItem(){
Column(){
Image($r('app.media.medic01'))
.width('100%')
.borderRadius(8)
//商品信息
Column(){
//第一行 商品名称
Row({space:10}){
Text('布洛芬胶囊').fontSize(12).fontWeight(300)
.maxLines(1)
Text('¥36.78').fontSize(10).fontColor('#ff4d4f')
.fontWeight(FontWeight.Bold)
}
//第一行 评论数量+购物车
Row({space:10}){
Text('3421条评论').fontSize(12)
.fontColor('#999')
Image($r('app.media.gouwu')).width(20).height(20)
.fillColor('#333')
}
}
}.width('90%').margin({top:5})
}
})
}.listDirection(Axis.Vertical)
.lanes(2) //2列
.width('100%')
.padding(8)
.layoutWeight(1)
}.width('100%')
.height('100%')
.backgroundColor('#ffffff')
}
}
```
#### 便民药品2
```ts
//定义药品的接口
interface Medic{
id:number,
image: ResourceStr,
goodname:string,
price: number,
comments:number
}
@Entry
@Component
struct medic {
//声明药品的数据
@State medics: Medic[] = [
{
id: 1,
image: $r('app.media.medic01'),
goodname: '阿莫西林胶囊',
price: 28.5,
comments: 2345
},
{
id: 2,
image: $r('app.media.medic02'),
goodname: '布洛芬缓释胶囊',
price: 15.8,
comments: 1890
},
{
id: 3,
image: $r('app.media.medic03'),
goodname: '维生素C片',
price: 32.0,
comments: 3200
},
{
id: 4,
image: $r('app.media.medic04'),
goodname: '创可贴',
price: 9.9,
comments: 1567
},
{
id: 5,
image: $r('app.media.medic05'),
goodname: '板蓝根颗粒',
price: 18.5,
comments: 2789
},
{
id: 6,
image: $r('app.media.medic06'),
goodname: '感冒灵颗粒',
price: 22.0,
comments: 3456
},
{
id: 7,
image: $r('app.media.medic07'),
goodname: '头孢克肟片',
price: 35.0,
comments: 1234
},
{
id: 8,
image: $r('app.media.medic08'),
goodname: '止咳糖浆',
price: 26.5,
comments: 2100
},
{
id: 9,
image: $r('app.media.medic09'),
goodname: '蒙脱石散',
price: 19.8,
comments: 1678
},
{
id: 10,
image: $r('app.media.medic10'),
goodname: '健胃消食片',
price: 12.5,
comments: 2987
},
{
id: 11,
image: $r('app.media.medic11'),
goodname: '氯雷他定片',
price: 24.0,
comments: 1432
},
{
id: 12,
image: $r('app.media.medic12'),
goodname: '红霉素软膏',
price: 8.5,
comments: 3541
},
{
id: 13,
image: $r('app.media.medic13'),
goodname: '云南白药气雾剂',
price: 68.0,
comments: 987
},
{
id: 14,
image: $r('app.media.medic14'),
goodname: '藿香正气水',
price: 15.0,
comments: 2654
},
{
id: 15,
image: $r('app.media.medic15'),
goodname: '六味地黄丸',
price: 45.0,
comments: 1876
},
{
id: 16,
image: $r('app.media.medic16'),
goodname: '复方丹参滴丸',
price: 38.5,
comments: 1543
},
{
id: 17,
image: $r('app.media.medic17'),
goodname: '葡萄糖酸钙口服液',
price: 42.0,
comments: 2234
},
{
id: 18,
image: $r('app.media.medic18'),
goodname: '维生素B族片',
price: 55.0,
comments: 1765
},
{
id: 19,
image: $r('app.media.medic19'),
goodname: '伊曲康唑胶囊',
price: 88.0,
comments: 654
},
{
id: 20,
image: $r('app.media.medic20'),
goodname: '奥美拉唑肠溶片',
price: 36.0,
comments: 2456
},
{
id: 21,
image: $r('app.media.medic21'),
goodname: '硝酸甘油片',
price: 29.0,
comments: 1321
},
{
id: 22,
image: $r('app.media.medic22'),
goodname: '安眠药片',
price: 56.0,
comments: 998
},
{
id: 23,
image: $r('app.media.medic23'),
goodname: '小儿氨酚黄那敏颗粒',
price: 23.5,
comments: 2876
},
{
id: 24,
image: $r('app.media.medic24'),
goodname: '开塞露',
price: 6.5,
comments: 4123
},
{
id: 25,
image: $r('app.media.medic25'),
goodname: '眼药水',
price: 19.0,
comments: 3450
},
{
id: 26,
image: $r('app.media.medic26'),
goodname: '钙尔奇D片',
price: 128.0,
comments: 789
}
];
build() {
Column(){
//标题
Row(){
Text('便民药品').fontSize(20)
.fontWeight(FontWeight.Bold)
}
//商品列表要有一个循环,而且能够向下拖动
List(){ //列表组件 能够向上向下拖动
//循环的事上面的那个数组
ForEach(this.medics,(medic:Medic)=>{//ForEach(Array.from({length:10}),()=>{
ListItem(){
Column(){
Image(medic.image)
.width('100%')
.borderRadius(8)
//商品信息
Column(){
//第一行 商品名称
Row({space:10}){
Text(medic.goodname).fontSize(16).fontWeight(300)
.maxLines(1)
Text(`¥${medic.price}`).fontSize(10).fontColor('#ff4d4f')
.fontWeight(FontWeight.Bold)
}
//第一行 评论数量+购物车
Row({space:10}){
Text(`${medic.comments}条评论`).fontSize(12)
.fontColor('#999')
Image($r('app.media.gouwu')).width(20).height(20)
.fillColor('#333')
}
}
}.width('90%').margin({top:5})
}
})
}.listDirection(Axis.Vertical)
.lanes(2) //2列
.width('100%')
.padding(8)
.layoutWeight(1)
}.width('100%')
.height('100%')
.backgroundColor('#ffffff')
}
}
```
## 数据库
装
```
Mysql装解压缩的版本,已经放在群里。
安装步骤:
http://blog.csdn.net/Dailyblue/article/details/125027446
数据库链接的终端。用它能很方便的操作数据库。
通过网盘分享的文件:Navicat170.rar
链接: https://pan.baidu.com/s/1acruVrVXrVPElKVcWmAPrg?pwd=ytw8 提取码: ytw8 复制这段内容后打开百度网盘手机App,操作更方便哦
破解要看readme.txt文件
```


```mysql
#不要求你们能写出sql
#但是要求差不多能看懂,能猜懂
drop database syhis; #删除数据库
#创建数据库
create database syhis;
#使用数据库
use syhis;
#创建数据表
create table medic(
id int auto_increment primary key COMMENT '自增id',
goodname varchar(20) comment '药品名称',
price NUMERIC(8,2) comment '价格',
comments int comment '评论数量'
)engine=innodb charset=utf8; #数据库的引擎为innodb 编码字符集为utf8
#查询
select * from medic;
#增加
insert into medic values (null,'敌敌畏',888.88,2000);
#删除数据库的数据
delete from medic;
```
**数据表的最基本的操作**
```sql
####################################################################
#没有重新创建库,使用的还是原来的数据库
#从新创建一张表,重新进行测试
create table test(
tid int auto_increment primary key,
tname varchar(20),
tsex char(2)
)engine=innodb charset=utf8;
#查询
select * from test;
#插入
insert into test values (null,'毛含笑','女');
insert into test values (null,'郑超','女');
insert into test values (null,'张余','男');
insert into test values (null,'李宗伟','女');
#删除
delete from test; #一条不剩
```
## 科室
### 数据表
```sql
#如果你已经存在syhis数据库,那么你就不用再重新创建这个数据库了
use syhis;
#建立一个科室的表
create table dept(
deptid int auto_increment primary key, #科室的id
deptname varchar(20) #科室的名称
)engine=innodb charset=utf8; #引擎和编码字符集
#查询
select * from dept;
truncate dept; #截断表让所有id重头开始
#增加
#增加25个不同科室
insert into dept values (1,'内科');
insert into dept values (2,'外科');
insert into dept values (3,'妇产科');
insert into dept values (4,'儿科');
insert into dept values (5,'眼科');
insert into dept values (6,'耳鼻喉科');
insert into dept values (7,'口腔科');
insert into dept values (8,'皮肤科');
insert into dept values (9,'急诊科');
insert into dept values (10,'中医科');
insert into dept values (11,'骨科');
insert into dept values (12,'神经内科');
insert into dept values (13,'神经外科');
insert into dept values (14,'心血管内科');
insert into dept values (15,'呼吸内科');
insert into dept values (16,'消化内科');
insert into dept values (17,'肾内科');
insert into dept values (18,'内分泌科');
insert into dept values (19,'肿瘤科');
insert into dept values (20,'康复科');
insert into dept values (21,'麻醉科');
insert into dept values (22,'放射科');
insert into dept values (23,'超声科');
insert into dept values (24,'检验科');
insert into dept values (25,'病理科');
```
### 后端
## Idea的安装
**激活**:
运行JetBrains+2025+最新全家桶激活\jetbra-pojie\win2021-2025\scripts\install.vbs文件。双击就行。
然后等待几秒到几十秒,直到出现以下弹框,则表示脚本执行成功。

**3. 打开IDE,输入激活码**
打开你要激活的 IDE。输入对应软件的激活码。 **注意:** 记得初次安装打开 IDE,不要选中任何区域,需要选中不指定区域。

```
ZCB571FZHV-eyJsaWNlbnNlSWQiOiJaQ0I1NzFGWkhWIiwibGljZW5zZWVOYW1lIjoiZnV6emVzIGFsbHkiLCJhc3NpZ25lZU5hbWUiOiIiLCJhc3NpZ25lZUVtYWlsIjoiIiwibGljZW5zZVJlc3RyaWN0aW9uIjoiIiwiY2hlY2tDb25jdXJyZW50VXNlIjpmYWxzZSwicHJvZHVjdHMiOlt7ImNvZGUiOiJQREIiLCJmYWxsYmFja0RhdGUiOiIyMDIzLTA3LTAxIiwicGFpZFVwVG8iOiIyMDIzLTA3LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBTSSIsImZhbGxiYWNrRGF0ZSI6IjIwMjMtMDctMDEiLCJwYWlkVXBUbyI6IjIwMjMtMDctMDEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFBDIiwiZmFsbGJhY2tEYXRlIjoiMjAyMy0wNy0wMSIsInBhaWRVcFRvIjoiMjAyMy0wNy0wMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQQ1dNUCIsImZhbGxiYWNrRGF0ZSI6IjIwMjMtMDctMDEiLCJwYWlkVXBUbyI6IjIwMjMtMDctMDEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFBTIiwiZmFsbGJhY2tEYXRlIjoiMjAyMy0wNy0wMSIsInBhaWRVcFRvIjoiMjAyMy0wNy0wMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQUkIiLCJmYWxsYmFja0RhdGUiOiIyMDIzLTA3LTAxIiwicGFpZFVwVG8iOiIyMDIzLTA3LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IklJIiwiZmFsbGJhY2tEYXRlIjoiMjAyMy0wNy0wMSIsInBhaWRVcFRvIjoiMjAyMy0wNy0wMSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUEdPIiwiZmFsbGJhY2tEYXRlIjoiMjAyMy0wNy0wMSIsInBhaWRVcFRvIjoiMjAyMy0wNy0wMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQU1ciLCJmYWxsYmFja0RhdGUiOiIyMDIzLTA3LTAxIiwicGFpZFVwVG8iOiIyMDIzLTA3LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBXUyIsImZhbGxiYWNrRGF0ZSI6IjIwMjMtMDctMDEiLCJwYWlkVXBUbyI6IjIwMjMtMDctMDEiLCJleHRlbmRlZCI6dHJ1ZX1dLCJtZXRhZGF0YSI6IjAxMjAyMjA3MDFQU0FOMDAwMDA1IiwiaGFzaCI6IlRSSUFMOi01OTQ5ODgxMjIiLCJncmFjZVBlcmlvZERheXMiOjcsImF1dG9Qcm9sb25nYXRlZCI6ZmFsc2UsImlzQXV0b1Byb2xvbmdhdGVkIjpmYWxzZX0=-JNpWl3tvfBw9nYALTrBlJzoryrKHhqmiBxP5IljC6Hlgmb6YlOH8vPngzoyLYa+cGDMVj6fipEpm+BEqIA7oAoBYSu1ZPdzkHAa94apJg+CUQwuw+EJaATdKTANuKYTBsay6WsnrUh8vbIaJpGz19z+uOAc4xRP+gtuyjiwkNECZ6Y9qD+Dx3Gm5xXI3UvKqjPYIhXk23n1pjlxFIUmhD7BumdxF8JHmJJhd/K5FaXQU/K9pMp70GfmSS2KJgxm6SXfslWs/bF5GTY3i1GA6ez05ZyJwsmJMZ1v6W7GWrWNHDLK7i7aXhOLdK9u+pCz+2FpKmadRznpSmixDzj37ig==-MIIETDCCAjSgAwIBAgIBDTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTIwMTAxOTA5MDU1M1oXDTIyMTAyMTA5MDU1M1owHzEdMBsGA1UEAwwUcHJvZDJ5LWZyb20tMjAyMDEwMTkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCUlaUFc1wf+CfY9wzFWEL2euKQ5nswqb57V8QZG7d7RoR6rwYUIXseTOAFq210oMEe++LCjzKDuqwDfsyhgDNTgZBPAaC4vUU2oy+XR+Fq8nBixWIsH668HeOnRK6RRhsr0rJzRB95aZ3EAPzBuQ2qPaNGm17pAX0Rd6MPRgjp75IWwI9eA6aMEdPQEVN7uyOtM5zSsjoj79Lbu1fjShOnQZuJcsV8tqnayeFkNzv2LTOlofU/Tbx502Ro073gGjoeRzNvrynAP03pL486P3KCAyiNPhDs2z8/COMrxRlZW5mfzo0xsK0dQGNH3UoG/9RVwHG4eS8LFpMTR9oetHZBAgMBAAGjgZkwgZYwCQYDVR0TBAIwADAdBgNVHQ4EFgQUJNoRIpb1hUHAk0foMSNM9MCEAv8wSAYDVR0jBEEwP4AUo562SGdCEjZBvW3gubSgUouX8bOhHKQaMBgxFjAUBgNVBAMMDUpldFByb2ZpbGUgQ0GCCQDSbLGDsoN54TATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggIBABqRoNGxAQct9dQUFK8xqhiZaYPd30TlmCmSAaGJ0eBpvkVeqA2jGYhAQRqFiAlFC63JKvWvRZO1iRuWCEfUMkdqQ9VQPXziE/BlsOIgrL6RlJfuFcEZ8TK3syIfIGQZNCxYhLLUuet2HE6LJYPQ5c0jH4kDooRpcVZ4rBxNwddpctUO2te9UU5/FjhioZQsPvd92qOTsV+8Cyl2fvNhNKD1Uu9ff5AkVIQn4JU23ozdB/R5oUlebwaTE6WZNBs+TA/qPj+5/we9NH71WRB0hqUoLI2AKKyiPw++FtN4Su1vsdDlrAzDj9ILjpjJKA1ImuVcG329/WTYIKysZ1CWK3zATg9BeCUPAV1pQy8ToXOq+RSYen6winZ2OO93eyHv2Iw5kbn1dqfBw1BuTE29V2FJKicJSu8iEOpfoafwJISXmz1wnnWL3V/0NxTulfWsXugOoLfv0ZIBP1xH9kmf22jjQ2JiHhQZP7ZDsreRrOeIQ/c4yR8IQvMLfC0WKQqrHu5ZzXTH4NO3CwGWSlTY74kE91zXB5mwWAx1jig+UXYc2w4RkVhy0//lOmVya/PEepuuTTI4+UJwC7qbVlh5zfhj8oTNUXgN0AOc+Q0/WFPl1aw5VV/VrO8FCoB15lFVlpKaQ1Yh+DVU8ke+rt9Th0BCHXe0uZOEmH0nOnH/0onD
```
点击激活。如果激活码不能用,在网上再找一个。
**效果验证**
进入软件查看,已经激活到 2099-12-31 了。

先安装jdk, 再安装idea。
设置maven. (所有公共的资源部的一个仓库),默认idea里面带maven, 但是指向地址是国外。
你拿我的压缩包,解压到D:\tools\apache-maven-3.6.0-bin\apache-maven-3.6.0目录下。

### Maven
设置idea的两个地方:
地方1:
设置

地方2:
为新项目设置

idea的maven配置就好了。
### Idea建立工程
文件----新建---项目
空项目---输入你的项目名称
项目右键---新建---模块
**最关键的一部,一定要选择为maven**
代开pom.xml进行修改
pom.xml
```xml
```yml
server:
port: 8080 #服务的端口号
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/syhis?useUnicode=true&characterEncoding=utf8
username: root
password: ilovelaohan
#spring链接数据库的信息
```
#### 4: 启动扫描包
在启动类上加一个@MapperScan("com.han.syhis.mapper")

#### 5: 先测试一下
#### 6:写控制器类
```java
package com.han.syhis.controller;
import com.han.syhis.entity.Dept;
import com.han.syhis.service.IDeptService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*
* 前端控制器 *
* * @author laohan * @since 2026-06-10 */ @RestController public class DeptController { @Resource private IDeptService deptService; @GetMapping("/dept/findAll") @CrossOrigin //跨域 public List findAll(){ List
```ts
@Entry
@Component
struct dept {
build() {
List(){
ForEach(Array.from({length:20}),()=>{
ListItem(){ //list里面必须而且只能放 ListItem组件
Flex({alignItems:ItemAlign.Center,justifyContent:FlexAlign.SpaceBetween}){
Text('科室名称')
Image($r('app.media.right')).width(30)
}.border({color:'#cccccc',style:BorderStyle.Solid,width:{bottom:1}})
}.padding(10)
})
}.width('100%').layoutWeight(1) //高度自适应
}
}
```
#### Axios远程请求
1:安装axios
```
方法1: ohpm install @ohos/axios
方法2: 根目录下oh-package.json5中添加依赖
"dependencies": {
"@ohos/axios":"^2.27"
}
屏幕的右上方有一个SyncNow,点击,然后就装好了。跟我们昨天Java里面的maven一样的。
```
2: 配置权限
在entry/src/main/module.json5中申请权限
```json
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
```
3:请求
```tsx
import axios,{AxiosResponse} from "@ohos/axios";
//导入远程的请求类
import { get } from "../util/axios";
//导入自定义的包装类
interface Dept{
deptid:number,
deptname:string
}
@Entry
@Component
struct dept {
@State deptList:Array
```tsx
import dayjs, { Dayjs } from "@hview/dayjs";
import {weekDict} from "../util/Entity";
@Entry
@Component
struct empllist {
@State dateList:Array
```tsx
import dayjs, { Dayjs } from "@hview/dayjs";
import {weekDict,Emp} from "../util/Entity";
import {get} from "../util/axios";
@Entry
@Component
struct empllist {
@State dateList:Array
Entity.ts
```
export interface Dept{
deptid:number,
deptname:string
}
export interface weekDict{
week:number,
date:string
}
export interface Emp{
empid: number,
empname: string,
deptid: number,
levelid: number,
levelname: string,
money: number
}
export const timebetween:Array
```tsx
@Entry
@Component
struct my {
build() {
//上下两部分
//上面 左边箭头 个人中心 右边 更多的图标
//下面 个人的详细信息 挂号信息
Column(){
Row(){
Image($r('app.media.ic_arrow_left')).width(30)
Text('个人中心')
Image($r('app.media.ic_more')).width(24)
}.width('100%')
.backgroundColor('#ccc')
.height(40)
.justifyContent(FlexAlign.SpaceBetween)
.padding({left:10,right:10})
Column(){
List({space:15}){
ForEach(Array.from({length:3}),()=>{
ListItem(){
Column(){
Grid(){
GridItem(){Text('就诊人:')}.align(Alignment.Start)
GridItem(){Text('严秋婷')}.align(Alignment.Start)
GridItem(){Text('科室:')}.align(Alignment.Start)
GridItem(){Text('眼科')}.align(Alignment.Start)
GridItem(){Text('年龄:')}.align(Alignment.Start)
GridItem(){Text('21')}.align(Alignment.Start)
GridItem(){Text('医生:')}.align(Alignment.Start)
GridItem(){Text('刘德华')}.align(Alignment.Start)
GridItem(){Text('性别:')}.align(Alignment.Start)
GridItem(){Text('女')}.align(Alignment.Start)
GridItem(){Text('挂号费:')}.align(Alignment.Start)
GridItem(){Text('¥60.00')}.align(Alignment.Start)
GridItem(){Text('时间')}.align(Alignment.Start)
GridItem(){Text('2026-09-09')}.align(Alignment.Start)
GridItem(){Text('时间段')}.align(Alignment.Start)
GridItem(){Text('8.00-9.00')}.align(Alignment.Start)
}.rowsTemplate('1fr 1fr 1fr 1fr')
.columnsTemplate('2fr 3fr 2fr 3fr')
.width('90%').height(120)
.margin({top:5,left:10})
}
}
.border({color:'#ccc',width:{bottom:1}})
})
}
}.backgroundColor(Color.White).width('100%').height('100%')
.backgroundColor('#eeeeee')
}.width('100%')
.height('100%')
.backgroundColor('#ccc')
.expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])
}
}
```
数据库
后端
## 鸿蒙技术点
### Tab导航
最简单的
```
@Entry
@Component
struct tab {
build() {
Tabs({barPosition:BarPosition.End}){//不写属性,默认出现在顶端
TabContent(){Text('商品内容')}.tabBar("商品")
TabContent(){Text('购物车内容')}.tabBar("购物车")
TabContent(){Text('AI')}.tabBar("AI")
TabContent(){Text('消息内容')}.tabBar("消息")
TabContent(){Text('我的信息')}.tabBar("我的")
}
}
}
```
第二步
```
@Entry
@Component
struct tab {
@Builder
mybuilder(title:string){ //相当于一个自定义组件
Text(title)
}
build() {
Tabs({barPosition:BarPosition.End}){//不写属性,默认出现在顶端
TabContent(){Text('商品内容')}.tabBar(this.mybuilder('挂号'))
TabContent(){Text('购物车内容')}.tabBar(this.mybuilder('药品'))
TabContent(){Text('AI')}.tabBar("AI")
TabContent(){Text('消息内容')}.tabBar(this.mybuilder('购物车'))
TabContent(){Text('我的信息')}.tabBar(this.mybuilder('我的'))
}
}
}
```
第三步
```
@Entry
@Component
struct tab {
@State index:number = 0
@Builder
mybuilder(index:number,title:string,img:ResourceStr){ //相当于一个自定义组件
Column(){
if(title=="AI"){
Image(img).width(40)
}else{
Image(img).width(30)
.fillColor(this.index==index?Color.Black:Color.Pink)
Text(title)
}
}
}
build() {
Tabs({barPosition:BarPosition.End}){//不写属性,默认出现在顶端
TabContent(){Text('商品内容')}.tabBar(this.mybuilder(0,'挂号',$r('app.media.guahao')))
TabContent(){Text('购物车内容')}.tabBar(this.mybuilder(1,'药品',$r('app.media.mdeic')))
TabContent(){Text('AI')}.tabBar(this.mybuilder(2,'AI',$r('app.media.AI')))
TabContent(){Text('消息内容')}.tabBar(this.mybuilder(3,'购物车',$r('app.media.gouwu')))
TabContent(){Text('我的信息')}.tabBar(this.mybuilder(4,'我的',$r('app.media.wode')))
}.onSelected((index:number)=>{
console.log('你选中了',index);
this.index = index;
})
}
}
```
### 整合整个页面
```
需要把你的每个在导航栏中出现的组件前面都要写成 export 进行导出。改了4个文件。
my.ets
export struct my
medic.ets
export struct medic
dept.ets
export struct dept
carts.ets
export struct carts
```
```
import { my } from "../pages/my";
import { carts } from "../pages/carts";
import { medic } from "../pages/medic";
import { dept } from "../pages/dept";
@Entry
@Component
struct tab {
@State index:number = 0
@Builder
mybuilder(index:number,title:string,img:ResourceStr){ //相当于一个自定义组件
Column(){
if(title=="AI"){
Image(img).width(40)
}else{
Image(img).width(30)
.fillColor(this.index==index?Color.Black:Color.Pink)
Text(title)
}
}
}
build() {
Tabs({barPosition:BarPosition.End}){//不写属性,默认出现在顶端
TabContent(){dept()}.tabBar(this.mybuilder(0,'挂号',$r('app.media.guahao')))
TabContent(){medic()}.tabBar(this.mybuilder(1,'药品',$r('app.media.mdeic')))
TabContent(){Text('AI')}.tabBar(this.mybuilder(2,'AI',$r('app.media.AI')))
TabContent(){carts()}.tabBar(this.mybuilder(3,'购物车',$r('app.media.gouwu')))
TabContent(){my()}.tabBar(this.mybuilder(4,'我的',$r('app.media.wode')))
}.onSelected((index:number)=>{
console.log('你选中了',index);
this.index = index;
})
}
}
```
这个代码还有一个bug,等待下周解决,因为代码要完全组件化开发。
### 自定义组件
组件:框架直接提供的就是系统组件,我们自己写的,想通用的就是自定义组件。
```
@Entry //一个模块的入口
@Component //就是一个组件
struct Hello{
//往往正式项目,只有一个ets文件有@Entry。其他的文件,都是组件,它只有@Component
//@Component不能单独,独立显示,必须依赖于入口
}
```
第一个定义组件
```
@Entry
@Component
struct testComp1 {
build() {
Column(){
Text('我是入口')
Text('我是入口')
Text('我是入口')
Comp1()
Comp1()
Comp1()
}
}
}
//自定义组件
// 跟你的入口文件张的一抹一眼,就是没有@Entry
@Component
struct Comp1{
build() {
Column(){
Text('我是一个组件')
Text('我是一个组件')
Text('我是一个组件')
}
}
}
```
自定义头中尾
```
@Entry
@Component
struct testComp1 {
build() {
Column(){
MyHead()
MyMain()
MyFoot()
}
}
}
//自定义组件
// 跟你的入口文件张的一抹一眼,就是没有@Entry
@Component
struct MyHead{
build() {
Row(){
Text('我是头部').height(50).backgroundColor(Color.Brown).width('100%')
}
}
}
@Component
struct MyMain{
build() {
Column(){
Text('我是中间的部分')
Text('我是中间的部分')
Text('我是中间的部分')
}.backgroundColor('#ccc').width('100%')
.layoutWeight(1)
}
}
@Component
struct MyFoot{
build() {
Row(){
Text('我是低部').height(50).backgroundColor(Color.Green).width('100%')
}
}
}
```
### 组件间的传参
A组件的参数,如何传递给B组件,如何再传递给C组件。
@Prop
@Link
@Provide
@Consume
```
@Prop @Link 只能父子组件直接传参,直接是直接,不能隔代。必须是父子父子直接嵌套,中间不能隔其他组件。而且必须手工传参。
这个代码写起来笔记麻烦。因为要手工。子组件不能改父组件的值。
参数,我想只存在于父子之间。不想参数的范围太广。
@Prop是单向的,@Link是双向的。 都不能跨代。
@Privde @Consume 跨多层传参(爷爷---》儿子----》孙子----》曾孙),无需逐层传递,支持任意层级。 中间组件完全不用管。
后者自动注入。
爷爷---》儿子----》孙子----》曾孙
放 取
写法简单,方便,但是参数的范围大。子组件可以改父组件的值。
```
@Prop
```tsx
@Entry
@Component
struct FatherComp {
//父组件定义一个变量
@State fcar:string = '劳斯莱斯'
build() {
Column(){
Text('孩他爹有的车'+this.fcar)
Button('他爹的按钮').onClick(()=>{
//改变自己的车的值
this.fcar = '兰博基尼'
//父组件的值改变,同时也会改变子组件的值
})
SonComp({
scar:this.fcar //把父组件的值给了子组件
}) //手工传入,子组件才会有这个参数
}.backgroundColor(Color.Orange)
}
}
@Component
struct SonComp{
//子组件来接受父组件传递的参数
@Prop scar:string='' //@Prop就是接受父组件传过来的参数
//只要加上@Prop就可以得到父组件的参数
build() {
Column(){
Text('我是子组件,父类的车是'+this.scar)
Button('他娃的按钮').onClick(()=>{
this.scar = '三轮车'
//更改子组件的参数
})
}.backgroundColor(Color.Pink)
}
}
```
@Link
prop只能实现单向同步,只能父传子,但是@Link可以实现双向同步。父--子---父
使用步骤:
将父组件的状态属性传递给子组件
子组件通过@Link修饰就可以了
```
把上面的代码//子组件来接受父组件传递的参数
@Link scar:string 只改这一句话,就已经能实现双向传参了。
```
```tsx
interface Person{
name:string,
age:number
}
@Entry
@Component
struct FatherComp {
@State count:number = 0;
@State person:Person = {
name:'潘凤',
age : 18
}
build() {
Column(){
Text('父组件'+this.count)
Text(JSON.stringify(this.person))
Button('add').onClick(()=>{
this.count++
})
SonComp({
count:this.count,
person:this.person
}) //手工传入,子组件才会有这个参数
}.backgroundColor(Color.Orange)
}
}
@Component
struct SonComp{
//子组件来接受父组件传递的参数
@Link count:number
@Link person:Person
//只要加上@Prop就可以得到父组件的参数
build() {
Column(){
Text('我是子组件'+this.count)
Text(JSON.stringify(this.person))
Button('--').onClick(()=>{
this.count--
})
}.backgroundColor(Color.Pink)
}
}
```
@Provider @Consume
两个一般会成对出现,可以跨级。@Provider向后传参,@Consume从上一级,上几级接受参数。
跨级双向同步。
```
@Entry
@Component
struct F {
@Provide count:number = 0;
build() {
Column(){
Text('父组件'+this.count)
Button('父组件按钮').onClick(()=>{
this.count++
})
C()
}.backgroundColor(Color.Pink)
}
}
@Component
struct C{
@Consume count:number; //父组件不用额外传参,子组件不用额外接受参数
build() {
Column(){
Text('子组件'+this.count)
Button('子组件按钮').onClick(()=>{
this.count++
})
S()
}.backgroundColor(Color.Yellow)
}
}
@Component
struct S{
@Consume count:number; //父组件不用额外传参,子组件不用额外接受参数
build() {
Column(){
Text('孙组件'+this.count)
Button('孙组件按钮').onClick(()=>{
this.count++
})
}.backgroundColor(Color.Green)
}
}
```
## 生命周期
理解就好了。概念。
组件也页面在创建显示销毁的整个过程,会自动执行一系列的【生命周期钩子函数】,系统会自动调用的函数。
他能自动执行一些代码
```
仅仅@Entry修饰页面组件
onPageShow: 页面每次显示的时候都会触发
onPageHide: 页面每次隐藏触发。
OnBackPress:点击返回按钮的时候触发。
@Entry和@Component都有的:
aboutToAppear: 创建组件后就执行,可以修改状态变量
aboutToDispear: 组件实例销户前执行,不允许修改状态变量
```
```tsx
@Entry
@Component
struct testlife {
aboutToAppear(): void {
//查询后端数据
console.log('aboutToAppear method be called');
}
aboutToDisappear(): void {
//想销毁数据的时候
console.log('aboutToDisappear method be called');
}
onPageShow(): void {
//对页面数据进行渲染的
console.log('onPageShow method be called');
}
onPageHide(): void {
//保存会话,然后断开,后续再用
console.log('onPageHide method be called');
}
onBackPress(): boolean | void {
//你按下上一步按钮的
console.log('onBackPress method be called');
}
build() {
Column(){
Button("你看我不见")
}
}
}
```
## 登录链接
按下登录按钮就跳转到了具体的tab页面。
```
index.ets文件
import { router } from "@kit.ArkUI";
Button('登录').width('100%').onClick(()=>{
console.log('登录');
router.pushUrl({
url:'pages/tab'
})
})
main_page.json
{
"src": [
"pages/Index",
"pages/dept",
"pages/emplist",
"pages/empitem",
"pages/tab"
]
}
```
## 注册
给患者使用的。关于医生管理,科室管理,挂号管理,时间段管理,这些都是后台。本次项目中就不体现了。
### 鸿蒙静态界面
```tsx
@Entry
@Component
struct register {
build() {
Column(){
Text('注册新用户').fontSize(30).fontWeight(700)
Text('石油医院挂号系统不会泄露您的隐私信息')
.fontColor('#ff9188e').margin({top:10})
//网上见到的,往往是你输入完手机号之后,对方会给你发一个验证密码
//你验证码输入正确,才代表这个手机号是你的
//取回密码,也是通过手机发验证码来验证的
//如果通过代码,给对方手机发验证码
//阿里云市场
TextInput({placeholder:'请输入手机号'}).height(50)
.margin({top:30})
TextInput({placeholder:'请输入密码'}).height(50)
.margin({top:30})
.type(InputType.Password)
TextInput({placeholder:'请输入姓名'}).height(50)
.margin({top:30})
TextInput({placeholder:'请输入身份证号'}).height(50)
.margin({top:30})
Row({space:20}){
Radio({value:'男',group:'sexgroup'}).checked(true)
Text('男').fontSize(20).margin({right:20})
Radio({value:'女',group:'sexgroup'})
Text('女').fontSize(20).margin({right:20})
}.height(50).width('100%')
.margin({top:20}).justifyContent(FlexAlign.Center)
Button('注册')
.width('85%').height(60).margin({top:30})
.shadow({radius:10,color:'#000000'})
}.width('100%')
.alignItems(HorizontalAlign.Center)
.padding({top:30})
}
}
```
界面已经能够显示出来了,但是我将来得把这个页面上的数据,收集,封装,传递给后端,进行注册。
收集页面数据
在你的utils/Entity.ts文件中新加入如下代码
```json
//封装了你将来要获取的页面数据
export interface Userinfo
{
userid?: number, //加?代表的意思是这个值可以有,也可以没有 如果不加?那么这个值必须存在
phone?:string,
password?:string,
username?:string,
idcard?:string,
gender?:string
}
```
我们就可以在鸿蒙的前端页面中使用这个数据了
```tsx
import {Userinfo} from "../util/Entity";
@Entry
@Component
struct register {
@State userinfo: Userinfo = {
gender:'男'
}
build() {
Column(){
Text('注册新用户').fontSize(30).fontWeight(700)
Text('石油医院挂号系统不会泄露您的隐私信息')
.fontColor('#ff9188e').margin({top:10})
//网上见到的,往往是你输入完手机号之后,对方会给你发一个验证密码
//你验证码输入正确,才代表这个手机号是你的
//取回密码,也是通过手机发验证码来验证的
//如果通过代码,给对方手机发验证码
//阿里云市场
TextInput({placeholder:'请输入手机号'}).height(50)
.margin({top:30})
.onChange((value) => {
this.userinfo.phone = value
})
TextInput({placeholder:'请输入密码'}).height(50)
.margin({top:30})
.type(InputType.Password)
.onChange((value) => {
this.userinfo.password = value
})
TextInput({placeholder:'请输入姓名'}).height(50)
.margin({top:30})
.onChange((value) => {
this.userinfo.username = value
})
TextInput({placeholder:'请输入身份证号'}).height(50)
.margin({top:30})
.onChange((value) => {
this.userinfo.idcard = value
})
Row({space:20}){
Radio({value:'男',group:'sexgroup'}).checked(true)
.onChange((isChecked:boolean) => {
if(isChecked){
this.userinfo.gender = '男'
}
})
Text('男').fontSize(20).margin({right:20})
Radio({value:'女',group:'sexgroup'})
.onChange((isChecked:boolean) => {
if(isChecked){
this.userinfo.gender = '女'
}
})
Text('女').fontSize(20).margin({right:20})
}.height(50).width('100%')
.margin({top:20}).justifyContent(FlexAlign.Center)
Button('注册')
.width('85%').height(60).margin({top:30})
.shadow({radius:10,color:'#000000'})
.onClick(()=>{
console.log(JSON.stringify(this.userinfo));
})
}.width('100%')
.alignItems(HorizontalAlign.Center)
.padding({top:30})
}
}
```
### 数据表
```mysql
create table if not EXISTS userinfo
(
userid int auto_increment primary key, #主键id
phone VARCHAR(20), #电话
password varchar(32), #密码
username varchar(30), #用户的真实姓名
idcard varchar(20), #身份证号
gender char(2) #性别
)engine=innodb charset=utf8;
```
### 后端部分
先利用CodeGenerate生成关于userinfo的所有代码。
```java
package com.han.syhis.controller;
import com.han.syhis.entity.Userinfo;
import com.han.syhis.service.IUserinfoService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
/**
* * 前端控制器 *
* * @author laohan * @since 2026-06-15 */ @RestController public class UserinfoController { @Resource private IUserinfoService userinfoService; //注册 @PostMapping("/register") @CrossOrigin public boolean register(@RequestBody Userinfo info){ return userinfoService.save(info); } } ``` ### 鸿蒙调用后端
```typescript
import {Userinfo} from "../util/Entity";
import {post} from "../util/axios";
@Entry
@Component
struct register {
@State userinfo: Userinfo = {
gender:'男'
}
build() {
Column(){
Text('注册新用户').fontSize(30).fontWeight(700)
Text('石油医院挂号系统不会泄露您的隐私信息')
.fontColor('#ff9188e').margin({top:10})
//网上见到的,往往是你输入完手机号之后,对方会给你发一个验证密码
//你验证码输入正确,才代表这个手机号是你的
//取回密码,也是通过手机发验证码来验证的
//如果通过代码,给对方手机发验证码
//阿里云市场
TextInput({placeholder:'请输入手机号'}).height(50)
.margin({top:30})
.onChange((value) => {
this.userinfo.phone = value
})
TextInput({placeholder:'请输入密码'}).height(50)
.margin({top:30})
.type(InputType.Password)
.onChange((value) => {
this.userinfo.password = value
})
TextInput({placeholder:'请输入姓名'}).height(50)
.margin({top:30})
.onChange((value) => {
this.userinfo.username = value
})
TextInput({placeholder:'请输入身份证号'}).height(50)
.margin({top:30})
.onChange((value) => {
this.userinfo.idcard = value
})
Row({space:20}){
Radio({value:'男',group:'sexgroup'}).checked(true)
.onChange((isChecked:boolean) => {
if(isChecked){
this.userinfo.gender = '男'
}
})
Text('男').fontSize(20).margin({right:20})
Radio({value:'女',group:'sexgroup'})
.onChange((isChecked:boolean) => {
if(isChecked){
this.userinfo.gender = '女'
}
})
Text('女').fontSize(20).margin({right:20})
}.height(50).width('100%')
.margin({top:20}).justifyContent(FlexAlign.Center)
Button('注册')
.width('85%').height(60).margin({top:30})
.shadow({radius:10,color:'#000000'})
.onClick(()=>{
console.log(JSON.stringify(this.userinfo));
post('/register',this.userinfo,(content:Boolean)=>{
console.log('注册成功');
})
})
}.width('100%')
.alignItems(HorizontalAlign.Center)
.padding({top:30})
}
}
```
### 密码加密
现在的密码是明文。111.数据库泄漏后,所有人都会知道你们的密码。
希望哪怕是数据库管理员,能够看到你的密文,但是根据你的密文,也推不出来你的明文密码。
加密:使用一些不可逆的加密算法,算出来的一个密文。
比如: 密码111111 密文:给你的密码按照位数*10%3取余数 8976532 可逆的。
不可逆:密码给你,你无法通过密码的密文推出明文密码。
#### 测试加密
1:在java项目中的pom.xml中新加入一个坐标,导入新的加密工具包。
```xml
* 前端控制器 *
* * @author laohan * @since 2026-06-15 */ @RestController public class UserinfoController { @Resource private IUserinfoService userinfoService; //注册 @PostMapping("/register") @CrossOrigin public boolean register(@RequestBody Userinfo info){ //这个是昨天的注册,直接明文存储了密码 // return userinfoService.save(info); //下面是今天进行加密的代码 String password = info.getPassword();//取出用户输入的密码 password = DigestUtil.md5Hex( password);//对用户输入的密码进行加密 info.setPassword(password);//把这个加密后的password再放入对象 return userinfoService.save(info); } } ``` 继续访问你昨天的注册代码,那么发现数据库中密码已经存储为密文。 修改鸿蒙的界面 1:resources/profile/main_page.json ``` { "src": [ "pages/Index", "pages/dept", "pages/emplist", "pages/empitem", "pages/tab", "pages/register" ] } ``` 2: 修改注册页面 ```typescript import {Userinfo} from "../util/Entity"; import {post} from "../util/axios"; import { router } from "@kit.ArkUI"; @Entry @Component struct register { @State userinfo: Userinfo = { gender:'男' } build() { Column(){ Text('注册新用户').fontSize(30).fontWeight(700) Text('石油医院挂号系统不会泄露您的隐私信息') .fontColor('#ff9188e').margin({top:10}) //网上见到的,往往是你输入完手机号之后,对方会给你发一个验证密码 //你验证码输入正确,才代表这个手机号是你的 //取回密码,也是通过手机发验证码来验证的 //如果通过代码,给对方手机发验证码 //阿里云市场 TextInput({placeholder:'请输入手机号'}).height(50) .margin({top:30}) .onChange((value) => { this.userinfo.phone = value }) TextInput({placeholder:'请输入密码'}).height(50) .margin({top:30}) .type(InputType.Password) .onChange((value) => { this.userinfo.password = value }) TextInput({placeholder:'请输入姓名'}).height(50) .margin({top:30}) .onChange((value) => { this.userinfo.username = value }) TextInput({placeholder:'请输入身份证号'}).height(50) .margin({top:30}) .onChange((value) => { this.userinfo.idcard = value }) Row({space:20}){ Radio({value:'男',group:'sexgroup'}).checked(true) .onChange((isChecked:boolean) => { if(isChecked){ this.userinfo.gender = '男' } }) Text('男').fontSize(20).margin({right:20}) Radio({value:'女',group:'sexgroup'}) .onChange((isChecked:boolean) => { if(isChecked){ this.userinfo.gender = '女' } }) Text('女').fontSize(20).margin({right:20}) }.height(50).width('100%') .margin({top:20}).justifyContent(FlexAlign.Center) Button('注册') .width('85%').height(60).margin({top:30}) .shadow({radius:10,color:'#000000'}) .onClick(()=>{ console.log(JSON.stringify(this.userinfo)); const uiContext = this.getUIContext(); post('/register',this.userinfo,(content:Boolean)=>{ console.log('注册成功'); uiContext.getPromptAction().showToast({ message:'注册用户成功', duration:2000 //2秒钟之后,弹框自动消失 }) //延时两秒后自动跳转到登录页面 setTimeout(()=>{ console.log('准备跳转页面'); router.pushUrl({ url: 'pages/Index' }) },2000) }) }) }.width('100%') .alignItems(HorizontalAlign.Center) .padding({top:30}) } } ``` ## 登录 ### 后端 项目下Controller/UserinfoController这个类 ```java package com.han.syhis.controller; import cn.hutool.crypto.digest.DigestUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.han.syhis.entity.Userinfo; import com.han.syhis.service.IUserinfoService; import jakarta.annotation.Resource; import org.apache.catalina.User; import org.springframework.web.bind.annotation.*; /** ** 前端控制器 *
* * @author laohan * @since 2026-06-15 */ @RestController public class UserinfoController { @Resource private IUserinfoService userinfoService; //登录 这段代码是新增加 @PostMapping("/login") public Userinfo login(@RequestBody Userinfo info){//存储的事手机号和密码 //需要把用户输入的密码进行加密,才能和数据库做对比 String password = info.getPassword();//取出用户输入的密码 password = DigestUtil.md5Hex( password);//对用户输入的密码进行加密 info.setPassword(password);//把这个加密后的password再放入对象 QueryWrapper
修改的事index.ets文件
```typescript
import { router } from "@kit.ArkUI";
import { post } from "../util/axios";
import {Userinfo} from "../util/Entity";
@Entry
@Component
struct Index {
@State userinfo:Userinfo = {
phone:'',
password:'',
}
build() {
Column({space:15}){
Image($r('app.media.huawei')).width(60)
Text('石油医院挂号系统').fontSize(28).fontWeight(900)
.margin({bottom:80})
TextInput({
placeholder:'请输入手机号'
}).onChange((value)=>{
this.userinfo.phone = value
})
TextInput({
placeholder:'请输入密码'
}).onChange((value)=>{
this.userinfo.password = value
}).type(InputType.Password)
Button('登录').width('100%').onClick(()=>{
console.log('开始登录');
//1:用户名密码不正确 提示
//2:用户密码正确 跳转页面
const uiContext = this.getUIContext();
post('login',this.userinfo,(content:Userinfo)=>{
if(content.userid!=null){
console.log('登陆成功');
uiContext.getPromptAction().showToast({
message: '登录成功,即将跳转到首页',
duration: 2000
})
setTimeout(()=>{
router.pushUrl({
url:'pages/tab'
})
},2000)
}else{
console.log('登录失败');
uiContext.showAlertDialog({
message: '用户名或密码错误,请重新输入'
})
}
})
})
Row(){
Image($r('app.media.zfb_tab_me')).width(20)
.fillColor(Color.Red).margin({right:10})
Text('前往注册')
.margin({right:50})
.onClick(()=>{
router.pushUrl({
url:'pages/register'
})
})
Image($r('app.media.ic_more')).width(20)
.fillColor(Color.Green)
Text('忘记密码').margin({left:10})
}
}.padding(20)
.width('100%').height('100%')
.alignItems(HorizontalAlign.Center) //最左边
.justifyContent(FlexAlign.Center) // 中间
}
}
```
### @AppStorage
@Provider @Consumer @Prop @Link 都能够实现传参。跨组件传参。
@AppStorage是全局的UI状态管理中心。简单来说就是一个单例对象,他在项目中维系了一个实例。能够实现跨多个文件,多也页面,多个组件中共享变量的问题。一般用它来做存储的登录信息。放在内存中全局共享。可以和PersisterentStrorage进行配合,能够完成持久化。帮祝你完成记住用户名和密码的功能。
#### 1:存储信息
```
AppStorage.seteOrCreate(key,value)
能够把数据存储起来,全局性质的,供你今后在其他地方使用
```
在Index.ets文件中,登录成功之后的代码里面加了这么一句话
```typescript
AppStorage.setOrCreate('userinfo',content);
```
在整个项目的生命周期中,都可以取到这个存储起来元素。
#### 2:取信息
在你的项目的任何地方,的任何代码里。都可以直接获取存储的元素。
```typescript
@StrorageLink('userinfo') userinfo:Userinfo = {} as Userinfo
```
我们就获取到,是那个登录的用户信息。
在my.ets文件中进行测试
```typescript
import {Userinfo} from "../util/Entity";
@Entry
@Component
export struct my {
@StorageLink("userinfo") userinfo:Userinfo = {} as Userinfo
aboutToAppear(): void {
console.log('当前登录的用户是:'+this.userinfo.userid+" "+this.userinfo.phone);
}
build() {
//上下两部分
//上面 左边箭头 个人中心 右边 更多的图标
//下面 个人的详细信息 挂号信息
Column(){
Row(){
Image($r('app.media.ic_arrow_left')).width(30)
Text('个人中心')
Image($r('app.media.ic_more')).width(24)
}.width('100%')
.backgroundColor('#ccc')
.height(40)
.justifyContent(FlexAlign.SpaceBetween)
.padding({left:10,right:10})
Column(){
List({space:15}){
ForEach(Array.from({length:3}),()=>{
ListItem(){
Column(){
Grid(){
GridItem(){Text('就诊人:')}.align(Alignment.Start)
GridItem(){Text('严秋婷')}.align(Alignment.Start)
GridItem(){Text('科室:')}.align(Alignment.Start)
GridItem(){Text('眼科')}.align(Alignment.Start)
GridItem(){Text('年龄:')}.align(Alignment.Start)
GridItem(){Text('21')}.align(Alignment.Start)
GridItem(){Text('医生:')}.align(Alignment.Start)
GridItem(){Text('刘德华')}.align(Alignment.Start)
GridItem(){Text('性别:')}.align(Alignment.Start)
GridItem(){Text('女')}.align(Alignment.Start)
GridItem(){Text('挂号费:')}.align(Alignment.Start)
GridItem(){Text('¥60.00')}.align(Alignment.Start)
GridItem(){Text('时间')}.align(Alignment.Start)
GridItem(){Text('2026-09-09')}.align(Alignment.Start)
GridItem(){Text('时间段')}.align(Alignment.Start)
GridItem(){Text('8.00-9.00')}.align(Alignment.Start)
}.rowsTemplate('1fr 1fr 1fr 1fr')
.columnsTemplate('2fr 3fr 2fr 3fr')
.width('90%').height(120)
.margin({top:5,left:10})
}
}
.border({color:'#ccc',width:{bottom:1}})
})
}
}.backgroundColor(Color.White).width('100%').height('100%')
.backgroundColor('#eeeeee')
}.width('100%')
.height('100%')
.backgroundColor('#ccc')
.expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])
}
}
```
## 导航栈
1:api画了一个横线,代表就是API过时了。
2:router.putshUrl 跳转,整个页面进行跳转,而不是组件间进行跳转
3:HarmonyOS Next版本中,推荐使用导航栈,而不是router.putshUrl
### 基础的导航栈讲解
AStack.ets
```typescript
import { BStack } from "./BStack";
import { CStack } from "./CStack";
export interface PageParam{
deptid?:number
}
@Entry
@Component
struct AStack {
//在A点击去B,在B里面点击去C
//router.pushUrl还需要把页面写在main_page.json中。
//而导航栈不用这个操作,而是全部写在程序的入口页面
//创建一个导航栈,并通过@Provider提供给子组件使用
//1:声明导航栈
@Provide("pathStack") pageStack:NavPathStack = new NavPathStack();
build() {
//使用Navigation作为根容器
//2:把页面所有内容放入导航容器
Navigation(this.pageStack){
Column(){//如果你要采用导航栈,根节点不能是Colun,而必须是导航栈作为根节点
Text('这是A页面')
Button('我要去B').onClick(()=>{
//把B页面压入导航栈
//声明一个对象作为参数传递给下一个页面
const params:PageParam = {deptid:1}
//第二个参数就是你要传递的参数
this.pageStack.pushPathByName('BStack',params)
})
}
}.mode(NavigationMode.Stack)
.navDestination(this.PageMap)
}
//3:构造所有页面导航栈的规则
@Builder
PageMap(name:string){
if(name=='BStack'){
BStack();
}else if (name=='CStack') {
CStack()
}
}
}
```
BStack.ets
```typescript
import { PageParam } from "./AStack";
@Component
export struct BStack {
//在A点击去B,在B里面点击去C
//router.pushUrl还需要把页面写在main_page.json中。
//而导航栈不用这个操作,而是全部写在程序的入口页面
//接收导航栈
@Consume("pathStack") pathStack:NavPathStack; //这个值是从父组件来的
aboutToAppear(): void {
//准备接受参数
const param = this.pathStack.getParamByName("BStack")[0] as PageParam
console.log('接收到参数'+param.deptid);
}
build() {
NavDestination(){
Column(){
Text('这是B页面')
Button('我要去C').onClick(()=>{
this.pathStack.pushPathByName('CStack',null);
})
}.width('100%')
}.hideTitleBar( true)
}
}
```
CStack.ets
```typescript
@Component
export struct CStack {
//在A点击去B,在B里面点击去C
//router.pushUrl还需要把页面写在main_page.json中。
//而导航栈不用这个操作,而是全部写在程序的入口页面
build() {
NavDestination(){
Column(){
Text('这是C页面')
}
}
}
}
```
### 部门,医生, 医生详情改成导航栈
我需要改三个页面 dept.ets emplist.ets empitem.ets文件。
1:dept.ets
```
1:声明导航栈
2:把跟节点容器放入Navigateion跟容器
3:声明导航规则
```
```typescript
import axios,{AxiosResponse} from "@ohos/axios";
//导入远程的请求类
import { get } from "../util/axios";
//导入自定义的包装类
import {Dept} from "../util/Entity";
import { router } from "@kit.ArkUI";
import {emplist} from "./emplist";
import {empitem} from "./empitem";
export interface PageParams{
deptid?:number,
doctorid?:number
}
@Component
export struct dept {
//声明创建一个导航栈
@Provide("pathStack") pageStack:NavPathStack = new NavPathStack();
@State deptList:Array
### 后端
EmpMapper.java
```java
package com.han.syhis.mapper;
import com.han.syhis.entity.Emp;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* * Mapper 接口 *
* * @author laohan * @since 2026-06-11 */ @Mapper public interface EmpMapper extends BaseMapper* 前端控制器 *
* * @author laohan * @since 2026-06-11 */ @RestController public class EmpController { @Resource private IEmpService empService; @GetMapping("/emp/findByDeptid") @CrossOrigin public List findAll(@RequestParam("deptid") Integer deptid){ return empService.findByDeptid(deptid); } @Resource private EmpMapper empMapper; @GetMapping("/emp/findByempid") @CrossOrigin public Emp empid(@RequestParam("empid") Integer empid){ return empMapper.findByempid(empid); } } ``` ``` http://localhost:8080/emp/findByempid?empid=2 测试地址 ``` ### 前端 entity.ts ``` //封装了你将来要获取的页面数据 export interface Checkin { checkinid?:number, deptid?:number, //#号挂在那个部门下 empid?:number, //#号挂在那个医生下 userid?:number, //#谁挂的号 money?:number, //#挂号费 checkdate?:string, checktime?:string } export interface Userinfo { userid?: number, //加?代表的意思是这个值可以有,也可以没有 如果不加?那么这个值必须存在 phone?:string, password?:string, username?:string, idcard?:string, gender?:string } export interface Dept{ deptid:number, deptname:string } export interface weekDict{ week:number, date:string, alldate:string } export interface Emp{ empid?: number, empname?: string, deptid?: number, levelid?: number, levelname?: string, money?: number } export const timebetween:Array* 前端控制器 *
* * @author laohan * @since 2026-06-17 */ @RestController public class CheckinController { @Resource private ICheckinService checkinService; @PostMapping("/checkin") @CrossOrigin public boolean checkin(@RequestBody Checkin checkin){ return checkinService.save(checkin); } } ``` ### 前端
Entity.ts
```json
//封装了你将来要获取的页面数据
export interface Checkin
{
checkinid?:number,
deptid?:number, //#号挂在那个部门下
empid?:number, //#号挂在那个医生下
userid?:number, //#谁挂的号
money?:number, //#挂号费
checkdate?:string,
checktime?:string
}
export interface Userinfo
{
userid?: number, //加?代表的意思是这个值可以有,也可以没有 如果不加?那么这个值必须存在
phone?:string,
password?:string,
username?:string,
idcard?:string,
gender?:string
}
export interface Dept{
deptid:number,
deptname:string
}
export interface weekDict{
week:number,
date:string,
alldate:string
}
export interface Emp{
empid?: number,
empname?: string,
deptid?: number,
levelid?: number,
levelname?: string,
money?: number
}
export const timebetween:Array* Mapper 接口 *
* * @author laohan * @since 2026-06-17 */ @Mapper public interface CheckinMapper extends BaseMapper* *
* * @author laohan * @since 2026-06-17 */ @Getter @Setter public class Checkin implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "checkinid", type = IdType.AUTO) private Integer checkinid; @Override public String toString() { return "Checkin{" + "checkinid=" + checkinid + ", deptid=" + deptid + ", empid=" + empid + ", userid=" + userid + ", money=" + money + ", checkdate=" + checkdate + ", checktime='" + checktime + '\'' + '}'; } private Integer deptid; private Integer empid; private Integer userid; private BigDecimal money; private LocalDate checkdate; private String checktime; //如下4个是新增的 private String gender; private String username; private String empname; private String deptname; } ``` CheckinControll.java ```java package com.han.syhis.controller; import com.han.syhis.entity.Checkin; import com.han.syhis.mapper.CheckinMapper; import com.han.syhis.service.ICheckinService; import jakarta.annotation.Resource; import org.springframework.web.bind.annotation.*; import java.util.List; /** ** 前端控制器 *
* * @author laohan * @since 2026-06-17 */ @RestController public class CheckinController { @Resource private ICheckinService checkinService; @PostMapping("/checkin") @CrossOrigin public boolean checkin(@RequestBody Checkin checkin){ System.out.println("获取到前端的数据 "+checkin); return checkinService.save(checkin); } //看我自己的挂号 @Resource private CheckinMapper checkinMapper; @GetMapping("/checkin/findByUserid") public List
Entity.ts
```
//封装了你将来要获取的页面数据
export interface Checkin
{
checkinid?:number,
deptid?:number, //#号挂在那个部门下
empid?:number, //#号挂在那个医生下
userid?:number, //#谁挂的号
money?:number, //#挂号费
checkdate?:string,
checktime?:string
gender?:string //新增的字段
username?:string //新增的字段
empname?:string //新增的字段
deptname?:string //新增的字段
}
export interface Userinfo
{
userid?: number, //加?代表的意思是这个值可以有,也可以没有 如果不加?那么这个值必须存在
phone?:string,
password?:string,
username?:string,
idcard?:string,
gender?:string
}
export interface Dept{
deptid:number,
deptname:string
}
export interface weekDict{
week:number,
date:string,
alldate:string
}
export interface Emp{
empid?: number,
empname?: string,
deptid?: number,
levelid?: number,
levelname?: string,
money?: number
}
export const timebetween:Array* 药品信息表 前端控制器 *
* * @author laohan * @since 2026-06-17 */ @RestController public class MedicController { @Resource private IMedicService medicService; @GetMapping("/medic/findAll") public List findAll(){ return medicService.list(); } } ``` 你如何把媒体文件发布成互联网文件。
把你原来的鸿蒙里面的那些图片,直接复制到后端idea的项目的resources/static/就可以了直接通过浏览器访问了。
### 鸿蒙前端
utils/entity.ts
```
//封装了你将来要获取的页面数据
export interface Medic {
id?: number,
image?: string,
goodname?: string,
price?: number,
comments?: number
}
export interface Checkin
{
checkinid?:number,
deptid?:number, //#号挂在那个部门下
empid?:number, //#号挂在那个医生下
userid?:number, //#谁挂的号
money?:number, //#挂号费
checkdate?:string,
checktime?:string
gender?:string //新增的字段
username?:string //新增的字段
empname?:string //新增的字段
deptname?:string //新增的字段
}
export interface Userinfo
{
userid?: number, //加?代表的意思是这个值可以有,也可以没有 如果不加?那么这个值必须存在
phone?:string,
password?:string,
username?:string,
idcard?:string,
gender?:string
}
export interface Dept{
deptid:number,
deptname:string
}
export interface weekDict{
week:number,
date:string,
alldate:string
}
export interface Emp{
empid?: number,
empname?: string,
deptid?: number,
levelid?: number,
levelname?: string,
money?: number
}
export const timebetween:Array