From cfef51c6d13a6064e75aa6df63682d9d1127f23d Mon Sep 17 00:00:00 2001
From: yumaojun03 <719118794@qq.com>
Date: Sun, 3 Aug 2025 17:29:14 +0800
Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E7=99=BB=E5=BD=95=E8=B7=B3?=
=?UTF-8?q?=E8=BD=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
devcloud/audit/audit/sender.go | 60 ++---
devcloud/mcenter/permission/checker.go | 45 ++--
devcloud/web/docs/README.md | 186 ++++++++++++++
devcloud/web/package-lock.json | 325 +++++++++++++++++++++++++
devcloud/web/package.json | 2 +
devcloud/web/src/api/README.md | 1 +
devcloud/web/src/api/client.js | 31 +++
devcloud/web/src/api/mcenter.js | 9 +
devcloud/web/src/pages/LoginPage.vue | 52 +++-
devcloud/web/src/router/index.js | 4 +-
devcloud/web/src/storage/app.js | 0
devcloud/web/src/storage/token.js | 3 +
devcloud/web/vite.config.js | 12 +-
13 files changed, 663 insertions(+), 67 deletions(-)
create mode 100644 devcloud/web/src/api/README.md
create mode 100644 devcloud/web/src/api/client.js
create mode 100644 devcloud/web/src/api/mcenter.js
create mode 100644 devcloud/web/src/storage/app.js
create mode 100644 devcloud/web/src/storage/token.js
diff --git a/devcloud/audit/audit/sender.go b/devcloud/audit/audit/sender.go
index 19eb689..0a45215 100644
--- a/devcloud/audit/audit/sender.go
+++ b/devcloud/audit/audit/sender.go
@@ -14,41 +14,43 @@ import (
func (a *EventSender) SendEvent() restful.FilterFunction {
return func(req *restful.Request, resp *restful.Response, fc *restful.FilterChain) {
sr := req.SelectedRoute()
- md := NewMetaData(sr.Metadata())
+ if sr != nil {
+ md := NewMetaData(sr.Metadata())
- // 开关打开,则开启审计
- if md.GetBool(META_AUDIT_KEY) {
+ // 开关打开,则开启审计
+ if md.GetBool(META_AUDIT_KEY) {
- // 获取当前是否需要审计
- e := event.NewEvent()
+ // 获取当前是否需要审计
+ e := event.NewEvent()
- // 用户信息
- tk := token.GetTokenFromCtx(req.Request.Context())
- if tk != nil {
- e.Who = tk.UserName
- e.Namespace = tk.NamespaceName
- }
+ // 用户信息
+ tk := token.GetTokenFromCtx(req.Request.Context())
+ if tk != nil {
+ e.Who = tk.UserName
+ e.Namespace = tk.NamespaceName
+ }
- // ioc 里面获取当前应用的名称
- e.Service = application.Get().AppName
- e.ResourceType = md.GetString(endpoint.META_RESOURCE_KEY)
- e.Action = md.GetString(endpoint.META_ACTION_KEY)
+ // ioc 里面获取当前应用的名称
+ e.Service = application.Get().AppName
+ e.ResourceType = md.GetString(endpoint.META_RESOURCE_KEY)
+ e.Action = md.GetString(endpoint.META_ACTION_KEY)
- // {id} /:id
- e.ResourceId = req.PathParameter("id")
- e.UserAgent = req.Request.UserAgent()
- e.Extras["method"] = sr.Method()
- e.Extras["path"] = sr.Path()
- e.Extras["operation"] = sr.Operation()
+ // {id} /:id
+ e.ResourceId = req.PathParameter("id")
+ e.UserAgent = req.Request.UserAgent()
+ e.Extras["method"] = sr.Method()
+ e.Extras["path"] = sr.Path()
+ e.Extras["operation"] = sr.Operation()
- // 补充处理后的数据
- e.StatusCode = resp.StatusCode()
- // 发送给topic, 使用这个中间件的使用者,需要配置kafka
- err := a.wirter.WriteMessages(context.Background(), e.ToKafkaMessage())
- if err != nil {
- a.log.Error().Msgf("send message error, %s", err)
- } else {
- a.log.Debug().Msgf("send audit event ok, who: %s, resource: %s, action: %s", e.Who, e.ResourceType, e.Action)
+ // 补充处理后的数据
+ e.StatusCode = resp.StatusCode()
+ // 发送给topic, 使用这个中间件的使用者,需要配置kafka
+ err := a.wirter.WriteMessages(context.Background(), e.ToKafkaMessage())
+ if err != nil {
+ a.log.Error().Msgf("send message error, %s", err)
+ } else {
+ a.log.Debug().Msgf("send audit event ok, who: %s, resource: %s, action: %s", e.Who, e.ResourceType, e.Action)
+ }
}
}
diff --git a/devcloud/mcenter/permission/checker.go b/devcloud/mcenter/permission/checker.go
index 1d6c63a..9bd3180 100644
--- a/devcloud/mcenter/permission/checker.go
+++ b/devcloud/mcenter/permission/checker.go
@@ -78,28 +78,31 @@ func (c *Checker) Check(r *restful.Request, w *restful.Response, next *restful.F
// 1. 知道用户当前访问的是哪个接口, 当前url 匹配到的路由是哪个
// SelectedRoute, 它可以返回当前URL适配哪个路有, RouteReader
// 封装了一个函数 来获取Meta信息 NewEntryFromRestRouteReader
- route := endpoint.NewEntryFromRestRouteReader(r.SelectedRoute())
- if route.RequiredAuth {
- // 校验身份
- tk, err := c.CheckToken(r)
- if err != nil {
- response.Failed(w, err)
- return
+ sr := r.SelectedRoute()
+ if sr != nil {
+ route := endpoint.NewEntryFromRestRouteReader(sr)
+ if route.RequiredAuth {
+ // 校验身份
+ tk, err := c.CheckToken(r)
+ if err != nil {
+ response.Failed(w, err)
+ return
+ }
+
+ // 校验权限
+ if err := c.CheckPolicy(r, tk, route); err != nil {
+ response.Failed(w, err)
+ return
+ }
+
+ // 如果校验成功,需要把 用户的身份信息,放到请求的上下文中,方便后面的逻辑获取
+ // context.WithValue 来往ctx 添加 value
+ // key: value, value token对象
+ ctx := context.WithValue(r.Request.Context(), token.CTX_TOKEN_KEY, tk)
+
+ // ctx 生成一个新的,继续往下传递
+ r.Request = r.Request.WithContext(ctx)
}
-
- // 校验权限
- if err := c.CheckPolicy(r, tk, route); err != nil {
- response.Failed(w, err)
- return
- }
-
- // 如果校验成功,需要把 用户的身份信息,放到请求的上下文中,方便后面的逻辑获取
- // context.WithValue 来往ctx 添加 value
- // key: value, value token对象
- ctx := context.WithValue(r.Request.Context(), token.CTX_TOKEN_KEY, tk)
-
- // ctx 生成一个新的,继续往下传递
- r.Request = r.Request.WithContext(ctx)
}
// 请求处理
diff --git a/devcloud/web/docs/README.md b/devcloud/web/docs/README.md
index b5e7e3e..1da68cc 100644
--- a/devcloud/web/docs/README.md
+++ b/devcloud/web/docs/README.md
@@ -22,10 +22,196 @@ import '@arco-design/web-vue/dist/arco.css'
app.use(ArcoVue)
```
+## ajax
+
+如何将表单数据 提交给服务器, 封装的比较友好的js的http客户端, [axios](https://axios-http.com/docs/intro)
+
+```sh
+import axios from 'axios'
+
+// 封装一个axios的实例,http cient实例
+// https://axios-http.com/zh/docs/instance
+const client = axios.create({
+ baseURL: 'http://127.0.0.1:8080',
+ timeout: 3000,
+})
+
+export default client
+```
+
+基于客户端封装的mcenter client
+
+```sh
+import client from './client'
+
+var API = {
+ Login: (data) => {
+ return client.post('/api/devcloud/v1/token', data)
+ },
+}
+
+export default API
+```
+
+## 配置vite代理开发
+
+```js
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [vue(), vueDevTools()],
+ resolve: {
+ alias: {
+ '@': fileURLToPath(new URL('./src', import.meta.url)),
+ },
+ },
+ server: {
+ proxy: {
+ '/api': 'http://127.0.0.1:8080',
+ },
+ },
+})
+```
+
+去掉baseURL,应用使用代理
+
+```js
+// 封装一个axios的实例,http cient实例
+// https://axios-http.com/zh/docs/instance
+const client = axios.create({
+ timeout: 3000,
+})
+```
+
+## 统一处理 API的 异常
+
+设置axios的中间件, 统一识别并处理报错
+
+```js
+// 拦截API的返回结果, 如果是异常 提取异常信息,并展示
+// 如果正常 则直接返回 API的响应结果
+// https://axios-http.com/zh/docs/interceptors
+client.interceptors.response.use(
+ (data) => {
+ return data.data
+ },
+ (error) => {
+ // 提取错误
+ var msg = error.message
+
+ // 如果有更加详细的信息
+ if (error.response.data.message) {
+ msg = error.response.data.message
+ }
+
+ Message.error(msg)
+ return error
+ },
+)
+```
+
## 登陆页面

+1. UI
+
+```vue
+
+
+
+
+
+
欢迎登录
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 记住
+
+
+ 登录
+
+
+
+
+
+```
+
+2. 对接
+
+```js
+// 表单的提交
+const handleSubmit = async (data) => {
+ // 判断表单是否验证成功
+ if (data.errors == null) {
+ // 通过HttpClient把数据提交给后端
+ const resp = await mcenter.Login(data.values)
+ console.log(resp)
+ }
+}
+```
+
+3. 状态处理(useStorage)
+
+```sh
+npm i @vueuse/core
+```
+
+```sh
+import { useStorage } from '@vueuse/core'
+
+export default useStorage('token', {}, localStorage, { mergeDefaults: true })
+```
+
+```js
+// 表单的提交
+const handleSubmit = async (data) => {
+ // 判断表单是否验证成功
+ if (data.errors == null) {
+ // 通过HttpClient把数据提交给后端
+ const resp = await mcenter.Login(data.values)
+ // 用户登录后,这些用户信息我们怎么保存喃 1. cookie, session storage, localstorage
+ // localStorage.setItem('token', JSON.stringify(resp))
+ // localStorage.getItem('token')
+ // 把 localStorage 做成响应式的
+ // https://cn.vuejs.org/guide/reusability/composables.html
+ token.value = resp
+ }
+}
+```
+
+4. 登录成功后进行跳转
+
+```js
+// 登录完成后,需要跳转到后台页面
+// location.assign('/users/eduardo')
+// vue router对象, 提供路由跳转的功能
+// 字符串路径
+// router.push('/users/eduardo')
+// 指定到组件名称
+router.push({ name: 'HomePage' })
+```
+
## Layout(多套子系统)
## 具体子页面
diff --git a/devcloud/web/package-lock.json b/devcloud/web/package-lock.json
index 5acad3f..021aa31 100644
--- a/devcloud/web/package-lock.json
+++ b/devcloud/web/package-lock.json
@@ -8,6 +8,8 @@
"name": "web",
"version": "0.0.0",
"dependencies": {
+ "@vueuse/core": "^13.6.0",
+ "axios": "^1.11.0",
"vue": "^3.5.18",
"vue-router": "^4.5.1"
},
@@ -1598,6 +1600,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/web-bluetooth": {
+ "version": "0.0.21",
+ "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
+ "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
+ "license": "MIT"
+ },
"node_modules/@vitejs/plugin-vue": {
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz",
@@ -1852,6 +1860,44 @@
"integrity": "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA==",
"license": "MIT"
},
+ "node_modules/@vueuse/core": {
+ "version": "13.6.0",
+ "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-13.6.0.tgz",
+ "integrity": "sha512-DJbD5fV86muVmBgS9QQPddVX7d9hWYswzlf4bIyUD2dj8GC46R1uNClZhVAmsdVts4xb2jwp1PbpuiA50Qee1A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/web-bluetooth": "^0.0.21",
+ "@vueuse/metadata": "13.6.0",
+ "@vueuse/shared": "13.6.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "vue": "^3.5.0"
+ }
+ },
+ "node_modules/@vueuse/metadata": {
+ "version": "13.6.0",
+ "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-13.6.0.tgz",
+ "integrity": "sha512-rnIH7JvU7NjrpexTsl2Iwv0V0yAx9cw7+clymjKuLSXG0QMcLD0LDgdNmXic+qL0SGvgSVPEpM9IDO/wqo1vkQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/shared": {
+ "version": "13.6.0",
+ "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-13.6.0.tgz",
+ "integrity": "sha512-pDykCSoS2T3fsQrYqf9SyF0QXWHmcGPQ+qiOVjlYSzlWd9dgppB2bFSM1GgKKkt7uzn0BBMV3IbJsUfHG2+BCg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "vue": "^3.5.0"
+ }
+ },
"node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz",
@@ -1925,6 +1971,23 @@
"dev": true,
"license": "Python-2.0"
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/axios": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmmirror.com/axios/-/axios-1.11.0.tgz",
+ "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.4",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/b-tween": {
"version": "0.3.3",
"resolved": "https://registry.npmmirror.com/b-tween/-/b-tween-0.3.3.tgz",
@@ -2023,6 +2086,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz",
@@ -2130,6 +2206,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/compute-scroll-into-view": {
"version": "1.0.20",
"resolved": "https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz",
@@ -2276,6 +2364,29 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/electron-to-chromium": {
"version": "1.5.194",
"resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.194.tgz",
@@ -2305,6 +2416,51 @@
"url": "https://github.com/sponsors/antfu"
}
},
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/esbuild": {
"version": "0.25.8",
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.8.tgz",
@@ -2743,6 +2899,42 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.11",
+ "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.4.tgz",
+ "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
@@ -2758,6 +2950,15 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -2768,6 +2969,43 @@
"node": ">=6.9.0"
}
},
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/get-stream": {
"version": "9.0.1",
"resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-9.0.1.tgz",
@@ -2811,6 +3049,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
@@ -2821,6 +3071,45 @@
"node": ">=8"
}
},
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/hookable": {
"version": "5.5.3",
"resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
@@ -3155,6 +3444,36 @@
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
@@ -3526,6 +3845,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
diff --git a/devcloud/web/package.json b/devcloud/web/package.json
index ccd99cd..6158d8a 100644
--- a/devcloud/web/package.json
+++ b/devcloud/web/package.json
@@ -14,6 +14,8 @@
"format": "prettier --write src/"
},
"dependencies": {
+ "@vueuse/core": "^13.6.0",
+ "axios": "^1.11.0",
"vue": "^3.5.18",
"vue-router": "^4.5.1"
},
diff --git a/devcloud/web/src/api/README.md b/devcloud/web/src/api/README.md
new file mode 100644
index 0000000..8293660
--- /dev/null
+++ b/devcloud/web/src/api/README.md
@@ -0,0 +1 @@
+# 存放所有后端的API调用封装
diff --git a/devcloud/web/src/api/client.js b/devcloud/web/src/api/client.js
new file mode 100644
index 0000000..af2fe5d
--- /dev/null
+++ b/devcloud/web/src/api/client.js
@@ -0,0 +1,31 @@
+import axios from 'axios'
+import { Message } from '@arco-design/web-vue'
+
+// 封装一个axios的实例,http cient实例
+// https://axios-http.com/zh/docs/instance
+const client = axios.create({
+ timeout: 3000,
+})
+
+// 拦截API的返回结果, 如果是异常 提取异常信息,并展示
+// 如果正常 则直接返回 API的响应结果
+// https://axios-http.com/zh/docs/interceptors
+client.interceptors.response.use(
+ (data) => {
+ return data.data
+ },
+ (error) => {
+ // 提取错误
+ var msg = error.message
+
+ // 如果有更加详细的信息
+ if (error.response.data.message) {
+ msg = error.response.data.message
+ }
+
+ Message.error(msg)
+ return error
+ },
+)
+
+export default client
diff --git a/devcloud/web/src/api/mcenter.js b/devcloud/web/src/api/mcenter.js
new file mode 100644
index 0000000..b97ee2a
--- /dev/null
+++ b/devcloud/web/src/api/mcenter.js
@@ -0,0 +1,9 @@
+import client from './client'
+
+var API = {
+ Login: (data) => {
+ return client.post('/api/devcloud/v1/token', data)
+ },
+}
+
+export default API
diff --git a/devcloud/web/src/pages/LoginPage.vue b/devcloud/web/src/pages/LoginPage.vue
index 0030004..1a68787 100644
--- a/devcloud/web/src/pages/LoginPage.vue
+++ b/devcloud/web/src/pages/LoginPage.vue
@@ -6,16 +6,21 @@
欢迎登录
-
-
+
+
-
-
+
+
@@ -34,18 +39,45 @@
diff --git a/devcloud/web/src/router/index.js b/devcloud/web/src/router/index.js
index eb728be..8fa7843 100644
--- a/devcloud/web/src/router/index.js
+++ b/devcloud/web/src/router/index.js
@@ -7,12 +7,12 @@ const router = createRouter({
routes: [
{
path: '/',
- name: 'home',
+ name: 'HomePage',
component: HomePage,
},
{
path: '/login',
- name: 'login',
+ name: 'LoginPage',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
diff --git a/devcloud/web/src/storage/app.js b/devcloud/web/src/storage/app.js
new file mode 100644
index 0000000..e69de29
diff --git a/devcloud/web/src/storage/token.js b/devcloud/web/src/storage/token.js
new file mode 100644
index 0000000..5c54647
--- /dev/null
+++ b/devcloud/web/src/storage/token.js
@@ -0,0 +1,3 @@
+import { useStorage } from '@vueuse/core'
+
+export default useStorage('token', {}, localStorage, { mergeDefaults: true })
diff --git a/devcloud/web/vite.config.js b/devcloud/web/vite.config.js
index 4217010..4641b76 100644
--- a/devcloud/web/vite.config.js
+++ b/devcloud/web/vite.config.js
@@ -6,13 +6,15 @@ import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
- plugins: [
- vue(),
- vueDevTools(),
- ],
+ plugins: [vue(), vueDevTools()],
resolve: {
alias: {
- '@': fileURLToPath(new URL('./src', import.meta.url))
+ '@': fileURLToPath(new URL('./src', import.meta.url)),
+ },
+ },
+ server: {
+ proxy: {
+ '/api': 'http://127.0.0.1:8080',
},
},
})