feat(部署): 新增 deployment/ 内外网两套按侧部署包

按 demo/ 的写法把交付包改成「角色由目录决定」:iw/ 拷内网机、ow/ 拷外网机,
各自含镜像 tar、SQL、配置与 install.sh,install.sh 不再收 iw/ow 参数。

前端不再打进镜像,改为静态包放在 <侧>/web/ 只读挂进 nginx:1.27-alpine,
现场临时改页面直接替换文件 + restart web 即可。数据仍全部挂宿主机,
子目录命名与 deploy/offline 一致(pgdata/redis/mq/upload/logs/gate),
默认根改为包内 ./volumes,放数据盘只改 .env 的 SFILE_DATA_ROOT。

后端镜像 sfile-app:1.0.1 含传输优化那一批(实测组包 11.4×、解包 9.9×)。
出包脚本 deployment/scripts/build-package.sh 负责 jar→镜像→前端双包→sql→tar→VERSION。
This commit is contained in:
KodouWZF
2026-11-04 21:44:56 +08:00
parent 339f2c34ab
commit d39b3b035d
884 changed files with 316455 additions and 0 deletions

71
deployment/iw/.env Normal file
View File

@@ -0,0 +1,71 @@
# =============================================================================
# s-file 部署配置 —— 内网机(iw)
#
# 装机后必须立刻改的两处:admin 登录口令(首次登录后在页面上改)、
# 新用户初始密码 USER_DEFAULT_PASSWORD
# 下面的库/MQ 口令是出厂默认值,交付单要抄一份并建议现场轮换。
# 现场改过的 .env 属于该台机器的实际配置,不要提交回仓库。
# =============================================================================
# ---------- 本机角色(内网机固定 iw,别改) ----------
SFILE_ROLE=iw
# 传输方向:内网机 1 / 外网机 2,写反了摆渡方向就反了
SFILE_TRANSFER_LOCATION=1
# ---------- 镜像(images/ 里的 tar docker load 后就是这些 tag) ----------
APP_IMAGE=sfile-app:1.1.0
NGINX_IMAGE=nginx:1.27-alpine
PG_IMAGE=postgres:18
REDIS_IMAGE=redis:8
MQ_IMAGE=rabbitmq:3.13-management-alpine
# postgres 18+ 数据目录挂载点是 /var/lib/postgresql,15- 要改成 /var/lib/postgresql/data
PG_DATA_DIR=/var/lib/postgresql
# ---------- 对外访问:只暴露前端 ----------
WEB_HOST=0.0.0.0
WEB_PORT=80
# ---------- 口令与密钥 ----------
POSTGRES_DB=s_file
POSTGRES_USER=sfile
POSTGRES_PASSWORD=Sfile-iw-Pg-N1tOz1MxgdaS
MQ_USER=sfile
MQ_PASSWORD=Sfile-iw-Mq-UTqVSnCDZ0LB
JWT_SECRET=86a6b015f3292eb3fdab298d3eced941da4276d47e24e924b82ab8adee397d70
USER_DEFAULT_PASSWORD=Sfile-iw-Usr-FBLS-0fA
# ---------- 发号器与容器网段(与外网机各用一段,同机并跑时才需要错开) ----------
APP_SUBNET=172.30.18.0/24
APP_GATEWAY=172.30.18.1
APP_NODE_IP=172.30.18.10
APP_WORK_ID=1
# ---------- 宿主机数据目录 ----------
# 默认落在本目录 volumes/ 下(相对 docker-compose.yml)。
# 要放到独立数据盘就改成绝对路径,例如 /data/sfile,改完 install.sh 会自动建目录
SFILE_DATA_ROOT=./volumes
# 光闸摆渡目录:out = 本机发出,in = 本机收到。
# 光闸设备要能访问到这两个路径,现场通常改成绝对路径并告知光闸厂商
GATE_SEND_DIR=./volumes/gate/out
GATE_RECV_DIR=./volumes/gate/in
# ---------- MeshSafe 文件安全检测 ----------
# 该侧没有部署 MeshSafe 就把 MESHSAFE_ENABLED 改成 false,下面几项可以不管
# 启用时凭证必须与 MeshSafe 侧 MESHSAFE_API_CLIENTS 白名单里的 client_id:secret 逐字一致
MESHSAFE_ENABLED=true
MESHSAFE_BASE_URL=http://host.docker.internal:44380
MESHSAFE_CLIENT_ID=sfile-iw
MESHSAFE_SECRET=CHANGE_ME_meshsafe_secret
MESHSAFE_CHANNEL=sfile-iw
# 等保从严建议 false:检测服务不可用时阻断而不是放行
MESHSAFE_FAIL_OPEN=true
MESHSAFE_TIMEOUT_SECONDS=120
MESHSAFE_POLL_TIMEOUT_MINUTES=60
MESHSAFE_POLL_CRON=0/10 * * * * ?
# ---------- 资源与运行时 ----------
TZ=Asia/Shanghai
APP_JAVA_OPTS=-Xms1g -Xmx3g -Dfile.encoding=UTF-8
REDIS_MAXMEMORY=512mb
# 摆渡目录监听周期。改这个要同步改 config/application.yml 的 round-budget-seconds(留 1 秒余量)
FILE_TRANSFER_MONITOR_CRON=0/5 * * * * ?

8
deployment/iw/.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
# 镜像 tar 是出包产物(约 640MB),不进 git
images/*.tar
images/SHA256SUMS.txt
dist/
# volumes/ 是运行时数据(pgdata / redis / mq / upload / logs / gate),不进 git
# 前端静态包在 web/,属于交付物,要进 git
volumes/

111
deployment/iw/README.md Normal file
View File

@@ -0,0 +1,111 @@
# s-file 内网机部署包(iw)
本目录**就是**一台内网服务器的完整部署包:镜像 tar、前端静态包、SQL、配置、安装脚本都在里面,
整目录拷到内网机即可装机,不需要联网、不需要回仓库取任何东西。
外网机用同级的 `../ow/`,两份除了 `.env` 与 `web/`(前端内/外网包)之外完全一样。
完整拓扑、两侧差异表、已知坑见仓库里的 [`../部署说明.md`](../部署说明.md)。
---
## 1. 装机(三步)
```bash
# 1) 整目录拷到内网机,例如 /opt/sfile-iw
cd /opt/sfile-iw
# 2) 改配置:至少确认 MeshSafe(没接检测就把 MESHSAFE_ENABLED 改成 false)
vi .env
# 3) 一键装:自检 -> 校验并载入镜像 -> 建数据目录 -> 起栈 -> 等健康
./scripts/install.sh
```
装完会打印访问地址 `http://<本机IP>:<WEB_PORT>`。**首次登录后立刻改掉 admin 的初始口令。**
重复执行 `install.sh` 是安全的:只重建有差异的容器,不动已初始化好的数据库。
---
## 2. 目录说明
```
├── docker-compose.yml 5 个服务(web/app/pg/redis/mq),现场不改
├── .env 本机全部可变项:角色/端口/口令/目录/MeshSafe ← 只改这个
├── config/application.yml 后端静态默认配置,不放任何口令(口令走 .env 注入)
├── nginx/web.conf 前端站点 + /api 反代,改端口/上传上限时看这里
├── web/ 前端静态包(内网包),挂进 nginx 当站点根
├── sql/01-init-table.sql 全量建表 02-init-data.sql 初始数据(admin、机构、平台编码)
├── sql/upgrade/ 已上线老库的增量脚本,新装不用跑(见 sql/README.md)
├── images/*.tar 5 个镜像 + SHA256SUMS.txt
├── scripts/install.sh 一键安装
└── volumes/ 运行时数据,install.sh 自动创建
├── pgdata/ redis/ mq/ 三个中间件的数据
├── upload/ 用户上传的文件本体
├── logs/ 后端日志(logs/nginx 是前端访问日志)
└── gate/out/ gate/in/ 光闸摆渡:本机发出 / 本机收到
```
数据全在宿主机 `volumes/` 下,容器删了数据还在。要放到独立数据盘就改 `.env` 的
`SFILE_DATA_ROOT`(以及 `GATE_SEND_DIR`/`GATE_RECV_DIR`)为绝对路径,重跑 `install.sh`。
---
## 3. 现场要确认的 6 件事(都在 `.env`)
| 项 | 变量 | 内网机出厂值 / 建议 |
|---|---|---|
| 前端对外端口 | `WEB_PORT` | `80`;被占用就改 8080/9080,同步改访问地址 |
| 数据盘根目录 | `SFILE_DATA_ROOT` | `./volumes`;正式环境建议改绝对路径指到独立数据盘(≥200G) |
| 光闸摆渡目录 | `GATE_SEND_DIR` / `GATE_RECV_DIR` | `./volumes/gate/out` / `in`;**与光闸厂商确认挂载点**,发出与收到必须是两个不同目录 |
| 传输方向 | `SFILE_TRANSFER_LOCATION` | 内网机固定 `1`(外网机是 `2`)。**写反了摆渡方向就反了** |
| MeshSafe | `MESHSAFE_ENABLED` / `_BASE_URL` / `_CLIENT_ID` / `_SECRET` | 没接检测 → `MESHSAFE_ENABLED=false`;接了 → secret 必须与 MeshSafe 侧 `MESHSAFE_API_CLIENTS` 白名单里的 `client_id:secret` 逐字一致 |
| 口令 | `POSTGRES_PASSWORD` / `MQ_PASSWORD` / `JWT_SECRET` / `USER_DEFAULT_PASSWORD` | 出厂已给随机值可直接跑;`USER_DEFAULT_PASSWORD` 是新建用户的初始密码,**必须改并告知业务员** |
---
## 4. 改前端页面(不用重建镜像)
前端是解压好的静态包,`web/` 就是站点根:
```bash
# 替换整个前端包
rm -rf web && cp -r /path/to/new/dist web
docker compose restart web
# 只改单个文件(例如临时改个文案)
vi web/assets/xxx.js # 或替换 index.html
docker compose restart web # 浏览器再强刷一次(Ctrl+F5)
```
`web/` 是只读挂载,容器不会写它;改坏了从仓库 `frontend/` 重新构建一份覆盖即可。
构建产物的文件名自带 hash,`index.html` 不做缓存,所以换包后用户浏览器会自动取到新文件。
---
## 5. 运维
```bash
docker compose ps # 状态(5 个都该是 healthy)
docker logs -f sfile-iw-app # 后端日志(含送检/摆渡全过程)
docker compose restart app # 改完 .env / config 后重启后端
docker compose restart web # 替换 web/ 里的前端文件后刷新站点
docker compose down # 停止(不动数据)
```
**备份只需三样**:`volumes/pgdata`(库)、`volumes/upload`(文件本体)、`.env`(口令)。
恢复:换机器后按原路径放回 + `docker load` + `./scripts/install.sh`。
改了 `.env` 里的口令/网段这类**建容器时固化**的值,光 `restart` 不生效,要
`docker compose up -d`(重建容器)。数据库口令属于建库时写入,改它要连 `volumes/pgdata` 一起处理。
---
## 6. 装不上时先看这三条
1. `images/` 少 tar 或 sha256 不对 → 交付盘拷坏了,重拷(`install.sh` 会明确报哪一条)。
2. 架构不符(信创 ARM 机装了 amd64 包)→ `install.sh` 会拦;回构建机用 `TARGET_PLATFORM=linux/arm64` 重新出包。
3. 端口/网段与机器上已有容器冲突 → 改 `.env` 的 `WEB_PORT`,或整段换 `APP_SUBNET`/`APP_GATEWAY`/`APP_NODE_IP`(三个值必须同网段)。
其余坑(发号器 workerId、nginx 透传 Host、PostgreSQL 18 数据目录挂载点、监听周期与传输快慢)
见 [`../部署说明.md`](../部署说明.md) 最后一节。

19
deployment/iw/VERSION.txt Normal file
View File

@@ -0,0 +1,19 @@
s-file 部署包 1.1.0(内网机 iw)
构建平台: linux/amd64
导出时间: 2026-11-04 21:34:45
后端 jar: fa77c56(+ 未提交改动则与本仓库当前源码一致)
镜像清单(sha256 见 images/SHA256SUMS.txt):
nginx.tar 21M "RepoTags":["nginx:1.27-alpine"]
postgres.tar 161M "RepoTags":["postgres:18"]
rabbitmq.tar 84M "RepoTags":["rabbitmq:3.13-management-alpine"]
redis.tar 53M "RepoTags":["redis:8"]
sfile-app.tar 313M "RepoTags":["sfile-app:1.1.0"]
前端静态包: web/(内网包/外网包已分别就位,改页面直接替换文件)
SQL: sql/01-init-table.sql sql/02-init-data.sql 老库增量: sql/upgrade/
现场步骤(本机执行):
1) 整目录拷到服务器,例如 /opt/sfile-iw && cd /opt/sfile-iw
2) vi .env # 至少确认 MESHSAFE_ENABLED/SECRET、WEB_PORT、SFILE_DATA_ROOT、GATE_*
3) ./scripts/install.sh

View File

@@ -0,0 +1,110 @@
# =============================================================================
# s-file 客户侧静态默认配置(两台机器共用同一份,现场一般不用改)
#
# 随角色/环境变化的取值一律由 docker-compose 的环境变量注入,本文件不放:
# 数据库/Redis/MQ 地址与口令、JWT 密钥、用户初始密码、传输方向与摆渡目录、
# MeshSafe 开关与凭证、MQ 交换机命名 —— 全部在 .env 里填
# 这样交付物里不存在任何写死的口令或密钥
# =============================================================================
server:
port: 8080
spring:
application:
name: s-file
datasource:
driver-class-name: org.postgresql.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5
min-idle: 5
max-active: 50
validation-query: SELECT 1
test-while-idle: true
# 摆渡解包/送检会在多任务里并发取连接,压太低会出现等待
max-wait: 10000
redis:
timeout: 5000
lettuce:
pool:
max-active: 16
max-idle: 8
servlet:
multipart:
max-file-size: 500MB
max-request-size: 500MB
main:
allow-bean-definition-overriding: true
mybatis-plus:
mapper-locations: classpath*:com/senmesh/**/mapper/*.xml
# 平台编码,需与 sql/02-init-data.sql 里 uc_platform.platform_code 一致
system:
code: 1
security:
jwt:
enable: true
# secret 由环境变量 SECURITY_JWT_SECRET 注入,勿在此填写
expiration: 86400000
header: Authorization
ignoring: /error,/favicon.ico
login-page: /login
superior-only: false
# 单机自闭环部署:权限走本地库,不接外部用户中心
use-local: true
allow-if-all-abstain-decisions: true
oauth2:
enable: false
not-logs: ""
anonymous: ""
# 新用户初始密码由环境变量 USER_DEFAULT_PASSWORD 注入
user:
default:
password: ${USER_DEFAULT_PASSWORD:}
file:
upload-dir: /data/upload
storage:
type: local
transfer:
# location / send-dir / receive-dir / monitor.cron 均由环境变量注入
# 解包时是否再做一次内容风险识别(依赖下面的 dify,未部署 dify 时保持 false)
unpack-risk-check: false
monitor:
# 单轮处理时间预算(秒)。超预算即结束本轮,剩余留给下一轮。
# 与监听周期配套:周期 5 秒则预算留 4 秒,保证两轮不互相挤压。
# 目录持续积压(日志「目录剩余待处理」超过 50)时调大此值
round-budget-seconds: 4
# 单轮兜底个数上限,防止极端场景单轮过长
round-max-files: 500
# 包内单个文件大小上限(MB)。解包时整个文件读进堆,峰值约 2-3 倍文件大小,
# 超限直接标 .error 而不是解包到 OOM。按 APP_JAVA_OPTS 的 -Xmx 调整:-Xmx3g 对应 512
max-unpack-size-mb: 512
# 校验不通过或解包异常,且文件静止超过该秒数即判定为坏包,标 .error 停止重试。
# 用于区分「光闸还在搬」与「搬完了但是坏包」,必须大于光闸搬运单个包的最长时间
stale-after-seconds: 300
# 内容风险识别(Dify)。未部署 Dify 时留空并保持 file.transfer.unpack-risk-check=false
dify:
risk:
rule:
api-key: ""
scan:
api-key: ""
# MeshSafe 全段由环境变量注入(MESHSAFE_*),未部署时 MESHSAFE_ENABLED=false 即可,
# 前端会自动隐藏「安全检测」列,跨网摆渡不受影响
meshsafe:
review-sync-to-meshsafe: true
# 接口文档在生产关闭
swagger:
enable: false
logging:
level:
com.senmesh: info

View File

@@ -0,0 +1,192 @@
# =============================================================================
# s-file 信创文件安全传输系统 —— 单台服务器一套(内网机 iw / 外网机 ow 通用同一份)
#
# 两台机器之间只靠光闸摆渡目录互通,彼此不开任何网络端口。
# 随角色变化的取值全在同目录 .env 里,本文件现场不用改。
#
# ./scripts/install.sh 自检 -> 校验并载入 images/*.tar -> 建目录 -> 起栈 -> 等健康
#
# 数据一律落在宿主机,不建 docker 卷(默认在本目录 volumes/ 下,见 .env 的 SFILE_DATA_ROOT):
# volumes/pgdata PostgreSQL 数据 volumes/redis Redis AOF
# volumes/mq RabbitMQ 数据 volumes/upload 用户上传的文件本体
# volumes/logs 后端日志(+logs/nginx) volumes/gate/out|in 光闸发出/收到的传输包
#
# 前端是已构建好的静态包,直接放在 web/ 目录挂进 nginx:
# 改页面 = 替换 web/ 下的文件,docker compose restart web 即可,不用重新构建镜像。
#
# 只发布前端端口;后端 / PostgreSQL / Redis / RabbitMQ 仅在容器网络内可达。
# =============================================================================
name: sfile-${SFILE_ROLE:?缺少 SFILE_ROLE(内网机 iw / 外网机 ow)}
services:
web:
image: ${NGINX_IMAGE:?缺少 NGINX_IMAGE}
container_name: sfile-${SFILE_ROLE}-web
restart: unless-stopped
ports:
- "${WEB_HOST:-0.0.0.0}:${WEB_PORT:-80}:80"
environment:
TZ: ${TZ:-Asia/Shanghai}
volumes:
- ./nginx/web.conf:/etc/nginx/conf.d/default.conf:ro
# 前端静态包:宿主机 web/ 目录即站点根,替换文件即换页面
- ./web:/usr/share/nginx/html:ro
- ${SFILE_DATA_ROOT:?缺少 SFILE_DATA_ROOT}/logs/nginx:/var/log/nginx
depends_on:
app:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -sf -o /dev/null http://127.0.0.1:80/ || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
networks: [sfile]
app:
image: ${APP_IMAGE:?缺少 APP_IMAGE}
container_name: sfile-${SFILE_ROLE}-app
restart: unless-stopped
stop_grace_period: 30s
environment:
TZ: ${TZ:-Asia/Shanghai}
# 发号器 workerId 按「容器 IP」取键,取不到会回退 99 而 99 > 31 直接启动失败,
# 因此这里锁死 app 的容器 IP,并把同一个键写进 JVM 参数,两处永远一致
JAVA_OPTS: "${APP_JAVA_OPTS:--Xms1g -Xmx3g -Dfile.encoding=UTF-8} -Dcode.snowflake.workid.${APP_NODE_IP:?缺少 APP_NODE_IP}=${APP_WORK_ID:?缺少 APP_WORK_ID}"
SPRING_CONFIG_ADDITIONAL_LOCATION: file:/config/application.yml
SPRING_DATASOURCE_URL: jdbc:postgresql://pg:5432/${POSTGRES_DB:?缺少 POSTGRES_DB}
SPRING_DATASOURCE_USERNAME: ${POSTGRES_USER:?缺少 POSTGRES_USER}
SPRING_DATASOURCE_PASSWORD: ${POSTGRES_PASSWORD:?缺少 POSTGRES_PASSWORD}
SPRING_REDIS_HOST: redis
SPRING_REDIS_PORT: 6379
SPRING_RABBITMQ_HOST: mq
SPRING_RABBITMQ_PORT: 5672
SPRING_RABBITMQ_USERNAME: ${MQ_USER:?缺少 MQ_USER}
SPRING_RABBITMQ_PASSWORD: ${MQ_PASSWORD:?缺少 MQ_PASSWORD}
# 两侧交换机/广播 ID 必须不同,防止有人把两套栈并到一台机器时串消息
RABBITMQ_CUSTOM_TOPIC_EXCHANGE_NAME: s-file-${SFILE_ROLE}-topic
RABBITMQ_CUSTOM_DELAYED_EXCHANGE_NAME: s-file-${SFILE_ROLE}-delayed
RABBITMQ_CUSTOM_BROADCAST_ID: s-file-${SFILE_ROLE}-broadcast
SECURITY_JWT_SECRET: ${JWT_SECRET:?缺少 JWT_SECRET}
USER_DEFAULT_PASSWORD: ${USER_DEFAULT_PASSWORD:?缺少 USER_DEFAULT_PASSWORD}
# 内网机 1 / 外网机 2,写反了摆渡方向就反了
FILE_TRANSFER_LOCATION: "${SFILE_TRANSFER_LOCATION:?缺少 SFILE_TRANSFER_LOCATION}"
FILE_TRANSFER_SEND_DIR: /data/transfer/send
FILE_TRANSFER_RECEIVE_DIR: /data/transfer/receive
FILE_TRANSFER_MONITOR_CRON: "${FILE_TRANSFER_MONITOR_CRON:-0/5 * * * * ?}"
MESHSAFE_ENABLED: ${MESHSAFE_ENABLED:-true}
MESHSAFE_BASE_URL: ${MESHSAFE_BASE_URL:-}
MESHSAFE_CLIENT_ID: ${MESHSAFE_CLIENT_ID:-}
MESHSAFE_SECRET: ${MESHSAFE_SECRET:-}
MESHSAFE_CHANNEL: ${MESHSAFE_CHANNEL:-sfile-${SFILE_ROLE}}
MESHSAFE_FAIL_OPEN: ${MESHSAFE_FAIL_OPEN:-true}
MESHSAFE_TIMEOUT_SECONDS: ${MESHSAFE_TIMEOUT_SECONDS:-120}
MESHSAFE_POLL_TIMEOUT_MINUTES: ${MESHSAFE_POLL_TIMEOUT_MINUTES:-60}
MESHSAFE_POLL_CRON: ${MESHSAFE_POLL_CRON:-0/10 * * * * ?}
volumes:
- ./config/application.yml:/config/application.yml:ro
- ${SFILE_DATA_ROOT}/upload:/data/upload
- ${SFILE_DATA_ROOT}/logs:/app/logs
# 摆渡目录:容器内固定路径,宿主机侧由光闸设备负责单向搬运
- ${GATE_SEND_DIR:?缺少 GATE_SEND_DIR}:/data/transfer/send
- ${GATE_RECV_DIR:?缺少 GATE_RECV_DIR}:/data/transfer/receive
# MeshSafe 与应用同机部署时靠它从容器内访问宿主机端口;
# Docker < 20.10 不支持 host-gateway,或 MeshSafe 在独立服务器时,删掉这两行即可
extra_hosts:
- "host.docker.internal:host-gateway"
depends_on:
pg:
condition: service_healthy
redis:
condition: service_healthy
mq:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -s --max-time 5 -o /dev/null http://127.0.0.1:8080/ || exit 1"]
interval: 30s
timeout: 8s
retries: 5
# 首次建库要跑全量 DDL,冷启动给足时间
start_period: 180s
networks:
sfile:
ipv4_address: ${APP_NODE_IP}
pg:
image: ${PG_IMAGE:?缺少 PG_IMAGE}
container_name: sfile-${SFILE_ROLE}-pg
restart: unless-stopped
stop_grace_period: 60s
environment:
TZ: ${TZ:-Asia/Shanghai}
POSTGRES_DB: ${POSTGRES_DB:?缺少 POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER:?缺少 POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?缺少 POSTGRES_PASSWORD}
# 空库首次启动才执行 initdb.d,已有数据卷时会被忽略
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --lc-collate=C --lc-ctype=C"
volumes:
# postgres 18+ 数据目录挂载点是 /var/lib/postgresql,15- 是 .../data,见 .env 的 PG_DATA_DIR
- ${SFILE_DATA_ROOT}/pgdata:${PG_DATA_DIR:-/var/lib/postgresql}
- ./sql/01-init-table.sql:/docker-entrypoint-initdb.d/01-init-table.sql:ro
- ./sql/02-init-data.sql:/docker-entrypoint-initdb.d/02-init-data.sql:ro
healthcheck:
# 必须强制走 TCP(-h 127.0.0.1):首次 initdb 期间镜像会临时起一个只听 unix socket
# 的实例,此时用默认 socket 探测也会返回成功,导致 app 抢跑连库失败
test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 10
start_period: 60s
networks: [sfile]
redis:
image: ${REDIS_IMAGE:?缺少 REDIS_IMAGE}
container_name: sfile-${SFILE_ROLE}-redis
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes", "--maxmemory", "${REDIS_MAXMEMORY:-512mb}", "--maxmemory-policy", "allkeys-lru"]
environment:
TZ: ${TZ:-Asia/Shanghai}
volumes:
- ${SFILE_DATA_ROOT}/redis:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5
networks: [sfile]
mq:
image: ${MQ_IMAGE:?缺少 MQ_IMAGE}
container_name: sfile-${SFILE_ROLE}-mq
restart: unless-stopped
stop_grace_period: 30s
environment:
TZ: ${TZ:-Asia/Shanghai}
RABBITMQ_DEFAULT_USER: ${MQ_USER:?缺少 MQ_USER}
RABBITMQ_DEFAULT_PASS: ${MQ_PASSWORD:?缺少 MQ_PASSWORD}
volumes:
- ${SFILE_DATA_ROOT}/mq:/var/lib/rabbitmq
healthcheck:
test: ["CMD-SHELL", "rabbitmq-diagnostics -q ping"]
interval: 20s
timeout: 10s
retries: 10
start_period: 60s
networks: [sfile]
networks:
sfile:
driver: bridge
ipam:
config:
# 锁 app 容器 IP 是为了发号器 workerId 取键;subnet/网关/app IP 三个值必须同网段。
# 若与客户机器上已有 docker 网段冲突,整段换掉(如 172.31.88.0/24)即可
- subnet: ${APP_SUBNET:?缺少 APP_SUBNET}
gateway: ${APP_GATEWAY:?缺少 APP_GATEWAY}

View File

@@ -0,0 +1,44 @@
server {
listen 80;
server_name _;
charset utf-8;
# 站点根 = 宿主机 web/ 目录(compose 里 ./web:/usr/share/nginx/html:ro)
# 临时改页面:替换 web/ 下的文件后 docker compose restart web,不用重建镜像
root /usr/share/nginx/html;
index index.html;
# 与后端 multipart 上限(500MB)保持一致,改这里要同步改 config/application.yml
client_max_body_size 500m;
client_body_timeout 300s;
# /api/xxx -> 后端 /xxx(去掉 /api 前缀,与前端构建时的 VITE_API_URL=/api 对应)
# app 是 compose 里的服务名,改了服务名这里要跟着改
location /api/ {
proxy_pass http://app:8080/;
proxy_http_version 1.1;
# 必须保留端口($http_host):后端 getRootDomain 对「无端口的 IP/localhost」会抛
# IllegalStateException,导致登录成功回调 500。改成 $host 就会复现这个坑
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 60s;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
# 大文件上传不在 nginx 侧缓冲,直接流给后端
proxy_request_buffering off;
}
# SPA:hash 路由,静态资源找不到时回落 index.html
location / {
try_files $uri $uri/ /index.html;
}
# 构建产物的文件名自带 hash,可以放心缓存;index.html 不在其中,换包后浏览器直接拿到新的
location ~* \.(js|mjs|css|woff2?|ttf|png|jpe?g|gif|svg|ico)$ {
expires 7d;
access_log off;
}
}

198
deployment/iw/scripts/install.sh Executable file
View File

@@ -0,0 +1,198 @@
#!/usr/bin/env bash
# =============================================================================
# s-file 一键安装(在本机执行;内网机用 iw/ 那份,外网机用 ow/ 那份)
#
# cd /opt/sfile-iw && ./scripts/install.sh
#
# 做六件事:环境自检 -> 校验交付物 -> 校验并载入镜像 tar -> 建数据目录 -> 起栈 -> 等健康
# 幂等:重复执行只重建有差异的容器,不动已初始化好的数据库
# 本目录就是配置:角色/口令/端口/目录全在同级 .env 里,改完重跑本脚本即可
# =============================================================================
set -euo pipefail
HERE="$(cd "$(dirname "$0")/.." && pwd)"
cd "$HERE"
envget() { grep -E "^[[:space:]]*$1=" .env | tail -1 | cut -d= -f2- | tr -d '"' | sed 's/[[:space:]]*$//'; }
step() { printf '\n\033[1;36m==> %s\033[0m\n' "$1"; }
die() { printf '\033[1;31m!!! %s\033[0m\n' "$1" >&2; exit 1; }
[ -f .env ] || die "缺少 .env(交付包不完整,本目录下应有一份出厂 .env)"
ROLE="$(envget SFILE_ROLE)"
case "$ROLE" in
iw|ow) ;;
*) die ".env 里 SFILE_ROLE=「$ROLE」不合法,只能是 iw(内网机)或 ow(外网机)" ;;
esac
echo "本机角色:$ROLE(传输方向 location=$(envget SFILE_TRANSFER_LOCATION))"
# ---------- 1. 前置自检 ----------
step "检查 docker 与 compose"
command -v docker >/dev/null 2>&1 || die "未安装 docker,请先装 Docker Engine(信创系统用厂商源,版本号 >= 20.10)"
docker info >/dev/null 2>&1 || die "docker 守护进程不可用,检查服务是否启动、当前用户是否在 docker 组"
if docker compose version >/dev/null 2>&1; then
DC="docker compose"
elif command -v docker-compose >/dev/null 2>&1; then
DC="docker-compose"
else
die "缺少 compose:安装 docker compose v2 插件,或用 docker-compose 命令"
fi
echo " 使用:$DC"
echo " docker server:$(docker version --format '{{.Server.Version}}')"
if grep -q "CHANGE_ME" .env; then
# MeshSafe 的 secret 只有真的启用检测时才必须填,否则现场没接 MeshSafe 就装不了机
if [ "$(envget MESHSAFE_ENABLED)" = "true" ] && grep -qE "^MESHSAFE_SECRET=.*CHANGE_ME" .env; then
die "启用了 MeshSafe 但 MESHSAFE_SECRET 还是占位值:按 MeshSafe 交付单改成白名单里的 secret,或把 MESHSAFE_ENABLED 改成 false"
fi
rest="$(grep -n CHANGE_ME .env | grep -v '^.*MESHSAFE_SECRET=' | cut -d: -f2 | tr '\n' ' ')"
[ -z "$rest" ] || die ".env 里还有 CHANGE_ME 未替换:$rest"
fi
step "检查交付物"
[ -d images ] || die "缺少 images/ 目录(镜像 tar 应在本目录的 images/ 下)"
tar_count=$(find images -maxdepth 1 -name '*.tar' | wc -l)
[ "$tar_count" -eq 5 ] || die "images/ 下应有 5 个 .tar(app/nginx/postgres/redis/rabbitmq),实际 $tar_count 个:$(ls images)"
for f in sql/01-init-table.sql sql/02-init-data.sql config/application.yml nginx/web.conf; do
[ -s "$f" ] || die "缺少 $f(交付包不完整)"
done
# 前端是静态包,缺了 nginx 起来只有默认页,看着像装好了其实没有界面
[ -s web/index.html ] || die "缺少 web/index.html —— 前端静态包没随包带过来"
[ -n "$(ls -A web/assets 2>/dev/null)" ] || die "web/assets 是空的 —— 前端静态包不完整"
echo " 镜像 tar:5 个,SQL / 后端配置 / nginx 配置 / 前端包就位"
# 端口占用先探一次:装到一半发现 80 被占,回滚比改 .env 麻烦
WEB_PORT="$(envget WEB_PORT)"
if command -v ss >/dev/null 2>&1 && ss -ltn 2>/dev/null | awk '{print $4}' | grep -qE "[:.]${WEB_PORT:-80}$"; then
printf ' \033[1;33m提示:宿主机 %s 端口已被占用,改 .env 的 WEB_PORT 后重跑\033[0m\n' "${WEB_PORT:-80}"
fi
# ---------- 2. 校验交付盘 + 镜像架构 ----------
# 650M 的 tar 经 U 盘/内网 scp 拷坏是最常见的现场故障,坏包 load 到一半才报错更难查
if [ -f images/SHA256SUMS.txt ] && [ "${SKIP_CHECKSUM:-0}" != "1" ]; then
step "校验镜像 tar 完整性(sha256,约半分钟)"
( cd images && sha256sum -c SHA256SUMS.txt ) \
|| die "有 tar 与 SHA256SUMS.txt 不一致:交付盘拷坏了,重新拷一份;确认无碍可 SKIP_CHECKSUM=1 跳过"
fi
step "核对镜像架构"
HOST_ARCH="$(uname -m)"
case "$HOST_ARCH" in
x86_64) EXPECT="amd64" ;;
aarch64|arm64) EXPECT="arm64" ;;
*) EXPECT="unknown" ;;
esac
echo " 本机:$HOST_ARCH (期望镜像架构 ${EXPECT})"
# 架构在镜像的 config blob 里,不在 manifest.json —— manifest.json 只给 Config 的路径
tar_arch() {
local t="$1" cfg
cfg="$(tar -xOf "$t" manifest.json 2>/dev/null | tr -d '\n' \
| { grep -oE '"Config":"[^"]+"' || true; } | awk -F'"' 'NR==1{print $4}')"
[ -n "$cfg" ] || { echo ""; return 0; }
tar -xOf "$t" "$cfg" 2>/dev/null | tr -d '\n' \
| { grep -oE '"architecture":"[a-z0-9-]+"' || true; } | awk -F'"' 'NR==1{print $4}'
}
if [ "$EXPECT" != "unknown" ]; then
# app 和 pg 各查一个:一个是自己构建的,一个是基础镜像,架构错了必是出盘时选错平台
for t in images/sfile-app.tar images/postgres.tar; do
[ -f "$t" ] || continue
# 不能用 `| head -1`:pipefail 下 head 提前关管道会让上游 grep 收到 SIGPIPE(141),脚本静默中断
IMG_ARCH="$(tar_arch "$t")"
if [ -n "${IMG_ARCH:-}" ] && [ "$IMG_ARCH" != "$EXPECT" ]; then
die "$(basename "$t") 是 $IMG_ARCH,本机是 $EXPECT —— 别硬装,回来重出对应架构的包"
fi
printf ' %-18s %s\n' "$(basename "$t")" "${IMG_ARCH:-未识别,继续}"
done
fi
# ---------- 3. 载入镜像 ----------
step "docker load 载入离线镜像"
for t in images/*.tar; do
echo " <- $t"
docker load -i "$t"
done
# compose 用的是 .env 里的 tag,缺一个就会去联网拉,离线机上直接卡死
for img in "$(envget APP_IMAGE)" "$(envget NGINX_IMAGE)" "$(envget PG_IMAGE)" \
"$(envget REDIS_IMAGE)" "$(envget MQ_IMAGE)"; do
docker image inspect "$img" >/dev/null 2>&1 \
|| die "载入后仍看不到镜像 $img —— tar 与 .env 的 tag 不一致,别继续,回来看 images/ 和 .env"
echo " ✓ $img"
done
# ---------- 4. 目录 ----------
step "创建数据与摆渡目录"
DATA_ROOT="$(envget SFILE_DATA_ROOT)"
GATE_SEND="$(envget GATE_SEND_DIR)"
GATE_RECV="$(envget GATE_RECV_DIR)"
[ -n "$DATA_ROOT" ] || die ".env 里 SFILE_DATA_ROOT 为空"
mkdir -p "$DATA_ROOT"/{upload,logs/nginx,pgdata,redis,mq}
mkdir -p "$GATE_SEND" "$GATE_RECV"
# 数据盘挂载点没起来时直接建目录会落到根分区,先确认一下
case "$DATA_ROOT" in
/*) mountpoint -q "$DATA_ROOT" 2>/dev/null \
|| printf ' \033[1;33m提示:%s 不是独立挂载点,确认容量够(上传+库+日志)\033[0m\n' "$DATA_ROOT" ;;
*) echo " 数据目录用本目录下的相对路径:$(cd "$DATA_ROOT" && pwd)" ;;
esac
# pgdata 提前给到容器内 postgres 的 uid=999,避免镜像入口脚本 chown 失败;
# redis/mq 的官方入口脚本自己会改属主,这里只保证目录存在且可写
chown -R 999:999 "$DATA_ROOT/pgdata" 2>/dev/null || true
chmod -R 750 "$DATA_ROOT" 2>/dev/null || true
# SELinux(麒麟/统信多为 enforcing):无 :z 标记的绑定挂载需要放开标签,否则库起不来、
# nginx 读不到前端包(表现为 403)。这里把 compose 里所有 bind 挂载点都标一遍
if command -v chcon >/dev/null 2>&1; then
chcon -Rt svirt_sandbox_file_t \
"$HERE/config" "$HERE/nginx" "$HERE/web" "$HERE/sql" \
"$DATA_ROOT" "$GATE_SEND" "$GATE_RECV" 2>/dev/null \
|| echo " chcon 失败(未启用 SELinux 可忽略)"
fi
echo " $DATA_ROOT / $GATE_SEND / $GATE_RECV 就位"
# ---------- 5. 起栈 ----------
step "启动服务(首次建库约 1-3 分钟)"
$DC up -d
step "等待健康检查"
for svc in pg redis mq app web; do
name="sfile-${ROLE}-${svc}"
printf ' %-24s ' "$name"
st=""
for _ in $(seq 1 60); do
st="$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$name" 2>/dev/null || echo missing)"
case "$st" in
healthy|running) printf '\033[32m%s\033[0m\n' "$st"; break ;;
missing) sleep 2 ;;
*) sleep 5 ;;
esac
done
if [ "$st" != "healthy" ] && [ "$st" != "running" ]; then
printf '\033[31m超时(最后状态:%s)\033[0m\n' "${st:-unknown}"
$DC ps
echo " 看日志:docker logs --tail 200 ${name}"
exit 1
fi
done
# ---------- 6. 出口信息 ----------
IP="$(hostname -I 2>/dev/null | tr ' ' '\n' | { grep -E '^[0-9]+\.' || true; } | awk 'NR==1{print}')"
step "完成"
cat <<EOF
访问地址: http://${IP:-<本机IP>}:${WEB_PORT:-80}
角色: ${ROLE}(传输方向 location=$(envget SFILE_TRANSFER_LOCATION))
数据目录: $(cd "$DATA_ROOT" && pwd)
摆渡: 发出 $GATE_SEND / 收到 $GATE_RECV
MeshSafe: $(envget MESHSAFE_ENABLED) -> $(envget MESHSAFE_BASE_URL)
常用命令:
$DC ps 看状态
docker logs -f sfile-${ROLE}-app 看后端日志
$DC restart app 改完 .env / config 后重启后端
$DC restart web 替换 web/ 里的前端文件后刷新站点
EOF
echo " 首次登录后立刻改掉 admin 的默认口令。"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
-- 系统uc_platform
INSERT INTO uc_platform
(platform_code, name, full_name, short_name, business, deleted, create_time)
VALUES(1, '文档系统', 's-file', 'file', true, FALSE, now());
-- 平台机构/平台机构管理员
INSERT INTO xs_org
(org_name, org_code, type, address_code, address_name, description, quality, enable, activated, parent_id, credit_code, trade, deleted, create_by, create_time, update_by, update_time, proxy_by, activation_code, phone, query_children, org_logo, registered_address, company_size, business_license, recruit_position_type)
VALUES('senmesh', 'O001', '1', '440232', NULL, NULL, false, TRUE, TRUE, NULL, '', NULL, FALSE, 0, now(), 1, now(), null, NULL, null, NULL, null, '1234', '6', null, '1');
INSERT INTO uc_user
(username, password, type, supeiror, security_code, nickname, avatar, phone, phone_binding, real_name, card_no, authenticated, status, email, address, education, init_user_id, enabled, account_non_expired, account_non_locked, credentials_non_expired, deleted, create_by, create_time, update_by, update_time, proxy_by, gender, birthday)
VALUES('admin', '$2a$10$0N3iaxx2sYv0hXvYzS4.6.yriL.DfjRTjED7Y4vkqxzbxi2dNpBou', 1, TRUE, '$2a$10$mGA1jdBzq8micEr02KiJ9OiYQz1fc/PSVG0hN0EYUuxhZp8EI1M2q', '平台管理员', '', '13888888888', TRUE, '平台管理员', NULL, FALSE, 2, null, NULL, NULL, NULL, TRUE, TRUE, TRUE, TRUE, FALSE, 0, now(), 1, NULL, NULL, NULL, NULL);
INSERT INTO uc_org_user
(user_id, org_id, administrator, deleted, create_by, create_time, update_by, update_time, proxy_by)
VALUES(1, 1, TRUE, FALSE, 0, now(), NULL, NULL, NULL);
-- 平台uc_org_relation
INSERT INTO uc_org_relation
(org_id, org_type, parent_id, path, platform_code, platform_name, deleted, create_by, create_time, update_by, update_time, proxy_by)
VALUES(1, 1, 0, '1', 1, NULL, FALSE, NULL, NULL, NULL, NULL, NULL);
-- ----------------------------
-- Records of x_file_category
-- ----------------------------
INSERT INTO x_file_category (file_category, file_suffix, deleted, create_by, create_time) VALUES
('video', 'mp4', FALSE, 0, NOW()),
('video', 'mkv', FALSE, 0, NOW()),
('video', 'avi', FALSE, 0, NOW()),
('video', 'mov', FALSE, 0, NOW()),
('video', 'wmv', FALSE, 0, NOW()),
('video', 'flv', FALSE, 0, NOW()),
('audio', 'mp3', FALSE, 0, NOW()),
('audio', 'wav', FALSE, 0, NOW()),
('audio', 'flac', FALSE, 0, NOW()),
('audio', 'aac', FALSE, 0, NOW()),
('document', 'txt', FALSE, 0, NOW()),
('document', 'docx', FALSE, 0, NOW()),
('document', 'pdf', FALSE, 0, NOW()),
('document', 'epub', FALSE, 0, NOW()),
('other', 'zip', FALSE, 0, NOW()),
('other', 'rar', FALSE, 0, NOW()),
('other', '7z', FALSE, 0, NOW()),
('other', 'jpg', FALSE, 0, NOW()),
('other', 'png', FALSE, 0, NOW()),
('other', 'gif', FALSE, 0, NOW()),
('other', 'tiff', FALSE, 0, NOW());

View File

@@ -0,0 +1,42 @@
建表与初始数据脚本已随包放好,文件名前缀决定执行顺序(先建表后灌数据):
| 文件 | 来源 | 说明 |
|---|---|---|
| `01-init-table.sql` | `backend/db/init-table-postgres-full.sql` | 全量 DDL,含 `x_file_security` 安全检测表与 `idx_file_record_md5_code` 索引 |
| `02-init-data.sql` | `backend/db/init-data.sql` | admin 账号、机构、平台编码(`system.code=1` 要与此一致) |
出包时用 `deployment/scripts/build-package.sh` 从仓库重新覆盖这两份,别手改副本。
只有 `POSTGRES_*` 指向的库为空时,PostgreSQL 官方镜像才会执行 `docker-entrypoint-initdb.d`;
数据目录已有数据时会跳过 —— 想重建就把 `volumes/pgdata` 一起清掉再 `up`。
## upgrade/ —— 已上线老库的增量脚本(新装不用跑)
| 文件 | 作用 |
|---|---|
| `upgrade-20260914-upload-config.sql` | 新增 `x_upload_config`(机构上传后缀白名单/大小上限/开关) |
| `upgrade-20260915-release.sql` | 与上一份同一件事(上线汇总版),**两者跑其一即可** |
| `upgrade-20261101-meshsafe-file-security.sql` | 新增 `x_file_security` 文件安全检测表与字段 |
| `upgrade-20261103-transfer-perf.sql` | 给 `xs_file_record.md5_code` 补索引(解包时按 MD5 去重查询,缺索引就是每文件一次全表扫描) |
客户如果从 2026-09 之前的老库升上来,本包(PostgreSQL)真正缺的只有三个对象:
`x_upload_config`、`x_file_security`、`idx_file_record_md5_code`。
这三项在 `01-init-table.sql` 里都已是 PostgreSQL 写法,老库升级建议直接照它补,别整份管道进 psql:
```bash
# 先看缺不缺
docker exec -i sfile-iw-pg psql -U sfile -d s_file -c \
"\dt x_upload_config" -c "\dt x_file_security" -c "\di idx_file_record_md5_code"
# 只补 md5 索引(这份脚本带「-- 2. PostgreSQL」分节标题,可以截出来跑)
awk '/^-- 2\. PostgreSQL/{f=1} f' sql/upgrade/upgrade-20261103-transfer-perf.sql \
| docker exec -i sfile-iw-pg psql -U sfile -d s_file
```
> 注意:这 4 份历史增量脚本是**达梦/MySQL 优先**写的,`upgrade-20260915-release.sql` 的 PostgreSQL 段整段是注释掉的,
> 只有 `upgrade-20261101`、`upgrade-20261103` 两份带可执行的「第 2 节 PostgreSQL」。别照着 MySQL 段硬跑。
这两份带可执行第 2 节的脚本都是「第 1 节 MySQL/达梦、第 2 节 PostgreSQL」双库混排,**只能跑第 2 节**,
整份管道进去会先执行 MySQL 那节。它们不会自动执行,要人工触发(容器名内网机 `sfile-iw-pg` / 外网机 `sfile-ow-pg`)。
数据量大时建索引会锁写,放到业务低峰执行;不能停写就用脚本里注明的 `CONCURRENTLY` 写法。

View File

@@ -0,0 +1,62 @@
-- =============================================================
-- 升级脚本:机构上传配置(文件上传类型/大小限制)
-- 日期:2026-09-14
-- 说明:新增 x_upload_config 表(一行对应一个机构)。
-- 机构管理员可配置本机构允许上传的文件后缀白名单、
-- 单文件大小上限、上传总开关;未配置的机构默认允许全部。
-- 拦截点:网盘上传落库(normal_user_file/create)。
-- 执行方式:MySQL/达梦(DM8 MySQL兼容模式)执行第 1 节;
-- PostgreSQL 执行第 2 节。
-- =============================================================
-- -------------------------------------------------------------
-- 1. MySQL / 达梦 DM8
-- -------------------------------------------------------------
CREATE TABLE `x_upload_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`org_id` bigint(20) DEFAULT NULL COMMENT '机构id',
`upload_enabled` bit(1) DEFAULT b'1' COMMENT '是否允许上传',
`allow_all_type` bit(1) DEFAULT b'1' COMMENT '是否允许全部类型(false时按allowed_suffixes白名单校验)',
`allowed_suffixes` varchar(1024) DEFAULT NULL COMMENT '允许的文件后缀(逗号分隔,小写),allow_all_type=false时生效',
`max_file_size` bigint(20) DEFAULT NULL COMMENT '单文件大小上限(MB),空或0不限制',
`deleted` bit(1) DEFAULT b'0' COMMENT '是否删除',
`create_by` bigint(20) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`proxy_by` bigint(20) DEFAULT NULL COMMENT '代理人',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_org_id` (`org_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='机构上传配置';
-- -------------------------------------------------------------
-- 2. PostgreSQL
-- -------------------------------------------------------------
CREATE TABLE x_upload_config (
id BIGSERIAL PRIMARY KEY,
org_id BIGINT DEFAULT NULL,
upload_enabled BOOLEAN DEFAULT TRUE,
allow_all_type BOOLEAN DEFAULT TRUE,
allowed_suffixes VARCHAR(1024) DEFAULT NULL,
max_file_size BIGINT DEFAULT NULL,
deleted BOOLEAN DEFAULT FALSE,
create_by BIGINT DEFAULT NULL,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT DEFAULT NULL,
update_time TIMESTAMP DEFAULT NULL,
proxy_by BIGINT DEFAULT NULL,
CONSTRAINT uk_upload_config_org_id UNIQUE (org_id)
);
COMMENT ON TABLE x_upload_config IS '机构上传配置';
COMMENT ON COLUMN x_upload_config.id IS '主键ID';
COMMENT ON COLUMN x_upload_config.org_id IS '机构id';
COMMENT ON COLUMN x_upload_config.upload_enabled IS '是否允许上传';
COMMENT ON COLUMN x_upload_config.allow_all_type IS '是否允许全部类型(false时按allowed_suffixes白名单校验)';
COMMENT ON COLUMN x_upload_config.allowed_suffixes IS '允许的文件后缀(逗号分隔,小写),allow_all_type=false时生效';
COMMENT ON COLUMN x_upload_config.max_file_size IS '单文件大小上限(MB),空或0不限制';
COMMENT ON COLUMN x_upload_config.deleted IS '是否删除';
COMMENT ON COLUMN x_upload_config.create_by IS '创建人';
COMMENT ON COLUMN x_upload_config.create_time IS '创建时间';
COMMENT ON COLUMN x_upload_config.update_by IS '修改人';
COMMENT ON COLUMN x_upload_config.update_time IS '修改时间';
COMMENT ON COLUMN x_upload_config.proxy_by IS '代理人';

View File

@@ -0,0 +1,90 @@
-- =====================================================================
-- s-file 上线数据库脚本(2026-09-15 版本)
-- 适用场景:已有生产库升级(老版本 → 当前版本)
--
-- 本次版本(用户启停/注销、机构账号查询、手机号查记录、机构上传配置)
-- 相对老版本的数据库变更只有一项:
-- 新增表 x_upload_config(机构上传配置)
-- 其余功能(启停/注销/查询)全部复用已有表字段,无需任何变更。
--
-- 【执行说明】
-- * 生产主力库为达梦 DM8(MySQL 兼容模式)→ 只执行【第一部分】
-- * 若目标库是 PostgreSQL → 只执行【第二部分】
-- * 执行前建议备份;执行后核对【第三部分】的验证 SQL
-- * 可重复执行(幂等):表已存在时再执行会报"已存在"错误,属正常,
-- 说明该脚本已执行过,无需处理
-- =====================================================================
-- =====================================================================
-- 第一部分:达梦 DM8 / MySQL
-- =====================================================================
CREATE TABLE x_upload_config (
id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
org_id BIGINT DEFAULT NULL COMMENT '机构id',
upload_enabled BIT(1) DEFAULT b'1' COMMENT '是否允许上传',
allow_all_type BIT(1) DEFAULT b'1' COMMENT '是否允许全部类型(false时按allowed_suffixes白名单校验)',
allowed_suffixes VARCHAR(1024) DEFAULT NULL COMMENT '允许的文件后缀(逗号分隔,小写),allow_all_type=false时生效',
max_file_size BIGINT DEFAULT NULL COMMENT '单文件大小上限(MB),空或0不限制',
deleted BIT(1) DEFAULT b'0' COMMENT '是否删除',
create_by BIGINT DEFAULT NULL COMMENT '创建人',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_by BIGINT DEFAULT NULL COMMENT '修改人',
update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
proxy_by BIGINT DEFAULT NULL COMMENT '代理人',
PRIMARY KEY (id) USING BTREE,
UNIQUE KEY uk_org_id (org_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='机构上传配置';
-- 说明:不需要初始化数据。
-- 未配置的机构 = 默认策略(允许上传全部类型、不限大小),
-- 由各机构管理员在管理后台"上传配置"页面自行配置后落库。
-- =====================================================================
-- 第二部分:PostgreSQL
-- =====================================================================
-- CREATE TABLE x_upload_config (
-- id BIGSERIAL PRIMARY KEY,
-- org_id BIGINT DEFAULT NULL,
-- upload_enabled BOOLEAN DEFAULT TRUE,
-- allow_all_type BOOLEAN DEFAULT TRUE,
-- allowed_suffixes VARCHAR(1024) DEFAULT NULL,
-- max_file_size BIGINT DEFAULT NULL,
-- deleted BOOLEAN DEFAULT FALSE,
-- create_by BIGINT DEFAULT NULL,
-- create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- update_by BIGINT DEFAULT NULL,
-- update_time TIMESTAMP DEFAULT NULL,
-- proxy_by BIGINT DEFAULT NULL,
-- CONSTRAINT uk_upload_config_org_id UNIQUE (org_id)
-- );
-- COMMENT ON TABLE x_upload_config IS '机构上传配置';
-- COMMENT ON COLUMN x_upload_config.id IS '主键ID';
-- COMMENT ON COLUMN x_upload_config.org_id IS '机构id';
-- COMMENT ON COLUMN x_upload_config.upload_enabled IS '是否允许上传';
-- COMMENT ON COLUMN x_upload_config.allow_all_type IS '是否允许全部类型(false时按allowed_suffixes白名单校验)';
-- COMMENT ON COLUMN x_upload_config.allowed_suffixes IS '允许的文件后缀(逗号分隔,小写),allow_all_type=false时生效';
-- COMMENT ON COLUMN x_upload_config.max_file_size IS '单文件大小上限(MB),空或0不限制';
-- COMMENT ON COLUMN x_upload_config.deleted IS '是否删除';
-- COMMENT ON COLUMN x_upload_config.create_by IS '创建人';
-- COMMENT ON COLUMN x_upload_config.create_time IS '创建时间';
-- COMMENT ON COLUMN x_upload_config.update_by IS '修改人';
-- COMMENT ON COLUMN x_upload_config.update_time IS '修改时间';
-- COMMENT ON COLUMN x_upload_config.proxy_by IS '代理人';
-- =====================================================================
-- 第三部分:执行后验证(达梦/MySQL 语法)
-- =====================================================================
-- 1) 表存在且为空(0 行正常)
-- SELECT COUNT(*) FROM x_upload_config;
-- 2) 唯一约束存在(应返回 uk_org_id)
-- SELECT INDEX_NAME FROM USER_INDEXES WHERE TABLE_NAME = 'X_UPLOAD_CONFIG';
-- 3) (可选)回滚脚本 —— 如需回滚上线:
-- DROP TABLE x_upload_config;

View File

@@ -0,0 +1,71 @@
-- =============================================================
-- 升级脚本:MeshSafe 文件安全检测对接
-- 日期:2026-11-01
-- 说明:新增 x_file_security 表(按文件编码维度记录安全检测结果)。
-- 文件上传/传输接收解包后自动提交 MeshSafe 检测,
-- 检测结论(通过/不通过)回写本表;同一文件允许多条检测
-- 记录(人工复核、重新检测均新增记录),业务取最新一条生效。
-- 检测不通过的文件禁止分享与跨网传输(下载预览不受限)。
-- 执行方式:MySQL/达梦(DM8 MySQL兼容模式)执行第 1 节;
-- PostgreSQL 执行第 2 节。
-- =============================================================
-- -------------------------------------------------------------
-- 1. MySQL / 达梦 DM8
-- -------------------------------------------------------------
CREATE TABLE `x_file_security` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`file_code` varchar(32) DEFAULT NULL COMMENT '文件编码',
`task_id` varchar(64) DEFAULT NULL COMMENT 'MeshSafe检测任务ID',
`scan_status` varchar(2) DEFAULT NULL COMMENT '检测状态:1检测中/2通过/3不通过/4检测失败',
`action` varchar(32) DEFAULT NULL COMMENT 'MeshSafe处置动作:pass/manual_review/reject',
`reason` varchar(1024) DEFAULT NULL COMMENT '检测结论说明',
`result_json` text DEFAULT NULL COMMENT '检测完整结果JSON',
`review_comment` varchar(512) DEFAULT NULL COMMENT '人工复核说明(人工改判时有值)',
`deleted` bit(1) DEFAULT b'0' COMMENT '是否删除',
`create_by` bigint(20) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`proxy_by` bigint(20) DEFAULT NULL COMMENT '代理人',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_file_security_file_code` (`file_code`) USING BTREE,
KEY `idx_file_security_scan_status` (`scan_status`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件安全检测记录';
-- -------------------------------------------------------------
-- 2. PostgreSQL
-- -------------------------------------------------------------
CREATE TABLE x_file_security (
id BIGSERIAL PRIMARY KEY,
file_code VARCHAR(32) DEFAULT NULL,
task_id VARCHAR(64) DEFAULT NULL,
scan_status VARCHAR(2) DEFAULT NULL,
action VARCHAR(32) DEFAULT NULL,
reason VARCHAR(1024) DEFAULT NULL,
result_json TEXT DEFAULT NULL,
review_comment VARCHAR(512) DEFAULT NULL,
deleted BOOLEAN DEFAULT FALSE,
create_by BIGINT DEFAULT NULL,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT DEFAULT NULL,
update_time TIMESTAMP DEFAULT NULL,
proxy_by BIGINT DEFAULT NULL
);
CREATE INDEX idx_file_security_file_code ON x_file_security(file_code);
CREATE INDEX idx_file_security_scan_status ON x_file_security(scan_status);
COMMENT ON TABLE x_file_security IS '文件安全检测记录';
COMMENT ON COLUMN x_file_security.id IS '主键ID';
COMMENT ON COLUMN x_file_security.file_code IS '文件编码';
COMMENT ON COLUMN x_file_security.task_id IS 'MeshSafe检测任务ID';
COMMENT ON COLUMN x_file_security.scan_status IS '检测状态:1检测中/2通过/3不通过/4检测失败';
COMMENT ON COLUMN x_file_security.action IS 'MeshSafe处置动作:pass/manual_review/reject';
COMMENT ON COLUMN x_file_security.reason IS '检测结论说明';
COMMENT ON COLUMN x_file_security.result_json IS '检测完整结果JSON';
COMMENT ON COLUMN x_file_security.review_comment IS '人工复核说明(人工改判时有值)';
COMMENT ON COLUMN x_file_security.deleted IS '是否删除';
COMMENT ON COLUMN x_file_security.create_by IS '创建人';
COMMENT ON COLUMN x_file_security.create_time IS '创建时间';
COMMENT ON COLUMN x_file_security.update_by IS '修改人';
COMMENT ON COLUMN x_file_security.update_time IS '修改时间';
COMMENT ON COLUMN x_file_security.proxy_by IS '代理人';

View File

@@ -0,0 +1,26 @@
-- =============================================================
-- 升级脚本:跨网传输链路性能优化(第一批)
-- 日期:2026-11-03
-- 说明:给 xs_file_record.md5_code 补索引。
-- 文件入库时会用 MD5 做内容去重查询
-- (FileServiceImpl 上传 → find(md5Code)),此前该列无索引,
-- 每个文件入库都是一次全表扫描。解包一个含 N 个文件的传输包
-- 就是 N 次全表扫描,数据量上来后是多文件解包的主要数据库开销。
-- 新环境由 init 脚本建表时已包含该索引,本脚本仅供已上线环境增量执行。
-- 执行方式:MySQL/达梦(DM8 MySQL兼容模式)执行第 1 节;
-- PostgreSQL 执行第 2 节。
-- 注意:表数据量大时建索引会锁写,建议业务低峰执行。
-- 重复执行会报「索引已存在」,忽略即可。
-- =============================================================
-- -------------------------------------------------------------
-- 1. MySQL / 达梦 DM8
-- -------------------------------------------------------------
CREATE INDEX idx_file_record_md5_code ON xs_file_record(md5_code);
-- -------------------------------------------------------------
-- 2. PostgreSQL
-- -------------------------------------------------------------
-- 表已有数据且不能停写时,改用下面这句(不可在事务块内执行):
-- CREATE INDEX CONCURRENTLY idx_file_record_md5_code ON xs_file_record(md5_code);
CREATE INDEX IF NOT EXISTS idx_file_record_md5_code ON xs_file_record(md5_code);

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{qn as e,zn as t}from"./index-BaTxSAlR.js";var n=e(t());function r(){return(0,n.jsx)(`div`,{className:`p-4 min-h-full`,children:(0,n.jsx)(`div`,{className:`p-8 rounded-lg`,children:(0,n.jsx)(`div`,{className:`flex items-center justify-center py-10`,children:(0,n.jsx)(`div`,{className:`text-base text-black/50`,children:`欢迎使用管理后台`})})})})}export{r as component};

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

View File

@@ -0,0 +1 @@
import{fn as e}from"./index-BaTxSAlR.js";var t=e(`chevron-left`,[[`path`,{d:`m15 18-6-6 6-6`,key:`1wnfg3`}]]);export{t};

View File

@@ -0,0 +1 @@
import{fn as e}from"./index-BaTxSAlR.js";var t=e(`chevron-right`,[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]);export{t};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{t as e}from"./chevron-right-_MvSGoRx.js";import{Vn as t,en as n,in as r,qn as i,zn as a}from"./index-BaTxSAlR.js";t();var o=i(a(),1);function s({...e}){return(0,o.jsx)(`nav`,{"aria-label":`breadcrumb`,"data-slot":`breadcrumb`,...e})}function c({className:e,...t}){return(0,o.jsx)(`ol`,{"data-slot":`breadcrumb-list`,className:n(`text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5`,e),...t})}function l({className:e,...t}){return(0,o.jsx)(`li`,{"data-slot":`breadcrumb-item`,className:n(`inline-flex items-center gap-1.5`,e),...t})}function u({asChild:e,className:t,...i}){return(0,o.jsx)(e?r:`a`,{"data-slot":`breadcrumb-link`,className:n(`hover:text-foreground transition-colors`,t),...i})}function d({className:e,...t}){return(0,o.jsx)(`span`,{"data-slot":`breadcrumb-page`,role:`link`,"aria-disabled":`true`,"aria-current":`page`,className:n(`text-foreground font-normal`,e),...t})}function f({children:t,className:r,...i}){return(0,o.jsx)(`li`,{"data-slot":`breadcrumb-separator`,role:`presentation`,"aria-hidden":`true`,className:n(`[&>svg]:size-3.5`,r),...i,children:t??(0,o.jsx)(e,{})})}function p({directorys:e,onChangeDirectorys:t,className:n}){return(0,o.jsx)(s,{className:n,children:(0,o.jsxs)(c,{children:[(0,o.jsx)(l,{children:(0,o.jsx)(u,{onClick:()=>t({id:0}),className:`cursor-pointer`,children:`根目录`})}),e.length>0&&(0,o.jsx)(f,{}),e.length>0&&e.map((n,r)=>(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(l,{children:r===e.length-1?(0,o.jsx)(d,{className:`cursor-default`,children:n.fileName}):(0,o.jsx)(u,{onClick:()=>t(n),className:`cursor-pointer`,children:n.fileName.length>6?n.fileName.slice(0,6)+`...`:n.fileName})},n.id),r!==e.length-1&&(0,o.jsx)(f,{},`separator`+n.id)]}))]})})}export{p as t};

View File

@@ -0,0 +1 @@
import{cn as e,ln as t}from"./index-BaTxSAlR.js";export{t as toast};

View File

@@ -0,0 +1 @@
import{Vn as e,Y as t,fn as n,qn as r,zn as i}from"./index-BaTxSAlR.js";var a=n(`chevron-down`,[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]),o=r(e(),1),s=r(i(),1),c=Object.defineProperty,l=(e,t)=>c(e,`name`,{value:t,configurable:!0}),u=Object.freeze({position:`absolute`,border:0,width:1,height:1,padding:0,margin:-1,overflow:`hidden`,clip:`rect(0, 0, 0, 0)`,whiteSpace:`nowrap`,wordWrap:`normal`}),d=o.forwardRef(l(function(e,n){return(0,s.jsx)(t.span,{...e,ref:n,style:{...u,...e.style}})},`VisuallyHidden`));export{d as n,a as r,u as t};

View File

@@ -0,0 +1 @@
import{A as e,O as t,Vn as n,Y as r,b as i,j as a,k as o,qn as s,sn as c,u as l,zn as u}from"./index-BaTxSAlR.js";import{n as d,t as f}from"./dist-CpxP8T7M.js";var p=s(n(),1),m=Object.defineProperty,h=(e,t)=>m(e,`name`,{value:t,configurable:!0}),g=!1;function _(){let[e,t]=p.useState(g);return p.useEffect(()=>{g||(g=!0,t(!0))},[]),e}h(_,`useIsHydrated`);var v=p.useSyncExternalStore;function y(){return()=>{}}h(y,`subscribe`);function b(){return v(y,()=>!0,()=>!1)}h(b,`useIsHydratedModern`);var x=typeof v==`function`?b:_,S=s(u(),1),C=Object.defineProperty,w=(e,t)=>C(e,`name`,{value:t,configurable:!0}),T=`rovingFocusGroup.onEntryFocus`,E={bubbles:!1,cancelable:!0},D=`RovingFocusGroup`,[O,k,A]=d(D),[j,M]=o(D,[A]),N={Vertical:`vertical`,Horizontal:`horizontal`},P={LTR:`ltr`,RTL:`rtl`},[F,I]=j(D),L=p.forwardRef(w(function(e,t){return(0,S.jsx)(O.Provider,{scope:e.__scopeRovingFocusGroup,children:(0,S.jsx)(O.Slot,{scope:e.__scopeRovingFocusGroup,children:(0,S.jsx)(R,{...e,ref:t})})})},`RovingFocusGroup`)),R=p.forwardRef(w(function(n,i){let{__scopeRovingFocusGroup:a,orientation:o,loop:s=!1,dir:u,currentTabStopId:d,defaultCurrentTabStopId:m,onCurrentTabStopIdChange:h,onEntryFocus:g,preventScrollOnEntryFocus:_=!1,...v}=n,y=p.useRef(null),b=c(i,y),x=f(u),[C,w]=l({prop:d,defaultProp:m??null,onChange:h,caller:D}),[O,A]=p.useState(!1),j=t(g),M=k(a),N=p.useRef(!1),[P,I]=p.useState(0);return p.useEffect(()=>{let e=y.current;if(e)return e.addEventListener(T,j),()=>e.removeEventListener(T,j)},[j]),(0,S.jsx)(F,{scope:a,orientation:o,dir:x,loop:s,currentTabStopId:C,onItemFocus:p.useCallback(e=>w(e),[w]),onItemShiftTab:p.useCallback(()=>A(!0),[]),onFocusableItemAdd:p.useCallback(()=>I(e=>e+1),[]),onFocusableItemRemove:p.useCallback(()=>I(e=>e-1),[]),children:(0,S.jsx)(r.div,{tabIndex:O||P===0?-1:0,"data-orientation":o,...v,ref:b,style:{outline:`none`,...n.style},onMouseDown:e(n.onMouseDown,()=>{N.current=!0}),onFocus:e(n.onFocus,e=>{let t=!N.current;if(e.target===e.currentTarget&&t&&!O){let t=new CustomEvent(T,E);if(e.currentTarget.dispatchEvent(t),!t.defaultPrevented){let e=M().filter(e=>e.focusable);W([e.find(e=>e.active),e.find(e=>e.id===C),...e].filter(Boolean).map(e=>e.ref.current),_)}}N.current=!1}),onBlur:e(n.onBlur,()=>A(!1))})})},`RovingFocusGroupImpl`)),z=`RovingFocusGroupItem`,B=p.forwardRef(w(function(t,n){let{__scopeRovingFocusGroup:o,focusable:s=!0,active:c=!1,tabStopId:l,children:u,...d}=t,f=i(),m=l||f,h=I(z,o),g=h.currentTabStopId===m,_=k(o),{onFocusableItemAdd:v,onFocusableItemRemove:y,currentTabStopId:b}=h,C=x();return a(()=>{if(!(!C||!s))return v(),()=>y()},[C,s,v,y]),p.useEffect(()=>{if(!(C||!s))return v(),()=>y()},[C,s,v,y]),(0,S.jsx)(O.ItemSlot,{scope:o,id:m,focusable:s,active:c,children:(0,S.jsx)(r.span,{tabIndex:g?0:-1,"data-orientation":h.orientation,...d,ref:n,onMouseDown:e(t.onMouseDown,e=>{s?h.onItemFocus(m):e.preventDefault()}),onFocus:e(t.onFocus,()=>h.onItemFocus(m)),onKeyDown:e(t.onKeyDown,e=>{if(e.key===`Tab`&&e.shiftKey){h.onItemShiftTab();return}if(e.target!==e.currentTarget)return;let t=U(e,h.orientation,h.dir);if(t!==void 0){if(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey)return;e.preventDefault();let n=_().filter(e=>e.focusable).map(e=>e.ref.current);if(t===`last`)n.reverse();else if(t===`prev`||t===`next`){t===`prev`&&n.reverse();let r=n.indexOf(e.currentTarget);n=h.loop?G(n,r+1):n.slice(r+1)}setTimeout(()=>W(n))}}),children:typeof u==`function`?u({isCurrentTabStop:g,hasTabStop:b!=null}):u})})},`RovingFocusGroupItem`)),V={ArrowLeft:`prev`,ArrowUp:`prev`,ArrowRight:`next`,ArrowDown:`next`,PageUp:`first`,Home:`first`,PageDown:`last`,End:`last`};function H(e,t){return t===P.RTL?e===`ArrowLeft`?`ArrowRight`:e===`ArrowRight`?`ArrowLeft`:e:e}w(H,`getDirectionAwareKey`);function U(e,t,n){let r=H(e.key,n);if(!(t===N.Vertical&&[`ArrowLeft`,`ArrowRight`].includes(r))&&!(t===N.Horizontal&&[`ArrowUp`,`ArrowDown`].includes(r)))return V[r]}w(U,`getFocusIntent`);function W(e,t=!1){let n=document.activeElement;for(let r of e)if(r===n||(r.focus({preventScroll:t}),document.activeElement!==n))return}w(W,`focusFirst`);function G(e,t){return e.map((n,r)=>e[(t+r)%e.length])}w(G,`wrapArray`);export{B as n,M as r,L as t};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{$ as e,Bt as t,G as n,H as r,It as i,Jt as a,K as o,Q as s,Qt as c,R as l,U as u,V as d,Vn as f,Vt as p,W as m,Zt as h,et as g,ln as _,q as v,qn as y,qt as b,tt as x,yn as S,z as C,zn as w,zt as T}from"./index-BaTxSAlR.js";import{a as E,n as D,o as O,r as k,s as A,t as j}from"./dialog-CnxDxMp1.js";const M=e=>{let{mutateAsync:n,isPending:r}=S({mutationFn:p,...e||{}}),{mutateAsync:a,isPending:o}=S({mutationFn:t,...e||{}}),{mutateAsync:s,isPending:c}=S({mutationFn:i,...e||{}}),l=e=>t=>{_.promise(e(t),{loading:`提交中...`,success:`操作成功`})};return{enable:l(n),disable:l(a),adminCancel:l(s),enableIsPending:r,disableIsPending:o,cancelIsPending:c}};var N=y(f(),1),P=y(w(),1),F=s({newPassword:e().nonempty({message:`新密码不能为空`}),confirmPassword:e().nonempty({message:`确认密码不能为空`})});function I({open:e,setOpen:t,data:i}){let{mutateAsync:s,isPending:l}=S({mutationFn:a,onSuccess(){t(!1)}}),f=x({resolver:g(F),defaultValues:{newPassword:``,confirmPassword:``}});(0,N.useEffect)(()=>{e&&f.reset()},[e]);let p=e=>{_.promise(s({...e,userId:i.userId??i.id}),{loading:`提交中...`,success:`修改成功`})};return(0,P.jsx)(j,{open:e,onOpenChange:t,children:(0,P.jsxs)(k,{className:`w-[400px]`,children:[(0,P.jsx)(O,{children:(0,P.jsx)(A,{children:`重置密码`})}),(0,P.jsx)(r,{...f,children:(0,P.jsxs)(`form`,{onSubmit:f.handleSubmit(p),className:`space-y-4`,children:[(0,P.jsx)(m,{control:f.control,name:`newPassword`,render:({field:e})=>(0,P.jsxs)(n,{children:[(0,P.jsx)(o,{children:`新密码`}),(0,P.jsx)(u,{children:(0,P.jsx)(d,{...e,type:`password`})}),(0,P.jsx)(v,{})]})}),(0,P.jsx)(m,{control:f.control,name:`confirmPassword`,render:({field:e})=>(0,P.jsxs)(n,{children:[(0,P.jsx)(o,{children:`确认密码`}),(0,P.jsx)(u,{children:(0,P.jsx)(d,{...e,type:`password`})}),(0,P.jsx)(v,{})]})}),(0,P.jsxs)(E,{children:[(0,P.jsx)(D,{asChild:!0,children:(0,P.jsx)(c,{variant:`outline`,children:`取消`})}),(0,P.jsxs)(c,{type:`submit`,disabled:l,children:[l&&(0,P.jsx)(h,{}),`确定`]})]})]})})]})})}const L=e=>{let{mutateAsync:t,isPending:n}=S({mutationFn:e=>e.id?b(e):T(e),...e||{}});return{save:e=>{_.promise(t(e),{loading:`提交中...`,success:`操作成功`})},saveIsPending:n}};var R=`Qaz123567!@#`,z=t=>s({phone:t?e().nonempty({message:`手机号不能为空`}):e().optional(),username:t?e().optional():e().nonempty({message:`用户名不能为空`}),realName:e().nonempty({message:`真实姓名不能为空`})});function B({open:e,setOpen:t,refetch:i,data:a}){let s=(a==null?void 0:a.userId)??(a==null?void 0:a.id),f=(0,N.useMemo)(()=>!s,[s]),p=x({resolver:g((0,N.useMemo)(()=>z(f),[f])),defaultValues:{phone:``,username:``,realName:``}}),_=p.watch(`phone`),{save:y,saveIsPending:b}=L({onSuccess(){t(!1),i==null||i()}});(0,N.useEffect)(()=>{e&&(p.reset(),a&&(p.setValue(`username`,(a==null?void 0:a.username)||``),p.setValue(`realName`,(a==null?void 0:a.realName)||``)))},[e,a,p]);let S=e=>{y({id:s,...e})};return(0,P.jsx)(j,{open:e,onOpenChange:t,children:(0,P.jsxs)(k,{className:`w-[400px]`,children:[(0,P.jsx)(O,{children:(0,P.jsx)(A,{children:f?`创建用户`:`修改用户`})}),(0,P.jsx)(r,{...p,children:(0,P.jsxs)(`form`,{onSubmit:p.handleSubmit(S),className:`space-y-4`,children:[(0,P.jsx)(m,{control:p.control,name:f?`phone`:`username`,render:({field:e})=>(0,P.jsxs)(n,{children:[(0,P.jsx)(o,{children:`手机号`}),(0,P.jsx)(u,{children:(0,P.jsx)(d,{...e})}),(0,P.jsx)(v,{})]})}),(0,P.jsx)(m,{control:p.control,name:`realName`,render:({field:e})=>(0,P.jsxs)(n,{children:[(0,P.jsx)(o,{children:`真实姓名`}),(0,P.jsx)(u,{children:(0,P.jsx)(d,{...e})}),(0,P.jsx)(v,{})]})}),f&&(0,P.jsx)(l,{children:(0,P.jsxs)(C,{children:[(0,P.jsxs)(`div`,{children:[`用户账号:`,_]}),(0,P.jsxs)(`div`,{children:[`初始密码:`,R]})]})}),(0,P.jsxs)(E,{children:[(0,P.jsx)(D,{asChild:!0,children:(0,P.jsx)(c,{variant:`outline`,children:`取消`})}),(0,P.jsxs)(c,{type:`submit`,disabled:b,children:[b&&(0,P.jsx)(h,{}),`确定`]})]})]})})]})})}export{I as n,M as r,B as t};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{t as e}from"./useLocation-B-0SqFIj.js";import{$ as t,G as n,H as r,I as i,K as a,L as o,Q as s,Qt as c,U as l,V as u,W as d,Zt as f,_n as p,en as m,et as h,ln as g,mn as _,nn as v,q as y,qn as b,rt as x,tt as S,un as C,xt as w,yn as T,zn as E}from"./index-BaTxSAlR.js";var D=b(E(),1);function O({className:e,...t}){return(0,D.jsx)(`div`,{"data-slot":`empty`,className:m(`flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12`,e),...t})}function k({className:e,...t}){return(0,D.jsx)(`div`,{"data-slot":`empty-header`,className:m(`flex max-w-sm flex-col items-center gap-2 text-center`,e),...t})}var A=v(`flex shrink-0 items-center justify-center mb-2 [&_svg]:pointer-events-none [&_svg]:shrink-0`,{variants:{variant:{default:`bg-transparent`,icon:`bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6`}},defaultVariants:{variant:`default`}});function j({className:e,variant:t=`default`,...n}){return(0,D.jsx)(`div`,{"data-slot":`empty-icon`,"data-variant":t,className:m(A({variant:t,className:e})),...n})}function M({className:e,...t}){return(0,D.jsx)(`div`,{"data-slot":`empty-title`,className:m(`text-lg font-medium tracking-tight`,e),...t})}var N=s({accessCode:t().length(6,{message:`提取码只能是6位`}).nonempty({message:`提取码不能为空`})}),P=`森睿智传`;function F(){let t=p(),s=S({resolver:h(N),defaultValues:{accessCode:``}}),m=i.useSearch(),{mutateAsync:v,isPending:b}=T({mutationFn:e=>w(e),onSuccess(e,n){t.navigate({to:`/extract/list?accessCode=`+n.accessCode+`&shareId=`+n.shareId})}}),E=e=>{g.promise(v({...m,...e}),{loading:`校验中`,success:`校验通过`})},A=x(),F=e();return!A&&F.pathname===`/extract`?(0,D.jsx)(_,{to:`/login?redirect=`+encodeURIComponent(encodeURIComponent(F.href))}):(0,D.jsx)(`div`,{className:`flex items-center justify-center min-h-screen box-border`,children:(0,D.jsxs)(`div`,{children:[(0,D.jsxs)(`div`,{className:`flex justify-center items-center mb-4 gap-2`,children:[(0,D.jsx)(`img`,{src:o,alt:``,className:`size-12 object-contain rounded-full bg-white overflow-hidden`}),(0,D.jsx)(`div`,{className:`text-3xl`,children:P})]}),(0,D.jsxs)(`div`,{className:`w-[480px] p-10 bg-white rounded-xl`,children:[(0,D.jsx)(`div`,{className:`text-center text-2xl`,children:`文件提取`}),m.shareId?(0,D.jsx)(r,{...s,children:(0,D.jsxs)(`form`,{onSubmit:s.handleSubmit(E),className:`space-y-8 mt-12`,children:[(0,D.jsx)(d,{control:s.control,name:`accessCode`,render:({field:e})=>(0,D.jsxs)(n,{children:[(0,D.jsx)(a,{children:`提取码`}),(0,D.jsx)(l,{children:(0,D.jsx)(u,{placeholder:`请输入提取码`,...e})}),(0,D.jsx)(y,{})]})}),(0,D.jsxs)(c,{type:`submit`,className:`w-full`,disabled:b,children:[b&&(0,D.jsx)(f,{}),`提交`]})]})}):(0,D.jsx)(O,{children:(0,D.jsxs)(k,{children:[(0,D.jsx)(j,{variant:`default`,children:(0,D.jsx)(C,{size:24})}),(0,D.jsx)(M,{children:`无效的分享链接`})]})})]})]})})}export{F as component};

View File

@@ -0,0 +1 @@
import{fn as e}from"./index-BaTxSAlR.js";var t=e(`file`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}]]);export{t};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{fn as e}from"./index-BaTxSAlR.js";var t=e(`file-image`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`circle`,{cx:`10`,cy:`12`,r:`2`,key:`737tya`}],[`path`,{d:`m20 17-1.296-1.296a2.41 2.41 0 0 0-3.408 0L9 22`,key:`wt3hpn`}]]),n=e(`file-play`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M15.033 13.44a.647.647 0 0 1 0 1.12l-4.065 2.352a.645.645 0 0 1-.968-.56v-4.704a.645.645 0 0 1 .967-.56z`,key:`1tzo1f`}]]),r=e(`file-type`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M11 18h2`,key:`12mj7e`}],[`path`,{d:`M12 12v6`,key:`3ahymv`}],[`path`,{d:`M9 13v-.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5v.5`,key:`qbrxap`}]]);export{n,t as r,r as t};

View File

@@ -0,0 +1 @@
import{fn as e}from"./index-BaTxSAlR.js";var t=e(`folder`,[[`path`,{d:`M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z`,key:`1kt360`}]]);export{t};

View File

@@ -0,0 +1 @@
import{fn as e}from"./index-BaTxSAlR.js";var t=e(`folder-input`,[[`path`,{d:`M2 9V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-1`,key:`fm4g5t`}],[`path`,{d:`M2 13h10`,key:`pgb2dq`}],[`path`,{d:`m9 16 3-3-3-3`,key:`6m91ic`}]]);export{t};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{n as e,t}from"./file-category-filter-BIAErrxo.js";import{t as n}from"./file-COj1kCUn.js";import{t as r}from"./folder-input--tEWrMtP.js";import{t as i}from"./folder-Dl7FxCLT.js";import{n as a,t as o}from"./remove-file-dialog-cN0TGs4y.js";import{F as s,M as c,Qt as l,Vn as u,ct as d,lt as f,pt as p,qn as m,st as h,tn as g,zn as _}from"./index-BaTxSAlR.js";import{t as v}from"./directory-breadcrumb-u3uCxukv.js";import{t as y}from"./data-table-CEq6a930.js";import{t as b}from"./pagination-Bragnnjj.js";import{t as x}from"./use-fetch-files-rnWwNE4C.js";import"./dialog-CnxDxMp1.js";var S=m(u()),C=m(_());function w({handleChangeParentId:e,handleMove:t,handleRemove:a,handleFilePreview:o}){return[{accessorKey:`fileName`,header:`文件名`,cell:({row:t})=>{var a;return(0,C.jsxs)(`div`,{className:`flex items-center gap-1 break-all cursor-pointer hover:underline hover:text-primary group`,onClick:()=>{var n;(t==null||(n=t.original)==null?void 0:n.fileType)===d.DIRECTORY?e(t==null?void 0:t.original):o(t==null?void 0:t.original)},children:[(t==null||(a=t.original)==null?void 0:a.fileType)===d.FILE?(0,C.jsx)(C.Fragment,{children:(0,C.jsx)(n,{size:18,className:`text-primary`})}):(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(i,{size:18,className:`text-amber-500 group-hover:hidden`}),(0,C.jsx)(r,{size:18,className:`text-amber-500 group-hover:block hidden`})]}),(0,C.jsx)(`span`,{children:t.getValue(`fileName`)})]})}},{accessorKey:`createTime`,header:`创建日期`,cell:({row:e})=>(0,C.jsx)(`div`,{children:e.getValue(`createTime`)})},{accessorKey:`fileSize`,header:`文件大小`,cell:({row:e})=>(0,C.jsx)(`div`,{children:g(e.getValue(`fileSize`))})},{accessorKey:`fileCategory`,header:`文件种类`,cell:({row:e})=>(0,C.jsx)(`div`,{children:e.original.fileType===d.FILE?s(e.getValue(`fileCategory`)):`-`})},{accessorKey:`fileStatus`,header:()=>(0,C.jsx)(`div`,{className:`text-center`,children:`状态`}),cell:({row:e})=>(0,C.jsx)(`div`,{className:`text-center`,children:(0,C.jsx)(c,{status:e.original.fileStatus})})},{id:`actions`,enableHiding:!1,header:`操作`,cell:({row:e})=>{let n=e.original;return(0,C.jsxs)(`div`,{className:`space-x-2`,children:[(0,C.jsx)(l,{size:`sm`,variant:`destructive`,onClick:()=>a(e.original),children:`删除`}),(0,C.jsx)(l,{size:`sm`,variant:`outline`,onClick:()=>t(e.original),children:`移动`}),n.fileType===d.FILE&&(0,C.jsx)(l,{variant:`outline`,size:`sm`,onClick:()=>{p({code:n.fileCode})},children:`下载`})]})}}]}function T(){let[n,r]=(0,S.useState)(null),[i,s]=(0,S.useState)(!1),c=e=>{r(e),s(!0)},[l,u]=(0,S.useState)(!1),d=e=>{r(e),u(!0)},[p,m]=(0,S.useState)(!1),g=e=>{r(e),m(!0)},[_,T]=(0,S.useState)(`all`),E=(0,S.useMemo)(()=>({rootType:f.INSIDE,fileStatusIn:[h.VALID,h.PARSING,h.TRANSFERING,h.FAILED].join(`,`),fileCategory:_===`all`?void 0:_}),[_]),{openDirectorys:D,changeOpenDirectorys:O,table:k,query:A,reset:j}=x({useColumns:e=>w({handleChangeParentId:e,handleMove:c,handleRemove:d,handleFilePreview:g}),queryKey:[`insideFiles`],params:E});return(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(a,{open:i,setOpen:s,data:n,params:E,refetch:A.refetch}),(0,C.jsx)(o,{open:l,setOpen:u,data:n,refetch:A.refetch}),(0,C.jsx)(e,{open:p,setOpen:m,data:n}),(0,C.jsxs)(`div`,{className:`p-4 box-border min-h-full space-y-4`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`div`,{className:`text-lg`,children:`我的发送`}),(0,C.jsx)(`div`,{className:`text-xs text-black/50`,children:`文件传输的状态`})]}),(0,C.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,C.jsx)(t,{fileCategory:_,setFileCategory:T,reset:j})}),(0,C.jsxs)(`div`,{className:`p-4 rounded-lg border bg-white space-y-2`,children:[(0,C.jsx)(v,{directorys:D,onChangeDirectorys:O}),(0,C.jsxs)(`div`,{className:`relative overflow-hidden`,children:[(0,C.jsx)(y,{table:k,query:A}),(0,C.jsx)(b,{table:k,className:`justify-end p-2 sticky bottom-0 left-0 right-0 z-10 bg-white`})]})]})]})]})}export{T as component,w as useColumns};

View File

@@ -0,0 +1 @@
import{t as e}from"./useQuery-dxbdhNvu.js";import{n as t,t as n}from"./file-category-filter-BIAErrxo.js";import{t as r}from"./file-COj1kCUn.js";import{t as i}from"./folder-input--tEWrMtP.js";import{t as a}from"./folder-Dl7FxCLT.js";import{F as o,P as s,Qt as c,Vn as l,ct as u,pt as d,qn as f,tn as p,xt as m,zn as h}from"./index-BaTxSAlR.js";import{t as g}from"./directory-breadcrumb-u3uCxukv.js";import{n as _,r as v,t as y}from"./data-table-CEq6a930.js";import"./dialog-CnxDxMp1.js";var b=f(l(),1);const x=(t,n,r)=>{let[i,a]=(0,b.useState)([]),[o,s]=(0,b.useState)(0),c=e({queryKey:[`shareFileList`,o],queryFn:()=>m({...n,...r,parentId:o}).then(e=>e.data)}),l=e=>{s(e.id),a(t=>[...t,e])},u=t(l);return{parentId:o,handleChangeParentId:l,openDirectorys:i,changeOpenDirectorys:e=>{s(e==null?void 0:e.id),a(t=>{let n=t.findIndex(t=>t.id===(e==null?void 0:e.id));return n>-1?[...t.slice(0,n+1)]:[]})},table:_({data:(c==null?void 0:c.data)||[],columns:u,getCoreRowModel:v()}),query:c,reset:()=>{a([]),s(0)}}};var S=f(h());function C(e,t){return[{accessorKey:`fileName`,header:`文件名`,cell:({row:n})=>{var o;return(0,S.jsxs)(`div`,{className:`flex items-center gap-1 break-all cursor-pointer hover:underline hover:text-primary group`,onClick:()=>{var r;(n==null||(r=n.original)==null?void 0:r.fileType)===u.DIRECTORY?e(n==null?void 0:n.original):t(n==null?void 0:n.original)},children:[(n==null||(o=n.original)==null?void 0:o.fileType)===u.FILE?(0,S.jsx)(S.Fragment,{children:(0,S.jsx)(r,{size:18,className:`text-primary`})}):(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(a,{size:18,className:`text-amber-500 group-hover:hidden`}),(0,S.jsx)(i,{size:18,className:`text-amber-500 group-hover:block hidden`})]}),(0,S.jsx)(`span`,{children:n.getValue(`fileName`)})]})}},{accessorKey:`createTime`,header:`创建日期`,cell:({row:e})=>(0,S.jsx)(`div`,{children:e.getValue(`createTime`)})},{accessorKey:`fileSize`,header:`文件大小`,cell:({row:e})=>(0,S.jsx)(`div`,{children:p(e.getValue(`fileSize`))})},{accessorKey:`fileCategory`,header:`文件种类`,cell:({row:e})=>(0,S.jsx)(`div`,{children:e.original.fileType===u.FILE?o(e.getValue(`fileCategory`)):`-`})},{id:`actions`,enableHiding:!1,header:`操作`,cell:({row:e})=>{let t=e.original;return(0,S.jsx)(`div`,{className:`space-x-2`,children:t.fileType===u.FILE&&(0,S.jsx)(c,{variant:`outline`,size:`sm`,onClick:()=>{d({code:t.fileCode})},children:`下载`})})}}]}function w(){let e=s.useSearch(),[r,i]=(0,b.useState)(null),[a,o]=(0,b.useState)(!1),c=e=>{i(e),o(!0)},[l,u]=(0,b.useState)(`all`),{table:d,query:f,openDirectorys:p,changeOpenDirectorys:m,reset:h}=x(e=>C(e,c),e,(0,b.useMemo)(()=>({fileCategory:l===`all`?void 0:l}),[l]));return(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(t,{open:a,setOpen:o,data:r}),(0,S.jsx)(`div`,{className:`p-4 min-h-screen`,children:(0,S.jsxs)(`div`,{className:`rounded-xl bg-white/50 backdrop-blur-lg min-h-full space-y-4 p-4`,children:[(0,S.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,S.jsx)(n,{fileCategory:l,setFileCategory:u,reset:h})}),(0,S.jsxs)(`div`,{className:`p-4 rounded-lg border bg-white space-y-2`,children:[(0,S.jsx)(g,{directorys:p,onChangeDirectorys:m}),(0,S.jsx)(`div`,{className:`relative overflow-hidden`,children:(0,S.jsx)(y,{table:d,query:f})})]})]})})]})}export{w as component,C as useColumns};

View File

@@ -0,0 +1 @@
import{n as e,t}from"./radio-group-dGI8aZOA.js";import{$ as n,G as r,H as i,J as a,K as o,L as s,N as c,Q as l,Qt as u,U as d,Ut as f,V as p,Vn as m,W as h,Wt as g,Zt as _,_n as v,et as y,ln as b,ot as x,q as S,qn as C,tt as w,yn as T,zn as E}from"./index-BaTxSAlR.js";var D=C(m()),O=C(E()),k=l({username:n().min(2,{message:`账号只能是4~16个字符`}),password:n().min(2,{message:`密码只能是4~32个字符`})}),A=`森睿智传`;function j(){let n=v(),[l,m]=(0,D.useState)(null),[C,E]=(0,D.useState)(``),j=w({resolver:y(k),defaultValues:{username:``,password:``}}),M=e=>{x.setState({token:e.data.token}),n.navigate({to:decodeURIComponent(decodeURIComponent(n.state.location.search.redirect||`/`)),replace:!0})},{mutateAsync:N,isPending:P}=T({mutationFn:async e=>{try{return await f(e)}catch(e){var t;if((e==null?void 0:e.code)===`600`&&!(e==null||(t=e.errorData)==null||(t=t.orgs)==null)&&t.length)return{needSelectOrg:!0,...e.errorData};throw e}},onSuccess(e){if(e!=null&&e.needSelectOrg){E(String(e.orgs[0].orgId)),m({tempToken:e.tempToken,orgs:e.orgs});return}M(e)}}),{mutateAsync:F,isPending:I}=T({mutationFn:e=>g(e.tempToken,e.orgId),onSuccess(e){M(e)}}),L=e=>{let t=N({...e,userType:1});b.promise(t,{loading:`登录中...`,success:e=>e!=null&&e.needSelectOrg?`请选择机构`:`登录成功`})};return(0,O.jsx)(`div`,{className:`flex items-center justify-center min-h-screen box-border`,children:(0,O.jsxs)(`div`,{children:[(0,O.jsxs)(`div`,{className:`flex justify-center items-center mb-4 gap-2`,children:[(0,O.jsx)(`img`,{src:s,alt:``,className:`size-12 object-contain rounded-full bg-white overflow-hidden`}),(0,O.jsx)(`div`,{className:`text-3xl`,children:A})]}),(0,O.jsx)(`div`,{className:`w-[480px] p-10 bg-white rounded-xl`,children:l?(0,O.jsxs)(O.Fragment,{children:[(0,O.jsx)(`div`,{className:`text-center text-2xl`,children:`选择机构`}),(0,O.jsx)(`div`,{className:`text-center text-sm text-black/50 mt-2`,children:`当前账号属于多个机构,请选择要登录的机构`}),(0,O.jsx)(t,{value:C,onValueChange:E,className:`space-y-1 mt-8`,children:l.orgs.map(t=>(0,O.jsxs)(`div`,{onClick:()=>E(String(t.orgId)),className:`flex items-center gap-3 rounded-lg border p-3 cursor-pointer transition-colors ${C===String(t.orgId)?`border-primary bg-primary/10`:`hover:bg-black/5`}`,children:[(0,O.jsx)(e,{value:String(t.orgId),id:`org-${t.orgId}`}),(0,O.jsxs)(a,{htmlFor:`org-${t.orgId}`,className:`flex items-center gap-2 flex-1 cursor-pointer`,children:[(0,O.jsx)(`span`,{children:t.orgName}),t.administrator&&(0,O.jsx)(c,{variant:`outline`,className:`text-primary border-primary`,children:`管理员`})]})]},t.orgId))}),(0,O.jsxs)(`div`,{className:`space-y-3 mt-8`,children:[(0,O.jsxs)(u,{className:`w-full`,disabled:I||!C,onClick:()=>{if(!C||!l)return;let e=F({tempToken:l.tempToken,orgId:C});b.promise(e,{loading:`登录中...`,success:`登录成功`})},children:[I&&(0,O.jsx)(_,{}),`进入系统`]}),(0,O.jsx)(u,{variant:`outline`,className:`w-full`,disabled:I,onClick:()=>m(null),children:`返回登录`})]})]}):(0,O.jsxs)(O.Fragment,{children:[(0,O.jsx)(`div`,{className:`text-center text-2xl`,children:`用户登录`}),(0,O.jsx)(i,{...j,children:(0,O.jsxs)(`form`,{onSubmit:j.handleSubmit(L),className:`space-y-8 mt-12`,children:[(0,O.jsx)(h,{control:j.control,name:`username`,render:({field:e})=>(0,O.jsxs)(r,{children:[(0,O.jsx)(o,{children:`用户名`}),(0,O.jsx)(d,{children:(0,O.jsx)(p,{placeholder:`用户名`,...e})}),(0,O.jsx)(S,{})]})}),(0,O.jsx)(h,{control:j.control,name:`password`,render:({field:e})=>(0,O.jsxs)(r,{children:[(0,O.jsx)(o,{children:`密码`}),(0,O.jsx)(d,{children:(0,O.jsx)(p,{type:`password`,placeholder:`密码`,...e})}),(0,O.jsx)(S,{})]})}),(0,O.jsxs)(u,{type:`submit`,className:`w-full`,disabled:P,children:[P&&(0,O.jsx)(_,{}),`提交`]})]})})]})})]})})}export{j as component};

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{Yt as e}from"./index-BaTxSAlR.js";const t=t=>e.get(`/user/page/platform_user`,{params:t}),n=t=>e.post(`/uc/org/create`,t),r=t=>e.put(`/uc/org/modify`,t),i=t=>e.get(`/uc/org/page`,{params:t});export{r as i,i as n,t as r,n as t};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{n as e,t}from"./file-category-filter-BIAErrxo.js";import{t as n}from"./file-COj1kCUn.js";import{t as r}from"./folder-input--tEWrMtP.js";import{t as i}from"./folder-Dl7FxCLT.js";import{n as a,t as o}from"./remove-file-dialog-cN0TGs4y.js";import{F as s,M as c,Qt as l,Vn as u,ct as d,lt as f,pt as p,qn as m,st as h,tn as g,zn as _}from"./index-BaTxSAlR.js";import{t as v}from"./directory-breadcrumb-u3uCxukv.js";import{t as y}from"./data-table-CEq6a930.js";import{t as b}from"./pagination-Bragnnjj.js";import{t as x}from"./use-fetch-files-rnWwNE4C.js";import"./dialog-CnxDxMp1.js";var S=m(u()),C=m(_());function w({handleChangeParentId:e,handleMove:t,handleRemove:a,handleFilePreview:o}){return[{accessorKey:`fileName`,header:`文件名`,cell:({row:t})=>{var a;return(0,C.jsxs)(`div`,{className:`flex items-center gap-1 break-all cursor-pointer hover:underline hover:text-primary group`,onClick:()=>{var n;(t==null||(n=t.original)==null?void 0:n.fileType)===d.DIRECTORY?e(t==null?void 0:t.original):o(t==null?void 0:t.original)},children:[(t==null||(a=t.original)==null?void 0:a.fileType)===d.FILE?(0,C.jsx)(C.Fragment,{children:(0,C.jsx)(n,{size:18,className:`text-primary`})}):(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(i,{size:18,className:`text-amber-500 group-hover:hidden`}),(0,C.jsx)(r,{size:18,className:`text-amber-500 group-hover:block hidden`})]}),(0,C.jsx)(`span`,{children:t.getValue(`fileName`)})]})}},{accessorKey:`createTime`,header:`创建日期`,cell:({row:e})=>(0,C.jsx)(`div`,{children:e.getValue(`createTime`)})},{accessorKey:`fileSize`,header:`文件大小`,cell:({row:e})=>(0,C.jsx)(`div`,{children:g(e.getValue(`fileSize`))})},{accessorKey:`fileCategory`,header:`文件种类`,cell:({row:e})=>(0,C.jsx)(`div`,{children:e.original.fileType===d.FILE?s(e.getValue(`fileCategory`)):`-`})},{accessorKey:`fileStatus`,header:()=>(0,C.jsx)(`div`,{className:`text-center`,children:`状态`}),cell:({row:e})=>(0,C.jsx)(`div`,{className:`text-center`,children:(0,C.jsx)(c,{status:e.original.fileStatus})})},{id:`actions`,enableHiding:!1,header:`操作`,cell:({row:e})=>{let n=e.original;return(0,C.jsxs)(`div`,{className:`space-x-2`,children:[(0,C.jsx)(l,{size:`sm`,variant:`destructive`,onClick:()=>a(e.original),children:`删除`}),(0,C.jsx)(l,{size:`sm`,variant:`outline`,onClick:()=>t(e.original),children:`移动`}),n.fileType===d.FILE&&(0,C.jsx)(l,{variant:`outline`,size:`sm`,onClick:()=>{p({code:n.fileCode})},children:`下载`})]})}}]}function T(){let[n,r]=(0,S.useState)(null),[i,s]=(0,S.useState)(!1),c=e=>{r(e),s(!0)},[l,u]=(0,S.useState)(!1),d=e=>{r(e),u(!0)},[p,m]=(0,S.useState)(!1),g=e=>{r(e),m(!0)},[_,T]=(0,S.useState)(`all`),E=(0,S.useMemo)(()=>({rootType:f.OUTSIDE,fileStatusIn:[h.VALID,h.PARSING,h.TRANSFERING,h.FAILED].join(`,`),fileCategory:_===`all`?void 0:_}),[_]),{openDirectorys:D,changeOpenDirectorys:O,table:k,query:A,reset:j}=x({useColumns:e=>w({handleChangeParentId:e,handleMove:c,handleRemove:d,handleFilePreview:g}),queryKey:[`outsideFiles`],params:E});return(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(a,{open:i,setOpen:s,data:n,params:E,refetch:A.refetch}),(0,C.jsx)(o,{open:l,setOpen:u,data:n,refetch:A.refetch}),(0,C.jsx)(e,{open:p,setOpen:m,data:n}),(0,C.jsxs)(`div`,{className:`p-4 box-border min-h-full space-y-4`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`div`,{className:`text-lg`,children:`我的接收`}),(0,C.jsx)(`div`,{className:`text-xs text-black/50`,children:`文件传输的状态`})]}),(0,C.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,C.jsx)(t,{fileCategory:_,setFileCategory:T,reset:j})}),(0,C.jsxs)(`div`,{className:`p-4 rounded-lg border bg-white space-y-2`,children:[(0,C.jsx)(v,{directorys:D,onChangeDirectorys:O}),(0,C.jsxs)(`div`,{className:`relative overflow-hidden`,children:[(0,C.jsx)(y,{table:k,query:A}),(0,C.jsx)(b,{table:k,className:`justify-end p-2 sticky bottom-0 left-0 right-0 z-10 bg-white`})]})]})]})]})}export{T as component,w as useColumns};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{fn as e}from"./index-BaTxSAlR.js";var t=e(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]);export{t};

View File

@@ -0,0 +1 @@
import{Hn as e}from"./index-BaTxSAlR.js";var t=e(((e,t)=>{t.exports=`SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED`})),n=e(((e,n)=>{var r=t();function i(){}function a(){}a.resetWarningCache=i,n.exports=function(){function e(e,t,n,i,a,o){if(o!==r){var s=Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name=`Invariant Violation`,s}}e.isRequired=e;function t(){return e}var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:i};return n.PropTypes=n,n}})),r=e(((e,t)=>{t.exports=n()()}));export{r as t};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{t as e}from"./app-layout-D4ftBqmM.js";import{t}from"./shield-alert-XSqo2W3w.js";import{at as n,fn as r,qn as i,zn as a}from"./index-BaTxSAlR.js";import"./dialog-CnxDxMp1.js";var o=r(`building-2`,[[`path`,{d:`M10 12h4`,key:`a56b0p`}],[`path`,{d:`M10 8h4`,key:`1sr2af`}],[`path`,{d:`M14 21v-3a2 2 0 0 0-4 0v3`,key:`1rgiei`}],[`path`,{d:`M6 10H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-2`,key:`secmi2`}],[`path`,{d:`M6 21V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v16`,key:`16ra0t`}]]),s=r(`cloud-upload`,[[`path`,{d:`M12 13v8`,key:`1l5pq0`}],[`path`,{d:`M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242`,key:`1pljnt`}],[`path`,{d:`m8 17 4-4 4 4`,key:`1quai1`}]]),c=r(`file-search`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`circle`,{cx:`11.5`,cy:`14.5`,r:`2.5`,key:`1bq0ko`}],[`path`,{d:`M13.3 16.3 15 18`,key:`2quom7`}]]),l=r(`user-round-pen`,[[`path`,{d:`M2 21a8 8 0 0 1 10.821-7.487`,key:`1c8h7z`}],[`path`,{d:`M21.378 16.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z`,key:`1817ys`}],[`circle`,{cx:`10`,cy:`8`,r:`5`,key:`o932ke`}]]),u=r(`users`,[[`path`,{d:`M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2`,key:`1yyitq`}],[`path`,{d:`M16 3.128a4 4 0 0 1 0 7.744`,key:`16gr8j`}],[`path`,{d:`M22 21v-2a4 4 0 0 0-3-3.87`,key:`kshegd`}],[`circle`,{cx:`9`,cy:`7`,r:`4`,key:`nufk8`}]]),d=i(a()),f=[{title:`单位管理`,url:`/admin/tenant`,icon:(0,d.jsx)(o,{})},{title:`用户管理`,url:`/admin/user`,icon:(0,d.jsx)(l,{})},{title:`上传配置`,url:`/admin/upload-config`,icon:(0,d.jsx)(s,{})},{title:`机构账号`,url:`/admin/org-account`,icon:(0,d.jsx)(u,{})},{title:`记录查询`,url:`/admin/file-record`,icon:(0,d.jsx)(c,{})},{title:`审核`,url:`/admin/console`,icon:(0,d.jsx)(t,{})}],p=[`/admin/tenant`,`/admin/org-account`,`/admin/file-record`];function m(){let t=n();return(0,d.jsx)(e,{menus:f.filter(e=>t||!p.includes(e.url)),isAdmin:!0})}export{m as component};

View File

@@ -0,0 +1 @@
import{t as e}from"./folder-input--tEWrMtP.js";import{t}from"./folder-Dl7FxCLT.js";import{t as n}from"./app-layout-D4ftBqmM.js";import{fn as r,qn as i,zn as a}from"./index-BaTxSAlR.js";import"./dialog-CnxDxMp1.js";var o=r(`folder-output`,[[`path`,{d:`M2 7.5V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-1.5`,key:`1yk7aj`}],[`path`,{d:`M2 13h10`,key:`pgb2dq`}],[`path`,{d:`m5 10-3 3 3 3`,key:`1r8ie0`}]]),s=r(`house`,[[`path`,{d:`M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8`,key:`5wwlr5`}],[`path`,{d:`M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z`,key:`r6nss1`}]]),c=r(`recycle`,[[`path`,{d:`M7 19H4.815a1.83 1.83 0 0 1-1.57-.881 1.785 1.785 0 0 1-.004-1.784L7.196 9.5`,key:`x6z5xu`}],[`path`,{d:`M11 19h8.203a1.83 1.83 0 0 0 1.556-.89 1.784 1.784 0 0 0 0-1.775l-1.226-2.12`,key:`1x4zh5`}],[`path`,{d:`m14 16-3 3 3 3`,key:`f6jyew`}],[`path`,{d:`M8.293 13.596 7.196 9.5 3.1 10.598`,key:`wf1obh`}],[`path`,{d:`m9.344 5.811 1.093-1.892A1.83 1.83 0 0 1 11.985 3a1.784 1.784 0 0 1 1.546.888l3.943 6.843`,key:`9tzpgr`}],[`path`,{d:`m13.378 9.633 4.096 1.098 1.097-4.096`,key:`1oe83g`}]]),l=r(`share-2`,[[`circle`,{cx:`18`,cy:`5`,r:`3`,key:`gq8acd`}],[`circle`,{cx:`6`,cy:`12`,r:`3`,key:`w7nqdw`}],[`circle`,{cx:`18`,cy:`19`,r:`3`,key:`1xt0gg`}],[`line`,{x1:`8.59`,x2:`15.42`,y1:`13.51`,y2:`17.49`,key:`47mynk`}],[`line`,{x1:`15.41`,x2:`8.59`,y1:`6.51`,y2:`10.49`,key:`1n3mei`}]]),u=i(a()),d=[{title:`首页`,url:`/`,icon:(0,u.jsx)(s,{})},{title:`我的文件`,url:`/my`,icon:(0,u.jsx)(t,{})},{title:`我的接收`,url:`/outside`,icon:(0,u.jsx)(e,{})},{title:`我的发送`,url:`/inside`,icon:(0,u.jsx)(o,{})},{title:`分享`,url:`/share`,icon:(0,u.jsx)(l,{})},{title:`回收站`,url:`/recycle`,icon:(0,u.jsx)(c,{})}];function f(){return(0,u.jsx)(n,{menus:d})}export{f as component};

View File

@@ -0,0 +1 @@
import{fn as e}from"./index-BaTxSAlR.js";var t=e(`rotate-ccw`,[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`1357e3`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}]]),n=e(`search`,[[`path`,{d:`m21 21-4.34-4.34`,key:`14j7rj`}],[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}]]);export{t as n,n as t};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{fn as e}from"./index-BaTxSAlR.js";var t=e(`shield-alert`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`M12 8v4`,key:`1got3b`}],[`path`,{d:`M12 16h.01`,key:`1drbdi`}]]);export{t};

View File

@@ -0,0 +1 @@
import{A as e,Vn as t,Y as n,b as r,en as i,f as a,k as o,qn as s,u as c,zn as l}from"./index-BaTxSAlR.js";import{t as u}from"./dist-CpxP8T7M.js";import{n as d,r as f,t as p}from"./dist-AWHq1sQs.js";var m=s(t(),1),h=s(l(),1),g=Object.defineProperty,_=(e,t)=>g(e,`name`,{value:t,configurable:!0}),v={Automatic:`automatic`,Manual:`manual`},y=`Tabs`,[b,x]=o(y,[f]),S=f(),[C,w]=b(y),T=m.forwardRef(_(function(e,t){let{__scopeTabs:i,value:a,onValueChange:o,defaultValue:s,orientation:l=`horizontal`,dir:d,activationMode:f=v.Automatic,...p}=e,m=u(d),[g,_]=c({prop:a,onChange:o,defaultProp:s??``,caller:y});return(0,h.jsx)(C,{scope:i,baseId:r(),value:g,onValueChange:_,orientation:l,dir:m,activationMode:f,children:(0,h.jsx)(n.div,{dir:m,"data-orientation":l,...p,ref:t})})},`Tabs`)),E=`TabsList`,D=m.forwardRef(_(function(e,t){let{__scopeTabs:r,loop:i=!0,...a}=e,o=w(E,r),s=S(r);return(0,h.jsx)(p,{asChild:!0,...s,orientation:o.orientation,dir:o.dir,loop:i,children:(0,h.jsx)(n.div,{role:`tablist`,"aria-orientation":o.orientation,...a,ref:t})})},`TabsList`)),O=`TabsTrigger`,k=m.forwardRef(_(function(t,r){let{__scopeTabs:i,value:a,disabled:o=!1,...s}=t,c=w(O,i),l=S(i),u=M(c.baseId,a),f=N(c.baseId,a),p=a===c.value;return(0,h.jsx)(d,{asChild:!0,...l,focusable:!o,active:p,children:(0,h.jsx)(n.button,{type:`button`,role:`tab`,"aria-selected":p,"aria-controls":f,"data-state":p?`active`:`inactive`,"data-disabled":o?``:void 0,disabled:o,id:u,...s,ref:r,onMouseDown:e(t.onMouseDown,e=>{!o&&e.button===0&&e.ctrlKey===!1?(e.currentTarget.focus(),c.onValueChange(a)):e.preventDefault()}),onKeyDown:e(t.onKeyDown,e=>{o||e.target!==e.currentTarget||[` `,`Enter`].includes(e.key)&&c.onValueChange(a)}),onFocus:e(t.onFocus,()=>{let e=c.activationMode!==v.Manual;!p&&!o&&e&&c.onValueChange(a)})})})},`TabsTrigger`)),A=`TabsContent`,j=m.forwardRef(_(function(e,t){let{__scopeTabs:r,value:i,forceMount:o,children:s,...c}=e,l=w(A,r),u=M(l.baseId,i),d=N(l.baseId,i),f=i===l.value,p=m.useRef(f);return m.useEffect(()=>{let e=requestAnimationFrame(()=>p.current=!1);return()=>cancelAnimationFrame(e)},[]),(0,h.jsx)(a,{present:o||f,children:({present:r})=>(0,h.jsx)(n.div,{"data-state":f?`active`:`inactive`,"data-orientation":l.orientation,role:`tabpanel`,"aria-labelledby":u,hidden:!r,id:d,tabIndex:0,...c,ref:t,style:{...e.style,animationDuration:p.current?`0s`:void 0},children:r&&s})})},`TabsContent`));function M(e,t){return`${e}-trigger-${t}`}_(M,`makeTriggerId`);function N(e,t){return`${e}-content-${t}`}_(N,`makeContentId`);function P({className:e,...t}){return(0,h.jsx)(T,{"data-slot":`tabs`,className:i(`flex flex-col gap-2`,e),...t})}function F({className:e,...t}){return(0,h.jsx)(D,{"data-slot":`tabs-list`,className:i(`bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]`,e),...t})}function I({className:e,...t}){return(0,h.jsx)(k,{"data-slot":`tabs-trigger`,className:i(`data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,e),...t})}function L({className:e,...t}){return(0,h.jsx)(j,{"data-slot":`tabs-content`,className:i(`flex-1 outline-none`,e),...t})}export{I as i,L as n,F as r,P as t};

View File

@@ -0,0 +1 @@
import{t as e}from"./useQuery-dxbdhNvu.js";import{t}from"./plus-BHIlMeNy.js";import{$ as n,G as r,H as i,K as a,Q as o,Qt as s,R as c,U as l,V as u,Vn as d,W as f,Zt as p,et as m,ln as h,q as g,qn as _,tt as v,yn as y,z as b,zn as x}from"./index-BaTxSAlR.js";import{n as S,r as C,t as w}from"./data-table-CEq6a930.js";import{t as T}from"./pagination-Bragnnjj.js";import{a as E,n as D,o as O,r as k,s as A,t as j}from"./dialog-CnxDxMp1.js";import{i as M,n as N,t as P}from"./org-CX5LJyS0.js";var F=_(d(),1);const I=t=>{var n,r,i;let[a,o]=(0,F.useState)({pageIndex:0,pageSize:10}),s=e({queryKey:[`orgList`,a],queryFn:()=>N({pageSize:a.pageSize,pageNo:a.pageIndex+1}).then(e=>e.data)}),c=t();return{pagination:a,table:S({data:(s==null||(n=s.data)==null?void 0:n.entityList)||[],columns:c,getCoreRowModel:C(),manualPagination:!1,rowCount:(s==null||(r=s.data)==null?void 0:r.totalCount)||0,pageCount:(s==null||(i=s.data)==null?void 0:i.pageCount)||0,onPaginationChange:o,autoResetPageIndex:!1,state:{pagination:a}}),query:s}},L=e=>{let{mutateAsync:t,isPending:n}=y({mutationFn:e=>e.id?M(e):P({...e,parentId:1}),...e||{}});return{save:e=>{h.promise(t(e),{loading:`提交中...`,success:`操作成功`})},saveIsPending:n}};var R=_(x(),1),z=`Qaz123567!@#`,B=o({orgName:n().nonempty({message:`单位名称不能为空`}),type:n().nonempty({message:`单位类型不能为空`}),phone:n().nonempty({message:`管理员手机号不能为空`}),realName:n().nonempty({message:`管理员姓名不能为空`})});function V({open:e,setOpen:t,data:n,refetch:o}){let d=v({resolver:m(B),defaultValues:{orgName:``,type:`3`,phone:``,realName:``}}),{save:h,saveIsPending:_}=L({onSuccess(){t(!1),o==null||o()}});(0,F.useEffect)(()=>{e&&(d.reset(),n&&(d.setValue(`orgName`,n.orgName),d.setValue(`type`,n.type),d.setValue(`phone`,n.phone),d.setValue(`realName`,n.realName)))},[e]);let y=d.watch(`phone`),x=(0,F.useMemo)(()=>!(n!=null&&n.id),[n]),S=e=>{h({...e,id:n==null?void 0:n.id})};return(0,R.jsx)(j,{open:e,onOpenChange:t,children:(0,R.jsxs)(k,{className:`w-[400px]`,children:[(0,R.jsx)(O,{children:(0,R.jsx)(A,{children:x?`创建单位`:`修改单位`})}),(0,R.jsx)(i,{...d,children:(0,R.jsxs)(`form`,{onSubmit:d.handleSubmit(S),className:`space-y-4`,children:[(0,R.jsx)(f,{control:d.control,name:`orgName`,render:({field:e})=>(0,R.jsxs)(r,{children:[(0,R.jsx)(a,{children:`单位名称`}),(0,R.jsx)(l,{children:(0,R.jsx)(u,{...e})}),(0,R.jsx)(g,{})]})}),(0,R.jsx)(f,{control:d.control,name:`realName`,render:({field:e})=>(0,R.jsxs)(r,{children:[(0,R.jsx)(a,{children:`管理员姓名`}),(0,R.jsx)(l,{children:(0,R.jsx)(u,{...e})}),(0,R.jsx)(g,{})]})}),(0,R.jsx)(f,{control:d.control,name:`phone`,render:({field:e})=>(0,R.jsxs)(r,{children:[(0,R.jsx)(a,{children:`管理员手机号`}),(0,R.jsx)(l,{children:(0,R.jsx)(u,{...e})}),(0,R.jsx)(g,{})]})}),x&&(0,R.jsx)(c,{children:(0,R.jsxs)(b,{children:[(0,R.jsxs)(`div`,{children:[`管理员账号:`,y]}),(0,R.jsxs)(`div`,{children:[`初始密码:`,z]})]})}),(0,R.jsxs)(E,{children:[(0,R.jsx)(D,{asChild:!0,children:(0,R.jsx)(s,{variant:`outline`,children:`取消`})}),(0,R.jsxs)(s,{type:`submit`,disabled:_,children:[_&&(0,R.jsx)(p,{}),`确定`]})]})]})})]})})}function H({handleEditOrg:e}){return[{accessorKey:`orgName`,header:`单位名称`,cell:({row:e})=>(0,R.jsx)(`div`,{children:e.getValue(`orgName`)})},{accessorKey:`realName`,header:`管理员姓名`,cell:({row:e})=>(0,R.jsx)(`div`,{children:e.getValue(`realName`)})},{accessorKey:`phone`,header:`管理员手机号`,cell:({row:e})=>(0,R.jsx)(`div`,{children:e.getValue(`phone`)})},{accessorKey:`createTime`,header:`创建日期`,cell:({row:e})=>(0,R.jsx)(`div`,{children:e.getValue(`createTime`)})}]}function U(){let[e,n]=(0,F.useState)(null),[r,i]=(0,F.useState)(!1),a=e=>{n(e),i(!0)},{table:o,query:c}=I(()=>H({handleEditOrg:a}));return(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(V,{open:r,setOpen:i,data:e,refetch:c==null?void 0:c.refetch}),(0,R.jsxs)(`div`,{className:`p-4 box-border min-h-full space-y-4`,children:[(0,R.jsxs)(`div`,{children:[(0,R.jsx)(`div`,{className:`text-lg`,children:`单位管理`}),(0,R.jsx)(`div`,{className:`text-xs text-black/50`,children:`管理单位信息`})]}),(0,R.jsxs)(`div`,{className:`p-4 rounded-lg border bg-white space-y-2`,children:[(0,R.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,R.jsxs)(s,{onClick:()=>a(),children:[(0,R.jsx)(t,{}),`新增`]})}),(0,R.jsxs)(`div`,{className:`relative overflow-hidden`,children:[(0,R.jsx)(w,{table:o,query:c}),(0,R.jsx)(T,{table:o,className:`justify-end p-2 sticky bottom-0 left-0 right-0 z-10 bg-white`})]})]})]})]})}export{U as component,H as useColumns};

View File

@@ -0,0 +1 @@
import{Vn as e,en as t,qn as n,zn as r}from"./index-BaTxSAlR.js";e();var i=n(r(),1);function a({className:e,...n}){return(0,i.jsx)(`textarea`,{"data-slot":`textarea`,className:t(`border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm`,e),...n})}export{a as t};

View File

@@ -0,0 +1 @@
import{fn as e}from"./index-BaTxSAlR.js";var t=e(`upload`,[[`path`,{d:`M12 3v12`,key:`1x0j5s`}],[`path`,{d:`m17 8-5-5-5 5`,key:`7q97r8`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}]]);export{t};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{t as e}from"./useQuery-dxbdhNvu.js";import{Vn as t,ht as n,qn as r,ut as i}from"./index-BaTxSAlR.js";import{n as a,r as o}from"./data-table-CEq6a930.js";var s=r(t(),1);const c=({useColumns:t,queryKey:r,params:c})=>{var l,u,d;let[f,p]=(0,s.useState)([]),[m,h]=(0,s.useState)(0),[g,_]=(0,s.useState)({pageIndex:0,pageSize:10}),v=e({queryKey:[...r,g,m,c],queryFn:()=>n({parentId:m||0,pageSize:g.pageSize,pageNo:g.pageIndex+1,...c}).then(e=>e.data),refetchInterval:e=>{var t;return((e==null||(t=e.state)==null||(t=t.data)==null?void 0:t.entityList)||[]).some(e=>e.securityStatus===i.SCANNING)?2e3:!1}}),y=e=>{h(e.id),x.setPageIndex(0),p(t=>[...t,e])},b=t(y),x=a({data:(v==null||(l=v.data)==null?void 0:l.entityList)||[],columns:b,getCoreRowModel:o(),manualPagination:!1,rowCount:(v==null||(u=v.data)==null?void 0:u.totalCount)||0,pageCount:(v==null||(d=v.data)==null?void 0:d.pageCount)||0,onPaginationChange:_,autoResetPageIndex:!1,state:{pagination:g}});return{parentId:m,setParentId:h,handleChangeParentId:y,openDirectorys:f,changeOpenDirectorys:e=>{h(e==null?void 0:e.id),x.setPageIndex(0),p(t=>{let n=t.findIndex(t=>t.id===(e==null?void 0:e.id));return n>-1?[...t.slice(0,n+1)]:[]})},pagination:g,table:x,query:v,reset:()=>{h(0),x.setPageIndex(0),p([])}}};export{c as t};

View File

@@ -0,0 +1 @@
import{t as e}from"./useQuery-dxbdhNvu.js";import{Yt as t}from"./index-BaTxSAlR.js";const n=()=>{let{data:n}=e({queryKey:[`securityEnabled`],queryFn:()=>t.get(`/file_security/enabled`).then(e=>e.data),staleTime:300*1e3});return{securityEnabled:!!n}};export{n as t};

View File

@@ -0,0 +1 @@
import{t as e}from"./useQuery-dxbdhNvu.js";import{Yt as t}from"./index-BaTxSAlR.js";const n=()=>t.get(`/upload_config/info`),r=e=>t.post(`/upload_config/modify`,e),i=e=>t.get(`/upload_config/check`,{params:e}),a=()=>e({queryKey:[`uploadConfig`],queryFn:()=>n().then(e=>e==null?void 0:e.data)}),o=e=>{var t;if(!(!e||e.allowAllType||!((t=e.allowedSuffixes)!=null&&t.length)))return e.allowedSuffixes.map(e=>`.${String(e).replace(/^\.+/,``).toLowerCase()}`).join(`,`)},s=e=>{if(e!=null&&e.maxFileSize&&e.maxFileSize>0)return e.maxFileSize*1024*1024};export{r as a,i,s as n,a as r,o as t};

View File

@@ -0,0 +1 @@
import{_n as e,gn as t,hn as n,vn as r}from"./index-BaTxSAlR.js";function i(r){let i=e();return t(i.stores.location,n(r,i))}export{i as t};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{fn as e}from"./index-BaTxSAlR.js";var t=e(`x`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]);export{t};

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

View File

@@ -0,0 +1,44 @@
<!doctype html>
<html lang="zh">
<head>
<meta charset="utf-8" />
<!-- 避免IE兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="chrome=1,IE=edge" />
<!-- 极速模式渲染 -->
<meta name="renderer" content="webkit" />
<!-- 屏幕缩放大小 -->
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"
/>
<!-- 拨打电话 -->
<meta name="format-detection" content="telephone=yes" />
<!-- 设置缓存 -->
<meta
http-equiv="Cache-Control"
content="no-cache, no-store, must-revalidate"
/>
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<!-- SEO -->
<meta property="generator" content="react" />
<meta id="keywords" property="keywords" content="" />
<meta id="robots" property="robots" content="none" />
<meta name="description" content="" />
<meta property="og:title" content="" />
<meta property="og:description" content="" />
<meta property="og:locale" content="zh_CN" />
<!-- dns解析 -->
<link rel="dns-prefetch" href="" />
<!-- 图标 -->
<link id="favicon" rel="icon" href="/favicon.png" />
<!-- 标题 -->
<title>森睿智传</title>
<script type="module" crossorigin src="/assets/index-BaTxSAlR.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BbZGMJ6u.css">
</head>
<body>
<div id="root"></div>
</body>
</html>

View File

@@ -0,0 +1,177 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

79063
deployment/iw/web/pdfjs/build/pdf.worker.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More