feat: R1 重构对称迁移 + 升级依赖 + 配置文件分离
- 命名重构:tenant → customer(对齐后端 R1 重构) - Tenant → Customer / tenant_id → customerId - tenantStore → customerStore / getTenant/setTenant → getCustomer/setCustomer - cookie key tenant → customer, HTTP header tenantId → customerId - 后端契约更新:AuthResponse 加 sub 字段 - 接口 URL 修复:/auth/oidc/callback → /api/v1/auth/oidc/callback - 依赖升级:vue 3.5 / element-plus 2.8 / vite 5 / typescript 5.6 / sass 1.79 - 删 node-sass / scss / sass-loader / moment / mock/index.ts - 配置文件拆分:.env.development / .env.production / .env.example - 删除冗余 view/auth/auth/callback.vue 副本 - .gitignore 增加 dist / .opencode / tmp - 新增 AGENT.md 与后端风格对齐
This commit is contained in:
@@ -0,0 +1,43 @@
|
|||||||
|
# ============== 环境变量模板 ==============
|
||||||
|
# 复制为 .env.development / .env.production / .env.test 后填入真实值。
|
||||||
|
# 真实值不要 commit 到 git。
|
||||||
|
|
||||||
|
# 当前模式名(dev / test / prod)
|
||||||
|
VITE_MODE_NAME=development
|
||||||
|
|
||||||
|
# 资源 CDN 前缀
|
||||||
|
VITE_RES_URL=http://localhost:3000/
|
||||||
|
|
||||||
|
# 后端 API 基础地址
|
||||||
|
# dev: http://localhost:8080/auth
|
||||||
|
# prod: https://www.violin-home.cn
|
||||||
|
VITE_APP_URL=http://localhost:8080/auth
|
||||||
|
|
||||||
|
# 应用元信息
|
||||||
|
VITE_APP_TITLE=violin-home
|
||||||
|
VITE_APP_ID=123456
|
||||||
|
VITE_AGENT_ID=123456
|
||||||
|
|
||||||
|
# 是否启用 mock(dev 启用,prod 关闭)
|
||||||
|
VITE_LOGIN_TEST=true
|
||||||
|
|
||||||
|
# ============== OIDC / Authentik 配置 ==============
|
||||||
|
# 三个环境的 issuer + client-id + redirect-uri 都不一样。
|
||||||
|
# dev 与 prod 必须用 Authentik 后台两个独立的 Application,
|
||||||
|
# 因为 redirect-uri 不同(dev 走 localhost,prod 走域名)。
|
||||||
|
|
||||||
|
# Authentik 域名(dev / prod 共用,dev 仅用于登录页跳转)
|
||||||
|
VITE_OIDC_ISSUER=https://auth.violin-work.online
|
||||||
|
|
||||||
|
# 客户端 ID(在 Authentik 后台创建)
|
||||||
|
# dev: violin-home-dev
|
||||||
|
# prod: violin-home
|
||||||
|
VITE_OIDC_CLIENT_ID=
|
||||||
|
|
||||||
|
# 回调 URI(必须与 Authentik 后台配置的完全一致)
|
||||||
|
# dev: http://localhost:3000/auth/callback
|
||||||
|
# prod: https://www.violin-home.cn/auth/callback
|
||||||
|
VITE_OIDC_REDIRECT_URI=
|
||||||
|
|
||||||
|
# 编辑器标识
|
||||||
|
VITE_EDITOR=vscode
|
||||||
@@ -9,10 +9,17 @@ lerna-debug.log*
|
|||||||
|
|
||||||
node_modules
|
node_modules
|
||||||
dist-ssr
|
dist-ssr
|
||||||
|
dist
|
||||||
*.local
|
*.local
|
||||||
|
|
||||||
|
# 临时文件
|
||||||
|
tmp/
|
||||||
|
.opencode/
|
||||||
|
.opencode/tmp/
|
||||||
|
|
||||||
# 配置文件信息不能暴露
|
# 配置文件信息不能暴露
|
||||||
.env.*
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
|||||||
@@ -1 +1,210 @@
|
|||||||
# AGENT.md
|
# AGENT.md — violin-home
|
||||||
|
|
||||||
|
> 面向 AI agent 的工程导览:模块关系、路由约定、与后端的契约、扩展点。
|
||||||
|
> 代码即事实,本文件是索引;如代码与本文档冲突,**以代码为准**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 项目定位
|
||||||
|
|
||||||
|
violin-home 是 **violin 微服务套件的统一前端门户**,部署在 `https://www.violin-home.cn/`。
|
||||||
|
|
||||||
|
- 认证:**Authentik OIDC**,回调路径 `/auth/callback`,前端把 code POST 到 `violin-auth` 服务换 token
|
||||||
|
- 后端:依赖 violin-auth(认证)/ violin-bookmark(书签)/ violin-calendar(日历)/ violin-onenote / violin-cloud / 等子服务
|
||||||
|
- 域名:生产 `https://www.violin-home.cn/`;本地 dev 走 `.env.development` 的 `VITE_APP_URL`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
| 维度 | 选型 |
|
||||||
|
|------|------|
|
||||||
|
| 框架 | Vue 3.5 + Composition API (`<script setup>`) |
|
||||||
|
| 构建 | Vite 5 |
|
||||||
|
| 语言 | TypeScript 5.6 |
|
||||||
|
| UI | Element Plus 2.8 + Icons |
|
||||||
|
| 状态 | Pinia 2.2 |
|
||||||
|
| 路由 | vue-router 4.4(**memory history**,不是 hash / web) |
|
||||||
|
| HTTP | axios 1.7 |
|
||||||
|
| 图表 | ECharts 5 |
|
||||||
|
| Markdown | md-editor-v3 4 |
|
||||||
|
| 日期 | dayjs(**已废弃 moment**) |
|
||||||
|
| Mock | vite-plugin-mock 3(**仅 dev 启用**) |
|
||||||
|
| 拖拽 | vuedraggable 4 |
|
||||||
|
| 样式 | SCSS(Dart Sass 1.79,**已删除 node-sass**) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
violin-home/
|
||||||
|
├── public/ 静态资源(不打包)
|
||||||
|
│ ├── blog/*.ts 博客元数据(按业务模块拆分)
|
||||||
|
│ └── reset/ Authentik reset 入口(reset.html 等)
|
||||||
|
├── src/
|
||||||
|
│ ├── api/ axios 接口封装(每个业务一个文件)
|
||||||
|
│ ├── components/ 公共组件
|
||||||
|
│ │ ├── common/ 通用组件
|
||||||
|
│ │ ├── layout/ 顶层布局
|
||||||
|
│ │ ├── login/ 登录 / 注册 / sorryPage
|
||||||
|
│ │ ├── cloud/ 云盘 + aplayer 音乐
|
||||||
|
│ │ ├── illustration/ 插画
|
||||||
|
│ │ ├── customPic/ 自定义图片
|
||||||
|
│ │ └── operate/ 操作组件
|
||||||
|
│ ├── const/ 全局常量
|
||||||
|
│ ├── entity/ 实体类型(TypeScript interface)
|
||||||
|
│ ├── router/ 路由表(**统一指向 @/view/**)
|
||||||
|
│ ├── service/ 服务层(独立于 axios 的工具服务)
|
||||||
|
│ ├── store/ Pinia stores
|
||||||
|
│ ├── style/ 全局样式(mixin.scss 在 vite.config.ts 里自动注入)
|
||||||
|
│ ├── types/ 类型声明(*.d.ts)
|
||||||
|
│ ├── utils/ 工具函数(auth 令牌管理、request axios 封装、date、number)
|
||||||
|
│ ├── view/ **页面视图(业务页)** — 单数 view
|
||||||
|
│ ├── App.vue
|
||||||
|
│ ├── env.d.ts
|
||||||
|
│ ├── main.ts
|
||||||
|
│ └── permission.ts 路由守卫
|
||||||
|
├── mock/ vite-plugin-mock 的 mock 数据
|
||||||
|
├── authentik-deploy/ Authentik 部署相关(helm values、reset 脚本)
|
||||||
|
├── .env.development 本地开发
|
||||||
|
├── .env.test 测试环境
|
||||||
|
├── .env.production 生产环境
|
||||||
|
├── Dockerfile
|
||||||
|
├── Jenkinsfile
|
||||||
|
├── nginx.conf
|
||||||
|
├── vite.config.ts
|
||||||
|
└── tsconfig.json
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 路由约定
|
||||||
|
|
||||||
|
**全部路由指向 `@/view/`**(单数),包括 `/auth/callback`:
|
||||||
|
- `router/index.ts` 是**唯一**的路由表
|
||||||
|
- 路由 meta.name 是侧边栏展示的中文名
|
||||||
|
- `/auth/callback` 由 `view/auth/callback.vue` 处理 OIDC 回调(拿 code → POST `/auth/oidc/callback` 到 violin-auth → 存 token)
|
||||||
|
|
||||||
|
**禁止**新建 `views/`(复数)目录。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 认证流程(OIDC)
|
||||||
|
|
||||||
|
```
|
||||||
|
浏览器 → Authentik 登录页(不在本工程)
|
||||||
|
↓ 回调到 https://www.violin-home.cn/auth/callback?code=...&state=...
|
||||||
|
↓
|
||||||
|
view/auth/callback.vue
|
||||||
|
↓ POST { code, redirect_uri } → VITE_APP_URL + '/auth/oidc/callback'
|
||||||
|
↓
|
||||||
|
violin-auth 服务(cn.violin.auth.service.OAuthService.oidcAuthorize)
|
||||||
|
↓ 返回 { token, user_id, name }
|
||||||
|
↓
|
||||||
|
utils/auth.setToken / setTenant 存到 cookie + localStorage
|
||||||
|
↓ 跳到 /
|
||||||
|
```
|
||||||
|
|
||||||
|
**关键约定**:
|
||||||
|
- `redirect_uri` 必须和 Authentik 应用的配置完全一致(`VITE_OIDC_REDIRECT_URI`)
|
||||||
|
- `state` 必须校验(防 CSRF),前后端都用 `sessionStorage.oidc_state` 缓存
|
||||||
|
- token 由 `setToken()` 存到 cookie(`js-cookie`),后续 axios 请求拦截器自动加 `Authorization: Bearer <token>`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## HTTP 封装(utils/request.ts)
|
||||||
|
|
||||||
|
- `baseURL` = `import.meta.env.VITE_APP_URL`
|
||||||
|
- 请求拦截器:从 `js-cookie` 读 token,加到 header
|
||||||
|
- 响应拦截器:401 → 跳 `/login`;5xx → ElMessage 报错
|
||||||
|
|
||||||
|
每个业务模块在 `src/api/` 下有自己的文件(如 `api/bookmark.ts`),导出按业务分组的函数:
|
||||||
|
```ts
|
||||||
|
import { service } from '@/utils/request'
|
||||||
|
export const getBookmarks = (params: PageQuery) =>
|
||||||
|
service({ url: '/api/v1/bookmark', method: 'get', params })
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 状态管理(Pinia)
|
||||||
|
|
||||||
|
`src/store/` 下每个业务一个 store(settings、strategy、table、tenant)。**禁止**把所有状态塞进一个 store。
|
||||||
|
|
||||||
|
- `tenant` store 管当前 customer(对应后端的 customerId)
|
||||||
|
- `settings` store 管用户偏好
|
||||||
|
- `strategy` store 管 CTA 策略模板
|
||||||
|
- `table` store 管通用表格筛选/分页状态
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 与后端子服务的对应
|
||||||
|
|
||||||
|
| 路径前缀 | 后端服务 | 端口(K8s 内) |
|
||||||
|
|---------|---------|--------------|
|
||||||
|
| `/auth/**` | violin-auth | 8080 |
|
||||||
|
| `/api/v1/bookmark/**` | violin-bookmark | 8081 |
|
||||||
|
| `/api/v1/calendar/**` | violin-calendar | 8082 |
|
||||||
|
| `/api/v1/onenote/**` | violin-onenote | 8083 |
|
||||||
|
| `/api/v1/cloud/**` | violin-cloud | 8084 |
|
||||||
|
| `/api/v1/trader/**` | violin-trader | 8085 |
|
||||||
|
| `/api/v1/user/**` | violin-auth(user 模块) | 8080 |
|
||||||
|
|
||||||
|
路由由 K8s ingress 统一反向代理;前端只关心 `VITE_APP_URL` 单一域名。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 构建与运行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 安装依赖(推荐 pnpm,yarn 也行)
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# 本地 dev(启动 mock)
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# 生产构建(先类型检查,再打包)
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# 测试环境构建
|
||||||
|
npm run build:test
|
||||||
|
|
||||||
|
# 预览构建产物
|
||||||
|
npm run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
Node:v18+(**不要**用 v14/16,老的 sass-loader/node-sass 不兼容)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 已知坑(不要"清理"它们)
|
||||||
|
|
||||||
|
### 1. `view/` 单数 vs `views/` 复数
|
||||||
|
|
||||||
|
**永远只创建 `view/` 单数目录**。`views/` 是历史遗物,已删除过又留下空目录。
|
||||||
|
|
||||||
|
### 2. node-sass 已废弃
|
||||||
|
|
||||||
|
`package.json` 里**没有** `node-sass`。如果你看到 `npm install` 报 `node-sass` 相关错误,是因为旧依赖被缓存,**不要**手动加回 `node-sass`,用 Dart Sass(`sass: ^1.79`)即可。
|
||||||
|
|
||||||
|
### 3. axios 0.x → 1.x
|
||||||
|
|
||||||
|
升级到 axios 1.7 后,`axios.create()` 配置有少量变化(如 `paramsSerializer`)。如果你看到 `interceptor is not a function` 之类的报错,看下拦截器是否还兼容旧签名。
|
||||||
|
|
||||||
|
### 4. Vue Router 4 用 memory history
|
||||||
|
|
||||||
|
`createMemoryHistory()` 而非 `createWebHistory()` / `createWebHashHistory()`。刷新页面会丢路由——如果要做刷新保留路由,需要切到 `createWebHistory()` 并配合 K8s ingress 重写。
|
||||||
|
|
||||||
|
### 5. vite-plugin-mock 仅 dev 启用
|
||||||
|
|
||||||
|
生产构建不会带 mock(`localEnabled: command === 'serve'`)。如果发现生产缺数据,看下是不是依赖了 mock。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 相关项目
|
||||||
|
|
||||||
|
- `violin-auth` — 认证服务(OIDC + JWT 签发)
|
||||||
|
- `violin-bookmark` / `violin-calendar` / `violin-onenote` / `violin-cloud` / `violin-trader` — 业务子服务
|
||||||
|
- `violin-common` / `violin-core` — 后端共享框架
|
||||||
|
- `violin-parent` — 后端父 POM
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# ========== Secret(密码管理)============
|
||||||
|
# ⚠️ 生产环境请使用真正随机的密码
|
||||||
|
# 生成随机密码: python3 -c "import secrets; print(secrets.token_urlsafe(32))"
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: authentik-secrets
|
||||||
|
namespace: global
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# PostgreSQL 数据库密码
|
||||||
|
postgres-password: "你的postgres密码"
|
||||||
|
# Secret Key(用于加密 session、token 等)
|
||||||
|
authentik-secret-key: "你的随机密钥(至少32字符)"
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# ========== 5. Ingress 配置 ==========
|
||||||
|
# 使用 cert-manager 自动管理 Let's Encrypt 证书
|
||||||
|
# 如未安装 cert-manager: kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: authentik
|
||||||
|
namespace: auth
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: "nginx"
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
|
||||||
|
spec:
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- auth.violin-work.online
|
||||||
|
secretName: authentik-tls
|
||||||
|
rules:
|
||||||
|
- host: auth.violin-work.online
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: authentik-server
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
|
||||||
|
---
|
||||||
|
# 如果没有 cert-manager,用这个 ClusterIssuer(先安装 cert-manager)
|
||||||
|
# apiVersion: cert-manager.io/v1
|
||||||
|
# kind: ClusterIssuer
|
||||||
|
# metadata:
|
||||||
|
# name: letsencrypt-prod
|
||||||
|
# spec:
|
||||||
|
# acme:
|
||||||
|
# server: https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
# email: YOUR_EMAIL@domain.com # ⚠️ 改成你的邮箱
|
||||||
|
# privateKeySecretRef:
|
||||||
|
# name: letsencrypt-prod
|
||||||
|
# solvers:
|
||||||
|
# - http01:
|
||||||
|
# ingress:
|
||||||
|
# class: nginx
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Ingress - 只暴露 server 服务,worker 不需要对外访问
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: authentik
|
||||||
|
namespace: global
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: "nginx"
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
|
||||||
|
spec:
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- auth.violin-work.online
|
||||||
|
secretName: authentik-tls
|
||||||
|
rules:
|
||||||
|
- host: auth.violin-work.online
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: authentik-server
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
# Authentik 部署指南
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
authentik-deploy/
|
||||||
|
├── 00-ns.yaml # Namespace
|
||||||
|
├── 01-postgres.yaml # PostgreSQL 数据库
|
||||||
|
├── 02-secret.yaml # 密钥(密码)
|
||||||
|
├── auth-helm-values.yaml # Authentik Helm 配置
|
||||||
|
├── 03-ingress.yaml # Ingress + TLS 证书
|
||||||
|
├── install.sh # 一键安装脚本
|
||||||
|
└── README.md # 本文件
|
||||||
|
```
|
||||||
|
|
||||||
|
## 部署步骤
|
||||||
|
|
||||||
|
### 1. 准备
|
||||||
|
|
||||||
|
确保集群已安装:
|
||||||
|
- **Helm 3**
|
||||||
|
- **cert-manager**(自动管理 HTTPS 证书)
|
||||||
|
```bash
|
||||||
|
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 修改配置
|
||||||
|
|
||||||
|
编辑 `02-secret.yaml`,替换为真实随机密码:
|
||||||
|
```bash
|
||||||
|
# 生成随机密码
|
||||||
|
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
|
||||||
|
```
|
||||||
|
将输出填入 `authentik-secret-key` 和 `postgres-password`。
|
||||||
|
|
||||||
|
编辑 `03-ingress.yaml`,将 `YOUR_EMAIL@domain.com` 替换为你的邮箱。
|
||||||
|
|
||||||
|
### 3. 执行部署
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd authentik-deploy
|
||||||
|
chmod +x install.sh
|
||||||
|
./install.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
或手动按顺序执行:
|
||||||
|
```bash
|
||||||
|
kubectl create ns auth
|
||||||
|
kubectl apply -f 00-ns.yaml
|
||||||
|
kubectl apply -f 01-postgres.yaml
|
||||||
|
kubectl apply -f 02-secret.yaml
|
||||||
|
helm repo add authentik https://charts.goauthentik.io && helm repo update
|
||||||
|
helm install authentik authentik/authentik -n auth -f auth-helm-values.yaml
|
||||||
|
kubectl apply -f 03-ingress.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 初始化
|
||||||
|
|
||||||
|
部署完成后访问:
|
||||||
|
- **首次设置**: https://auth.violin-work.online/if/flow/initial/
|
||||||
|
- 设置管理员账号和密码
|
||||||
|
|
||||||
|
### 5. 验证
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get pods -n auth
|
||||||
|
kubectl logs -n auth -l app.kubernetes.io/component=server --tail=20
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 后续:配置其他服务接入 Authentik(OIDC)
|
||||||
|
|
||||||
|
### 在 Authentik 中创建 Application
|
||||||
|
|
||||||
|
1. 登录 Authentik Admin → **Applications**
|
||||||
|
2. 点击 **Create**:
|
||||||
|
- **Name**: OpenViking(或任意名称)
|
||||||
|
- **Slug**: openviking
|
||||||
|
- **Provider**: 创建 OIDC Provider(见下方)
|
||||||
|
3. 创建 Provider:
|
||||||
|
- **Name**: OpenViking Provider
|
||||||
|
- **Client ID**: openviking
|
||||||
|
- **Client Secret**: 生成一个随机值
|
||||||
|
- **Redirect URIs**: `https://viking.violin-work.online/-/oauth-callback/openviking/`(根据实际调整)
|
||||||
|
|
||||||
|
### OpenViking 配置 OIDC
|
||||||
|
|
||||||
|
在 OpenViking 的配置文件中加入:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"oidc": {
|
||||||
|
"issuer": "https://auth.violin-work.online",
|
||||||
|
"client_id": "openviking",
|
||||||
|
"client_secret": "你的client_secret"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### KubeSphere 配置 OIDC
|
||||||
|
|
||||||
|
在 KubeSphere Web 控制台:
|
||||||
|
- **平台管理 → 访问控制 → 企业设置 → 第三方登录**
|
||||||
|
- 填入 Authentik 的 OIDC 信息
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 维护
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 更新 Authentik
|
||||||
|
helm repo update && helm upgrade authentik authentik/authentik -n auth -f auth-helm-values.yaml
|
||||||
|
|
||||||
|
# 卸载
|
||||||
|
helm uninstall authentik -n auth && kubectl delete ns auth
|
||||||
|
```
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Authentik Helm - 2026.5.3 腾讯云镜像配置
|
||||||
|
|
||||||
|
global:
|
||||||
|
image:
|
||||||
|
repository: ccr.ccs.tencentyun.com/tei_agent/authentik-server
|
||||||
|
tag: "2026.5.3"
|
||||||
|
|
||||||
|
authentik:
|
||||||
|
secret_key: "Mb83201048"
|
||||||
|
postgresql:
|
||||||
|
host: "192.168.3.49"
|
||||||
|
port: 5432
|
||||||
|
name: "authentik"
|
||||||
|
user: "authentik"
|
||||||
|
password: "authentik"
|
||||||
|
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
size: 5Gi
|
||||||
|
|
||||||
|
postgresql:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
server:
|
||||||
|
replicas: 1
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
worker:
|
||||||
|
replicas: 1
|
||||||
|
|
||||||
|
geoip:
|
||||||
|
enabled: false
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# ========== 一键安装脚本(Linux/macOS)============
|
||||||
|
# 保存为 install.sh,执行: chmod +x install.sh && ./install.sh
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
EMAIL="admin@violin-work.online" # ⚠️ 改成你的邮箱(Let's Encrypt 通知用)
|
||||||
|
DOMAIN="auth.violin-work.online" # ⚠️ 改成你的域名
|
||||||
|
|
||||||
|
echo "=== 1. 创建 namespace ==="
|
||||||
|
kubectl create ns auth --dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
echo "=== 2. 创建 Secret ==="
|
||||||
|
kubectl apply -f 02-secret.yaml
|
||||||
|
|
||||||
|
echo "=== 3. 部署 PostgreSQL ==="
|
||||||
|
kubectl apply -f 01-postgres.yaml
|
||||||
|
|
||||||
|
echo "=== 4. 等待 PostgreSQL 就绪 ==="
|
||||||
|
kubectl wait --for=condition=ready pod -l app=authentik-postgres -n auth --timeout=120s
|
||||||
|
|
||||||
|
echo "=== 5. 添加 Helm 源并安装 Authentik ==="
|
||||||
|
helm repo add authentik https://charts.goauthentik.io --force-update
|
||||||
|
helm repo update
|
||||||
|
helm install authentik authentik/authentik -n auth -f auth-helm-values.yaml
|
||||||
|
|
||||||
|
echo "=== 6. 部署 Ingress + 证书 ==="
|
||||||
|
kubectl apply -f 03-ingress.yaml
|
||||||
|
|
||||||
|
echo "=== 7. 等待 Authentik Server 就绪 ==="
|
||||||
|
kubectl wait --for=condition=ready pod -l app.kubernetes.io/component=server -n auth --timeout=180s
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 部署完成! ==="
|
||||||
|
echo "访问: https://$DOMAIN"
|
||||||
|
echo "初始设置: https://$DOMAIN/if/flow/initial/"
|
||||||
|
echo ""
|
||||||
|
echo "查看状态:"
|
||||||
|
echo " kubectl get pods -n auth"
|
||||||
|
echo " kubectl logs -n auth -l app.kubernetes.io/component=server --tail=50"
|
||||||
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 189 KiB |
Vendored
-18
@@ -1,18 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>violin-home</title>
|
|
||||||
<script type="module" crossorigin src="/resets/index.e20aada4.js"></script>
|
|
||||||
<link rel="stylesheet" href="/resets/index.35a0e576.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
Vendored
-10
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{H as e}from"./index.e20aada4.js";import{l as i}from"./index.7b5a1be8.js";const t={"Content-Type":"application/json;charsetset=UTF-8"},l=r=>e({url:"/wiki/api/v1/reader/blogs",method:"GET",params:r,paramsSerializer:a=>i.stringify(a,{arrayFormat:"repeat"})}),p=()=>e({url:"/wiki/api/v1/reader/blog_type",method:"GET",headers:t}),n=r=>e({url:"/wiki/api/v1/reader/blog/"+r,method:"GET",headers:t}),u=()=>e({url:"/wiki/api/v1/reader/blogs/publish/all",method:"GET"}),g=r=>e({url:"/wiki/api/v1/reader/blogs/publish/"+r,method:"GET"});export{p as a,g as b,n as c,l as g,u as p};
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{H as r}from"./index.e20aada4.js";import{l as t}from"./index.7b5a1be8.js";const m=o=>r({url:"/bookmark/api/v1/bookmark",method:"GET",params:o,paramsSerializer:a=>t.stringify(a,{arrayFormat:"repeat"})}),s=o=>r({url:"/bookmark/api/v1/bookmark/insert",method:"PUT",data:o}),b=o=>r({url:"/bookmark/api/v1/bookmark/update",method:"POST",data:o}),u=o=>r({url:"/bookmark/api/v1/bookmark/delete/"+o,method:"DELETE"}),n=()=>r({url:"/bookmark/api/v1/bookmark/count",method:"GET"});export{n as b,u as d,s as p,m as s,b as u};
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
.b_section[data-v-f8c4f944],.bt_section[data-v-f8c4f944],.c_section[data-v-f8c4f944]{display:flex;flex-direction:column;align-items:stretch;border-right:1px solid royalblue}.title_style[data-v-f8c4f944]{display:flex}.title_style[data-v-f8c4f944] .el-input__inner{flex-direction:row;height:50px;font-size:20px;border-right:0px;border-left:0px;border-radius:0;border-top:1px solid royalblue;border-bottom:1px solid royalblue}.blog_editer[data-v-f8c4f944]{display:flex}.item_header[data-v-f8c4f944]{display:flex;align-items:center;border-top:1px solid royalblue;border-bottom:1px solid royalblue}.item_header_button[data-v-f8c4f944]{border:0px;height:50px}.side_bar[data-v-f8c4f944]{display:flex;align-items:center;justify-content:flex-start;width:20px}.item[data-v-f8c4f944]{padding:0;margin-top:3px;margin-bottom:3px;display:flex;height:50px;flex-direction:row;align-items:center;justify-items:center;user-select:none;border:0px;border-bottom:1px}.item>label[data-v-f8c4f944]{color:#333;height:50px;width:15px}.item>label[data-v-f8c4f944]:hover{cursor:move}.item>div[data-v-f8c4f944]{display:flex;flex-direction:column;align-items:flex-end;border:0px}.operate_button[data-v-f8c4f944]{border-color:#fff;width:20px;border:0px}.bt-input[data-v-f8c4f944]{margin:0;border:0px;padding-left:0;padding-right:5px;font-size:15px;overflow:hidden;line-height:50px;height:50px;width:100px;flex-grow:1;cursor:pointer;white-space:nowrap;text-overflow:ellipsis}.bt-input[data-v-f8c4f944]:hover{background-color:#ebebeb}.item>p[data-v-f8c4f944]{padding:6px 10px;color:#8e3333}.chosenClass[data-v-f8c4f944]{opacity:1;border:solid 1px red}.ghost[data-v-f8c4f944]{border:solid 1px rgb(19,41,239)!important}
|
|
||||||
BIN
Binary file not shown.
Vendored
-10
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{H as r}from"./index.e20aada4.js";const a=()=>r({url:"/trader/api/v1/strategy_file",method:"GET"}),s=()=>r({url:"/trader/api/v1/strategy_file/load",method:"GET"}),o=t=>r({url:"/trader/api/v1/strategy_file/"+t,method:"PUT"}),i=t=>r({url:"/trader/api/v1/strategy_file/"+t,method:"PATCH"}),d=t=>r({url:"/trader/api/v1/strategy_file/"+t,method:"DELETE"}),g=()=>r({url:"/trader/api/v1/strategies",method:"GET"}),n=t=>r({url:"/trader/api/v1/strategy/"+t.strategy_name,method:"POST",data:t}),l=t=>r({url:"/trader/api/v1/strategy/init/"+t,method:"PUT"}),u=t=>r({url:"/trader/api/v1/strategy/"+t,method:"PUT"}),_=t=>r({url:"/trader/api/v1/strategy/"+t,method:"PATCH"}),y=t=>r({url:"/trader/api/v1/strategy/"+t,method:"DELETE"});export{s as a,g as b,n as c,_ as d,y as e,a as g,l as i,o as l,d as r,u as s,i as u};
|
|
||||||
Vendored
-1
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
-1
@@ -1 +0,0 @@
|
|||||||
.el-button--text[data-v-19ae7838]{margin-right:15px}.el-select[data-v-19ae7838],.el-input[data-v-19ae7838]{width:300px}.dialog-footer button[data-v-19ae7838]:first-child{margin-right:10px}
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
import{g as I,l as N,u as T,r as V}from"./cta_strategy.0971c7e2.js";import{d as R,c as S,b as $,f as _,h as e,w as s,u as t,a2 as P,X as U,a3 as W,e as i,o as n,a4 as g,a5 as u,B as m,a6 as r,E as c,i as h,g as M,a1 as X,U as k}from"./index.e20aada4.js";const j={class:"bookmark"},q=h("\u6DFB\u52A0\u7B56\u7565\u6A21\u677F"),G=h(" -> "),H=h(" \u4E0A\u4F20\u7B56\u7565\u6A21\u677F "),J=M("div",{class:"el-upload__tip text-red"}," \u4E00\u6B21\u53EA\u80FD\u4E0A\u4F20\u4E00\u4E2A\u6587\u4EF6 ",-1),K={key:0,style:{cursor:"pointer"}},L={key:0,style:{cursor:"pointer"}},O={key:0,style:{cursor:"pointer"}},ee=R({setup(Q){const p=S([]),d=$(),f=()=>{I().then(l=>{p.length=0,l.data.forEach((a,y)=>{p.push(a)})})},E=l=>{d.value.clearFiles();const a=l[0];a.uid=W(),d.value.handleStart(a)},v=()=>{d.value.submit(),f()},w=l=>{l.status=2,N(l.file_name).then(a=>{a.status==200&&(l.status=1),a.status==500&&(l.status=0)})},C=l=>{T(l.class_name).then(a=>{a.status==200&&(l.status=0),a.status==500&&(l.status=1)})},b=l=>{V(l.file_name).then(a=>{f()}).catch(a=>{X({message:k("p",null,[k("i",{style:"color: teal"},a)])})})};return f(),(l,a)=>{const y=i("InfoFilled"),B=i("SuccessFilled"),x=i("WarningFilled"),A=i("CirclePlusFilled"),D=i("RemoveFilled"),z=i("Delete");return n(),_("div",j,[e(t(P),{ref_key:"upload",ref:d,class:"upload-demo",action:"http://localhost:5000/trader/api/v1/strategy_file",limit:1,"on-exceed":E,"auto-upload":!1},{trigger:s(()=>[e(t(g),{type:"primary"},{default:s(()=>[q]),_:1})]),tip:s(()=>[J]),default:s(()=>[G,e(t(g),{class:"ml-3",type:"success",onClick:v},{default:s(()=>[H]),_:1})]),_:1},512),e(t(U),{ref:"multipleTableRef",data:t(p),style:{width:"100%"}},{default:s(()=>[e(t(u),{type:"selection",width:"55"}),e(t(u),{type:"index",label:"index",width:"80"}),e(t(u),{prop:"file_name",label:"\u7B56\u7565\u6587\u4EF6\u540D",width:"200"}),e(t(u),{prop:"class_name",label:"\u7B56\u7565\u7C7B\u540D",width:"200"}),e(t(u),{prop:"status",label:"\u72B6\u6001",width:"60"},{default:s(o=>[o.row.status==0?(n(),m(t(r),{key:0,size:20},{default:s(()=>[e(y)]),_:1})):c("",!0),o.row.status==1?(n(),m(t(r),{key:1,size:20,color:"green"},{default:s(()=>[e(B)]),_:1})):c("",!0),o.row.status==2?(n(),m(t(r),{key:2,size:20,color:"gold"},{default:s(()=>[e(x)]),_:1})):c("",!0)]),_:1}),e(t(u),{prop:"url",label:"\u52A0\u8F7D",width:"60"},{default:s(o=>[o.row.status==0?(n(),_("span",K,[e(t(r),{size:20,onClick:F=>w(o.row),color:"blue"},{default:s(()=>[e(A)]),_:2},1032,["onClick"])])):c("",!0)]),_:1}),e(t(u),{prop:"url",label:"\u5378\u8F7D",width:"60"},{default:s(o=>[o.row.status==1?(n(),_("span",L,[e(t(r),{size:20,onClick:F=>C(o.row),color:"red"},{default:s(()=>[e(D)]),_:2},1032,["onClick"])])):c("",!0)]),_:1}),e(t(u),{prop:"url",label:"\u5220\u9664",width:"60"},{default:s(o=>[o.row.status==0?(n(),_("span",O,[e(t(r),{size:20,onClick:F=>b(o.row),color:"red"},{default:s(()=>[e(z)]),_:2},1032,["onClick"])])):c("",!0)]),_:1})]),_:1},8,["data"])])}}});export{ee as default};
|
|
||||||
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 70 KiB |
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{a as o}from"./number.46c8fb59.js";const r=(e,t)=>(e.getMonth()+1,e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),Math.floor((e.getMonth()+3)/3),e.getMilliseconds(),/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(e.getFullYear()+"").substr(4-RegExp.$1.length))),t),n=(e,t)=>(t||(t="yyyy-MM-dd hh:mm:ss"),r(new Date(e),t).toLocaleString()),l=e=>e.getFullYear()+"-"+o(e.getMonth()+1)+"-"+o(e.getDate());export{n as f,l as t};
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{E as s}from"./style.1aad9498.js";import{d as c,b as u,B as d,u as l,R as i,a8 as p,o as m}from"./index.e20aada4.js";import{u as f,a as _}from"./profile.50110a29.js";const U=c({setup(v){let e=u(""),a=u("");p().query;const r=async()=>{await f({content:e.value}).then(t=>{a.value=t.data.updateDatetime}).catch(()=>{})};return(async()=>{await _().then(t=>{e.value=t.data.content,a.value=t.data.updateDatetime}).catch(()=>{})})(),(t,o)=>(m(),d(l(s),{modelValue:l(e),"onUpdate:modelValue":o[0]||(o[0]=n=>i(e)?e.value=n:e=n),onSave:r},null,8,["modelValue"]))}});export{U as default};
|
|
||||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 410 KiB |
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
.dashboard-line-box .dashboard-line[data-v-19c5604b]{background-color:#fff;height:360px;width:100%}.dashboard-line-box .dashboard-line-title[data-v-19c5604b]{font-weight:600;margin-bottom:12px}.commit-table[data-v-554f7f6a]{background-color:#fff;height:400px}.commit-table-title[data-v-554f7f6a]{font-weight:600;margin-bottom:12px}.commit-table .log-item[data-v-554f7f6a]{display:flex;justify-content:space-between;margin-top:14px}.commit-table .log-item .key-box[data-v-554f7f6a]{justify-content:center}.commit-table .log-item .key[data-v-554f7f6a]{display:inline-flex;justify-content:center;align-items:center;width:20px;height:20px;border-radius:50%;background:#F0F2F5;text-align:center;color:#000000a6}.commit-table .log-item .key.top[data-v-554f7f6a]{background:#314659;color:#fff}.commit-table .log-item .message[data-v-554f7f6a]{color:#000000a6}.commit-table .log-item .form[data-v-554f7f6a]{color:#000000a6;margin-left:12px}.commit-table .log-item .flex[data-v-554f7f6a]{line-height:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.commit-table .log-item .flex-1[data-v-554f7f6a]{flex:1}.commit-table .log-item .flex-2[data-v-554f7f6a]{flex:2}.commit-table .log-item .flex-3[data-v-554f7f6a]{flex:3}.commit-table .log-item .flex-4[data-v-554f7f6a]{flex:4}.commit-table .log-item .flex-5[data-v-554f7f6a]{flex:5}.page[data-v-14e09d9b]{background:#f0f2f5;padding:0}.page .gva-card-box[data-v-14e09d9b]{padding:12px 16px}.page .gva-card-box+.gva-card-box[data-v-14e09d9b]{padding-top:0}.page .gva-card[data-v-14e09d9b]{box-sizing:border-box;background-color:#fff;border-radius:2px;height:auto;padding:26px 30px;overflow:hidden;box-shadow:0 0 7px 1px #00000008}.page .gva-top-card[data-v-14e09d9b]{height:260px;display:flex;align-items:center;justify-content:space-between;color:#777}.page .gva-top-card-left[data-v-14e09d9b]{height:100%;display:flex;flex-direction:column}.page .gva-top-card-left-title[data-v-14e09d9b]{font-size:22px;color:#343844}.page .gva-top-card-left-dot[data-v-14e09d9b]{font-size:16px;color:#6b7687;margin-top:24px}.page .gva-top-card-left-rows[data-v-14e09d9b]{margin-top:18px;color:#6b7687;width:600px;align-items:center}.page .gva-top-card-left-item[data-v-14e09d9b]{margin-top:14px}.page .gva-top-card-left-item+.gva-top-card-left-item[data-v-14e09d9b]{margin-top:24px}.page .gva-top-card-right[data-v-14e09d9b]{height:600px;width:600px;margin-top:28px}.page[data-v-14e09d9b] .el-card__header{padding:0;border-bottom:none}.page .card-header[data-v-14e09d9b]{padding-bottom:20px;border-bottom:1px solid #e8e8e8}.page .quick-entrance-title[data-v-14e09d9b]{height:30px;font-size:22px;color:#333;width:100%;border-bottom:1px solid #eee}.page .quick-entrance-items[data-v-14e09d9b]{display:flex;align-items:center;justify-content:center;text-align:center;color:#333}.page .quick-entrance-items .quick-entrance-item[data-v-14e09d9b]{padding:16px 28px;margin-top:-16px;margin-bottom:-16px;border-radius:4px;transition:all .2s;cursor:pointer;height:auto;text-align:center}.page .quick-entrance-items .quick-entrance-item[data-v-14e09d9b]:hover{box-shadow:0 0 7px #d9d9d98c}.page .quick-entrance-items .quick-entrance-item-icon[data-v-14e09d9b]{width:50px;height:50px!important;border-radius:8px;display:flex;align-items:center;justify-content:center;margin:0 auto}.page .quick-entrance-items .quick-entrance-item-icon i[data-v-14e09d9b]{font-size:24px}.page .quick-entrance-items .quick-entrance-item p[data-v-14e09d9b]{margin-top:10px}.page .echart-box[data-v-14e09d9b]{padding:14px}.dashboard-icon[data-v-14e09d9b]{font-size:20px;color:#55a0f8;width:30px;height:30px;margin-right:10px;display:flex;align-items:center}.flex-center[data-v-14e09d9b]{display:flex;align-items:center}@media (max-width: 750px){.gva-card[data-v-14e09d9b]{padding:20px 10px!important}.gva-card .gva-top-card[data-v-14e09d9b]{height:auto}.gva-card .gva-top-card-left-title[data-v-14e09d9b]{font-size:20px!important}.gva-card .gva-top-card-left-rows[data-v-14e09d9b]{margin-top:15px;align-items:center}.gva-card .gva-top-card-right[data-v-14e09d9b]{display:none}.gva-card .gva-middle-card-item[data-v-14e09d9b]{line-height:20px}.gva-card .dashboard-icon[data-v-14e09d9b]{font-size:18px}}
|
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
.category_card-box[data-v-2dc81d35]{display:flex;flex-wrap:wrap}.category_card__header[data-v-2dc81d35]{text-align:center;width:100px;line-height:100px;height:100px}.category_card__body[data-v-2dc81d35]{text-align:center}.onenote_card__header[data-v-2dc81d35]{width:120px}.onenote_card-box[data-v-2dc81d35]{display:flex;flex-direction:column}.onenote_item_card[data-v-2dc81d35]{display:flex;margin:10px}.onenote_category_card[data-v-2dc81d35]{display:flex;flex-direction:column;margin:20px;padding:20px}.category_icon[data-v-2dc81d35]{margin-bottom:50px}.category_theme[data-v-2dc81d35]{margin-right:30px}
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{v as q,H as U,_ as J,d as K,c as g,b as p,l as Q,f as u,M as X,B as Y,w as a,E as S,h as l,u as o,F as T,e as n,L as Z,o as i,g as c,z as r,x as ee,i as E,p as te,j as le,m as oe}from"./index.e20aada4.js";import{t as f}from"./date.86e91942.js";import{s as ae}from"./settings.e80a4132.js";import"./number.46c8fb59.js";const ne=q.create(),se=()=>ne({url:"https://holidays-jp.github.io/api/v1/2023/date.json",method:"GET"}),de={"Content-Type":"application/json;charsetset=UTF-8"},ie=_=>U({url:"/calendar/api/v1/event",method:"PUT",data:_}),ue=()=>U({url:"/calendar/api/v1/event",method:"GET",headers:de});const I=_=>(te("data-v-0e3dfbc2"),_=_(),le(),_),re={key:0,class:"date-cell-holiday"},ce=["onClick"],_e=I(()=>c("br",null,null,-1)),me={key:1,class:"date-cell"},pe=["onClick"],fe=["onClick"],ve={key:2,class:"date-cell-event"},he=I(()=>c("span",null,"\u5F85\u529E\u4E8B\u9879",-1)),be={class:"dialog-footer"},ge=E("Cancel"),ke=E(" Confirm "),ye=K({setup(_){const v=ae(),k=g({}),y=g([]),x=g({}),d=g({reminder_date:"",title:"",reminder_info:""}),D=p(new Date),m=p(!1),h="140px",w=p(!1),B=p(!0),F=p([]),$=["email","messageBox","\u624B\u673A\u77ED\u4FE1","\u5FAE\u4FE1\u901A\u77E5"],C=s=>{d.reminder_date=f(s),m.value=!0},N=async()=>{await ie(d).then(()=>{}),m.value=!1,O("refresh")},O=s=>{s==="refresh"&&(v.settings.isLoading=!0,v.settings.isRouterAlive=!1,oe(()=>{v.settings.isRouterAlive=!0,v.settings.isLoading=!1}))};return Q(async()=>{await se().then(s=>{Object.keys(s.data).forEach(t=>{k[t]=s.data[t]})}),await ue().then(s=>{y.length=0,s.data.forEach(t=>{y.push(t),x[t.reminder_date]=t.title})}),w.value=!0,B.value=!1}),(s,t)=>{const G=n("el-calendar"),V=n("el-table-column"),M=n("el-table"),b=n("el-form-item"),A=n("el-input"),R=n("el-checkbox"),z=n("el-checkbox-group"),H=n("el-form"),j=n("el-button"),P=n("el-dialog"),W=Z("loading");return i(),u(T,null,[w.value?X((i(),Y(G,{key:0,modelValue:D.value,"onUpdate:modelValue":t[0]||(t[0]=e=>D.value=e),"element-loading-text":"\u4E3B\u4EBA\uFF0C\u522B\u7740\u6025\u6211\u5728\u52AA\u529B\u52A0\u8F7D\u4E2D^_^"},{dateCell:a(({data:e})=>[Object.keys(o(k)).includes(o(f)(e.date))?(i(),u("div",re,[c("span",{style:{color:"red"},onClick:L=>C(e.date)},r(e.date.getDate()),9,ce),_e,c("span",null,r(o(k)[o(f)(e.date)]),1)])):(i(),u("div",me,[e.date.getDay()==0||e.date.getDay()==6?(i(),u("span",{key:0,style:{color:"red"},onClick:L=>C(e.date)},r(e.date.getDate()),9,pe)):(i(),u("span",{key:1,onClick:L=>C(e.date)},r(e.date.getDate()),9,fe))])),Object.keys(o(x)).includes(o(f)(e.date))?(i(),u("div",ve,[c("span",null,r(o(x)[o(f)(e.date)]),1)])):S("",!0)]),_:1},8,["modelValue"])),[[W,B.value]]):S("",!0),he,l(M,{data:o(y)},{default:a(()=>[l(V,{property:"reminder_date",label:"Date",width:"150"}),l(V,{property:"title",label:"title",width:"200"}),l(V,{property:"reminder_info",label:"eventInfo"})]),_:1},8,["data"]),l(P,{modelValue:m.value,"onUpdate:modelValue":t[5]||(t[5]=e=>m.value=e),title:"\u5F85\u529E\u4E8B\u9879"},{footer:a(()=>[c("span",be,[l(j,{onClick:t[4]||(t[4]=e=>m.value=!1)},{default:a(()=>[ge]),_:1}),l(j,{type:"primary",onClick:N},{default:a(()=>[ke]),_:1})])]),default:a(()=>[l(H,{model:o(d)},{default:a(()=>[l(b,{label:"\u65E5\u671F","label-width":h},{default:a(()=>[c("span",null,r(o(d).reminder_date),1)]),_:1}),l(b,{label:"title","label-width":h},{default:a(()=>[l(A,{modelValue:o(d).title,"onUpdate:modelValue":t[1]||(t[1]=e=>o(d).title=e),autocomplete:"off"},null,8,["modelValue"])]),_:1}),l(b,{label:"eventInfo","label-width":h},{default:a(()=>[l(A,{modelValue:o(d).reminder_info,"onUpdate:modelValue":t[2]||(t[2]=e=>o(d).reminder_info=e),autocomplete:"off",type:"textarea"},null,8,["modelValue"])]),_:1}),l(b,{label:"alert","label-width":h},{default:a(()=>[l(z,{modelValue:F.value,"onUpdate:modelValue":t[3]||(t[3]=e=>F.value=e),min:0,max:2},{default:a(()=>[(i(),u(T,null,ee($,e=>l(R,{key:e,label:e},{default:a(()=>[E(r(e),1)]),_:2},1032,["label"])),64))]),_:1},8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"])],64)}}});var De=J(ye,[["__scopeId","data-v-0e3dfbc2"]]);export{De as default};
|
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{d as s,B as a,w as n,a7 as c,a1 as l,e as i,o as r,i as p}from"./index.e20aada4.js";const _=p("Click to open the Message Box"),f=s({setup(m){const t=()=>{c.alert("This is a message","Title",{confirmButtonText:"OK",callback:e=>{l({type:"info",message:`action: ${e}`})}})};return(e,u)=>{const o=i("el-button");return r(),a(o,{text:"",onClick:t},{default:n(()=>[_]),_:1})}}});export{f as default};
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{_ as e,f as o,o as _}from"./index.e20aada4.js";const a={},n={class:"dialog-footer"};function r(c,s){return _(),o("span",n," \u5F53\u4F60\u770B\u5230\u4E86\uFF0C\u8FD9\u4E2A\u9875\u9762\uFF0C\u8FD9\u8868\u793A\u4E86\uFF0C\u4F60\u901A\u8FC7\u767E\u5EA6\u626B\u63CF\u767B\u9646\u4E86\u6211\u7684\u79D8\u5BC6\u57FA\u5730\uFF0C\u4F46\u662F\u5F88\u9057\u61BE\u7684\u544A\u8BC9\u4F60\uFF0C\u6211\u4EEC\u5C06\u4EE5\u975E\u6CD5\u767B\u5F55\u7684\u65B9\u5F0F\u5904\u7406\u4F60\u7684\u8BF7\u6C42\uFF0C88 ")}var d=e(a,[["render",r]]);export{d as default};
|
|
||||||
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-4
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-60
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
.blog_list{display:flex;flex-direction:column;border-bottom:1px solid rgba(151,151,151,.3);padding-top:10px;padding-bottom:10px}.page_style{margin-top:25px;display:flex;flex-direction:column;align-items:center}
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
.el-table--enable-row-hover .el-table__body tr:hover>td{background-color:transparent!important}
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
.dashboard{background-color:beige}.iconStyle{margin-right:"6px"}.operate,.descriptionsclass{display:flex;align-items:center}
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{d as q,c as z,b as m,l as P,q as X,a1 as p,U as o,f as C,g as D,h as e,w as n,u as d,F as B,e as s,o as b,x as A,B as E,$ as G,a0 as H,Y as J}from"./index.e20aada4.js";import{s as K,g as O,a as Q,c as T}from"./strategy.41e66528.js";import{t as W}from"./number.46c8fb59.js";const ee={class:"demo-collapse"},le={style:{cursor:"pointer"}},te=D("label",null," concel subscribe",-1),ue=q({setup(oe){const g=J(),_=K(),w=z([]),v=m(),y=m(),x=m(0),k=m(["1"]),f=m(""),I=()=>{!v.value||Q(v.value).then(l=>{p({message:o("p",null,[o("i",{style:"color: green"},"\u884C\u60C5\u8BA2\u9605\u6210\u529F")])}),_.select_subscribe_vt_symbols(),h()}).catch(l=>{p({message:o("p",null,[o("i",{style:"color: red"},"\u884C\u60C5\u8BA2\u9605\u5931\u8D25")])})})},M=()=>{!f.value||T(f.value).then(l=>{p({message:o("p",null,[o("i",{style:"color: green"},"\u53D6\u6D88\u8BA2\u9605\u6210\u529F")])}),h()}).catch(l=>{p({message:o("p",null,[o("i",{style:"color: red"},"\u53D6\u6D88\u8BA2\u9605\u5931\u8D25")])})})},U=(l,t)=>{let a=(l.last_price-l.open_price)/l.open_price;return W(a)},N=(l,t,a,i)=>{f.value=l.symbol+"."+l.exchange,console.log(f.value)},S=(l,t,a,i)=>{},L=(l,t,a)=>{var r;let i=(r=g==null?void 0:g.proxy)==null?void 0:r.$refs.contextmenu;a.preventDefault(),i.show({top:a.clientY,left:a.clientX}),window.onclick=()=>{i.hide()}},h=()=>(O().then(l=>{w.length=0,l.data.ticks.forEach(t=>{w.push(t)})}),h);return P(()=>{clearInterval(x.value),x.value=window.setInterval(h(),3e3)}),X(()=>{window.clearInterval(x.value)}),_.select_subscribe_vt_symbols().catch(l=>{p({message:o("p",null,[o("i",{style:"color: teal"},"\u8BFB\u53D6vt_symbols\u5931\u8D25")])})}),_.select_vt_symbols().catch(l=>{p({message:o("p",null,[o("i",{style:"color: teal"},"\u8BFB\u53D6vt_symbols\u5931\u8D25")])})}),_.select_exchanges().catch(l=>{p({message:o("p",null,[o("i",{style:"color: teal"},"\u8BFB\u53D6exchanges\u5931\u8D25")])})}),(l,t)=>{const a=s("el-option"),i=s("el-select"),r=s("el-col"),R=s("ZoomIn"),V=s("el-icon"),$=s("el-row"),F=s("el-collapse-item"),u=s("el-table-column"),Y=s("el-table"),Z=s("el-collapse"),j=s("CircleClose");return b(),C(B,null,[D("div",ee,[e(Z,{modelValue:k.value,"onUpdate:modelValue":t[3]||(t[3]=c=>k.value=c)},{default:n(()=>[e(F,{title:"\u8BA2\u9605\u884C\u60C5",name:"2"},{default:n(()=>[e($,null,{default:n(()=>[e(r,{span:4},{default:n(()=>[e(i,{modelValue:y.value,"onUpdate:modelValue":t[0]||(t[0]=c=>y.value=c),placeholder:"select a exchange"},{default:n(()=>[(b(!0),C(B,null,A(d(_).strategy.exchanges,c=>(b(),E(a,{value:c},null,8,["value"]))),256))]),_:1},8,["modelValue"])]),_:1}),e(r,{span:1}),e(r,{span:4},{default:n(()=>[e(i,{modelValue:v.value,"onUpdate:modelValue":t[1]||(t[1]=c=>v.value=c),placeholder:"select a vt_symbol"},{default:n(()=>[(b(!0),C(B,null,A(d(_).strategy.vt_symbols.get(y.value),c=>(b(),E(a,{value:c},null,8,["value"]))),256))]),_:1},8,["modelValue"])]),_:1}),e(r,{span:1}),e(r,{span:4},{default:n(()=>[D("span",le,[e(V,{size:25,onClick:t[2]||(t[2]=c=>I())},{default:n(()=>[e(R)]),_:1})])]),_:1})]),_:1})]),_:1}),e(F,{title:"\u8BA2\u9605\u4E00\u89C8",name:"1"},{default:n(()=>[e(Y,{onRowContextmenu:L,onCellMouseEnter:N,onCellMouseLeave:S,data:d(w),style:{width:"100%"}},{default:n(()=>[e(u,{fixed:"",prop:"symbol",label:"symbol",width:"80"}),e(u,{prop:"exchange",label:"exchange",width:"100"}),e(u,{prop:"name",label:"Name",width:"120"}),e(u,{prop:"last_price",label:"last_price",width:"120"}),e(u,{prop:"volume",label:"volume",width:"100"}),e(u,{prop:"open_price",label:"open_price",width:"120"}),e(u,{prop:"high_price",label:"high_price",width:"120"}),e(u,{prop:"low_price",label:"low_price",width:"100"}),e(u,{prop:"differ",label:"differ",width:"70"}),e(u,{prop:"differ_percent",label:"differ_per",formatter:U,width:"120"})]),_:1},8,["data"])]),_:1})]),_:1},8,["modelValue"])]),e(d(H),{"auto-ajust-placement":"",ref:"contextmenu"},{default:n(()=>[e(d(G),{onClick:M},{default:n(()=>[e(V,{class:"contextmenu-icon"},{default:n(()=>[e(j)]),_:1}),te]),_:1})]),_:1},512)],64)}}});export{ue as default};
|
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{H as M,d as z,c as b,b as f,f as L,h as l,w as a,u as r,X as N,F as V,Y as $,Z as g,e as y,o as i,B as p,$ as m,E as h,a0 as j,g as k}from"./index.e20aada4.js";const O={"Content-Type":"application/json;charsetset=UTF-8"},U=w=>M({url:"/cloud/api/v1/file/list",method:"GET",params:{url:w},headers:O});const X=k("label",null," _new folder",-1),Y=k("label",null," _copy",-1),A=k("label",null," _rename",-1),G=k("label",null," _delete",-1),H=k("label",null," _delete",-1),q=z({setup(w){const u=$(),R=b([]),n=b(new Set),C=b({isCtrl:!1,isShift:!1}),E=f(),x=f(),d=f(!0);f();const v=f(!1),F=(e,o,t,s)=>{n.has(e)||(x.value=e)},B=(e,o,t,s)=>{n.has(e)||(x.value=void 0)},S=(e,o,t)=>{C.isCtrl?n.has(e)?n.delete(e):n.add(e):(n.clear(),n.add(e))},T=(e,o,t)=>{var c;v.value=!0;let s=(c=u==null?void 0:u.proxy)==null?void 0:c.$refs.contextmenu;n.has(e)||(n.clear(),n.add(e)),t.preventDefault(),s.show({top:t.clientY,left:t.clientX}),window.onclick=()=>{s.hide(),v.value=!1}},_=()=>{},D=({row:e,rowIndex:o})=>{var t;if(n.has(e))return{background:"#B4C7E7"};if(((t=g(x.value))==null?void 0:t.name)==g(e).name)return{background:"#DAE3F3"}};return document.onkeydown=e=>{switch(e.key){case"Control":C.isCtrl=!0;break}},document.onkeyup=e=>{var o;switch(e.key){case"Control":C.isCtrl=!1;break;case"Escape":v.value?(((o=u==null?void 0:u.proxy)==null?void 0:o.$refs.contextmenu).hide(),v.value=!1):n.clear(),C.isCtrl=!0;break}},U("").then(e=>{e.data.forEach(o=>{const t={size:o.size,isDir:o.isDir,name:o.server_filename,path:o.path};R.push(t)})}),(e,o)=>{const t=y("el-table-column"),s=y("FolderOpened"),c=y("el-icon");return i(),L(V,null,[l(r(N),{data:r(R),onCellMouseEnter:F,onCellMouseLeave:B,"row-style":D,onRowContextmenu:T,onRowClick:S,ref_key:"multipleTableRef",ref:E},{default:a(()=>[l(t,{prop:"name",width:"200px"}),l(t,{prop:"isDir",width:"130px"}),l(t,{prop:"size",width:"130px"}),l(t,{prop:"path",width:"130px"})]),_:1},8,["data"]),l(r(j),{"auto-ajust-placement":"",ref:"contextmenu"},{default:a(()=>[d.value?(i(),p(r(m),{key:0,onClick:_},{default:a(()=>[l(c,{class:"contextmenu-icon"},{default:a(()=>[l(s)]),_:1}),X]),_:1})):h("",!0),d.value?(i(),p(r(m),{key:1,onClick:_},{default:a(()=>[l(c,{class:"contextmenu-icon"},{default:a(()=>[l(s)]),_:1}),Y]),_:1})):h("",!0),d.value?(i(),p(r(m),{key:2,onClick:_},{default:a(()=>[l(c,{class:"contextmenu-icon"},{default:a(()=>[l(s)]),_:1}),A]),_:1})):h("",!0),d.value?(i(),p(r(m),{key:3,onClick:_},{default:a(()=>[l(c,{class:"contextmenu-icon"},{default:a(()=>[l(s)]),_:1}),G]),_:1})):h("",!0),d.value?(i(),p(r(m),{key:4,onClick:_},{default:a(()=>[l(c,{class:"contextmenu-icon"},{default:a(()=>[l(s)]),_:1}),H]),_:1})):h("",!0)]),_:1},512)],64)}}});export{q as default};
|
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
.date-cell-holiday[data-v-0e3dfbc2]{background:#dfd}.date-cell-event[data-v-0e3dfbc2]{background:yellow}
|
|
||||||
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-61
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{g as x,a as j,p as q,b as A}from"./blogView.3f9577de.js";import{p as P}from"./profile.50110a29.js";import{d as T,c as h,f as m,h as e,w as l,u as a,F as y,x as k,g as i,r as C,e as u,o as r,B as W,z as B,i as c}from"./index.e20aada4.js";import"./index.7b5a1be8.js";const G=i("span",null,"\u5206\u7C7B\u641C\u7D22",-1),H=i("span",{class:"text-gray-500"},"-",-1),J=c("\u641C\u7D22"),K=c("\u521B\u4F5C"),M=c("\u91CD\u65B0\u53D1\u5E03Wiki"),O=c("\u91CD\u65B0\u53D1\u5E03profile"),Q={class:"blog_list"},R=["onClick"],X={style:{display:"flex","justify-content":"space-between","align-items":"center"}},Y={style:{"font-size":"12px",height:"16px","line-height":"16px",overflow:"hidden","text-overflow":"ellipsis"}},Z=c("\u91CD\u65B0\u53D1\u5E03 "),ee={class:"page_style"},ae=T({setup(te){const s=h({key_word:"",btId:"",start_day:"",end_day:"",page_number:1,page_size:5,total:1}),p=h([]),f=h([]),w=()=>{x(s).then(n=>{p.splice(0,p.length),n.data.forEach(t=>{p.push(t)})})},v=n=>{const{href:t}=C.resolve({path:"/view",query:{bid:n}});window.open(t,"_blank")},V=()=>{const{href:n}=C.resolve({path:"/write/"});window.open(n,"_blank")},E=()=>{q()},F=()=>{P()},D=n=>{A(n)};return x(s).then(n=>{n.data.forEach(t=>{p.push(t)})}),j().then(n=>{f.push({btId:"",btName:"\u9009\u62E9\u5206\u7C7B"}),n.data.forEach(t=>{const b={btId:t.btId,btName:t.btName};f.push(b)})}),(n,t)=>{const b=u("el-input"),d=u("el-col"),N=u("el-option"),I=u("el-select"),g=u("el-form-item"),z=u("el-date-picker"),U=u("el-time-picker"),_=u("el-button"),L=u("el-form"),S=u("el-pagination");return r(),m(y,null,[e(L,{model:a(s),"label-width":"120px"},{default:l(()=>[e(g,{label:"\u5173\u952E\u5B57\u641C\u7D22"},{default:l(()=>[e(d,{span:7},{default:l(()=>[e(b,{modelValue:a(s).key_word,"onUpdate:modelValue":t[0]||(t[0]=o=>a(s).key_word=o)},null,8,["modelValue"])]),_:1}),e(d,{span:1}),e(d,{span:10},{default:l(()=>[G,e(I,{modelValue:a(s).btId,"onUpdate:modelValue":t[1]||(t[1]=o=>a(s).btId=o),placeholder:"\u9009\u62E9\u5206\u7C7B"},{default:l(()=>[(r(!0),m(y,null,k(a(f),o=>(r(),W(N,{key:o.btId,label:o.btName,value:o.btId},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1})]),_:1}),e(g,{label:"\u521B\u4F5C\u65F6\u95F4"},{default:l(()=>[e(d,{span:7},{default:l(()=>[e(z,{modelValue:a(s).start_day,"onUpdate:modelValue":t[2]||(t[2]=o=>a(s).start_day=o),type:"date",placeholder:"\u5F00\u59CB\u65F6\u95F4",style:{width:"100%"}},null,8,["modelValue"])]),_:1}),e(d,{span:2,class:"text-center"},{default:l(()=>[H]),_:1}),e(d,{span:7},{default:l(()=>[e(U,{modelValue:a(s).end_day,"onUpdate:modelValue":t[3]||(t[3]=o=>a(s).end_day=o),placeholder:"\u7ED3\u675F\u65F6\u95F4",style:{width:"100%"}},null,8,["modelValue"])]),_:1}),e(d,{span:6,style:{"text-align":"center"}},{default:l(()=>[e(_,{type:"primary",onClick:w},{default:l(()=>[J]),_:1})]),_:1})]),_:1})]),_:1},8,["model"]),e(_,{onClick:V},{default:l(()=>[K]),_:1}),e(_,{onClick:E},{default:l(()=>[M]),_:1}),e(_,{onClick:F},{default:l(()=>[O]),_:1}),(r(!0),m(y,null,k(a(p),o=>(r(),m("div",Q,[i("h3",{style:{cursor:"pointer",width:"min-content","white-space":"nowrap"},onClick:$=>v(o.bid)},B(o.title),9,R),i("div",X,[i("p",Y,B(o.content),1),e(_,{size:"small",type:"success",onClick:$=>D(o.bid)},{default:l(()=>[Z]),_:2},1032,["onClick"])])]))),256)),i("div",ee,[e(S,{small:"",background:"",layout:"prev, pager, next",total:50,class:"mt-4"})])],64)}}});export{ae as default};
|
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
.el-button--text[data-v-84f682ae]{margin-right:15px}.el-select[data-v-84f682ae],.el-input[data-v-84f682ae]{width:300px}.dialog-footer button[data-v-84f682ae]:first-child{margin-right:10px}.el-button--text[data-v-25eee70b]{margin-right:15px}.el-select[data-v-25eee70b],.el-input[data-v-25eee70b]{width:300px}.dialog-footer button[data-v-25eee70b]:first-child{margin-right:10px}.dashboard{background-color:beige}.tag_list[data-v-85509c2e]{display:flex;border-top:1px solid rgba(151,151,151,.3);border-bottom:1px solid rgba(151,151,151,.3)}.click-icon[data-v-85509c2e]{width:40px;margin:10px;cursor:pointer}.create_dialog[data-v-85509c2e]{margin:10px}
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
.dashboard{background-color:beige}
|
|
||||||
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
.section-main{height:100%;padding:14px}.headerAvatar[data-v-db52df48]{display:flex;justify-content:center;align-items:center;margin-right:8px}.file[data-v-db52df48]{width:80px;height:80px;position:relative}.right-box[data-v-47d8c705]{padding-top:16px;display:flex;justify-content:flex-end;align-items:center}.right-box img[data-v-47d8c705]{vertical-align:middle;border:1px solid #ccc;border-radius:6px}.item[data-v-47d8c705]{margin-top:5px;margin-right:30px}.header-avatar[data-v-47d8c705]{display:flex;justify-content:center;align-items:center}.side_Style[data-v-52f0823c]{width:100px}.side-main[data-v-52f0823c]{width:200px}.gva-menu-item[data-v-52f0823c]{color:#fff}.el-menu-item.is-active[data-v-52f0823c]{color:var(--ddab178a);background:var(--ddab178a)}.el-header[data-v-4dcee88b]{border-bottom-style:solid;border-bottom-width:.5px;border-bottom-color:#9797974d}.el-main[data-v-4dcee88b]{padding:16px;overflow:hidden;height:100%}.el-aside[data-v-4dcee88b]{margin-left:-10px;background:#191a23;position:fixed}.el-footer[data-v-4dcee88b]{margin-top:20px;display:flex;justify-content:space-around}.homeWrap[data-v-4dcee88b]{position:absolute;top:0;height:100%;width:100%}
|
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
.text[data-v-623cde64]{font-size:14px}.item[data-v-623cde64]{padding:18px 0}.ttt[data-v-623cde64]{display:flex;flex-direction:column}.yuliu[data-v-623cde64]{height:300px;float:left;background:url(/assets/have_a_nice_day.4bde267a.jpeg) center top no-repeat;background-size:cover}
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{E as u}from"./style.1aad9498.js";import{d as i,b as s,f as m,g as d,z as p,u as a,h as c,R as f,F as g,a8 as V,o as B}from"./index.e20aada4.js";import{c as _}from"./blogView.3f9577de.js";import"./index.7b5a1be8.js";const k=i({setup(v){let e=s(""),o=s("");const n=V().query;return(()=>{_(n.bid).then(t=>{e.value=t.data.content,o.value=t.data.title})})(),(t,l)=>(B(),m(g,null,[d("h2",null,p(a(o)),1),c(a(u),{modelValue:a(e),"onUpdate:modelValue":l[0]||(l[0]=r=>f(e)?e.value=r:e=r),previewOnly:""},null,8,["modelValue"])],64))}});export{k as default};
|
|
||||||
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 64 KiB |
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
const r=t=>(t*100).toFixed(2)+"%",e=t=>t>10?t:"0"+t;export{e as a,r as t};
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{H as r}from"./index.e20aada4.js";const o={"Content-Type":"application/json;charsetset=UTF-8"},t=e=>r({url:"/wiki/api/v1/author/profile",method:"POST",data:e}),a=e=>r({url:"/wiki/api/v1/author/profile",method:"PUT",data:e}),p=()=>r({url:"/wiki/api/v1/author/profile/publish",method:"PUT"}),u=()=>r({url:"/wiki/api/v1/author/profile",method:"GET",headers:o}),l=()=>r({url:"/wiki/api/v1/author/profile/name",method:"GET",headers:o}),s=e=>r({url:"/wiki/api/v1/author/profile/judge",method:"POST",data:e});export{u as a,t as c,l as g,s as j,p,a as u};
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{d as f,c as b,f as V,h as e,w as l,u as o,F as C,i as m,g as B,a8 as E,e as r,o as F,bY as k,s as h,a as A,r as g}from"./index.e20aada4.js";const w=m(" \u8A72\u5F53\u30B7\u30B9\u30C6\u30E0\u306E\u3054\u5229\u7528\u306F\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005\u306B\u8A31\u53EF\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002"),x=B("br",null,null,-1),U=m(" \u8A31\u53EF\u304C\u306A\u3051\u308C\u3070\u3001\u30E6\u30FC\u30B6\u30FC\u60C5\u5831\u3092\u767B\u9332\u3057\u3066\u3082\u3001\u30B7\u30B9\u30C6\u30E0\u306E\u3054\u5229\u7528\u306F\u3067\u304D\u307E\u305B\u3093\u306E\u3067\u3001\u3054\u6CE8\u610F\u304F\u3060\u3055\u3044\u3002 "),v=m("Register"),y=m("Cancel"),R=f({setup(I){const d=E().query,u=b({phone_number:"",code:"",tenant_id:d.tenantId,account:d.account,token:d.token}),i=()=>{k(u).then(_=>{if(_.status==200){const t={id:d.tenantId,account:d.account};h(d.token),A(t);const{href:a}=g.resolve({path:"/"});window.open(a,"_self")}})};return(_,t)=>{const a=r("el-input"),s=r("el-form-item"),c=r("el-button"),p=r("el-form");return F(),V(C,null,[w,x,U,e(p,{model:o(u),"label-width":"120px"},{default:l(()=>[e(s,{label:"phone_number"},{default:l(()=>[e(a,{modelValue:o(u).phone_number,"onUpdate:modelValue":t[0]||(t[0]=n=>o(u).phone_number=n)},null,8,["modelValue"])]),_:1}),e(s,{label:"auth_code"},{default:l(()=>[e(a,{modelValue:o(u).code,"onUpdate:modelValue":t[1]||(t[1]=n=>o(u).code=n)},null,8,["modelValue"])]),_:1}),e(s,{label:"tenantId"},{default:l(()=>[e(a,{modelValue:o(u).tenant_id,"onUpdate:modelValue":t[2]||(t[2]=n=>o(u).tenant_id=n),disabled:!0},null,8,["modelValue"])]),_:1}),e(s,{label:"account"},{default:l(()=>[e(a,{modelValue:o(u).account,"onUpdate:modelValue":t[3]||(t[3]=n=>o(u).account=n),disabled:!0},null,8,["modelValue"])]),_:1}),e(s,{label:"token"},{default:l(()=>[e(a,{modelValue:o(u).token,"onUpdate:modelValue":t[4]||(t[4]=n=>o(u).token=n),disabled:!0},null,8,["modelValue"])]),_:1}),e(s,null,{default:l(()=>[e(c,{type:"primary",onClick:i},{default:l(()=>[v]),_:1}),e(c,null,{default:l(()=>[y]),_:1})]),_:1})]),_:1},8,["model"])],64)}}});export{R as default};
|
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{I as n,b as r,J as s}from"./index.e20aada4.js";const d=n("settings",()=>{const e=r({sideMode:"#191a23",isMobile:!1,isRouterAlive:!0,isLoading:!1,profileName:null}),i=s(()=>e.value.sideMode),o=s(()=>e.value.isMobile),t=s(()=>e.value.isRouterAlive),a=s(()=>e.value.isLoading),l=s(()=>e.value.profileName);return{settings:e,sideMode:i,isMobile:o,isRouterAlive:t,isLoading:a,profileName:l}});export{d as s};
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{_ as e,f as r,o as c}from"./index.e20aada4.js";const o={},s={class:"yuliu"};function t(_,a){return c(),r("div",s," \u8FD9\u4E2A\u4EBA\u5F88\u61D2\uFF0C\u4EC0\u4E48\u4E5F\u6CA1\u5199 ")}var f=e(o,[["render",t]]);export{f as default};
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
import{H as e,I as c,c as a}from"./index.e20aada4.js";const v=()=>e({url:"/trader/api/v1/accounts",method:"GET"}),d=s=>e({url:"/trader/api/v1/tick/"+s,method:"GET"}),y=()=>e({url:"/trader/api/v1/ticks",method:"GET"}),h=s=>e({url:"/trader/api/v1/order",method:"POST",data:s}),g=s=>e({url:"/trader/api/v1/subscribe/"+s,method:"GET"}),o=()=>e({url:"/trader/api/v1/subscribe/vt_symbols",method:"GET"}),p=s=>e({url:"/trader/api/v1/subscribe/"+s,method:"DELETE"}),n=()=>e({url:"/trader/api/v1/vt_symbols",method:"GET"}),b=()=>e({url:"/trader/api/v1/exchanges",method:"GET"}),E=c("strategy",()=>{const s=a({class_names:[],vt_symbols:new Map,subscribe_vt_symbols:[],exchanges:[]});return{strategy:s,select_exchanges:async()=>{s.exchanges.length==0&&b().then(t=>{s.exchanges=t.data.exchanges})},select_vt_symbols:async()=>{s.vt_symbols.size==0&&n().then(t=>{Object.keys(t.data.vt_symbols).forEach(r=>{s.vt_symbols.set(r,t.data.vt_symbols[r])})})},select_subscribe_vt_symbols:async()=>{s.subscribe_vt_symbols.length==0&&o().then(t=>{s.subscribe_vt_symbols=t.data.subscribe_vt_symbols})}}});export{g as a,v as b,p as c,d,h as e,y as g,E as s};
|
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
-84
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
@@ -1,6 +0,0 @@
|
|||||||
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
|
|
||||||
import tenant from './tenant';
|
|
||||||
|
|
||||||
export function setupMock() {
|
|
||||||
createProdMockServer([...tenant]);
|
|
||||||
}
|
|
||||||
Generated
+4069
-3125
File diff suppressed because it is too large
Load Diff
+27
-37
@@ -1,54 +1,44 @@
|
|||||||
{
|
{
|
||||||
"name": "violin-home",
|
"name": "violin-home",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.0",
|
"version": "2.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host",
|
"dev": "vite --host",
|
||||||
"build": "vue-tsc --noEmit && vite build",
|
"build": "vue-tsc --noEmit && vite build",
|
||||||
"development": "vite build --mode development",
|
"build:test": "vue-tsc --noEmit && vite build --mode test",
|
||||||
"test": "vite --mode test",
|
"build:dev": "vue-tsc --noEmit && vite build --mode development",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^1.1.4",
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"@types/node": "^17.0.23",
|
"axios": "^1.7.7",
|
||||||
"aplayer": "^1.10.1",
|
"clipboard": "^2.0.11",
|
||||||
"axios": "^0.26.1",
|
"copy-to-clipboard": "^3.3.3",
|
||||||
"clipboard": "^2.0.10",
|
"dayjs": "^1.11.13",
|
||||||
"copy-to-clipboard": "^3.3.1",
|
"echarts": "^5.5.1",
|
||||||
"echarts": "^5.3.2",
|
"element-plus": "^2.8.4",
|
||||||
"element-plus": "^2.1.7",
|
"js-cookie": "^3.0.5",
|
||||||
"js-cookie": "^3.0.1",
|
|
||||||
"lodash": "^4.17.21",
|
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"lodash-unified": "^1.0.2",
|
"md-editor-v3": "^4.20.1",
|
||||||
"md-editor-v3": "^1.11.6",
|
"pinia": "^2.2.4",
|
||||||
"moment": "^2.29.4",
|
"qs": "^6.13.0",
|
||||||
"node-sass": "^8.0.0",
|
"v-contextmenu": "^3.2.0",
|
||||||
"pinia": "^2.0.13",
|
"vue": "^3.5.12",
|
||||||
"qs": "^6.10.3",
|
"vue-router": "^4.4.5",
|
||||||
"sass": "^1.57.1",
|
|
||||||
"sass-loader": "^13.2.0",
|
|
||||||
"save": "^2.4.0",
|
|
||||||
"scss": "^0.2.4",
|
|
||||||
"style-loader": "^3.3.1",
|
|
||||||
"type-fest": "^2.12.2",
|
|
||||||
"vue": "^3.2.25",
|
|
||||||
"vue-router": "^4.0.14",
|
|
||||||
"vue-runtime-helpers": "^1.1.2",
|
|
||||||
"vuedraggable": "^4.1.0"
|
"vuedraggable": "^4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/js-cookie": "^3.0.1",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"@types/lodash-es": "^4.17.6",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/qs": "^6.9.7",
|
"@types/node": "^22.7.5",
|
||||||
"@vitejs/plugin-vue": "^2.3.0",
|
"@types/qs": "^6.9.15",
|
||||||
|
"@vitejs/plugin-vue": "^5.1.4",
|
||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
"typescript": "^4.5.4",
|
"sass": "^1.79.4",
|
||||||
"v-contextmenu": "^3.0.0",
|
"typescript": "~5.6.2",
|
||||||
"vite": "^2.9.13",
|
"vite": "^5.4.8",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-mock": "^2.9.6",
|
"vite-plugin-mock": "^3.0.2",
|
||||||
"vue-tsc": "^0.29.8"
|
"vue-tsc": "^2.1.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<span class="headerAvatar">
|
<span class="headerAvatar">
|
||||||
<template v-if="picType === 'avatar'">
|
<template v-if="picType === 'avatar'">
|
||||||
<el-avatar v-if="useTenantStore.tenant.headerImg" :size="30" :src="avatar" />
|
<el-avatar v-if="useCustomerStore.customer.headerImg" :size="30" :src="avatar" />
|
||||||
<el-avatar v-else :size="30" :src="noAvatar" />
|
<el-avatar v-else :size="30" :src="noAvatar" />
|
||||||
</template>
|
</template>
|
||||||
<template v-if="picType === 'img'">
|
<template v-if="picType === 'img'">
|
||||||
<img v-if="useTenantStore.tenant.headerImg" :src="avatar" class="avatar">
|
<img v-if="useCustomerStore.customer.headerImg" :src="avatar" class="avatar">
|
||||||
<img v-else :src="noAvatar" class="avatar">
|
<img v-else :src="noAvatar" class="avatar">
|
||||||
</template>
|
</template>
|
||||||
<template v-if="picType === 'file'">
|
<template v-if="picType === 'file'">
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { tenantStore } from '@/store/modules/tenant'
|
import { customerStore } from '@/store/modules/customer'
|
||||||
import noAvatarPng from '@/assets/nobody.jpg'
|
import noAvatarPng from '@/assets/nobody.jpg'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -33,13 +33,13 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
const path = ref(import.meta.env.VITE_BASE_API + '/')
|
const path = ref(import.meta.env.VITE_BASE_API + '/')
|
||||||
const noAvatar = ref(noAvatarPng)
|
const noAvatar = ref(noAvatarPng)
|
||||||
const useTenantStore = tenantStore()
|
const useCustomerStore = customerStore()
|
||||||
const avatar = computed(() => {
|
const avatar = computed(() => {
|
||||||
if (props.picSrc === '') {
|
if (props.picSrc === '') {
|
||||||
if (useTenantStore.tenant.headerImg !== '' && useTenantStore.tenant.headerImg.slice(0, 4) === 'http') {
|
if (useCustomerStore.customer.headerImg !== '' && useCustomerStore.customer.headerImg.slice(0, 4) === 'http') {
|
||||||
return useTenantStore.tenant.headerImg
|
return useCustomerStore.customer.headerImg
|
||||||
}
|
}
|
||||||
return path.value + useTenantStore.tenant.headerImg
|
return path.value + useCustomerStore.customer.headerImg
|
||||||
} else {
|
} else {
|
||||||
if (props.picSrc !== '' && props.picSrc.slice(0, 4) === 'http') {
|
if (props.picSrc !== '' && props.picSrc.slice(0, 4) === 'http') {
|
||||||
return props.picSrc
|
return props.picSrc
|
||||||
@@ -61,7 +61,6 @@ const file = computed(() => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file {
|
.file {
|
||||||
width: 80px;
|
width: 80px;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
<span class="header-avatar" style="cursor: pointer">
|
<span class="header-avatar" style="cursor: pointer">
|
||||||
<CustomPic />
|
<CustomPic />
|
||||||
<span v-show="!useSettingsStore.isMobile" style="margin-left: 5px">{{
|
<span v-show="!useSettingsStore.isMobile" style="margin-left: 5px">{{
|
||||||
useTenantStore.tenant.account
|
useCustomerStore.customer.account
|
||||||
}}</span>
|
}}</span>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<arrow-down />
|
<arrow-down />
|
||||||
@@ -67,10 +67,10 @@
|
|||||||
<el-dropdown-menu class="dropdown-group">
|
<el-dropdown-menu class="dropdown-group">
|
||||||
<el-dropdown-item>
|
<el-dropdown-item>
|
||||||
<span style="font-weight: 600;">
|
<span style="font-weight: 600;">
|
||||||
当前角色:{{ useTenantStore.tenant.account }}
|
当前角色:{{ useCustomerStore.customer.account }}
|
||||||
</span>
|
</span>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<template v-if="useTenantStore.tenant.account">
|
<template v-if="useCustomerStore.customer.account">
|
||||||
<!-- <el-dropdown-item v-for="item in userStore.userInfo.authorities.filter(i=>i.authorityId!==userStore.userInfo.authorityId)" :key="item.authorityId" @click="changeUserAuth(item.authorityId)">
|
<!-- <el-dropdown-item v-for="item in userStore.userInfo.authorities.filter(i=>i.authorityId!==userStore.userInfo.authorityId)" :key="item.authorityId" @click="changeUserAuth(item.authorityId)">
|
||||||
<span>
|
<span>
|
||||||
切换为:{{ item.authorityName }}
|
切换为:{{ item.authorityName }}
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
</el-dropdown-item> -->
|
</el-dropdown-item> -->
|
||||||
</template>
|
</template>
|
||||||
<el-dropdown-item icon="avatar" @click="toPerson">个人信息</el-dropdown-item>
|
<el-dropdown-item icon="avatar" @click="toPerson">个人信息</el-dropdown-item>
|
||||||
<el-dropdown-item icon="reading-lamp" @click="useTenantStore.logout">登 出</el-dropdown-item>
|
<el-dropdown-item icon="reading-lamp" @click="useCustomerStore.logout">登 出</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
@@ -89,13 +89,13 @@
|
|||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import CustomPic from "@/components/customPic/index.vue";
|
import CustomPic from "@/components/customPic/index.vue";
|
||||||
import { tenantStore } from '@/store/modules/tenant'
|
import { customerStore } from '@/store/modules/customer'
|
||||||
import { settingsStore } from '@/store/modules/settings'
|
import { settingsStore } from '@/store/modules/settings'
|
||||||
import { Message } from "@element-plus/icons-vue"
|
import { Message } from "@element-plus/icons-vue"
|
||||||
import { reactive, ref } from "vue";
|
import { reactive, ref } from "vue";
|
||||||
|
|
||||||
// -- IMPORT --
|
// -- IMPORT --
|
||||||
const useTenantStore = tenantStore()
|
const useCustomerStore = customerStore()
|
||||||
const useSettingsStore = settingsStore()
|
const useSettingsStore = settingsStore()
|
||||||
|
|
||||||
// -- REACTIVE OBJECT --
|
// -- REACTIVE OBJECT --
|
||||||
@@ -131,7 +131,7 @@ const toPerson = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
useTenantStore.reflush()
|
useCustomerStore.reflush()
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -4,17 +4,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<el-card class="box-card">
|
<el-card class="box-card">
|
||||||
|
|
||||||
<el-form ref="ruleFormRef" :model="loginForm" :rules="loginRules" status-icon label-width="120px"
|
<el-form>
|
||||||
class="demo-ruleForm">
|
|
||||||
<div class="title-container">
|
<div class="title-container">
|
||||||
<h3>秘密基地</h3>
|
<h3>秘密基地</h3>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<el-avatar :size="28" :src="baiduCloudImage" @click="scan(qrcode)" />
|
<el-button type="primary" size="large" @click="handleOidcLogin">统一登录</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-form-item>
|
|
||||||
其他登录方式暂时还没有哦
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
<div>
|
<div>
|
||||||
@@ -31,61 +27,25 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref } from 'vue'
|
import { reactive } from 'vue'
|
||||||
import type { FormInstance } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { tenantStore } from '../../store/modules/tenant'
|
|
||||||
import router from '../../router'
|
|
||||||
import baiduCloudImage from "../../assets/baiducloud.png"
|
|
||||||
import { config, scan } from '../../const/config'
|
|
||||||
|
|
||||||
|
const handleOidcLogin = () => {
|
||||||
|
const issuer = import.meta.env.VITE_OIDC_ISSUER
|
||||||
|
const clientId = import.meta.env.VITE_OIDC_CLIENT_ID
|
||||||
|
const redirectUri = encodeURIComponent(import.meta.env.VITE_OIDC_REDIRECT_URI)
|
||||||
|
const scope = encodeURIComponent('openid profile email')
|
||||||
|
const state = Math.random().toString(36).substring(2)
|
||||||
|
|
||||||
let qrcode = config.BAIDU_CLOUD_URL + config.RESPONSE_TYPE + config.CLIENT_ID + config.REDIRECT_URI + config.SCOPE + config.DEVICE_ID + config.QR_CODE + config.DISPLAY
|
if (!issuer || !clientId) {
|
||||||
|
ElMessage.error('OIDC 未配置,请联系管理员')
|
||||||
const useTenantStore = tenantStore()
|
|
||||||
|
|
||||||
const ruleFormRef = ref<FormInstance>()
|
|
||||||
const loginForm = reactive({
|
|
||||||
user_id: '',
|
|
||||||
password: ''
|
|
||||||
})
|
|
||||||
|
|
||||||
const validateUserName = (rule: any, value: string, callback: Function) => {
|
|
||||||
if (!value) {
|
|
||||||
callback(new Error("请输入的用户名"))
|
|
||||||
} else {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const validatePassword = (rule: any, value: string, callback: Function) => {
|
|
||||||
if (!value) {
|
|
||||||
callback(new Error("请输入密码"))
|
|
||||||
} else {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const loginRules = reactive({
|
|
||||||
user_id: [{ validator: validateUserName, trigger: 'blur' }],
|
|
||||||
password: [{ validator: validatePassword, trigger: 'blur' }]
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const dologin = (form: any) => {
|
|
||||||
|
|
||||||
if (!form)
|
|
||||||
return
|
return
|
||||||
// form.validate((valid: any) => {
|
}
|
||||||
// if (valid) {
|
|
||||||
// useTenantStore.login(loginForm.user_id, loginForm.password).then(res => {
|
|
||||||
// console.log(1)
|
|
||||||
// router.push({
|
|
||||||
// path: '/home'
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
|
|
||||||
// } else {
|
sessionStorage.setItem('oidc_state', state)
|
||||||
// return false
|
window.location.href =
|
||||||
// }
|
`${issuer}/application/o/authorize/?` +
|
||||||
// })
|
`client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&scope=${scope}&state=${state}`
|
||||||
}
|
}
|
||||||
|
|
||||||
const openSiteQuery = () => {
|
const openSiteQuery = () => {
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
<el-input v-model="register_form.code" />
|
<el-input v-model="register_form.code" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="tenantId">
|
<el-form-item label="customerId">
|
||||||
<el-input v-model="register_form.tenant_id" :disabled="true" />
|
<el-input v-model="register_form.customerId" :disabled="true" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="account">
|
<el-form-item label="account">
|
||||||
@@ -35,17 +35,17 @@ import { reactive } from 'vue'
|
|||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { register_user } from "./../../api/user";
|
import { register_user } from "./../../api/user";
|
||||||
import router from '../../router/index'
|
import router from '../../router/index'
|
||||||
import { setTenant, setToken } from '../../utils/auth';
|
import { setCustomer, setToken } from '../../utils/auth';
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const params = route.query
|
const params = route.query
|
||||||
|
|
||||||
|
|
||||||
// use phone number to register user(tenant)
|
// use phone number to register user(customer)
|
||||||
const register_form = reactive({
|
const register_form = reactive({
|
||||||
phone_number: '',
|
phone_number: '',
|
||||||
code: '',
|
code: '',
|
||||||
tenant_id: params.tenantId as string,
|
customerId: params.customerId as string,
|
||||||
account: params.account as string,
|
account: params.account as string,
|
||||||
token: params.token as string
|
token: params.token as string
|
||||||
})
|
})
|
||||||
@@ -54,13 +54,13 @@ const onSubmit = () => {
|
|||||||
register_user(register_form).then((response) => {
|
register_user(register_form).then((response) => {
|
||||||
|
|
||||||
if (response.status == 200) {
|
if (response.status == 200) {
|
||||||
const tenant = {
|
const customer = {
|
||||||
id: params.tenantId,
|
id: params.customerId,
|
||||||
account: params.account
|
account: params.account
|
||||||
}
|
}
|
||||||
|
|
||||||
setToken(params.token as string)
|
setToken(params.token as string)
|
||||||
setTenant(tenant)
|
setCustomer(customer)
|
||||||
|
|
||||||
const { href } = router.resolve({
|
const { href } = router.resolve({
|
||||||
path: '/'
|
path: '/'
|
||||||
|
|||||||
+9
-9
@@ -1,7 +1,7 @@
|
|||||||
import { Tenant } from '@/entity';
|
import { Customer } from '@/entity';
|
||||||
import { tenantStore } from '@/store/modules/tenant';
|
import { customerStore } from '@/store/modules/customer';
|
||||||
import router from '../router'
|
import router from '../router'
|
||||||
import { setToken, setTenant } from '../utils/auth'
|
import { setToken, setCustomer } from '../utils/auth'
|
||||||
|
|
||||||
// config/index.js
|
// config/index.js
|
||||||
const env = process.env.NODE_ENV!;
|
const env = process.env.NODE_ENV!;
|
||||||
@@ -45,14 +45,14 @@ const scan_method: any = {
|
|||||||
},
|
},
|
||||||
development: async () => {
|
development: async () => {
|
||||||
|
|
||||||
const useTenantStore = tenantStore()
|
const useCustomerStore = customerStore()
|
||||||
const tenant: Tenant = {
|
const customer: Customer = {
|
||||||
tenant_id: '7788',
|
customerId: '7788',
|
||||||
account: '小小的测试账户'
|
account: '小小的测试账户'
|
||||||
}
|
}
|
||||||
let token = 'ABCDEFG'
|
let token = 'ABCDEFG'
|
||||||
|
|
||||||
await useTenantStore.login(tenant, token).then(() => {
|
await useCustomerStore.login(customer, token).then(() => {
|
||||||
const { href } = router.resolve({
|
const { href } = router.resolve({
|
||||||
path: '/'
|
path: '/'
|
||||||
})
|
})
|
||||||
@@ -65,9 +65,9 @@ const scan_method: any = {
|
|||||||
})
|
})
|
||||||
|
|
||||||
setToken("token")
|
setToken("token")
|
||||||
setTenant(
|
setCustomer(
|
||||||
{
|
{
|
||||||
tenantId: "111"
|
customerId: "111"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
router.push({
|
router.push({
|
||||||
|
|||||||
+4
-3
@@ -1,5 +1,5 @@
|
|||||||
type Tenant = {
|
type Customer = {
|
||||||
tenant_id: string,
|
customerId: string,
|
||||||
account: string
|
account: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,4 +64,5 @@ const wikiType = (data: any) => {
|
|||||||
} as WikiType
|
} as WikiType
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Tenant, Theme, DataTimeline, Event, Wiki, wiki, WikiType, wikiType }
|
export type { Customer, Theme, DataTimeline, Event, Wiki, WikiType }
|
||||||
|
export { wiki, wikiType }
|
||||||
|
|||||||
Vendored
+11
@@ -6,3 +6,14 @@ declare module '*.vue' {
|
|||||||
const component: DefineComponent<{}, {}, any>
|
const component: DefineComponent<{}, {}, any>
|
||||||
export default component
|
export default component
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 兼容 element-plus 2.8.x 与 vue-tsc 2.x 的 GlobalComponents 索引类型
|
||||||
|
// (element-plus 在 .d.ts 里把 GlobalComponents 用作 Record<string, Component<...>>,
|
||||||
|
// 但 vue 默认声明没提供 index signature,触发 TS2344)
|
||||||
|
declare module 'vue' {
|
||||||
|
interface GlobalComponents {
|
||||||
|
[elemName: string]: any
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {}
|
||||||
|
|||||||
+2
-4
@@ -11,10 +11,8 @@ import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
|||||||
import contentmenu from 'v-contextmenu'
|
import contentmenu from 'v-contextmenu'
|
||||||
import 'v-contextmenu/dist/themes/default.css'
|
import 'v-contextmenu/dist/themes/default.css'
|
||||||
|
|
||||||
import { setupMock } from '../mock'
|
// mock 数据:vite-plugin-mock 3.x 在 dev 模式下由 vite 插件自动加载,
|
||||||
if (process.env.NODE_ENV === 'development') {
|
// 生产构建不带 mock(参考 AGENT.md「已知坑 #5」)
|
||||||
setupMock()
|
|
||||||
}
|
|
||||||
|
|
||||||
let app = createApp(App)
|
let app = createApp(App)
|
||||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||||
|
|||||||
+10
-10
@@ -1,10 +1,10 @@
|
|||||||
import router from './router'
|
import router from './router'
|
||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
import { getToken, getTenant } from './utils/auth'
|
import { getToken, getCustomer } from './utils/auth'
|
||||||
import { Tenant } from './entity/index'
|
import { Customer } from './entity/index'
|
||||||
import { tenantStore } from './store/modules/tenant'
|
import { customerStore } from './store/modules/customer'
|
||||||
|
|
||||||
const whiteList = ['/login', '/register', '/sorryPage', '/BlogViewer']
|
const whiteList = ['/login', '/register', '/sorryPage', '/BlogViewer', '/auth/callback']
|
||||||
let url = window.location.href
|
let url = window.location.href
|
||||||
|
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
@@ -18,7 +18,7 @@ router.beforeEach((to, from, next) => {
|
|||||||
next('/')
|
next('/')
|
||||||
break;
|
break;
|
||||||
case '/':
|
case '/':
|
||||||
const tenant = <Tenant>(JSON.parse(getTenant() as string))
|
const customer = <Customer>(JSON.parse(getCustomer() as string))
|
||||||
if (url.search("write") != -1) {
|
if (url.search("write") != -1) {
|
||||||
next('/BlogEditer')
|
next('/BlogEditer')
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ router.beforeEach((to, from, next) => {
|
|||||||
else {
|
else {
|
||||||
router.push({
|
router.push({
|
||||||
path: '/home',
|
path: '/home',
|
||||||
query: tenant
|
query: customer
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -71,12 +71,12 @@ router.beforeEach((to, from, next) => {
|
|||||||
let parameter_list = parameter.split("=")
|
let parameter_list = parameter.split("=")
|
||||||
query_data[parameter_list[0]] = parameter_list[1]
|
query_data[parameter_list[0]] = parameter_list[1]
|
||||||
})
|
})
|
||||||
const tenant = {
|
const customer = {
|
||||||
tenant_id: query_data.tenantId,
|
customerId: query_data.customerId,
|
||||||
account: query_data.account
|
account: query_data.account
|
||||||
}
|
}
|
||||||
const tenant_store = tenantStore()
|
const customer_store = customerStore()
|
||||||
tenant_store.login(tenant, query_data.token).then(() => {
|
customer_store.login(customer, query_data.token).then(() => {
|
||||||
const { href } = router.resolve({
|
const { href } = router.resolve({
|
||||||
path: '/'
|
path: '/'
|
||||||
});
|
});
|
||||||
|
|||||||
+5
-1
@@ -6,7 +6,7 @@ const home = () => import('@/view/dashboard/index.vue')
|
|||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
component: () => import('@/components/layout/layout.vue'),
|
component: () => import('@/components/layout/Layout.vue'),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/home',
|
path: '/home',
|
||||||
@@ -114,6 +114,10 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
path: "/login",
|
path: "/login",
|
||||||
component: login
|
component: login
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/auth/callback",
|
||||||
|
component: () => import('@/view/auth/callback.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/illustration",
|
path: "/illustration",
|
||||||
component: () => import('@/components/illustration/index.vue')
|
component: () => import('@/components/illustration/index.vue')
|
||||||
|
|||||||
@@ -187,8 +187,8 @@ const getSign = (
|
|||||||
openVal: number,
|
openVal: number,
|
||||||
closeVal: number,
|
closeVal: number,
|
||||||
closeDimIdx: number
|
closeDimIdx: number
|
||||||
) => {
|
): number => {
|
||||||
var sign
|
var sign: number
|
||||||
if (openVal > closeVal) {
|
if (openVal > closeVal) {
|
||||||
sign = -1
|
sign = -1
|
||||||
} else if (openVal < closeVal) {
|
} else if (openVal < closeVal) {
|
||||||
@@ -197,7 +197,7 @@ const getSign = (
|
|||||||
sign =
|
sign =
|
||||||
dataIndex > 0
|
dataIndex > 0
|
||||||
? // If close === open, compare with close of last record
|
? // If close === open, compare with close of last record
|
||||||
data[dataIndex - 1][closeDimIdx] <= closeVal
|
Number(data[dataIndex - 1][closeDimIdx]) <= closeVal
|
||||||
? 1
|
? 1
|
||||||
: -1
|
: -1
|
||||||
: // No record of previous, set to be positive
|
: // No record of previous, set to be positive
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import { defineStore, acceptHMRUpdate } from 'pinia'
|
||||||
|
import { authorize } from '../../api/user'
|
||||||
|
import { getToken, setToken, resetToken, setCustomer, getCustomer } from '../../utils/auth'
|
||||||
|
import { Customer } from '../../entity/index'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export const customerStore = defineStore('customer', () => {
|
||||||
|
const customer = ref({
|
||||||
|
account: '',
|
||||||
|
token: '',
|
||||||
|
id: '',
|
||||||
|
headerImg: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
|
||||||
|
})
|
||||||
|
|
||||||
|
const login = async (customer: Customer, token: string) => {
|
||||||
|
try {
|
||||||
|
await authorize({
|
||||||
|
customerId: customer.customerId, token: token
|
||||||
|
})
|
||||||
|
setToken(token)
|
||||||
|
setCustomer(customer)
|
||||||
|
} catch {
|
||||||
|
Promise.resolve("authorize error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const logout = async () => {
|
||||||
|
customer.value.account = ''
|
||||||
|
customer.value.token = ''
|
||||||
|
customer.value.id = ''
|
||||||
|
resetToken()
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
|
||||||
|
const reflush = async () => {
|
||||||
|
if (getToken()) {
|
||||||
|
const customerStorage = <Customer>(JSON.parse(getCustomer() as string))
|
||||||
|
const token = <string>getToken()
|
||||||
|
customer.value.account = customerStorage.account
|
||||||
|
customer.value.token = token
|
||||||
|
customer.value.id = customerStorage.customerId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
customer,
|
||||||
|
login,
|
||||||
|
logout,
|
||||||
|
reflush
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
if (import.meta.hot) {
|
||||||
|
import.meta.hot.accept(acceptHMRUpdate(customerStore, import.meta.hot))
|
||||||
|
}
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
import { defineStore, acceptHMRUpdate } from 'pinia'
|
|
||||||
import { authorize } from '../../api/user'
|
|
||||||
import { getToken, setToken, resetToken, setTenant, getTenant } from '../../utils/auth'
|
|
||||||
import { Tenant } from '../../entity/index'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
export const tenantStore = defineStore('tenant', () => {
|
|
||||||
const tenant = ref({
|
|
||||||
account: '',
|
|
||||||
token: '',
|
|
||||||
id: '',
|
|
||||||
headerImg: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
|
|
||||||
})
|
|
||||||
|
|
||||||
const login = async (tenant: Tenant, token: string) => {
|
|
||||||
try {
|
|
||||||
await authorize({
|
|
||||||
tenant_id: tenant.tenant_id, token: token
|
|
||||||
})
|
|
||||||
setToken(token)
|
|
||||||
setTenant(tenant)
|
|
||||||
} catch {
|
|
||||||
Promise.resolve("authorize error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const logout = async () => {
|
|
||||||
tenant.value.account = ''
|
|
||||||
tenant.value.token = ''
|
|
||||||
tenant.value.id = ''
|
|
||||||
resetToken()
|
|
||||||
window.location.reload()
|
|
||||||
}
|
|
||||||
|
|
||||||
const reflush = async () => {
|
|
||||||
if (getToken()) {
|
|
||||||
const tenantStorage = <Tenant>(JSON.parse(getTenant() as string))
|
|
||||||
const token = <string>getToken()
|
|
||||||
tenant.value.account = tenantStorage.account
|
|
||||||
tenant.value.token = token
|
|
||||||
tenant.value.id = tenantStorage.tenant_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
tenant,
|
|
||||||
login,
|
|
||||||
logout,
|
|
||||||
reflush
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
if (import.meta.hot) {
|
|
||||||
import.meta.hot.accept(acceptHMRUpdate(tenantStore, import.meta.hot))
|
|
||||||
}
|
|
||||||
+8
-8
@@ -1,24 +1,24 @@
|
|||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
|
|
||||||
const getToken = () => {
|
const getToken = (): string | undefined => {
|
||||||
return Cookies.get('token')
|
return Cookies.get('token')
|
||||||
}
|
}
|
||||||
|
|
||||||
const setToken = (token: String) => {
|
const setToken = (token: string) => {
|
||||||
Cookies.set('token', token)
|
Cookies.set('token', token)
|
||||||
}
|
}
|
||||||
|
|
||||||
const setTenant = (tenant: object) => {
|
const setCustomer = (customer: object) => {
|
||||||
Cookies.set('tenant', JSON.stringify(tenant))
|
Cookies.set('customer', JSON.stringify(customer))
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTenant = () => {
|
const getCustomer = (): string | undefined => {
|
||||||
return Cookies.get('tenant')
|
return Cookies.get('customer')
|
||||||
}
|
}
|
||||||
|
|
||||||
const resetToken = () => {
|
const resetToken = () => {
|
||||||
Cookies.remove('token')
|
Cookies.remove('token')
|
||||||
Cookies.remove('tenant')
|
Cookies.remove('customer')
|
||||||
}
|
}
|
||||||
|
|
||||||
export { getToken, setToken, resetToken, setTenant, getTenant }
|
export { getToken, setToken, resetToken, setCustomer, getCustomer }
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user