前端使用html+css+js,后端使用Spring Boot,数据库使用mysql,识别算法有两个,一个是使用百度OCR接口,一个是自己写一个python,用flask包装。
其中百度OCR接口可以去免费申请,然后把appid、apikey、secretKey填入application.properties即可
application.properties
spring.application.name=demo
# baidu_ocr_config
baidu.ocr.appid=your
baidu.ocr.apiKey=your
baidu.ocr.secretKey=your
# myself_ocr_model_config
myself.model.url=your flask
spring.thymeleaf.cache= false
# database
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#JPA
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
# application.properties
spring.web.resources.static-locations=classpath:/static/,classpath:/demo/static/
数据库
0. pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>demo</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<!-- 引入Lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 百度人工智能依赖 -->
<!-- https://mvnrepository.com/artifact/com.baidu.aip/java-sdk -->
<dependency>
<groupId>com.baidu.aip</groupId>
<artifactId>java-sdk</artifactId>
<version>4.11.3</version>
</dependency>
<!-- thymeleaf模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Spring Data JPA 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1. 项目结构
- config为一些配置设置
- controller为控制层
- dao为数据库实体层
- service为服务层
- css保存样式文件
- js保存js文件
- ocrImg是本地保存图片的位置,数据库里指存放图片在本地的地址
2. css代码
2.1 base.css
/* 去除常见标签默认的 margin 和 padding */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 设置网页统一的字体大小、行高、字体系列相关属性 */
body {
font: 16px/1.5 "Microsoft Yahei",
"Hiragino Sans GB", "Heiti SC", "WenQuanYi Micro Hei", sans-serif;
color: #333;
background-color: #f5f7f8;
}
/* 去除列表默认样式 */
ul,
ol {
list-style: none;
}
/* 去除默认的倾斜效果 */
em,
i {
font-style: normal;
}
/* 去除a标签默认下划线,并设置默认文字颜色 */
a {
text-decoration: none;
color: #333;
}
/* 设置img的垂直对齐方式为居中对齐,去除img默认下间隙 */
img {
width: 100%;
height: 100%;
vertical-align: middle;
}
/* 去除input默认样式 */
input {
border: none;
outline: none;
color: #333;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 400;
}
2.2 index.css
.container {
width: 10rem;
height: auto;
}
/* 顶部 */
.header {
display: flex;
padding: 0 .1563rem;
width: 10rem;
height: .3385rem;
align-items: center;
background-color: #fff;
}
.header img {
width: 30px;
height: 30px;
}
.header span {
margin-left: .026rem;
font-size: .1042rem;
}
/* 功能部分 */
.main {
width: 10rem;
height: auto;
padding: 0 .1563rem;
}
.operation {
display: flex;
margin: .1563rem 0;
}
.operation input {
display: none;
}
.operation button {
display: none;
}
.operation label {
display: flex;
margin-right: .1042rem;
width: .7813rem;
height: .2604rem;
border: .0052rem solid #cbc2c2;
border-radius: .0417rem;
align-items: center;
cursor: pointer;
}
.operation label:hover {
background-color: #d1f6ff;
}
.operation label .left {
margin-right: .0417rem;
padding: .0781rem 0;
width: .2083rem;
height: .2604rem;
text-align: center;
}
.operation label .left svg {
width: .1042rem;
height: .1042rem;
}
.operation label .right h2 {
font-size: .0833rem;
font-weight: bold;
color: #1296db;
}
.operation label .right h3 {
font-size: .0625rem;
color: #cbc2c2;
}
/* 主体 */
.function {
width: 9.70rem;
height: 3.125rem;
border-radius: .0938rem;
background-color: #fff;
overflow: hidden;
border: .0052rem solid #cbc2c2;
}
.function .title {
display: flex;
width: 100%;
height: .2604rem;
border-bottom: .0052rem solid #cbc2c2;
align-items: center;
}
.function .title h2 {
width: 50%;
padding-left: .1042rem;
font-size: .0833rem;
font-weight: bold;
color: #1f4d77;
}
.function .action {
display: flex;
width: 100%;
height: 2.8646rem;
}
.function .action .source {
width: 50%;
height: 2.8646rem;
border-right: .0052rem solid #cbc2c2;
}
.function .action .source img {
width: 100%;
height: 100%;
object-fit: contain;
margin: auto;
}
.function .action .result {
width: 50%;
height: 2.8646rem;
}
.function .action .result textarea{
width: 100%;
height: 100%;
font-size: .0833rem;
border: none;
}
/* 历史记录按钮 */
.circle-button {
position: absolute;
top : 75.5%;
right: 0.18rem;
bottom: 0.1064rem;
width: 0.1583rem;
height: 0.1583rem;
border: 1px solid black;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
background: transparent;
}
.circle-button::before {
content: "";
display: block;
width: 0.1063rem; /* 内部圆的直径 */
height: 0.1063rem;
border: 1px solid black; /* 细细的黑色边框 */
border-radius: 50%; /* 创建圆形效果 */
background: transparent; /* 设置背景为透明 */
}
.circle-button:hover {
border-color: #000; /* 鼠标悬停时保持黑色边框 */
}
#modelSelect {
background: transparent; /* 可以设置背景颜色 */
border: none; /* 移除边框 */
padding: 0; /* 移除内边距 */
margin: 0; /* 移除外边距 */
font-size: .0833rem;
font-weight: bold;
color: #1f4d77;
cursor: pointer; /* 改变鼠标指针 */
position: relative; /* 为了定位伪元素 */
display: inline-block; /* 使其与周围的元素在同一行显示 */
/* 增加宽度以适应文本和箭头 */
width: 100px; /* 或者使用您喜欢的宽度 */
/* 设置高度,以确保箭头在垂直方向上居中 */
height: 2em; /* 或者使用您喜欢的高度 */
line-height: 2em; /* 文本垂直居中 */
}
/* 加载动画 */
.loading {
border: 4px solid rgba(0, 0, 0, 0.1);
border-top-color: #1296db;
border-radius: 50%;
width: 24px;
height: 24px;
animation: spin 1s linear infinite;
position: absolute;
top: 50%;
left: 74%;
transform: translate(-50%, -50%);
display: none;
}
@keyframes spin {
0% {
transform: rotate(0deg); }
100% {
transform: rotate(360deg); }
}
2.3 re.css
.container {
display: flex;
flex-direction: column;
width