diff --git a/.gitignore b/.gitignore
index 28e33d7..f113dbf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
*/.vscode/
-*/public/
\ No newline at end of file
+*/public/
+projectDesigning.md
\ No newline at end of file
diff --git a/backend/pom.xml b/backend/pom.xml
index 80ef2f4..68c2c2e 100644
--- a/backend/pom.xml
+++ b/backend/pom.xml
@@ -30,6 +30,51 @@
21
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ com.baomidou
+ mybatis-plus-spring-boot3-starter
+ 3.5.11
+
+
+
+ io.jsonwebtoken
+ jjwt-api
+ 0.13.0
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ 0.13.0
+ runtime
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ 0.13.0
+ runtime
+
+
+
+ cn.hutool
+ hutool-all
+ 5.8.37
+
+
org.springframework.boot
spring-boot-starter-jdbc
diff --git a/backend/src/main/resources/database/init.sql b/backend/src/main/resources/database/init.sql
new file mode 100644
index 0000000..892f71e
--- /dev/null
+++ b/backend/src/main/resources/database/init.sql
@@ -0,0 +1,658 @@
+-- ============================================================
+-- 药品管理系统 (MedicineManagerSystem) — 数据库初始化脚本
+-- ============================================================
+-- 说明: 包含全部建表 DDL + 初始种子数据
+-- 引擎: InnoDB | 字符集: utf8mb4 | 排序: utf8mb4_unicode_ci
+-- 执行方式: mysql -u root -p < init.sql
+-- 建表顺序: 按外键依赖关系排序,确保执行无误
+-- ============================================================
+
+-- 创建数据库(如不存在)
+CREATE DATABASE IF NOT EXISTS `medicine_manager`
+ DEFAULT CHARACTER SET utf8mb4
+ DEFAULT COLLATE utf8mb4_unicode_ci;
+
+USE `medicine_manager`;
+
+-- ============================================================
+-- 第一部分: 建表 DDL (15 张表,按外键依赖排序)
+-- ============================================================
+
+-- -----------------------------------------------------------
+-- 1. 药品分类表(无外键)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `medicine_category`;
+CREATE TABLE `medicine_category` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '分类ID',
+ `parent_id` BIGINT NOT NULL DEFAULT 0 COMMENT '父分类ID(0=顶级分类)',
+ `name` VARCHAR(64) NOT NULL COMMENT '分类名称',
+ `code` VARCHAR(32) NOT NULL COMMENT '分类编码',
+ `sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序序号(升序)',
+ `description` VARCHAR(255) DEFAULT NULL COMMENT '分类描述',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_code` (`code`),
+ KEY `idx_parent_id` (`parent_id`),
+ KEY `idx_sort_order` (`sort_order`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='药品分类表';
+
+-- -----------------------------------------------------------
+-- 2. 药品主表(FK → medicine_category)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `medicine`;
+CREATE TABLE `medicine` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '药品ID',
+ `category_id` BIGINT NOT NULL COMMENT '所属分类ID',
+ `name` VARCHAR(128) NOT NULL COMMENT '药品通用名称',
+ `generic_name` VARCHAR(128) DEFAULT NULL COMMENT '英文/化学通用名',
+ `specification` VARCHAR(64) NOT NULL COMMENT '规格(如 0.25g*12片)',
+ `manufacturer` VARCHAR(128) NOT NULL COMMENT '生产厂家',
+ `approval_number` VARCHAR(64) NOT NULL COMMENT '批准文号(国药准字)',
+ `barcode` VARCHAR(64) DEFAULT NULL COMMENT '条形码',
+ `dosage_form` VARCHAR(32) DEFAULT NULL COMMENT '剂型(片剂/胶囊/注射液/颗粒等)',
+ `unit` VARCHAR(16) NOT NULL DEFAULT '盒' COMMENT '基本单位(盒/瓶/支/袋)',
+ `retail_price` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '零售价',
+ `wholesale_price` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '批发价',
+ `storage_condition` VARCHAR(128) DEFAULT NULL COMMENT '储存条件(常温/阴凉/冷藏)',
+ `shelf_life` INT DEFAULT NULL COMMENT '有效期(月)',
+ `warning_stock` INT NOT NULL DEFAULT 10 COMMENT '库存预警阈值',
+ `description` VARCHAR(500) DEFAULT NULL COMMENT '备注说明',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_approval_number` (`approval_number`),
+ UNIQUE KEY `uk_barcode` (`barcode`),
+ KEY `idx_name` (`name`),
+ KEY `idx_category_id` (`category_id`),
+ KEY `idx_manufacturer` (`manufacturer`),
+ CONSTRAINT `fk_medicine_category` FOREIGN KEY (`category_id`) REFERENCES `medicine_category` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='药品主表';
+
+-- -----------------------------------------------------------
+-- 3. 供应商表(无外键)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `supplier`;
+CREATE TABLE `supplier` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '供应商ID',
+ `name` VARCHAR(128) NOT NULL COMMENT '供应商名称',
+ `contact_person` VARCHAR(32) DEFAULT NULL COMMENT '联系人',
+ `phone` VARCHAR(20) DEFAULT NULL COMMENT '联系电话',
+ `email` VARCHAR(64) DEFAULT NULL COMMENT '电子邮箱',
+ `address` VARCHAR(255) DEFAULT NULL COMMENT '地址',
+ `bank_account` VARCHAR(64) DEFAULT NULL COMMENT '银行账号',
+ `bank_name` VARCHAR(128) DEFAULT NULL COMMENT '开户银行',
+ `tax_id` VARCHAR(32) DEFAULT NULL COMMENT '税号',
+ `license_number` VARCHAR(64) DEFAULT NULL COMMENT '经营许可证号',
+ `status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '状态(0=停用, 1=启用)',
+ `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ KEY `idx_name` (`name`),
+ KEY `idx_phone` (`phone`),
+ KEY `idx_status` (`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='供应商表';
+
+-- -----------------------------------------------------------
+-- 4. 客户表(无外键)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `customer`;
+CREATE TABLE `customer` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '客户ID',
+ `name` VARCHAR(128) NOT NULL COMMENT '客户名称',
+ `contact_person` VARCHAR(32) DEFAULT NULL COMMENT '联系人',
+ `phone` VARCHAR(20) DEFAULT NULL COMMENT '联系电话',
+ `email` VARCHAR(64) DEFAULT NULL COMMENT '电子邮箱',
+ `address` VARCHAR(255) DEFAULT NULL COMMENT '地址',
+ `type` VARCHAR(16) DEFAULT '个人' COMMENT '客户类型(个人/医院/药店/诊所/批发商)',
+ `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ KEY `idx_name` (`name`),
+ KEY `idx_phone` (`phone`),
+ KEY `idx_type` (`type`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户表';
+
+-- -----------------------------------------------------------
+-- 5. 仓库表(无外键)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `warehouse`;
+CREATE TABLE `warehouse` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '仓库ID',
+ `name` VARCHAR(64) NOT NULL COMMENT '仓库名称',
+ `code` VARCHAR(32) NOT NULL COMMENT '仓库编码',
+ `location` VARCHAR(255) DEFAULT NULL COMMENT '仓库位置',
+ `manager` VARCHAR(32) DEFAULT NULL COMMENT '负责人',
+ `status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '状态(0=停用, 1=启用)',
+ `remark` VARCHAR(255) DEFAULT NULL COMMENT '备注',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_code` (`code`),
+ KEY `idx_status` (`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='仓库表';
+
+-- -----------------------------------------------------------
+-- 6. 系统用户表(被 stock_in_record 和 stock_out_record 引用,需先创建)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `user`;
+CREATE TABLE `user` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
+ `username` VARCHAR(32) NOT NULL COMMENT '用户名(登录账号)',
+ `password` VARCHAR(128) NOT NULL COMMENT '密码(BCrypt 加密)',
+ `real_name` VARCHAR(32) DEFAULT NULL COMMENT '真实姓名',
+ `phone` VARCHAR(20) DEFAULT NULL COMMENT '手机号',
+ `email` VARCHAR(64) DEFAULT NULL COMMENT '电子邮箱',
+ `avatar` VARCHAR(255) DEFAULT NULL COMMENT '头像URL',
+ `status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '状态(0=停用, 1=启用)',
+ `last_login_time` DATETIME DEFAULT NULL COMMENT '最后登录时间',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_username` (`username`),
+ KEY `idx_phone` (`phone`),
+ KEY `idx_status` (`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统用户表';
+
+-- -----------------------------------------------------------
+-- 7. 角色表(被 user_role 引用,需先创建)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `role`;
+CREATE TABLE `role` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '角色ID',
+ `name` VARCHAR(32) NOT NULL COMMENT '角色名称',
+ `code` VARCHAR(32) NOT NULL COMMENT '角色编码(如 admin / warehouse / staff)',
+ `description` VARCHAR(255) DEFAULT NULL COMMENT '角色描述',
+ `status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '状态(0=停用, 1=启用)',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_code` (`code`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色表';
+
+-- -----------------------------------------------------------
+-- 8. 用户角色关联表(FK → user + role)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `user_role`;
+CREATE TABLE `user_role` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '关联ID',
+ `user_id` BIGINT NOT NULL COMMENT '用户ID',
+ `role_id` BIGINT NOT NULL COMMENT '角色ID',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_user_role` (`user_id`, `role_id`),
+ KEY `idx_user_id` (`user_id`),
+ KEY `idx_role_id` (`role_id`),
+ CONSTRAINT `fk_user_role_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
+ CONSTRAINT `fk_user_role_role` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户角色关联表';
+
+-- -----------------------------------------------------------
+-- 9. 菜单权限表(被 role_menu 引用,需先创建)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `menu`;
+CREATE TABLE `menu` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '菜单ID',
+ `parent_id` BIGINT NOT NULL DEFAULT 0 COMMENT '父菜单ID(0=顶级菜单)',
+ `name` VARCHAR(32) NOT NULL COMMENT '菜单名称',
+ `type` TINYINT(1) NOT NULL COMMENT '菜单类型(1=目录, 2=菜单, 3=按钮)',
+ `path` VARCHAR(128) DEFAULT NULL COMMENT '路由路径(type=2时填写)',
+ `component` VARCHAR(128) DEFAULT NULL COMMENT '组件路径(type=2时填写)',
+ `icon` VARCHAR(32) DEFAULT NULL COMMENT '图标名称(Element Plus icon)',
+ `permission_code` VARCHAR(64) DEFAULT NULL COMMENT '权限编码(type=3时填写,如 medicine:add)',
+ `sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序序号(升序)',
+ `visible` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否可见(0=隐藏, 1=显示)',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_permission_code` (`permission_code`),
+ KEY `idx_parent_id` (`parent_id`),
+ KEY `idx_type` (`type`),
+ KEY `idx_sort_order` (`sort_order`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='菜单权限表';
+
+-- -----------------------------------------------------------
+-- 10. 角色菜单关联表(FK → role + menu)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `role_menu`;
+CREATE TABLE `role_menu` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '关联ID',
+ `role_id` BIGINT NOT NULL COMMENT '角色ID',
+ `menu_id` BIGINT NOT NULL COMMENT '菜单ID',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_role_menu` (`role_id`, `menu_id`),
+ KEY `idx_role_id` (`role_id`),
+ KEY `idx_menu_id` (`menu_id`),
+ CONSTRAINT `fk_role_menu_role` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`),
+ CONSTRAINT `fk_role_menu_menu` FOREIGN KEY (`menu_id`) REFERENCES `menu` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色菜单关联表';
+
+-- -----------------------------------------------------------
+-- 11. 库存表(FK → medicine + warehouse)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `stock`;
+CREATE TABLE `stock` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '库存ID',
+ `medicine_id` BIGINT NOT NULL COMMENT '药品ID',
+ `warehouse_id` BIGINT NOT NULL COMMENT '仓库ID',
+ `batch_no` VARCHAR(32) NOT NULL COMMENT '批号',
+ `quantity` INT NOT NULL DEFAULT 0 COMMENT '库存数量',
+ `cost_price` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '成本价',
+ `production_date` DATE DEFAULT NULL COMMENT '生产日期',
+ `expiry_date` DATE NOT NULL COMMENT '有效期至',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ KEY `idx_medicine_id` (`medicine_id`),
+ KEY `idx_warehouse_id` (`warehouse_id`),
+ KEY `idx_expiry_date` (`expiry_date`),
+ KEY `idx_medicine_batch` (`medicine_id`, `warehouse_id`, `batch_no`),
+ KEY `idx_quantity` (`quantity`),
+ CONSTRAINT `fk_stock_medicine` FOREIGN KEY (`medicine_id`) REFERENCES `medicine` (`id`),
+ CONSTRAINT `fk_stock_warehouse` FOREIGN KEY (`warehouse_id`) REFERENCES `warehouse` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='库存表';
+
+-- -----------------------------------------------------------
+-- 12. 入库记录表(FK → supplier + warehouse + user)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `stock_in_record`;
+CREATE TABLE `stock_in_record` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '入库单ID',
+ `record_no` VARCHAR(32) NOT NULL COMMENT '入库单号(如 SI202607060001)',
+ `supplier_id` BIGINT NOT NULL COMMENT '供应商ID',
+ `warehouse_id` BIGINT NOT NULL COMMENT '入库仓库ID',
+ `total_amount` DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '入库总金额',
+ `operator_id` BIGINT NOT NULL COMMENT '操作人ID',
+ `in_date` DATE NOT NULL COMMENT '入库日期',
+ `status` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '状态(0=待审核, 1=已入库, 2=已取消)',
+ `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_record_no` (`record_no`),
+ KEY `idx_supplier_id` (`supplier_id`),
+ KEY `idx_warehouse_id` (`warehouse_id`),
+ KEY `idx_operator_id` (`operator_id`),
+ KEY `idx_status` (`status`),
+ KEY `idx_in_date` (`in_date`),
+ CONSTRAINT `fk_stock_in_supplier` FOREIGN KEY (`supplier_id`) REFERENCES `supplier` (`id`),
+ CONSTRAINT `fk_stock_in_warehouse` FOREIGN KEY (`warehouse_id`) REFERENCES `warehouse` (`id`),
+ CONSTRAINT `fk_stock_in_operator` FOREIGN KEY (`operator_id`) REFERENCES `user` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='入库记录表';
+
+-- -----------------------------------------------------------
+-- 13. 入库明细表(FK → stock_in_record + medicine)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `stock_in_detail`;
+CREATE TABLE `stock_in_detail` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '明细ID',
+ `record_id` BIGINT NOT NULL COMMENT '入库单ID',
+ `medicine_id` BIGINT NOT NULL COMMENT '药品ID',
+ `batch_no` VARCHAR(32) NOT NULL COMMENT '批号',
+ `quantity` INT NOT NULL COMMENT '入库数量',
+ `cost_price` DECIMAL(10,2) NOT NULL COMMENT '进价',
+ `total_price` DECIMAL(12,2) NOT NULL COMMENT '小计金额(quantity * cost_price)',
+ `production_date` DATE DEFAULT NULL COMMENT '生产日期',
+ `expiry_date` DATE NOT NULL COMMENT '有效期至',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ KEY `idx_record_id` (`record_id`),
+ KEY `idx_medicine_id` (`medicine_id`),
+ CONSTRAINT `fk_stock_in_detail_record` FOREIGN KEY (`record_id`) REFERENCES `stock_in_record` (`id`),
+ CONSTRAINT `fk_stock_in_detail_medicine` FOREIGN KEY (`medicine_id`) REFERENCES `medicine` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='入库明细表';
+
+-- -----------------------------------------------------------
+-- 14. 出库记录表(FK → customer + warehouse + user)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `stock_out_record`;
+CREATE TABLE `stock_out_record` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '出库单ID',
+ `record_no` VARCHAR(32) NOT NULL COMMENT '出库单号(如 SO202607060001)',
+ `customer_id` BIGINT DEFAULT NULL COMMENT '客户ID(销售出库时填写)',
+ `warehouse_id` BIGINT NOT NULL COMMENT '出库仓库ID',
+ `total_amount` DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '出库总金额',
+ `operator_id` BIGINT NOT NULL COMMENT '操作人ID',
+ `out_date` DATE NOT NULL COMMENT '出库日期',
+ `out_type` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '出库类型(1=销售出库, 2=领用出库, 3=报损出库, 4=退货出库)',
+ `status` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '状态(0=待审核, 1=已出库, 2=已取消)',
+ `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uk_record_no` (`record_no`),
+ KEY `idx_customer_id` (`customer_id`),
+ KEY `idx_warehouse_id` (`warehouse_id`),
+ KEY `idx_operator_id` (`operator_id`),
+ KEY `idx_status` (`status`),
+ KEY `idx_out_date` (`out_date`),
+ KEY `idx_out_type` (`out_type`),
+ CONSTRAINT `fk_stock_out_customer` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`id`),
+ CONSTRAINT `fk_stock_out_warehouse` FOREIGN KEY (`warehouse_id`) REFERENCES `warehouse` (`id`),
+ CONSTRAINT `fk_stock_out_operator` FOREIGN KEY (`operator_id`) REFERENCES `user` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='出库记录表';
+
+-- -----------------------------------------------------------
+-- 15. 出库明细表(FK → stock_out_record + medicine)
+-- -----------------------------------------------------------
+DROP TABLE IF EXISTS `stock_out_detail`;
+CREATE TABLE `stock_out_detail` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '明细ID',
+ `record_id` BIGINT NOT NULL COMMENT '出库单ID',
+ `medicine_id` BIGINT NOT NULL COMMENT '药品ID',
+ `batch_no` VARCHAR(32) NOT NULL COMMENT '批号',
+ `quantity` INT NOT NULL COMMENT '出库数量',
+ `unit_price` DECIMAL(10,2) NOT NULL COMMENT '出库单价',
+ `total_price` DECIMAL(12,2) NOT NULL COMMENT '小计金额(quantity * unit_price)',
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ `is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0=未删除, 1=已删除)',
+ PRIMARY KEY (`id`),
+ KEY `idx_record_id` (`record_id`),
+ KEY `idx_medicine_id` (`medicine_id`),
+ CONSTRAINT `fk_stock_out_detail_record` FOREIGN KEY (`record_id`) REFERENCES `stock_out_record` (`id`),
+ CONSTRAINT `fk_stock_out_detail_medicine` FOREIGN KEY (`medicine_id`) REFERENCES `medicine` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='出库明细表';
+
+
+-- ============================================================
+-- 第二部分: 种子数据
+-- ============================================================
+
+-- -----------------------------------------------------------
+-- 药品分类初始数据(14 条顶级分类)
+-- -----------------------------------------------------------
+INSERT INTO `medicine_category` (`id`, `parent_id`, `name`, `code`, `sort_order`, `description`) VALUES
+(1, 0, '抗生素类', 'ANTIBIOTIC', 1, '抗生素类药品,包括青霉素类、头孢菌素类、大环内酯类等'),
+(2, 0, '抗病毒类', 'ANTIVIRAL', 2, '抗病毒药品,用于治疗流感、肝炎等病毒性疾病'),
+(3, 0, '解热镇痛类', 'ANALGESIC', 3, '解热镇痛消炎药品,如阿司匹林、布洛芬、对乙酰氨基酚等'),
+(4, 0, '心血管类', 'CARDIOVASCULAR', 4, '心血管系统药品,包括降压药、降脂药、抗心律失常药等'),
+(5, 0, '呼吸系统类', 'RESPIRATORY', 5, '呼吸系统药品,包括止咳药、祛痰药、平喘药等'),
+(6, 0, '消化系统类', 'DIGESTIVE', 6, '消化系统药品,包括胃药、止泻药、肝胆用药等'),
+(7, 0, '内分泌类', 'ENDOCRINE', 7, '内分泌系统药品,包括降糖药、甲状腺用药、激素类等'),
+(8, 0, '维生素及矿物质类', 'VITAMIN', 8, '维生素、矿物质及营养补充剂'),
+(9, 0, '外用药类', 'EXTERNAL', 9, '外用药,包括皮肤用药、眼药水、贴膏等'),
+(10, 0, '中成药类', 'CHINESE_MED', 10, '中成药制剂,包括颗粒、丸剂、口服液等'),
+(11, 0, '生物制品类', 'BIOLOGICAL', 11, '生物制品,包括疫苗、血液制品、免疫制剂等'),
+(12, 0, '麻醉药品类', 'NARCOTIC', 12, '麻醉药品及精神类药品(需特殊管理)'),
+(13, 0, '医疗器械类', 'MEDICAL_DEVICE', 13, '医疗器械及耗材,如注射器、纱布、血压计等'),
+(14, 0, '其他', 'OTHER', 99, '其他未分类药品');
+
+-- -----------------------------------------------------------
+-- 仓库初始数据(1 条默认仓库)
+-- -----------------------------------------------------------
+INSERT INTO `warehouse` (`id`, `name`, `code`, `location`, `manager`, `status`, `remark`) VALUES
+(1, '主仓库', 'WH-MAIN', 'A栋1楼101室', '系统管理员', 1, '默认主仓库');
+
+-- -----------------------------------------------------------
+-- 角色初始数据(3 个默认角色)
+-- -----------------------------------------------------------
+INSERT INTO `role` (`id`, `name`, `code`, `description`, `status`) VALUES
+(1, '超级管理员', 'admin', '系统超级管理员,拥有所有权限', 1),
+(2, '仓库管理员', 'warehouse', '仓库管理员,负责库存、入库、出库管理', 1),
+(3, '普通员工', 'staff', '普通员工,仅有查看权限', 1);
+
+-- -----------------------------------------------------------
+-- 默认管理员用户(用户名: admin / 密码: admin123)
+-- BCrypt 加密: $2a$10$... 共 60 字符
+-- -----------------------------------------------------------
+INSERT INTO `user` (`id`, `username`, `password`, `real_name`, `phone`, `email`, `status`) VALUES
+(1, 'admin', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt6Z5EH', '系统管理员', '13800000000', 'admin@medicine.com', 1);
+
+-- -----------------------------------------------------------
+-- 用户角色关联(admin 用户 → 超级管理员角色)
+-- -----------------------------------------------------------
+INSERT INTO `user_role` (`user_id`, `role_id`) VALUES (1, 1);
+
+-- -----------------------------------------------------------
+-- 菜单权限初始数据(3 级树:目录 → 菜单 → 按钮)
+-- -----------------------------------------------------------
+
+-- ===== 仪表盘(一级菜单,排最前面) =====
+INSERT INTO `menu` (`id`, `parent_id`, `name`, `type`, `path`, `component`, `icon`, `permission_code`, `sort_order`) VALUES
+(55, 0, '仪表盘', 2, '/dashboard', 'views/dashboard/DashboardView', 'Odometer', NULL, 0),
+(56, 55, '仪表盘查看', 3, NULL, NULL, NULL, 'dashboard:view', 1);
+
+-- ===== 系统管理(目录) =====
+INSERT INTO `menu` (`id`, `parent_id`, `name`, `type`, `path`, `component`, `icon`, `permission_code`, `sort_order`) VALUES
+(1, 0, '系统管理', 1, NULL, NULL, 'Setting', NULL, 1),
+(2, 1, '用户管理', 2, '/user/list', 'views/user/UserList', 'User', NULL, 11),
+(3, 2, '用户查询', 3, NULL, NULL, NULL, 'user:list', 111),
+(4, 2, '用户详情', 3, NULL, NULL, NULL, 'user:query', 112),
+(5, 2, '新增用户', 3, NULL, NULL, NULL, 'user:add', 113),
+(6, 2, '编辑用户', 3, NULL, NULL, NULL, 'user:edit', 114),
+(7, 2, '删除用户', 3, NULL, NULL, NULL, 'user:delete', 115),
+(8, 2, '重置密码', 3, NULL, NULL, NULL, 'user:reset-pwd', 116),
+(9, 2, '分配角色', 3, NULL, NULL, NULL, 'user:assign-role',117),
+
+(10, 1, '角色管理', 2, '/role/list', 'views/role/RoleList', 'UserFilled', NULL, 12),
+(11, 10, '角色查询', 3, NULL, NULL, NULL, 'role:list', 121),
+(12, 10, '新增角色', 3, NULL, NULL, NULL, 'role:add', 122),
+(13, 10, '编辑角色', 3, NULL, NULL, NULL, 'role:edit', 123),
+(14, 10, '删除角色', 3, NULL, NULL, NULL, 'role:delete', 124),
+(15, 10, '分配权限', 3, NULL, NULL, NULL, 'role:assign-menu',125),
+
+(16, 1, '菜单管理', 2, '/menu/list', 'views/menu/MenuList', 'Menu', NULL, 13),
+(17, 16, '菜单查询', 3, NULL, NULL, NULL, 'menu:list', 131),
+(18, 16, '新增菜单', 3, NULL, NULL, NULL, 'menu:add', 132),
+(19, 16, '编辑菜单', 3, NULL, NULL, NULL, 'menu:edit', 133),
+(20, 16, '删除菜单', 3, NULL, NULL, NULL, 'menu:delete', 134);
+
+-- ===== 药品管理(目录) =====
+INSERT INTO `menu` (`id`, `parent_id`, `name`, `type`, `path`, `component`, `icon`, `permission_code`, `sort_order`) VALUES
+(21, 0, '药品管理', 1, NULL, NULL, 'MedicineBox', NULL, 2),
+(22, 21, '药品列表', 2, '/medicine/list', 'views/medicine/MedicineList', NULL, 'medicine:list', 21),
+(23, 22, '药品查询', 3, NULL, NULL, NULL, 'medicine:query', 211),
+(24, 22, '新增药品', 3, NULL, NULL, NULL, 'medicine:add', 212),
+(25, 22, '编辑药品', 3, NULL, NULL, NULL, 'medicine:edit', 213),
+(26, 22, '删除药品', 3, NULL, NULL, NULL, 'medicine:delete',214),
+
+(27, 21, '药品分类', 2, '/category/list', 'views/category/CategoryList', NULL, 'category:list', 22),
+(28, 27, '分类查询', 3, NULL, NULL, NULL, 'category:query', 221),
+(29, 27, '新增分类', 3, NULL, NULL, NULL, 'category:add', 222),
+(30, 27, '编辑分类', 3, NULL, NULL, NULL, 'category:edit', 223),
+(31, 27, '删除分类', 3, NULL, NULL, NULL, 'category:delete',224);
+
+-- ===== 库存管理(目录) =====
+INSERT INTO `menu` (`id`, `parent_id`, `name`, `type`, `path`, `component`, `icon`, `permission_code`, `sort_order`) VALUES
+(32, 0, '库存管理', 1, NULL, NULL, 'Box', NULL, 3),
+(33, 32, '库存列表', 2, '/stock/list', 'views/stock/StockList', NULL, 'stock:list', 31),
+(34, 33, '库存查询', 3, NULL, NULL, NULL, 'stock:query', 311),
+(35, 33, '库存盘点', 3, NULL, NULL, NULL, 'stock:check', 312),
+
+(36, 32, '入库管理', 2, '/stock-in/list', 'views/stockIn/StockInList', NULL, 'stock-in:list', 32),
+(37, 36, '入库查询', 3, NULL, NULL, NULL, 'stock-in:query', 321),
+(38, 36, '新增入库', 3, NULL, NULL, NULL, 'stock-in:add', 322),
+(39, 36, '审核入库', 3, NULL, NULL, NULL, 'stock-in:audit', 323),
+
+(40, 32, '出库管理', 2, '/stock-out/list', 'views/stockOut/StockOutList', NULL, 'stock-out:list', 33),
+(41, 40, '出库查询', 3, NULL, NULL, NULL, 'stock-out:query', 331),
+(42, 40, '新增出库', 3, NULL, NULL, NULL, 'stock-out:add', 332),
+(43, 40, '审核出库', 3, NULL, NULL, NULL, 'stock-out:audit', 333);
+
+-- ===== 往来单位(目录) =====
+INSERT INTO `menu` (`id`, `parent_id`, `name`, `type`, `path`, `component`, `icon`, `permission_code`, `sort_order`) VALUES
+(44, 0, '往来单位', 1, NULL, NULL, 'Connection', NULL, 4),
+(45, 44, '供应商管理', 2, '/supplier/list', 'views/supplier/SupplierList', NULL, 'supplier:list', 41),
+(46, 45, '供应商查询', 3, NULL, NULL, NULL, 'supplier:query', 411),
+(47, 45, '新增供应商', 3, NULL, NULL, NULL, 'supplier:add', 412),
+(48, 45, '编辑供应商', 3, NULL, NULL, NULL, 'supplier:edit', 413),
+(49, 45, '删除供应商', 3, NULL, NULL, NULL, 'supplier:delete',414),
+
+(50, 44, '客户管理', 2, '/customer/list', 'views/customer/CustomerList', NULL, 'customer:list', 42),
+(51, 50, '客户查询', 3, NULL, NULL, NULL, 'customer:query', 421),
+(52, 50, '新增客户', 3, NULL, NULL, NULL, 'customer:add', 422),
+(53, 50, '编辑客户', 3, NULL, NULL, NULL, 'customer:edit', 423),
+(54, 50, '删除客户', 3, NULL, NULL, NULL, 'customer:delete',424);
+
+-- -----------------------------------------------------------
+-- 角色菜单关联数据
+-- -----------------------------------------------------------
+
+-- 超级管理员(role_id=1):拥有所有菜单权限(共 56 条 menu)
+INSERT INTO `role_menu` (`role_id`, `menu_id`) VALUES
+(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,9),
+(1,10),(1,11),(1,12),(1,13),(1,14),(1,15),
+(1,16),(1,17),(1,18),(1,19),(1,20),
+(1,21),(1,22),(1,23),(1,24),(1,25),(1,26),
+(1,27),(1,28),(1,29),(1,30),(1,31),
+(1,32),(1,33),(1,34),(1,35),
+(1,36),(1,37),(1,38),(1,39),
+(1,40),(1,41),(1,42),(1,43),
+(1,44),(1,45),(1,46),(1,47),(1,48),(1,49),
+(1,50),(1,51),(1,52),(1,53),(1,54),
+(1,55),(1,56);
+
+-- 仓库管理员(role_id=2):库存管理全部 + 往来单位只读 + 仪表盘
+INSERT INTO `role_menu` (`role_id`, `menu_id`) VALUES
+(2,32), -- 库存管理(目录)
+(2,33),(2,34),(2,35), -- 库存列表 + 查询 + 盘点
+(2,36),(2,37),(2,38),(2,39), -- 入库管理 + 全部按钮
+(2,40),(2,41),(2,42),(2,43), -- 出库管理 + 全部按钮
+(2,44), -- 往来单位(目录)
+(2,45),(2,46), -- 供应商管理 + 查询(只读)
+(2,50),(2,51), -- 客户管理 + 查询(只读)
+(2,55),(2,56); -- 仪表盘
+
+-- 普通员工(role_id=3):仪表盘 + 药品/库存只看
+INSERT INTO `role_menu` (`role_id`, `menu_id`) VALUES
+(3,55),(3,56), -- 仪表盘
+(3,21), -- 药品管理(目录)
+(3,22),(3,23), -- 药品列表 + 查询(只读)
+(3,32), -- 库存管理(目录)
+(3,33),(3,34); -- 库存列表 + 查询(只读)
+
+
+-- -----------------------------------------------------------
+-- 仓库管理员用户(用户名: warehouse01 / 密码: admin123)
+-- -----------------------------------------------------------
+INSERT INTO `user` (`id`, `username`, `password`, `real_name`, `phone`, `email`, `status`) VALUES
+(2, 'warehouse01', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt6Z5EH', '张伟', '13800000001', 'zhangwei@medicine.com', 1),
+(3, 'staff01', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt6Z5EH', '李娜', '13800000002', 'lina@medicine.com', 1);
+
+-- -----------------------------------------------------------
+-- 用户角色关联
+-- -----------------------------------------------------------
+INSERT INTO `user_role` (`user_id`, `role_id`) VALUES (2, 2), (3, 3);
+
+-- -----------------------------------------------------------
+-- 药品初始数据(12 种常用药品)
+-- -----------------------------------------------------------
+INSERT INTO `medicine` (`id`, `category_id`, `name`, `generic_name`, `specification`, `manufacturer`, `approval_number`, `barcode`, `dosage_form`, `unit`, `retail_price`, `wholesale_price`, `storage_condition`, `shelf_life`, `warning_stock`, `description`) VALUES
+(1, 1, '阿莫西林胶囊', 'Amoxicillin Capsules', '0.25g×24粒', '石药集团中诺药业', '国药准字H13023923', '6901234567890', '胶囊剂', '盒', 18.50, 14.20, '密封、阴凉干燥处', 24, 50, '青霉素类广谱抗生素,适用于敏感菌引起的呼吸道、泌尿道感染等'),
+(2, 1, '头孢克肟分散片', 'Cefixime Dispersible', '0.1g×12片', '广州白云山制药总厂', '国药准字H20067177', '6901234567891', '片剂', '盒', 42.00, 33.50, '密封、阴凉干燥处', 24, 30, '第三代头孢菌素,用于敏感菌引起的呼吸道、泌尿系统感染'),
+(3, 3, '布洛芬缓释胶囊', 'Ibuprofen SR Capsules', '0.3g×20粒', '中美天津史克制药', '国药准字H10900089', '6901234567892', '胶囊剂', '盒', 25.80, 19.00, '密封保存', 36, 40, '非甾体抗炎药,用于缓解轻至中度疼痛及退热'),
+(4, 3, '对乙酰氨基酚片', 'Paracetamol Tablets', '0.5g×12片', '上海强生制药', '国药准字H31022137', '6901234567893', '片剂', '盒', 12.00, 8.50, '密封保存', 36, 60, '解热镇痛药,用于普通感冒或流感引起的发热及头痛'),
+(5, 4, '硝苯地平控释片', 'Nifedipine CR Tablets', '30mg×7片', '拜耳医药保健有限公司','国药准字J20180025', '6901234567894', '片剂', '盒', 38.50, 29.00, '遮光、密封保存', 36, 20, '钙通道阻滞剂,用于治疗高血压及冠心病'),
+(6, 5, '盐酸氨溴索口服液', 'Ambroxol Oral Solution', '100ml:0.6g', '深圳致君制药', '国药准字H20073942', '6901234567895', '口服液', '瓶', 28.00, 21.00, '遮光、阴凉处保存', 24, 30, '祛痰药,用于急慢性呼吸道疾病引起的痰液黏稠'),
+(7, 6, '奥美拉唑肠溶胶囊', 'Omeprazole Enteric Capsules', '20mg×14粒', '阿斯利康制药', '国药准字J20130093', '6901234567896', '胶囊剂', '盒', 56.00, 43.00, '遮光、密封、阴凉处', 24, 25, '质子泵抑制剂,用于胃溃疡、十二指肠溃疡及反流性食管炎'),
+(8, 7, '盐酸二甲双胍缓释片', 'Metformin HCl ER Tablets', '0.5g×30片', '中美上海施贵宝制药', '国药准字H20023370', '6901234567897', '片剂', '盒', 32.00, 24.50, '密封保存', 36, 40, '口服降糖药,用于2型糖尿病的治疗'),
+(9, 8, '维生素C片', 'Vitamin C Tablets', '0.1g×100片', '东北制药集团', '国药准字H21021078', '6901234567898', '片剂', '瓶', 8.50, 5.80, '遮光、密封保存', 24, 80, '维生素类非处方药,用于预防和治疗坏血病'),
+(10, 9, '阿昔洛韦乳膏', 'Acyclovir Cream', '10g:0.3g(3%)', '湖北科益药业', '国药准字H42022673', '6901234567899', '乳膏剂', '支', 8.00, 5.50, '密封、阴凉处保存', 24, 50, '抗病毒外用药,用于单纯疱疹及带状疱疹感染'),
+(11, 10,'连花清瘟胶囊', 'Lianhua Qingwen Capsules','0.35g×36粒', '石家庄以岭药业', '国药准字Z20040063', '6901234567900', '胶囊剂', '盒', 22.80, 16.50, '密封、阴凉干燥处', 24, 50, '中成药,用于流感和感冒引起的发热、咳嗽、咽痛'),
+(12, 7, '胰岛素注射液', 'Insulin Injection', '10ml:400单位', '诺和诺德(中国)制药', '国药准字J20171030', '6901234567901', '注射液', '支', 65.00, 49.00, '2-8℃冷藏,禁止冷冻', 24, 15, '用于1型糖尿病及需要胰岛素治疗的2型糖尿病患者');
+
+-- -----------------------------------------------------------
+-- 供应商初始数据(4 家)
+-- -----------------------------------------------------------
+INSERT INTO `supplier` (`id`, `name`, `contact_person`, `phone`, `email`, `address`, `bank_account`, `bank_name`, `tax_id`, `license_number`, `status`, `remark`) VALUES
+(1, '九州通医药集团股份有限公司', '陈经理', '027-88886666', 'chen@jzt.com.cn', '湖北省武汉市汉阳区龙阳大道特8号', '6222023202012345678', '中国工商银行武汉汉阳支行', '91420106714200579A', '鄂AA0270001', 1, '主要供应商,覆盖大部分抗生素和心血管药品'),
+(2, '华润医药商业集团有限公司', '王经理', '010-66668888', 'wang@crpharm.com', '北京市东城区安定门内大街88号', '6222020200012345678', '中国建设银行北京东四支行', '91110000610000278B', '京AA0100002', 1, '国企背景,供应价格稳定'),
+(3, '国药控股股份有限公司', '刘经理', '021-55559999', 'liu@sinopharm.com', '上海市黄浦区南京东路100号', '6222021001012345678', '中国银行上海市分行', '91310000607300379C', '沪AA0210003', 1, '全国最大医药流通企业,药品种类齐全'),
+(4, '上海医药集团股份有限公司', '赵经理', '021-33332222', 'zhao@shapharma.com', '上海市浦东新区张江高科技园区', '6222021001022345678', '交通银行上海张江支行', '91310000607300680A', '沪AA0210004', 0, '暂时停用,合同到期未续签');
+
+-- -----------------------------------------------------------
+-- 客户初始数据(4 个)
+-- -----------------------------------------------------------
+INSERT INTO `customer` (`id`, `name`, `contact_person`, `phone`, `email`, `address`, `type`, `remark`) VALUES
+(1, '市第一人民医院', '医务科-周主任', '0531-88881234', 'zhou@diyi-hospital.cn', '山东省济南市历下区解放路105号', '医院', '三甲医院,长期合作客户,月均采购量较大'),
+(2, '仁心大药房连锁有限公司', '采购部-吴经理', '0531-88882345', 'wu@renxin-pharmacy.cn', '山东省济南市市中区经七路66号', '药店', '连锁药店15家门店,需求稳定'),
+(3, '阳光社区卫生服务中心', '药房-郑主管', '0531-88883456', 'zheng@yangguang-chc.cn', '山东省济南市槐荫区阳光新路22号', '诊所', '基层医疗机构,以常用药为主'),
+(4, '康源堂中医门诊部', '门诊-孙医生', '0531-88884567', 'sun@kangyuantang.cn', '山东省济南市历城区花园路200号', '诊所', '中医门诊,主要采购中成药');
+
+-- -----------------------------------------------------------
+-- 库存初始数据(12 条,对应 12 种药品,含不同批号和效期)
+-- -----------------------------------------------------------
+INSERT INTO `stock` (`id`, `medicine_id`, `warehouse_id`, `batch_no`, `quantity`, `cost_price`, `production_date`, `expiry_date`) VALUES
+(1, 1, 1, '20260501A', 200, 13.80, '2026-05-10', '2028-05-09'),
+(2, 1, 1, '20260315B', 80, 13.50, '2026-03-20', '2028-03-19'),
+(3, 2, 1, '20260601A', 150, 32.00, '2026-06-05', '2028-06-04'),
+(4, 3, 1, '20260420A', 300, 18.00, '2026-04-25', '2029-04-24'),
+(5, 3, 1, '20251201B', 45, 17.50, '2025-12-10', '2026-09-09'), -- 近效期(3个月内),触发预警
+(6, 4, 1, '20260515A', 500, 7.80, '2026-05-20', '2029-05-19'),
+(7, 5, 1, '20260110A', 120, 28.00, '2026-01-15', '2029-01-14'),
+(8, 6, 1, '20260301A', 180, 20.00, '2026-03-05', '2028-03-04'),
+(9, 7, 1, '20260401A', 100, 42.00, '2026-04-05', '2028-04-04'),
+(10, 8, 1, '20260520A', 250, 23.50, '2026-05-25', '2029-05-24'),
+(11, 9, 1, '20260610A', 600, 5.20, '2026-06-15', '2028-06-14'),
+(12, 10, 1, '20260215A', 350, 5.00, '2026-02-20', '2028-02-19'),
+(13, 11, 1, '20260605A', 400, 15.80, '2026-06-10', '2028-06-09'),
+(14, 12, 1, '20260501C', 80, 48.00, '2026-05-05', '2027-05-04');
+
+-- -----------------------------------------------------------
+-- 入库记录 + 明细(2 笔入库单,模拟真实采购场景)
+-- -----------------------------------------------------------
+
+-- 入库单 #1:2026年7月1日从九州通采购,已确认入库
+INSERT INTO `stock_in_record` (`id`, `record_no`, `supplier_id`, `warehouse_id`, `total_amount`, `operator_id`, `in_date`, `status`, `remark`) VALUES
+(1, 'SI202607010001', 1, 1, 22696.00, 1, '2026-07-01', 1, '7月初常规补货采购');
+
+INSERT INTO `stock_in_detail` (`record_id`, `medicine_id`, `batch_no`, `quantity`, `cost_price`, `total_price`, `production_date`, `expiry_date`) VALUES
+(1, 1, '20260701A', 300, 13.60, 4080.00, '2026-06-20', '2028-06-19'),
+(1, 3, '20260701B', 400, 17.80, 7120.00, '2026-06-25', '2029-06-24'),
+(1, 6, '20260701C', 200, 19.80, 3960.00, '2026-06-15', '2028-06-14'),
+(1, 7, '20260701D', 150, 41.50, 6225.00, '2026-06-10', '2028-06-09'),
+(1, 5, '20260701E', 60, 27.50, 1650.00, '2026-06-01', '2029-05-31');
+
+-- 入库单 #2:2026年7月5日从国药控股采购,待审核
+INSERT INTO `stock_in_record` (`id`, `record_no`, `supplier_id`, `warehouse_id`, `total_amount`, `operator_id`, `in_date`, `status`, `remark`) VALUES
+(2, 'SI202607050002', 3, 1, 18445.00, 2, '2026-07-05', 0, '补充胰岛素及中成药库存');
+
+INSERT INTO `stock_in_detail` (`record_id`, `medicine_id`, `batch_no`, `quantity`, `cost_price`, `total_price`, `production_date`, `expiry_date`) VALUES
+(2, 8, '20260705A', 300, 23.00, 6900.00, '2026-06-28', '2029-06-27'),
+(2, 11, '20260705B', 500, 15.50, 7750.00, '2026-06-25', '2028-06-24'),
+(2, 12, '20260705C', 100, 47.50, 4750.00, '2026-06-20', '2027-06-19');
+
+-- -----------------------------------------------------------
+-- 出库记录 + 明细(1 笔出库单,模拟销售/领用场景)
+-- -----------------------------------------------------------
+
+-- 出库单 #1:2026年7月3日向市第一人民医院销售出库,已确认出库
+INSERT INTO `stock_out_record` (`id`, `record_no`, `customer_id`, `warehouse_id`, `total_amount`, `operator_id`, `out_date`, `out_type`, `status`, `remark`) VALUES
+(1, 'SO202607030001', 1, 1, 8170.00, 2, '2026-07-03', 1, 1, '第一人民医院常规领药');
+
+INSERT INTO `stock_out_detail` (`record_id`, `medicine_id`, `batch_no`, `quantity`, `unit_price`, `total_price`) VALUES
+(1, 1, '20260501A', 100, 18.50, 1850.00),
+(1, 7, '20260401A', 80, 56.00, 4480.00),
+(1, 6, '20260301A', 60, 28.00, 1680.00);
+
+
+-- ============================================================
+-- 完成
+-- ============================================================
+-- 执行方式: mysql -u root -p < init.sql
+-- 执行后请验证:
+-- 1. SHOW TABLES; -- 应显示 15 张表
+-- 2. SELECT COUNT(*) FROM `menu`; -- 应显示 56 条菜单
+-- 3. SELECT * FROM `user`; -- 应显示 3 个用户(admin, warehouse01, staff01)
+-- 4. SELECT * FROM `medicine`; -- 应显示 12 种药品
+-- 5. SELECT * FROM `stock`; -- 应显示 14 条库存记录
+-- 6. SELECT * FROM `stock_in_record`; -- 应显示 2 张入库单
+-- 7. SELECT * FROM `stock_in_detail`; -- 应显示 8 条入库明细
+-- 8. SELECT * FROM `stock_out_record`; -- 应显示 1 张出库单
+-- 9. SELECT * FROM `stock_out_detail`; -- 应显示 3 条出库明细
+-- ============================================================
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index d3456d2..d20b273 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -8,10 +8,16 @@
"name": "frontend",
"version": "0.0.0",
"dependencies": {
- "vue": "^3.5.39"
+ "@element-plus/icons-vue": "^2.x",
+ "axios": "^1.x",
+ "element-plus": "^2.x",
+ "pinia": "^2.x",
+ "vue": "^3.5.39",
+ "vue-router": "^4.x"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.7",
+ "sass": "^1.x",
"vite": "^8.1.1"
}
},
@@ -61,29 +67,22 @@
"node": ">=6.9.0"
}
},
- "node_modules/@emnapi/core": {
- "version": "1.11.1",
- "resolved": "https://registry.npmmirror.com/@emnapi/core/-/core-1.11.1.tgz",
- "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==",
- "dev": true,
+ "node_modules/@ctrl/tinycolor": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz",
+ "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==",
"license": "MIT",
- "optional": true,
- "peer": true,
- "dependencies": {
- "@emnapi/wasi-threads": "1.2.2",
- "tslib": "^2.4.0"
+ "engines": {
+ "node": ">=14"
}
},
- "node_modules/@emnapi/runtime": {
- "version": "1.11.1",
- "resolved": "https://registry.npmmirror.com/@emnapi/runtime/-/runtime-1.11.1.tgz",
- "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==",
- "dev": true,
+ "node_modules/@element-plus/icons-vue": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz",
+ "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==",
"license": "MIT",
- "optional": true,
- "peer": true,
- "dependencies": {
- "tslib": "^2.4.0"
+ "peerDependencies": {
+ "vue": "^3.2.0"
}
},
"node_modules/@emnapi/wasi-threads": {
@@ -97,6 +96,31 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.5.tgz",
+ "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.11"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.6",
+ "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.6.tgz",
+ "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.7.5",
+ "@floating-ui/utils": "^0.2.11"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.11.tgz",
+ "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
+ "license": "MIT"
+ },
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.5",
"resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
@@ -132,6 +156,327 @@
"url": "https://github.com/sponsors/Boshen"
}
},
+ "node_modules/@parcel/watcher": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.6.tgz",
+ "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "detect-libc": "^2.0.3",
+ "is-glob": "^4.0.3",
+ "node-addon-api": "^7.0.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher-android-arm64": "2.5.6",
+ "@parcel/watcher-darwin-arm64": "2.5.6",
+ "@parcel/watcher-darwin-x64": "2.5.6",
+ "@parcel/watcher-freebsd-x64": "2.5.6",
+ "@parcel/watcher-linux-arm-glibc": "2.5.6",
+ "@parcel/watcher-linux-arm-musl": "2.5.6",
+ "@parcel/watcher-linux-arm64-glibc": "2.5.6",
+ "@parcel/watcher-linux-arm64-musl": "2.5.6",
+ "@parcel/watcher-linux-x64-glibc": "2.5.6",
+ "@parcel/watcher-linux-x64-musl": "2.5.6",
+ "@parcel/watcher-win32-arm64": "2.5.6",
+ "@parcel/watcher-win32-ia32": "2.5.6",
+ "@parcel/watcher-win32-x64": "2.5.6"
+ }
+ },
+ "node_modules/@parcel/watcher-android-arm64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz",
+ "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-arm64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz",
+ "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-x64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz",
+ "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-freebsd-x64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz",
+ "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-glibc": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz",
+ "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-musl": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz",
+ "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-glibc": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz",
+ "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-musl": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz",
+ "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-x64-glibc": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz",
+ "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-x64-musl": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz",
+ "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-arm64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz",
+ "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-ia32": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz",
+ "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-x64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz",
+ "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@popperjs/core": {
+ "name": "@sxzz/popperjs-es",
+ "version": "2.11.8",
+ "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz",
+ "integrity": "sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/popperjs"
+ }
+ },
"node_modules/@rolldown/binding-android-arm64": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.4.tgz",
@@ -407,6 +752,28 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@types/lodash": {
+ "version": "4.17.24",
+ "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.24.tgz",
+ "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==",
+ "license": "MIT"
+ },
+ "node_modules/@types/lodash-es": {
+ "version": "4.17.12",
+ "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
+ "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/lodash": "*"
+ }
+ },
+ "node_modules/@types/web-bluetooth": {
+ "version": "0.0.21",
+ "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
+ "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
+ "license": "MIT"
+ },
"node_modules/@vitejs/plugin-vue": {
"version": "6.0.7",
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-6.0.7.tgz",
@@ -474,6 +841,12 @@
"@vue/shared": "3.5.39"
}
},
+ "node_modules/@vue/devtools-api": {
+ "version": "6.6.4",
+ "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
+ "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
+ "license": "MIT"
+ },
"node_modules/@vue/reactivity": {
"version": "3.5.39",
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.39.tgz",
@@ -524,12 +897,159 @@
"integrity": "sha512-l1rrBtBfTnmxvtsvdQDXltUUy8S1Y+ZaqdfUzmAnJkTd8Z8rv5v/ytW+TKiqEOWyHPoqtPlNFSs0lhRmYVSHVA==",
"license": "MIT"
},
+ "node_modules/@vueuse/core": {
+ "version": "14.3.0",
+ "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-14.3.0.tgz",
+ "integrity": "sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/web-bluetooth": "^0.0.21",
+ "@vueuse/metadata": "14.3.0",
+ "@vueuse/shared": "14.3.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "vue": "^3.5.0"
+ }
+ },
+ "node_modules/@vueuse/metadata": {
+ "version": "14.3.0",
+ "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-14.3.0.tgz",
+ "integrity": "sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/shared": {
+ "version": "14.3.0",
+ "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-14.3.0.tgz",
+ "integrity": "sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "vue": "^3.5.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/async-validator": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
+ "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==",
+ "license": "MIT"
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/axios": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmmirror.com/axios/-/axios-1.18.1.tgz",
+ "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.16.0",
+ "form-data": "^4.0.5",
+ "https-proxy-agent": "^5.0.1",
+ "proxy-from-env": "^2.1.0"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-5.0.0.tgz",
+ "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"license": "MIT"
},
+ "node_modules/dayjs": {
+ "version": "1.11.21",
+ "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.21.tgz",
+ "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==",
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/detect-libc": {
"version": "2.1.2",
"resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz",
@@ -540,6 +1060,46 @@
"node": ">=8"
}
},
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/element-plus": {
+ "version": "2.14.2",
+ "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.14.2.tgz",
+ "integrity": "sha512-eNH9uP3wQoNqieEIHXiNvIVv+zO5sZDU0CAZq5b0zqSN06DD0/V9xIq1R/qm3rw5k3nBTM1JvpxhCfRbaFLzDQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@ctrl/tinycolor": "^4.2.0",
+ "@element-plus/icons-vue": "^2.3.2",
+ "@floating-ui/dom": "^1.7.6",
+ "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.8",
+ "@types/lodash": "^4.17.24",
+ "@types/lodash-es": "^4.17.12",
+ "@vueuse/core": "14.3.0",
+ "async-validator": "^4.2.5",
+ "dayjs": "^1.11.20",
+ "lodash": "^4.18.1",
+ "lodash-es": "^4.18.1",
+ "lodash-unified": "^1.0.3",
+ "memoize-one": "^6.0.0",
+ "normalize-wheel-es": "^1.2.0",
+ "vue-component-type-helpers": "^3.3.3"
+ },
+ "peerDependencies": {
+ "vue": "^3.3.7"
+ }
+ },
"node_modules/entities": {
"version": "7.0.1",
"resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz",
@@ -552,6 +1112,51 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+ "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
@@ -576,6 +1181,42 @@
}
}
},
+ "node_modules/follow-redirects": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.16.0.tgz",
+ "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.6.tgz",
+ "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.4",
+ "mime-types": "^2.1.35"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
@@ -591,6 +1232,148 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/immutable": {
+ "version": "5.1.9",
+ "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.9.tgz",
+ "integrity": "sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/lightningcss": {
"version": "1.32.0",
"resolved": "https://registry.npmmirror.com/lightningcss/-/lightningcss-1.32.0.tgz",
@@ -852,6 +1635,31 @@
"url": "https://opencollective.com/parcel"
}
},
+ "node_modules/lodash": {
+ "version": "4.18.1",
+ "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz",
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/lodash-es": {
+ "version": "4.18.1",
+ "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.18.1.tgz",
+ "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/lodash-unified": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
+ "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/lodash-es": "*",
+ "lodash": "*",
+ "lodash-es": "*"
+ }
+ },
"node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz",
@@ -861,6 +1669,48 @@
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/memoize-one": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
+ "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
+ "license": "MIT"
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
"node_modules/nanoid": {
"version": "3.3.15",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.15.tgz",
@@ -879,6 +1729,20 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/node-addon-api": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz",
+ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/normalize-wheel-es": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
+ "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
@@ -899,6 +1763,28 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/pinia": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.3.1.tgz",
+ "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/devtools-api": "^6.6.3",
+ "vue-demi": "^0.14.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/posva"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.4.4",
+ "vue": "^2.7.0 || ^3.5.11"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/postcss": {
"version": "8.5.16",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.16.tgz",
@@ -927,6 +1813,29 @@
"node": "^10 || ^12 || >=14"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
+ "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-5.0.0.tgz",
+ "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
"node_modules/rolldown": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/rolldown/-/rolldown-1.1.4.tgz",
@@ -961,6 +1870,28 @@
"@rolldown/binding-win32-x64-msvc": "1.1.4"
}
},
+ "node_modules/sass": {
+ "version": "1.101.0",
+ "resolved": "https://registry.npmmirror.com/sass/-/sass-1.101.0.tgz",
+ "integrity": "sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "chokidar": "^5.0.0",
+ "immutable": "^5.1.5",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=20.19.0"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher": "^2.4.1"
+ }
+ },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -1095,6 +2026,53 @@
"optional": true
}
}
+ },
+ "node_modules/vue-component-type-helpers": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmmirror.com/vue-component-type-helpers/-/vue-component-type-helpers-3.3.6.tgz",
+ "integrity": "sha512-FkljacAwJ9BUoSUdpFe3VDy0sGigNlTH9+2zcXUWmZOjN8swiCkl3t48wOJun0OsUd2cEIda1l04tsxMiKIIrQ==",
+ "license": "MIT"
+ },
+ "node_modules/vue-demi": {
+ "version": "0.14.10",
+ "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
+ "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "vue-demi-fix": "bin/vue-demi-fix.js",
+ "vue-demi-switch": "bin/vue-demi-switch.js"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "@vue/composition-api": "^1.0.0-rc.1",
+ "vue": "^3.0.0-0 || ^2.6.0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/composition-api": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vue-router": {
+ "version": "4.6.4",
+ "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz",
+ "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/devtools-api": "^6.6.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/posva"
+ },
+ "peerDependencies": {
+ "vue": "^3.5.0"
+ }
}
}
}
diff --git a/frontend/package.json b/frontend/package.json
index 150e00b..ebb6c2b 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -9,10 +9,16 @@
"preview": "vite preview"
},
"dependencies": {
- "vue": "^3.5.39"
+ "vue": "^3.5.39",
+ "vue-router": "^4.x",
+ "pinia": "^2.x",
+ "axios": "^1.x",
+ "element-plus": "^2.x",
+ "@element-plus/icons-vue": "^2.x"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.7",
- "vite": "^8.1.1"
+ "vite": "^8.1.1",
+ "sass": "^1.x"
}
}