Commit
·
a6ec46c
0
Parent(s):
Reinitialize project and track PNG via LFS
Browse files- .gitattributes +3 -0
- app.py +76 -0
- controller.py +63 -0
- data/latents/scGPT/scGPT_atac.csv +3 -0
- data/latents/scGPT/scGPT_rna.csv +3 -0
- data/output/Extended_Data_2_inteaccu.xlsx +0 -0
- data/output/data/batch.csv +3 -0
- data/output/data/biomarker.csv +3 -0
- data/output/data/integration_accuracy.csv +3 -0
- data/output/output_metrics.yaml +9 -0
- data/output/raw_combine_traj.h5ad +3 -0
- data/shell/run_integration.sh +14 -0
- requirements.text +6 -0
- service.py +56 -0
- static/Image/PBMC10x/Cobolt.png +3 -0
- static/Image/PBMC10x/Deepmaps.png +3 -0
- static/Image/PBMC10x/GLUE.png +3 -0
- static/Image/PBMC10x/Geneformer.png +3 -0
- static/Image/PBMC10x/Harmony.png +3 -0
- static/Image/PBMC10x/LIGER.png +3 -0
- static/Image/PBMC10x/MMD-MA.png +3 -0
- static/Image/PBMC10x/MOFA.png +3 -0
- static/Image/PBMC10x/PCA.png +3 -0
- static/Image/PBMC10x/Pamona.png +3 -0
- static/Image/PBMC10x/TotalVI.png +3 -0
- static/Image/PBMC10x/UCE.png +3 -0
- static/Image/PBMC10x/UnionCom.png +3 -0
- static/Image/PBMC10x/bindsc.png +3 -0
- static/Image/PBMC10x/iNMF.png +3 -0
- static/Image/PBMC10x/scFoundation.png +3 -0
- static/Image/PBMC10x/scGPT_bc.png +3 -0
- static/Image/PBMC10x/scGPT_bc_zeroshot.png +3 -0
- static/Image/PBMC10x/scGPT_human.png +3 -0
- static/Image/PBMC10x/scGPT_human_zeroshot.png +3 -0
- static/Image/PBMC10x/scGPT_scvi.png +3 -0
- static/Image/PBMC10x/scJoint.png +3 -0
- static/Image/PBMC10x/scMDC.png +3 -0
- static/Image/PBMC10x/scMoMaT.png +3 -0
- static/Image/PBMC10x/scVI.png +3 -0
- static/Image/PBMC10x/seurat4.png +3 -0
- static/Image/PBMC10x/seurat5.png +3 -0
- static/Image/cuhk.png +3 -0
- static/Image/cuhk.pngZone.Identifier +3 -0
- static/assets/index-C9Enc7k_.css +1 -0
- static/assets/index-FSNbkXt5.js +0 -0
- static/favicon.ico +0 -0
- static/index.html +14 -0
.gitattributes
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.csv filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.h5ad filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
app.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# app.py (主入口文件)
|
| 2 |
+
import os
|
| 3 |
+
from fastapi import FastAPI, File, UploadFile
|
| 4 |
+
from fastapi.staticfiles import StaticFiles
|
| 5 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 6 |
+
import gradio as gr
|
| 7 |
+
import uvicorn
|
| 8 |
+
import aiofiles
|
| 9 |
+
from typing import List
|
| 10 |
+
import service
|
| 11 |
+
|
| 12 |
+
# ---------- 原 controller.py 的核心逻辑 ----------
|
| 13 |
+
uploadPath = "./data/latents/"
|
| 14 |
+
|
| 15 |
+
# 初始化 FastAPP
|
| 16 |
+
app = FastAPI()
|
| 17 |
+
|
| 18 |
+
# CORS 配置(保持与 controller.py 一致)
|
| 19 |
+
app.add_middleware(
|
| 20 |
+
CORSMiddleware,
|
| 21 |
+
allow_origins=["http://localhost:5173"], # 前端开发地址
|
| 22 |
+
allow_credentials=True,
|
| 23 |
+
allow_methods=["*"],
|
| 24 |
+
allow_headers=["*"],
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
# ---------- 原 controller.py 的路由 ----------
|
| 29 |
+
@app.get("/dataList/{datatype}")
|
| 30 |
+
async def read_data(datatype):
|
| 31 |
+
return service.getALlData() # 示例数据,替换为实际 service 调用
|
| 32 |
+
|
| 33 |
+
# 定义带路径参数的 GET 请求处理函数
|
| 34 |
+
@app.get("/details/{name}")
|
| 35 |
+
async def read_item(name: str = None):
|
| 36 |
+
data = service.getListByName("integration_accuracy.csv", name)
|
| 37 |
+
return data
|
| 38 |
+
|
| 39 |
+
@app.post("/upload")
|
| 40 |
+
async def upload_files(files: List[UploadFile] = File(...)):
|
| 41 |
+
for file in files:
|
| 42 |
+
save_path = os.path.join(uploadPath, file.filename)
|
| 43 |
+
try:
|
| 44 |
+
async with aiofiles.open(save_path, 'wb') as out_file:
|
| 45 |
+
content = await file.read()
|
| 46 |
+
await out_file.write(content)
|
| 47 |
+
except Exception as e:
|
| 48 |
+
return {"message": f"Error: {e}"}
|
| 49 |
+
finally:
|
| 50 |
+
await file.close()
|
| 51 |
+
return {"success": True, "message": "Files uploaded"}
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
# 挂载 Vue3 前端静态文件(部署时需要)
|
| 55 |
+
app.mount("/", StaticFiles(directory="static", html=True), name="static")
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
# ---------- 集成 Gradio 接口 ----------
|
| 59 |
+
def gradio_predict(text):
|
| 60 |
+
return f"Processed: {text}"
|
| 61 |
+
|
| 62 |
+
gradio_ui = gr.Interface(
|
| 63 |
+
fn=gradio_predict,
|
| 64 |
+
inputs=gr.Textbox(label="输入文本"),
|
| 65 |
+
outputs=gr.Textbox(label="处理结果"),
|
| 66 |
+
title="Gradio 交互界面"
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
# 将 Gradio 挂载到 /gradio 路径
|
| 70 |
+
app = gr.mount_gradio_app(app, gradio_ui, path="/gradio")
|
| 71 |
+
|
| 72 |
+
# ---------- 启动配置 ----------
|
| 73 |
+
if __name__ == "__main__":
|
| 74 |
+
# Hugging Face Spaces 使用 PORT 环境变量
|
| 75 |
+
port = int(os.getenv("PORT", 8000))
|
| 76 |
+
uvicorn.run(app, host="0.0.0.0", port=port)
|
controller.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import uvicorn
|
| 3 |
+
import aiofiles
|
| 4 |
+
from fastapi import FastAPI, HTTPException, File, UploadFile
|
| 5 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 6 |
+
from fastapi.responses import JSONResponse
|
| 7 |
+
|
| 8 |
+
from typing import List
|
| 9 |
+
|
| 10 |
+
import service
|
| 11 |
+
|
| 12 |
+
uploadPath = "./data/latents/"
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
app = FastAPI()
|
| 16 |
+
# 配置 CORS 中间件
|
| 17 |
+
app.add_middleware(
|
| 18 |
+
CORSMiddleware,
|
| 19 |
+
allow_origins=["http://localhost:5173"], # 允许的前端地址
|
| 20 |
+
allow_credentials=True, # 是否允许发送 Cookie
|
| 21 |
+
allow_methods=["*"], # 允许的 HTTP 方法(GET、POST、PUT 等)
|
| 22 |
+
allow_headers=["*"], # 允许的请求头
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
# 定义根路径的 GET 请求处理函数
|
| 26 |
+
@app.get("/")
|
| 27 |
+
async def read_root():
|
| 28 |
+
return {"message": "Hello, World!"}
|
| 29 |
+
|
| 30 |
+
@app.get("/dataList/{datatype}")
|
| 31 |
+
async def read_data(datatype):
|
| 32 |
+
return service.getALlData()
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
# 定义带路径参数的 GET 请求处理函数
|
| 39 |
+
@app.get("/details/{name}")
|
| 40 |
+
async def read_item(name: str = None):
|
| 41 |
+
data = service.getListByName("integration_accuracy.csv", name)
|
| 42 |
+
return data
|
| 43 |
+
|
| 44 |
+
# 定义 POST 请求处理函数
|
| 45 |
+
@app.post("/upload")
|
| 46 |
+
async def upload_files(files:List[UploadFile] = File(...)):
|
| 47 |
+
for file in files:
|
| 48 |
+
save_path = os.path.join(uploadPath, file.filename)
|
| 49 |
+
try:
|
| 50 |
+
async with aiofiles.open(save_path, 'wb') as out_file:
|
| 51 |
+
content = await file.read()
|
| 52 |
+
await out_file.write(content)
|
| 53 |
+
except Exception as e:
|
| 54 |
+
return {"message": f"出现错误: {e}"}
|
| 55 |
+
finally:
|
| 56 |
+
# 关闭文件
|
| 57 |
+
await file.close()
|
| 58 |
+
return {"success":True, "message": f"文件 {file.filename} 已成功保存"}
|
| 59 |
+
|
| 60 |
+
if __name__ == "__main__":
|
| 61 |
+
# 从环境变量中读取端口,默认为 8000
|
| 62 |
+
port = int(os.getenv("APP_PORT", 8000))
|
| 63 |
+
uvicorn.run(app, host="127.0.0.1", port=port)
|
data/latents/scGPT/scGPT_atac.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:fcf709485bf9250cf6c448474187f8f565fd813c568802f4265ffb34d9fe453f
|
| 3 |
+
size 61607066
|
data/latents/scGPT/scGPT_rna.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:fcf709485bf9250cf6c448474187f8f565fd813c568802f4265ffb34d9fe453f
|
| 3 |
+
size 61607066
|
data/output/Extended_Data_2_inteaccu.xlsx
ADDED
|
Binary file (73.6 kB). View file
|
|
|
data/output/data/batch.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:fc7cfc5042e7edb1e308222d6f782f30d9aacb87fb554eb90962791300cc177f
|
| 3 |
+
size 2151
|
data/output/data/biomarker.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:de188bb4cb0af2fdee272d0a9c2bd726362cc37d7bb989660c6d764474964385
|
| 3 |
+
size 8246
|
data/output/data/integration_accuracy.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7ad3a43c2e040c02eafe97bb2d7dfcb36e611cb603f66c53bc823b507161476c
|
| 3 |
+
size 4664
|
data/output/output_metrics.yaml
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
adjusted_rand_index: 0.1653
|
| 2 |
+
avg_silhouette_width: 0.4242
|
| 3 |
+
avg_silhouette_width_batch: 0.9889
|
| 4 |
+
foscttm: 0.0
|
| 5 |
+
graph_connectivity: 0.2809
|
| 6 |
+
mean_average_precision: 0.4612
|
| 7 |
+
neighbor_conservation: 0.0431
|
| 8 |
+
normalized_mutual_info: 0.3243
|
| 9 |
+
seurat_alignment_score: 1.0
|
data/output/raw_combine_traj.h5ad
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9e77aed4ced6a3cb4e86cb0a1cd44611fb5c55501003743cc9bd20eacca14580
|
| 3 |
+
size 11801924
|
data/shell/run_integration.sh
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
method=scGPT
|
| 2 |
+
echo '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++'
|
| 3 |
+
echo '+++++ Integration_accuracy real: '$method' +++++'
|
| 4 |
+
echo '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++'
|
| 5 |
+
|
| 6 |
+
for data_name in 10x-Multiome-Pbmc10k
|
| 7 |
+
do
|
| 8 |
+
echo "Evaluation with $data_name"
|
| 9 |
+
python integration_accuracy.py \
|
| 10 |
+
-d ../../data/download/$data_name/$data_name-small-RNA_uni.h5ad ../../data/download/$data_name/$data_name-small-ATAC_uni.h5ad \
|
| 11 |
+
-l ../../results/$method-output/$data_name/$data_name-small-rna.csv ../../results/$method-output/$data_name/$data_name-small-atac.csv \
|
| 12 |
+
-o ../../results/$method-output/$data_name/$data_name-cell_integration_info.yaml
|
| 13 |
+
echo "=================="
|
| 14 |
+
done
|
requirements.text
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastapi>=0.68.0
|
| 2 |
+
uvicorn>=0.15.0
|
| 3 |
+
gradio>=3.0
|
| 4 |
+
aiofiles>=0.7.0
|
| 5 |
+
python-multipart>=0.0.5 # 文件上传需要
|
| 6 |
+
pandas>=2.2.3
|
service.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import pandas as pd
|
| 3 |
+
|
| 4 |
+
basePath = "./data/output/data/"
|
| 5 |
+
uploadPath = "./data/latents/"
|
| 6 |
+
|
| 7 |
+
# def toJson(data):
|
| 8 |
+
# return {
|
| 9 |
+
# "success": True,
|
| 10 |
+
# "data": data
|
| 11 |
+
# }
|
| 12 |
+
def getALlData():
|
| 13 |
+
files = os.listdir(basePath)
|
| 14 |
+
|
| 15 |
+
merged_df = None
|
| 16 |
+
for each in files:
|
| 17 |
+
df = pd.read_csv(os.path.join(basePath, each))
|
| 18 |
+
|
| 19 |
+
if merged_df is None: merged_df = df
|
| 20 |
+
else: merged_df = pd.concat([merged_df, df], ignore_index=True)
|
| 21 |
+
|
| 22 |
+
grouped_df = merged_df.groupby(['methods', 'datasets']).mean().reset_index()
|
| 23 |
+
grouped_df = grouped_df.fillna(0)
|
| 24 |
+
for col in grouped_df.select_dtypes(include=['float']).columns:
|
| 25 |
+
grouped_df[col] = grouped_df[col].round(4)
|
| 26 |
+
|
| 27 |
+
data = grouped_df.to_dict(orient='records')
|
| 28 |
+
return data
|
| 29 |
+
|
| 30 |
+
def getList(datatype):
|
| 31 |
+
if datatype == "Integration Accuracy":
|
| 32 |
+
file = "integration_accuracy.csv"
|
| 33 |
+
elif datatype == "Batch Correction":
|
| 34 |
+
file = "batch.csv"
|
| 35 |
+
elif datatype == "Bio Conservation":
|
| 36 |
+
file = "biomarker.csv"
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
path = os.path.join(basePath, file)
|
| 40 |
+
df = pd.read_csv(path)
|
| 41 |
+
df["object_type"] = datatype
|
| 42 |
+
data = df.to_dict(orient='records')
|
| 43 |
+
return data
|
| 44 |
+
|
| 45 |
+
def getListByName(file, name):
|
| 46 |
+
path = os.path.join(basePath, file)
|
| 47 |
+
df = pd.read_csv(path)
|
| 48 |
+
filtered_records = df[df['methods'] == name]
|
| 49 |
+
data = filtered_records.to_dict(orient='records')
|
| 50 |
+
return data
|
| 51 |
+
|
| 52 |
+
def uploadFile(uploadFiles):
|
| 53 |
+
for file in uploadFiles:
|
| 54 |
+
save_path = os.path.join(uploadPath, file.filename)
|
| 55 |
+
file.save(save_path)
|
| 56 |
+
|
static/Image/PBMC10x/Cobolt.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/Deepmaps.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/GLUE.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/Geneformer.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/Harmony.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/LIGER.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/MMD-MA.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/MOFA.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/PCA.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/Pamona.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/TotalVI.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/UCE.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/UnionCom.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/bindsc.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/iNMF.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/scFoundation.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/scGPT_bc.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/scGPT_bc_zeroshot.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/scGPT_human.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/scGPT_human_zeroshot.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/scGPT_scvi.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/scJoint.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/scMDC.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/scMoMaT.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/scVI.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/seurat4.png
ADDED
|
Git LFS Details
|
static/Image/PBMC10x/seurat5.png
ADDED
|
Git LFS Details
|
static/Image/cuhk.png
ADDED
|
Git LFS Details
|
static/Image/cuhk.pngZone.Identifier
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[ZoneTransfer]
|
| 2 |
+
ZoneId=3
|
| 3 |
+
HostUrl=about:internet
|
static/assets/index-C9Enc7k_.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
.Container[data-v-5531406c]{height:100%}.detailContainer[data-v-2cb8acfe]{padding-left:20px;padding-right:20px;padding-top:20px;width:95%;margin:0 auto;color:#000;border-radius:8px}.table-wrapper[data-v-2cb8acfe]{overflow-x:auto}th[data-v-2cb8acfe],td[data-v-2cb8acfe]{padding:12px 15px;border:1px solid #4f536f;text-align:center}.metric-table th[data-v-2cb8acfe]:first-child,.metric-table td[data-v-2cb8acfe]:first-child{width:200px;min-width:200px;max-width:200px;text-align:left;padding-left:20px;position:sticky;left:0;z-index:1}.metric-table th[data-v-2cb8acfe]:not(:first-child),.metric-table td[data-v-2cb8acfe]:not(:first-child){width:auto;min-width:120px}.metric-header[data-v-2cb8acfe]{background:#434654;font-weight:700}.dataset-header[data-v-2cb8acfe]{background:#3a4455;color:#05e89d}.metric-label[data-v-2cb8acfe]{text-align:left;background:#434654;font-weight:700}.metric-value[data-v-2cb8acfe]{background:#2f3a4a}tr:hover td[data-v-2cb8acfe]{background-color:#454856}.header-container[data-v-2cb8acfe]{display:flex;justify-content:space-between;align-items:center;color:#000;padding-left:10px;border-bottom:1px solid black}.back-button[data-v-2cb8acfe]{color:#05080d;padding:8px 15px;border-radius:4px;text-decoration:none;transition:all .3s;display:flex;align-items:center;gap:5px;border:1px solid #05089D55}.back-button span[data-v-2cb8acfe]{font-weight:700;font-size:1.1em}.back-button[data-v-2cb8acfe]:hover{background:#434654;box-shadow:0 0 8px #535664;transform:translateY(-1px)}img[data-v-2cb8acfe]{max-width:100%;height:auto;margin-top:20px}.economy[data-v-3dd1c3a2]{padding-top:20px;width:100%;margin:20px auto;height:100%;display:flex;flex-direction:column}.ecoList[data-v-bc865045]{padding-left:20px;padding-right:20px;padding-top:5px;width:100%;height:870px;margin:0 auto;display:flex;flex-direction:column}.ecoListTables[data-v-bc865045]{color:#000;width:100%;height:100%;flex:1;display:flex;flex-direction:column;overflow:hidden}.ecoListTableHead[data-v-bc865045],.ecoListTableBody[data-v-bc865045]{table-layout:fixed;width:100%;border-collapse:collapse;background-color:#fafafa}.ecoListTableHeadDiv[data-v-bc865045]{flex-shrink:0;overflow:hidden;position:sticky;top:0;z-index:1}.ecoListTableBodyDiv[data-v-bc865045]{flex:1;width:calc(100% + 17px);padding-right:17px;overflow-x:scroll;overflow-y:auto}.ecoListTableHeadDiv[data-v-bc865045],.ecoListTableBodyDiv[data-v-bc865045]{position:static}.ecoListTableHead th[data-v-bc865045],.ecoListTableBody td[data-v-bc865045]{box-sizing:border-box;padding:12px 15px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border:.1px solid #f1f1f1;text-align:center}.ecoListTableHead th[data-v-bc865045]{cursor:pointer;-webkit-user-select:none;user-select:none}.ecoListTableHead th.active[data-v-bc865045],.ecoListTableBody tr[data-v-bc865045]:hover{background-color:#e1e1e1}.sort-icon[data-v-bc865045]{margin-left:3px}.ecoListTableHead th[data-v-bc865045]:first-child,.ecoListTableBody td[data-v-bc865045]:first-child{position:sticky;left:0;z-index:2;background:#fafafa;box-shadow:2px 0 4px #0000001a}.ecoListTableHead th[data-v-bc865045]:first-child{z-index:3}.type-filter[data-v-bc865045]{background:#fafafa;border:1px solid #4f536f;color:#000;padding:5px;border-radius:4px;font-size:.9em;width:95%;margin:2px 0}.type-filter[data-v-bc865045]:focus{outline:none;border-color:#1a3f90;box-shadow:0 0 3px #1890ff80}.detail-link[data-v-bc865045]{color:#1a3f90;text-decoration:none;transition:color .3s}.detail-link[data-v-bc865045]:hover{text-decoration:underline}.modalRatio[data-v-bc865045]{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:flex;justify-content:center;align-items:center;z-index:2}.modal-content[data-v-bc865045]{background:#2f3a4a;padding:20px;border-radius:8px;width:400px;color:#fff}.modal-title[data-v-bc865045]{margin:0 0 20px;font-size:16px}.custom-form[data-v-bc865045]{display:flex;flex-direction:column;gap:15px}.form-item[data-v-bc865045]{display:flex;align-items:center;justify-content:space-between}.form-item label[data-v-bc865045]{width:140px;font-size:14px}.form-item input[data-v-bc865045]{width:180px;padding:8px 12px;background:#3a4555;border:1px solid #4f536f;border-radius:4px;color:#fff;font-size:14px}input[type=number][data-v-bc865045]::-webkit-inner-spin-button{-webkit-appearance:none}.error-msg[data-v-bc865045]{color:#ff4d4f;font-size:12px;text-align:center;height:20px}.form-actions[data-v-bc865045]{display:flex;justify-content:flex-end;gap:10px;margin-top:15px}button[data-v-bc865045]{padding:8px 16px;border:none;border-radius:4px;cursor:pointer;font-size:14px}.cancel-btn[data-v-bc865045]{background:#4f536f;color:#fff}.submit-btn[data-v-bc865045]{background:#4d7398;color:#fff}.submit-btn[data-v-bc865045]:disabled{background:#4f536f;cursor:not-allowed;opacity:.7}.economy[data-v-b7ce071b]{padding-top:20px;width:90%;margin:20px auto;height:100%;display:flex;flex-direction:column}.economytHead[data-v-b7ce071b]{background-color:#1a3f90;margin:0 20px;width:100%}.top-header[data-v-b7ce071b]{margin:0 auto;padding:20px 45px;clear:both;color:#c6daf0}.logo[data-v-b7ce071b]{display:inline-block;vertical-align:middle}.logo-title[data-v-b7ce071b],.logo-title2[data-v-b7ce071b]{display:inline-block;vertical-align:middle;font-size:18px;line-height:1.2}.logo-title[data-v-b7ce071b]{margin-left:15px;padding-right:10px}.logo-title2[data-v-b7ce071b]{padding-left:15px;position:relative}.logo-title2[data-v-b7ce071b]:before{content:"";display:block;width:2px;height:55px;background-color:#756b5c;position:absolute;left:0;top:4px}.logo-title-right[data-v-b7ce071b]{float:right;text-align:right;font-weight:1000;color:#f5f5f5}.logo-title-right .first[data-v-b7ce071b]{font-size:30px;font-family:Anton,sans-serif}.logo-title-right.second[data-v-b7ce071b]{font-size:14px;color:#c6daf0;font-family:Varela Round,sans-serif}
|
static/assets/index-FSNbkXt5.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
static/favicon.ico
ADDED
|
|
static/index.html
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<link rel="icon" href="/favicon.ico">
|
| 6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 7 |
+
<title>Vite App</title>
|
| 8 |
+
<script type="module" crossorigin src="/assets/index-FSNbkXt5.js"></script>
|
| 9 |
+
<link rel="stylesheet" crossorigin href="/assets/index-C9Enc7k_.css">
|
| 10 |
+
</head>
|
| 11 |
+
<body>
|
| 12 |
+
<div id="app"></div>
|
| 13 |
+
</body>
|
| 14 |
+
</html>
|