From aaed19de059d58c31fbbc3db14f8f36cfaf66402 Mon Sep 17 00:00:00 2001 From: XuqmGroup Date: Tue, 21 Apr 2026 22:07:29 +0800 Subject: [PATCH] chore: initial commit --- .gitignore | 10 ++ ops-platform/env.d.ts | 9 + ops-platform/index.html | 12 ++ ops-platform/package.json | 27 +++ ops-platform/src/App.vue | 3 + ops-platform/src/api/client.ts | 24 +++ ops-platform/src/api/ops.ts | 37 +++++ ops-platform/src/main.ts | 13 ++ ops-platform/src/router/index.ts | 25 +++ ops-platform/src/views/auth/LoginView.vue | 40 +++++ ops-platform/src/views/layout/MainLayout.vue | 28 ++++ .../src/views/statistics/StatisticsView.vue | 42 +++++ .../src/views/tenants/TenantListView.vue | 79 +++++++++ ops-platform/tsconfig.app.json | 12 ++ ops-platform/tsconfig.json | 7 + ops-platform/tsconfig.node.json | 7 + ops-platform/vite.config.ts | 23 +++ package.json | 14 ++ tenant-platform/index.html | 13 ++ tenant-platform/package.json | 27 +++ tenant-platform/src/App.vue | 3 + tenant-platform/src/api/account.ts | 29 ++++ tenant-platform/src/api/app.ts | 53 ++++++ tenant-platform/src/api/auth.ts | 35 ++++ tenant-platform/src/api/client.ts | 32 ++++ tenant-platform/src/env.d.ts | 9 + tenant-platform/src/main.ts | 18 ++ tenant-platform/src/router/index.ts | 59 +++++++ tenant-platform/src/stores/auth.ts | 46 +++++ .../src/views/accounts/SubAccountView.vue | 157 ++++++++++++++++++ .../src/views/apps/AppDetailView.vue | 122 ++++++++++++++ .../src/views/apps/AppListView.vue | 102 ++++++++++++ .../src/views/auth/ForgotPasswordView.vue | 87 ++++++++++ tenant-platform/src/views/auth/LoginView.vue | 120 +++++++++++++ .../src/views/auth/RegisterView.vue | 119 +++++++++++++ .../src/views/dashboard/DashboardView.vue | 69 ++++++++ .../src/views/layout/MainLayout.vue | 109 ++++++++++++ tenant-platform/tsconfig.app.json | 12 ++ tenant-platform/tsconfig.json | 7 + tenant-platform/tsconfig.node.json | 7 + tenant-platform/vite.config.ts | 32 ++++ 41 files changed, 1679 insertions(+) create mode 100644 .gitignore create mode 100644 ops-platform/env.d.ts create mode 100644 ops-platform/index.html create mode 100644 ops-platform/package.json create mode 100644 ops-platform/src/App.vue create mode 100644 ops-platform/src/api/client.ts create mode 100644 ops-platform/src/api/ops.ts create mode 100644 ops-platform/src/main.ts create mode 100644 ops-platform/src/router/index.ts create mode 100644 ops-platform/src/views/auth/LoginView.vue create mode 100644 ops-platform/src/views/layout/MainLayout.vue create mode 100644 ops-platform/src/views/statistics/StatisticsView.vue create mode 100644 ops-platform/src/views/tenants/TenantListView.vue create mode 100644 ops-platform/tsconfig.app.json create mode 100644 ops-platform/tsconfig.json create mode 100644 ops-platform/tsconfig.node.json create mode 100644 ops-platform/vite.config.ts create mode 100644 package.json create mode 100644 tenant-platform/index.html create mode 100644 tenant-platform/package.json create mode 100644 tenant-platform/src/App.vue create mode 100644 tenant-platform/src/api/account.ts create mode 100644 tenant-platform/src/api/app.ts create mode 100644 tenant-platform/src/api/auth.ts create mode 100644 tenant-platform/src/api/client.ts create mode 100644 tenant-platform/src/env.d.ts create mode 100644 tenant-platform/src/main.ts create mode 100644 tenant-platform/src/router/index.ts create mode 100644 tenant-platform/src/stores/auth.ts create mode 100644 tenant-platform/src/views/accounts/SubAccountView.vue create mode 100644 tenant-platform/src/views/apps/AppDetailView.vue create mode 100644 tenant-platform/src/views/apps/AppListView.vue create mode 100644 tenant-platform/src/views/auth/ForgotPasswordView.vue create mode 100644 tenant-platform/src/views/auth/LoginView.vue create mode 100644 tenant-platform/src/views/auth/RegisterView.vue create mode 100644 tenant-platform/src/views/dashboard/DashboardView.vue create mode 100644 tenant-platform/src/views/layout/MainLayout.vue create mode 100644 tenant-platform/tsconfig.app.json create mode 100644 tenant-platform/tsconfig.json create mode 100644 tenant-platform/tsconfig.node.json create mode 100644 tenant-platform/vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..10dfc90 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +node_modules/ +dist/ +.DS_Store +*.class +target/ +build/ +.gradle/ +*.iml +.idea/ +*.log diff --git a/ops-platform/env.d.ts b/ops-platform/env.d.ts new file mode 100644 index 0000000..17aa348 --- /dev/null +++ b/ops-platform/env.d.ts @@ -0,0 +1,9 @@ +/// + +interface ImportMetaEnv { + readonly VITE_API_BASE_URL?: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} diff --git a/ops-platform/index.html b/ops-platform/index.html new file mode 100644 index 0000000..6a2b5d7 --- /dev/null +++ b/ops-platform/index.html @@ -0,0 +1,12 @@ + + + + + + XuqmGroup 运营平台 + + +
+ + + diff --git a/ops-platform/package.json b/ops-platform/package.json new file mode 100644 index 0000000..d7f940c --- /dev/null +++ b/ops-platform/package.json @@ -0,0 +1,27 @@ +{ + "name": "ops-platform", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite --port 5174", + "build": "vue-tsc -b && vite build", + "preview": "vite preview" + }, + "dependencies": { + "axios": "^1.7.9", + "element-plus": "^2.9.1", + "@element-plus/icons-vue": "^2.3.1", + "pinia": "^3.0.1", + "vue": "^3.5.13", + "vue-router": "^4.5.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.2.3", + "typescript": "^5.8.2", + "vite": "^6.2.2", + "vue-tsc": "^2.2.8", + "unplugin-auto-import": "^0.18.2", + "unplugin-vue-components": "^0.27.4" + } +} diff --git a/ops-platform/src/App.vue b/ops-platform/src/App.vue new file mode 100644 index 0000000..98240ae --- /dev/null +++ b/ops-platform/src/App.vue @@ -0,0 +1,3 @@ + diff --git a/ops-platform/src/api/client.ts b/ops-platform/src/api/client.ts new file mode 100644 index 0000000..91acb67 --- /dev/null +++ b/ops-platform/src/api/client.ts @@ -0,0 +1,24 @@ +import axios from 'axios' + +const client = axios.create({ + baseURL: import.meta.env.VITE_API_BASE_URL ?? '/api', +}) + +client.interceptors.request.use((config) => { + const token = localStorage.getItem('ops_token') + if (token) config.headers.Authorization = `Bearer ${token}` + return config +}) + +client.interceptors.response.use( + (res) => res, + (err) => { + if (err.response?.status === 401) { + localStorage.removeItem('ops_token') + window.location.href = '/login' + } + return Promise.reject(err) + } +) + +export default client diff --git a/ops-platform/src/api/ops.ts b/ops-platform/src/api/ops.ts new file mode 100644 index 0000000..ad35e4f --- /dev/null +++ b/ops-platform/src/api/ops.ts @@ -0,0 +1,37 @@ +import client from './client' + +export interface TenantItem { + id: string + username: string + nickname: string + email: string + phone?: string + type: 'MAIN' | 'SUB' + status: 'ACTIVE' | 'DISABLED' | 'PENDING_EMAIL' + parentId?: string + createdAt: string +} + +export interface TenantPage { + content: TenantItem[] + total: number + totalPages: number +} + +export interface Statistics { + totalTenants: number + todayNew: number + activeApps: number + onlineUsers: number +} + +export const opsApi = { + listTenants: (keyword = '', page = 0, size = 20) => + client.get<{ data: TenantPage }>('/ops/tenants', { params: { keyword, page, size } }), + + toggleStatus: (id: string) => + client.post(`/ops/tenants/${id}/toggle-status`), + + statistics: () => + client.get<{ data: Statistics }>('/ops/statistics'), +} diff --git a/ops-platform/src/main.ts b/ops-platform/src/main.ts new file mode 100644 index 0000000..562f76f --- /dev/null +++ b/ops-platform/src/main.ts @@ -0,0 +1,13 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import ElementPlus from 'element-plus' +import * as ElementPlusIconsVue from '@element-plus/icons-vue' +import 'element-plus/dist/index.css' +import App from './App.vue' +import router from './router' + +const app = createApp(App) +for (const [key, component] of Object.entries(ElementPlusIconsVue)) { + app.component(key, component) +} +app.use(createPinia()).use(router).use(ElementPlus).mount('#app') diff --git a/ops-platform/src/router/index.ts b/ops-platform/src/router/index.ts new file mode 100644 index 0000000..9b41266 --- /dev/null +++ b/ops-platform/src/router/index.ts @@ -0,0 +1,25 @@ +import { createRouter, createWebHistory } from 'vue-router' + +const router = createRouter({ + history: createWebHistory(), + routes: [ + { path: '/login', component: () => import('@/views/auth/LoginView.vue') }, + { + path: '/', + component: () => import('@/views/layout/MainLayout.vue'), + meta: { requiresAuth: true }, + children: [ + { path: '', redirect: '/tenants' }, + { path: 'tenants', component: () => import('@/views/tenants/TenantListView.vue') }, + { path: 'statistics', component: () => import('@/views/statistics/StatisticsView.vue') }, + ], + }, + ], +}) + +router.beforeEach((to) => { + const token = localStorage.getItem('ops_token') + if (to.meta.requiresAuth && !token) return '/login' +}) + +export default router diff --git a/ops-platform/src/views/auth/LoginView.vue b/ops-platform/src/views/auth/LoginView.vue new file mode 100644 index 0000000..e9365e5 --- /dev/null +++ b/ops-platform/src/views/auth/LoginView.vue @@ -0,0 +1,40 @@ + + + diff --git a/ops-platform/src/views/layout/MainLayout.vue b/ops-platform/src/views/layout/MainLayout.vue new file mode 100644 index 0000000..1275bb9 --- /dev/null +++ b/ops-platform/src/views/layout/MainLayout.vue @@ -0,0 +1,28 @@ + + + diff --git a/ops-platform/src/views/statistics/StatisticsView.vue b/ops-platform/src/views/statistics/StatisticsView.vue new file mode 100644 index 0000000..4f94de2 --- /dev/null +++ b/ops-platform/src/views/statistics/StatisticsView.vue @@ -0,0 +1,42 @@ + + + diff --git a/ops-platform/src/views/tenants/TenantListView.vue b/ops-platform/src/views/tenants/TenantListView.vue new file mode 100644 index 0000000..3f63a33 --- /dev/null +++ b/ops-platform/src/views/tenants/TenantListView.vue @@ -0,0 +1,79 @@ + + + diff --git a/ops-platform/tsconfig.app.json b/ops-platform/tsconfig.app.json new file mode 100644 index 0000000..6e90efc --- /dev/null +++ b/ops-platform/tsconfig.app.json @@ -0,0 +1,12 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/ops-platform/tsconfig.json b/ops-platform/tsconfig.json new file mode 100644 index 0000000..ba5ccc4 --- /dev/null +++ b/ops-platform/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.node.json" }, + { "path": "./tsconfig.app.json" } + ] +} diff --git a/ops-platform/tsconfig.node.json b/ops-platform/tsconfig.node.json new file mode 100644 index 0000000..61c4276 --- /dev/null +++ b/ops-platform/tsconfig.node.json @@ -0,0 +1,7 @@ +{ + "extends": "@tsconfig/node22/tsconfig.json", + "include": ["vite.config.*"], + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo" + } +} diff --git a/ops-platform/vite.config.ts b/ops-platform/vite.config.ts new file mode 100644 index 0000000..37aa493 --- /dev/null +++ b/ops-platform/vite.config.ts @@ -0,0 +1,23 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import AutoImport from 'unplugin-auto-import/vite' +import Components from 'unplugin-vue-components/vite' +import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' +import { fileURLToPath, URL } from 'node:url' + +export default defineConfig({ + plugins: [ + vue(), + AutoImport({ resolvers: [ElementPlusResolver()] }), + Components({ resolvers: [ElementPlusResolver()] }), + ], + resolve: { + alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) }, + }, + server: { + port: 5174, + proxy: { + '/api': { target: 'http://localhost:8081', changeOrigin: true }, + }, + }, +}) diff --git a/package.json b/package.json new file mode 100644 index 0000000..f4901bb --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "xuqmgroup-web", + "private": true, + "packageManager": "yarn@1.22.22", + "workspaces": [ + "tenant-platform", + "ops-platform" + ], + "scripts": { + "dev:tenant": "yarn workspace tenant-platform dev", + "dev:ops": "yarn workspace ops-platform dev", + "build": "yarn workspaces run build" + } +} diff --git a/tenant-platform/index.html b/tenant-platform/index.html new file mode 100644 index 0000000..f9ebe93 --- /dev/null +++ b/tenant-platform/index.html @@ -0,0 +1,13 @@ + + + + + + + XuqmGroup 开放平台 + + +
+ + + diff --git a/tenant-platform/package.json b/tenant-platform/package.json new file mode 100644 index 0000000..3f91c84 --- /dev/null +++ b/tenant-platform/package.json @@ -0,0 +1,27 @@ +{ + "name": "tenant-platform", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc -b && vite build", + "preview": "vite preview" + }, + "dependencies": { + "axios": "^1.7.9", + "element-plus": "^2.9.1", + "@element-plus/icons-vue": "^2.3.1", + "pinia": "^3.0.1", + "vue": "^3.5.13", + "vue-router": "^4.5.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.2.3", + "typescript": "^5.8.2", + "vite": "^6.2.2", + "vue-tsc": "^2.2.8", + "unplugin-auto-import": "^0.18.2", + "unplugin-vue-components": "^0.27.4" + } +} diff --git a/tenant-platform/src/App.vue b/tenant-platform/src/App.vue new file mode 100644 index 0000000..98240ae --- /dev/null +++ b/tenant-platform/src/App.vue @@ -0,0 +1,3 @@ + diff --git a/tenant-platform/src/api/account.ts b/tenant-platform/src/api/account.ts new file mode 100644 index 0000000..efea874 --- /dev/null +++ b/tenant-platform/src/api/account.ts @@ -0,0 +1,29 @@ +import client from './client' + +export interface SubAccount { + id: string + username: string + email: string + nickname: string + phone?: string + status: 'ACTIVE' | 'DISABLED' + createdAt: string +} + +export const accountApi = { + list: () => client.get<{ data: SubAccount[] }>('/sub-accounts'), + + sendVerifyCode: (email: string) => + client.post('/sub-accounts/send-verify-code', null, { params: { email } }), + + verifyEmail: (email: string, code: string) => + client.post('/sub-accounts/verify-email', null, { params: { email, code } }), + + create: (data: { username: string; password: string; email?: string; nickname: string; phone?: string }) => + client.post<{ data: SubAccount }>('/sub-accounts', data), + + disable: (id: string) => client.delete(`/sub-accounts/${id}`), + + generatePassword: () => + client.get<{ data: { password: string } }>('/sub-accounts/generate-password'), +} diff --git a/tenant-platform/src/api/app.ts b/tenant-platform/src/api/app.ts new file mode 100644 index 0000000..a21fff4 --- /dev/null +++ b/tenant-platform/src/api/app.ts @@ -0,0 +1,53 @@ +import client from './client' + +export interface App { + id: string + tenantId: string + packageName: string + name: string + description?: string + iconUrl?: string + appKey: string + appSecret: string + createdAt: string +} + +export interface CreateAppRequest { + packageName: string + name: string + description?: string + iconUrl?: string +} + +export interface FeatureService { + id: string + appId: string + platform: 'ANDROID' | 'IOS' | 'HARMONY' + serviceType: 'IM' | 'PUSH' | 'UPDATE' + enabled: boolean + secretKey: string + createdAt: string +} + +export const appApi = { + list: () => client.get<{ data: App[] }>('/apps'), + + get: (id: string) => client.get<{ data: App }>(`/apps/${id}`), + + create: (data: CreateAppRequest) => client.post<{ data: App }>('/apps', data), + + update: (id: string, data: CreateAppRequest) => client.put<{ data: App }>(`/apps/${id}`, data), + + delete: (id: string) => client.delete(`/apps/${id}`), + + getServices: (appId: string) => + client.get<{ data: FeatureService[] }>(`/apps/${appId}/services`), + + toggleService: (appId: string, platform: string, serviceType: string, enable: boolean) => + client.post<{ data: FeatureService }>(`/apps/${appId}/services/toggle`, null, { + params: { platform, serviceType, enable }, + }), + + regenerateKey: (appId: string, serviceId: string) => + client.post<{ data: FeatureService }>(`/apps/${appId}/services/${serviceId}/regenerate-key`), +} diff --git a/tenant-platform/src/api/auth.ts b/tenant-platform/src/api/auth.ts new file mode 100644 index 0000000..cf5a5e4 --- /dev/null +++ b/tenant-platform/src/api/auth.ts @@ -0,0 +1,35 @@ +import client from './client' + +export interface LoginRequest { + account: string + password: string + captchaKey: string + captchaCode: string +} + +export interface RegisterRequest { + username: string + password: string + email: string + nickname: string + phone?: string + emailCode: string +} + +export const authApi = { + getCaptcha: () => client.get<{ data: { key: string; image: string } }>('/auth/captcha'), + + sendEmailCode: (email: string, purpose: string) => + client.post('/auth/send-email-code', null, { params: { email, purpose } }), + + register: (data: RegisterRequest) => client.post('/auth/register', data), + + login: (data: LoginRequest) => + client.post<{ data: { token: string } }>('/auth/login', data), + + forgotPassword: (email: string) => + client.post('/auth/forgot-password', null, { params: { email } }), + + resetPassword: (email: string, code: string, newPassword: string) => + client.post('/auth/reset-password', null, { params: { email, code, newPassword } }), +} diff --git a/tenant-platform/src/api/client.ts b/tenant-platform/src/api/client.ts new file mode 100644 index 0000000..798bdc1 --- /dev/null +++ b/tenant-platform/src/api/client.ts @@ -0,0 +1,32 @@ +import axios from 'axios' +import { ElMessage } from 'element-plus' +import router from '@/router' + +const client = axios.create({ + baseURL: import.meta.env.VITE_API_BASE_URL ?? '/api', + timeout: 15000, +}) + +client.interceptors.request.use((config) => { + const token = localStorage.getItem('token') + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + return config +}) + +client.interceptors.response.use( + (res) => res, + (error) => { + if (error.response?.status === 401) { + localStorage.removeItem('token') + router.push('/login') + } else { + const msg = error.response?.data?.message ?? '请求失败' + ElMessage.error(msg) + } + return Promise.reject(error) + }, +) + +export default client diff --git a/tenant-platform/src/env.d.ts b/tenant-platform/src/env.d.ts new file mode 100644 index 0000000..8ab4f00 --- /dev/null +++ b/tenant-platform/src/env.d.ts @@ -0,0 +1,9 @@ +/// + +interface ImportMetaEnv { + readonly VITE_API_BASE_URL: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} diff --git a/tenant-platform/src/main.ts b/tenant-platform/src/main.ts new file mode 100644 index 0000000..1d3619a --- /dev/null +++ b/tenant-platform/src/main.ts @@ -0,0 +1,18 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import ElementPlus from 'element-plus' +import * as ElementPlusIconsVue from '@element-plus/icons-vue' +import 'element-plus/dist/index.css' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +for (const [key, component] of Object.entries(ElementPlusIconsVue)) { + app.component(key, component) +} + +app.use(createPinia()) +app.use(router) +app.use(ElementPlus) +app.mount('#app') diff --git a/tenant-platform/src/router/index.ts b/tenant-platform/src/router/index.ts new file mode 100644 index 0000000..9f43276 --- /dev/null +++ b/tenant-platform/src/router/index.ts @@ -0,0 +1,59 @@ +import { createRouter, createWebHistory } from 'vue-router' +import { useAuthStore } from '@/stores/auth' + +const router = createRouter({ + history: createWebHistory(), + routes: [ + { + path: '/login', + component: () => import('@/views/auth/LoginView.vue'), + }, + { + path: '/register', + component: () => import('@/views/auth/RegisterView.vue'), + }, + { + path: '/forgot-password', + component: () => import('@/views/auth/ForgotPasswordView.vue'), + }, + { + path: '/', + component: () => import('@/views/layout/MainLayout.vue'), + meta: { requiresAuth: true }, + children: [ + { + path: '', + redirect: '/dashboard', + }, + { + path: 'dashboard', + component: () => import('@/views/dashboard/DashboardView.vue'), + }, + { + path: 'apps', + component: () => import('@/views/apps/AppListView.vue'), + }, + { + path: 'apps/:id', + component: () => import('@/views/apps/AppDetailView.vue'), + }, + { + path: 'accounts', + component: () => import('@/views/accounts/SubAccountView.vue'), + }, + ], + }, + ], +}) + +router.beforeEach((to) => { + const auth = useAuthStore() + if (to.meta.requiresAuth && !auth.token) { + return '/login' + } + if ((to.path === '/login' || to.path === '/register') && auth.token) { + return '/dashboard' + } +}) + +export default router diff --git a/tenant-platform/src/stores/auth.ts b/tenant-platform/src/stores/auth.ts new file mode 100644 index 0000000..9136dcf --- /dev/null +++ b/tenant-platform/src/stores/auth.ts @@ -0,0 +1,46 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' + +export interface UserInfo { + id: string + username: string + nickname: string + type: 'MAIN' | 'SUB' +} + +export const useAuthStore = defineStore('auth', () => { + const token = ref(localStorage.getItem('token')) + const user = ref(null) + + function setToken(t: string) { + token.value = t + localStorage.setItem('token', t) + parseUser(t) + } + + function parseUser(t: string) { + try { + const payload = JSON.parse(atob(t.split('.')[1])) + user.value = { + id: payload.sub, + username: payload.username, + nickname: payload.nickname, + type: payload.type, + } + } catch { + user.value = null + } + } + + function logout() { + token.value = null + user.value = null + localStorage.removeItem('token') + } + + if (token.value) { + parseUser(token.value) + } + + return { token, user, setToken, logout } +}) diff --git a/tenant-platform/src/views/accounts/SubAccountView.vue b/tenant-platform/src/views/accounts/SubAccountView.vue new file mode 100644 index 0000000..06d6761 --- /dev/null +++ b/tenant-platform/src/views/accounts/SubAccountView.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/tenant-platform/src/views/apps/AppDetailView.vue b/tenant-platform/src/views/apps/AppDetailView.vue new file mode 100644 index 0000000..a6e1398 --- /dev/null +++ b/tenant-platform/src/views/apps/AppDetailView.vue @@ -0,0 +1,122 @@ + + + + + diff --git a/tenant-platform/src/views/apps/AppListView.vue b/tenant-platform/src/views/apps/AppListView.vue new file mode 100644 index 0000000..a1db724 --- /dev/null +++ b/tenant-platform/src/views/apps/AppListView.vue @@ -0,0 +1,102 @@ + + + + + diff --git a/tenant-platform/src/views/auth/ForgotPasswordView.vue b/tenant-platform/src/views/auth/ForgotPasswordView.vue new file mode 100644 index 0000000..93c4411 --- /dev/null +++ b/tenant-platform/src/views/auth/ForgotPasswordView.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/tenant-platform/src/views/auth/LoginView.vue b/tenant-platform/src/views/auth/LoginView.vue new file mode 100644 index 0000000..a1bffb6 --- /dev/null +++ b/tenant-platform/src/views/auth/LoginView.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/tenant-platform/src/views/auth/RegisterView.vue b/tenant-platform/src/views/auth/RegisterView.vue new file mode 100644 index 0000000..8526e7b --- /dev/null +++ b/tenant-platform/src/views/auth/RegisterView.vue @@ -0,0 +1,119 @@ + + + + + diff --git a/tenant-platform/src/views/dashboard/DashboardView.vue b/tenant-platform/src/views/dashboard/DashboardView.vue new file mode 100644 index 0000000..5d92c67 --- /dev/null +++ b/tenant-platform/src/views/dashboard/DashboardView.vue @@ -0,0 +1,69 @@ + + + diff --git a/tenant-platform/src/views/layout/MainLayout.vue b/tenant-platform/src/views/layout/MainLayout.vue new file mode 100644 index 0000000..ec9d20c --- /dev/null +++ b/tenant-platform/src/views/layout/MainLayout.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/tenant-platform/tsconfig.app.json b/tenant-platform/tsconfig.app.json new file mode 100644 index 0000000..6e90efc --- /dev/null +++ b/tenant-platform/tsconfig.app.json @@ -0,0 +1,12 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/tenant-platform/tsconfig.json b/tenant-platform/tsconfig.json new file mode 100644 index 0000000..ba5ccc4 --- /dev/null +++ b/tenant-platform/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.node.json" }, + { "path": "./tsconfig.app.json" } + ] +} diff --git a/tenant-platform/tsconfig.node.json b/tenant-platform/tsconfig.node.json new file mode 100644 index 0000000..61c4276 --- /dev/null +++ b/tenant-platform/tsconfig.node.json @@ -0,0 +1,7 @@ +{ + "extends": "@tsconfig/node22/tsconfig.json", + "include": ["vite.config.*"], + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo" + } +} diff --git a/tenant-platform/vite.config.ts b/tenant-platform/vite.config.ts new file mode 100644 index 0000000..447ac3b --- /dev/null +++ b/tenant-platform/vite.config.ts @@ -0,0 +1,32 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import AutoImport from 'unplugin-auto-import/vite' +import Components from 'unplugin-vue-components/vite' +import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' +import { fileURLToPath, URL } from 'node:url' + +export default defineConfig({ + plugins: [ + vue(), + AutoImport({ + resolvers: [ElementPlusResolver()], + }), + Components({ + resolvers: [ElementPlusResolver()], + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + }, + }, + server: { + port: 5173, + proxy: { + '/api': { + target: 'http://localhost:8081', + changeOrigin: true, + }, + }, + }, +})