本系统采用前后端分离架构,前端使用Vue 3 + Element Plus,后端使用Spring Boot 2.7,数据库使用MySQL 8.0,通过飞书开放平台API实现身份认证与消息通知。
前端技术栈:Vue 3.2 + Vite 4.0 + Element Plus 2.3 + Axios 1.3
后端技术栈:Spring Boot 2.7.8 + MyBatis Plus 3.5.3 + MySQL 8.0.32
飞书集成:飞书开放平台SDK 1.0.14
安装Node.js 16.17.0:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
nvm install 16.17.0
nvm use 16.17.0
安装Java开发环境:
sudo apt update
sudo apt install openjdk-11-jdk
java -version
安装MySQL数据库:
sudo apt install mysql-server-8.0
sudo mysql_secure_installation
访问飞书开放平台:https://open.feishu.cn/app
创建企业自建应用,获取以下关键信息:
在应用权限配置中,开启以下权限:

创建数据库:
CREATE DATABASE archive_management DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
创建核心数据表:
-- 档案分类表
CREATE TABLE archive_category (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
category_code VARCHAR(50) NOT NULL COMMENT '分类编码',
category_name VARCHAR(100) NOT NULL COMMENT '分类名称',
parent_id BIGINT DEFAULT 0 COMMENT '父级ID',
sort_order INT DEFAULT 0 COMMENT '排序',
created_by VARCHAR(100) COMMENT '创建人',
created_time DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_category_code (category_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='档案分类表';
-- 档案信息表
CREATE TABLE archive_info (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
archive_no VARCHAR(50) NOT NULL COMMENT '档案编号',
archive_name VARCHAR(200) NOT NULL COMMENT '档案名称',
category_id BIGINT NOT NULL COMMENT '分类ID',
keywords VARCHAR(500) COMMENT '关键词',
storage_location VARCHAR(200) COMMENT '存储位置',
file_type VARCHAR(20) COMMENT '文件类型',
file_size BIGINT COMMENT '文件大小',
file_path VARCHAR(500) COMMENT '文件路径',
secret_level VARCHAR(20) COMMENT '密级',
expire_date DATE COMMENT '到期日期',
status TINYINT DEFAULT 1 COMMENT '状态:1-正常 2-借出 3-销毁',
created_by VARCHAR(100) COMMENT '创建人',
created_time DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_by VARCHAR(100) COMMENT '更新人',
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_category (category_id),
INDEX idx_archive_no (archive_no),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='档案信息表';
-- 档案借阅表
CREATE TABLE archive_borrow (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
archive_id BIGINT NOT NULL COMMENT '档案ID',
borrower_id VARCHAR(100) NOT NULL COMMENT '借阅人ID',
borrower_name VARCHAR(100) NOT NULL COMMENT '借阅人姓名',
borrow_reason VARCHAR(500) COMMENT '借阅事由',
borrow_date DATE NOT NULL COMMENT '借阅日期',
expected_return_date DATE NOT NULL COMMENT '预计归还日期',
actual_return_date DATE COMMENT '实际归还日期',
borrow_status TINYINT DEFAULT 1 COMMENT '状态:1-借出 2-已归还 3-超期',
created_time DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_archive (archive_id),
INDEX idx_borrower (borrower_id),
INDEX idx_status (borrow_status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='档案借阅表';
创建Spring Boot项目:
curl https://start.spring.io/starter.zip \
-d type=maven-project \
-d language=java \
-d bootVersion=2.7.8 \
-d baseDir=archive-backend \
-d groupId=com.example \
-d artifactId=archive \
-d name=archive \
-d dependencies=web,mybatis,mysql,lombok \
-o archive-backend.zip
unzip archive-backend.zip
添加依赖到pom.xml:
com.feishu
feishu-sdk
1.0.14
com.baomidou
mybatis-plus-boot-starter
3.5.3
创建application-feishu.yml配置文件:
feishu:
app-id: ${FEISHU_APP_ID:your_app_id_here}
app-secret: ${FEISHU_APP_SECRET:your_app_secret_here}
encrypt-key: ${FEISHU_ENCRYPT_KEY:your_encrypt_key_here}
verification-token: ${FEISHU_VERIFICATION_TOKEN:your_verification_token_here}
redirect-uri: https://your-domain.com/api/feishu/callback
创建飞书配置类:
@Configuration
@ConfigurationProperties(prefix = "feishu")
@Data
public class FeishuConfig {
private String appId;
private String appSecret;
private String encryptKey;
private String verificationToken;
private String redirectUri;
}
@Component
public class FeishuService {
@Autowired
private FeishuConfig feishuConfig;
private AppTicketManager appTicketManager;
private TenantAccessTokenManager tenantAccessTokenManager;
@PostConstruct
public void init() {
AppSettings appSettings = new AppSettings();
appSettings.setAppId(feishuConfig.getAppId());
appSettings.setAppSecret(feishuConfig.getAppSecret());
appSettings.setVerificationToken(feishuConfig.getVerificationToken());
appSettings.setEncryptKey(feishuConfig.getEncryptKey());
this.appTicketManager = new AppTicketManager(appSettings);
this.tenantAccessTokenManager = new TenantAccessTokenManager(appSettings, appTicketManager);
}
public String getTenantAccessToken() throws Exception {
return tenantAccessTokenManager.getTenantAccessToken();
}
public UserInfo getUserInfo(String code) throws Exception {
String accessToken = getTenantAccessToken();
// 调用飞书API获取用户信息
// 实现代码省略
}
}
创建档案控制器:
@RestController
@RequestMapping("/api/archive")
public class ArchiveController {
@Autowired
private ArchiveService archiveService;
@PostMapping("/upload")
public Result uploadArchive(@RequestParam("file") MultipartFile file,
@RequestParam("categoryId") Long categoryId,
@RequestParam("archiveName") String archiveName,
HttpServletRequest request) {
String userToken = request.getHeader("X-User-Token");
// 验证用户权限
// 处理文件上传
// 保存档案信息
return Result.success(archiveId);
}
@GetMapping("/search")
public Result searchArchives(@RequestParam(required = false) String keyword,
@RequestParam(required = false) Long categoryId,
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
Page result = archiveService.search(keyword, categoryId, page, size);
return Result.success(result);
}
@PostMapping("/borrow")
public Result borrowArchive(@RequestBody BorrowRequest request,
HttpServletRequest httpRequest) {
String userId = getUserIdFromToken(httpRequest);
archiveService.borrowArchive(request.getArchiveId(), userId, request.getReason());
// 发送飞书通知
sendFeishuNotification(userId, "档案借阅申请已提交");
return Result.success();
}
}
创建Vue项目:
npm create vue@3 archive-frontend
cd archive-frontend
npm install element-plus axios vue-router
npm install
配置飞书登录:
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import router from './router'
const app = createApp(App)
app.use(ElementPlus)
app.use(router)
app.mount('app')
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Login from '../views/Login.vue'
import Dashboard from '../views/Dashboard.vue'
const routes = [
{
path: '/',
redirect: '/login'
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/dashboard',
name: 'Dashboard',
component: Dashboard,
meta: { requiresAuth: true }
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
// 路由守卫,检查飞书登录状态
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth) {
const userToken = localStorage.getItem('feishu_token')
if (!userToken) {
// 跳转到飞书登录
const feishuLoginUrl = `https://open.feishu.cn/open-apis/authen/v1/index?redirect_uri=${encodeURIComponent(window.location.origin + '/callback')}&app_id=${process.env.VUE_APP_FEISHU_APP_ID}`
window.location.href = feishuLoginUrl
} else {
next()
}
} else {
next()
}
})
创建档案列表组件:
{{ formatFileSize(scope.row.fileSize) }}
{{ getStatusText(scope.row.status) }}
查看
借阅
后端部署脚本:
!/bin/bash
deploy-backend.sh
1. 停止旧服务
systemctl stop archive-backend
2. 备份旧版本
cp /opt/archive/archive-backend.jar /opt/archive/backup/archive-backend-$(date +%Y%m%d%H%M%S).jar
3. 部署新版本
cp target/archive-backend.jar /opt/archive/
4. 创建systemd服务文件
cat > /etc/systemd/system/archive-backend.service << EOF
[Unit]
Description=Archive Management Backend Service
After=network.target
[Service]
Type=simple
User=archive
WorkingDirectory=/opt/archive
ExecStart=/usr/bin/java -jar -Dspring.profiles.active=prod archive-backend.jar
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
5. 启动服务
systemctl daemon-reload
systemctl start archive-backend
systemctl enable archive-backend