Commit 684caa69 authored by 水玉婷's avatar 水玉婷
Browse files

feat:打通用户信息

parent 219e9ed3
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"@ant-design/icons-vue": "^6.1.0", "@ant-design/icons-vue": "^6.1.0",
"ant-design-vue": "^3.2.0", "ant-design-vue": "^3.2.0",
"axios": "^1.13.2",
"dayjs": "^1.11.0", "dayjs": "^1.11.0",
"echarts": "^6.0.0", "echarts": "^6.0.0",
"event-source-polyfill": "^1.0.31", "event-source-polyfill": "^1.0.31",
...@@ -671,6 +672,48 @@ ...@@ -671,6 +672,48 @@
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/axios": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.4",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/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/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/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": { "node_modules/compute-scroll-into-view": {
"version": "1.0.20", "version": "1.0.20",
"resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz",
...@@ -713,6 +756,15 @@ ...@@ -713,6 +756,15 @@
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/dom-align": { "node_modules/dom-align": {
"version": "1.12.4", "version": "1.12.4",
"resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz", "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz",
...@@ -725,6 +777,20 @@ ...@@ -725,6 +777,20 @@
"integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==", "integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/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/echarts": { "node_modules/echarts": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/echarts/-/echarts-6.0.0.tgz", "resolved": "https://registry.npmjs.org/echarts/-/echarts-6.0.0.tgz",
...@@ -761,6 +827,51 @@ ...@@ -761,6 +827,51 @@
"errno": "cli.js" "errno": "cli.js"
} }
}, },
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/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.npmjs.org/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.npmjs.org/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.npmjs.org/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": { "node_modules/esbuild": {
"version": "0.18.20", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
...@@ -811,6 +922,42 @@ ...@@ -811,6 +922,42 @@
"integrity": "sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA==", "integrity": "sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/follow-redirects": {
"version": "1.15.11",
"resolved": "https://registry.npmjs.org/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.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"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": { "node_modules/fsevents": {
"version": "2.3.3", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
...@@ -826,6 +973,64 @@ ...@@ -826,6 +973,64 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0" "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
} }
}, },
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/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.npmjs.org/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/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/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/graceful-fs": { "node_modules/graceful-fs": {
"version": "4.2.11", "version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
...@@ -834,6 +1039,45 @@ ...@@ -834,6 +1039,45 @@
"license": "ISC", "license": "ISC",
"optional": true "optional": true
}, },
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/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.npmjs.org/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.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/iconv-lite": { "node_modules/iconv-lite": {
"version": "0.6.3", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
...@@ -959,6 +1203,15 @@ ...@@ -959,6 +1203,15 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/mime": { "node_modules/mime": {
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
...@@ -973,6 +1226,27 @@ ...@@ -973,6 +1226,27 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/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.npmjs.org/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/nanoid": { "node_modules/nanoid": {
"version": "3.3.11", "version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
...@@ -1070,6 +1344,12 @@ ...@@ -1070,6 +1344,12 @@
"node": "^10 || ^12 || >=14" "node": "^10 || ^12 || >=14"
} }
}, },
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/prr": { "node_modules/prr": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
......
...@@ -9,17 +9,18 @@ ...@@ -9,17 +9,18 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"vue": "^3.3.0",
"vue-router": "^4.2.0",
"@ant-design/icons-vue": "^6.1.0", "@ant-design/icons-vue": "^6.1.0",
"echarts": "^6.0.0",
"ant-design-vue": "^3.2.0", "ant-design-vue": "^3.2.0",
"axios": "^1.13.2",
"dayjs": "^1.11.0", "dayjs": "^1.11.0",
"event-source-polyfill": "^1.0.31" "echarts": "^6.0.0",
"event-source-polyfill": "^1.0.31",
"vue": "^3.3.0",
"vue-router": "^4.2.0"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^4.2.0", "@vitejs/plugin-vue": "^4.2.0",
"vite": "^4.3.0", "less": "^4.4.2",
"less": "^4.4.2" "vite": "^4.3.0"
} }
} }
\ No newline at end of file
import { createApp } from 'vue' import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
import { setRouter } from './utils/router-manager'
const app = createApp(App) const app = createApp(App)
app.use(router) app.use(router)
// 设置全局路由实例
setRouter(router)
app.mount('#app') app.mount('#app')
\ No newline at end of file
import { createRouter, createWebHistory } from 'vue-router' import { createRouter, createWebHashHistory } from 'vue-router' // 改为Hash模式
import wechat from '../utils/wechat' import wechat from '../utils/wechat'
const routes = [ const routes = [
...@@ -20,7 +20,7 @@ const routes = [ ...@@ -20,7 +20,7 @@ const routes = [
] ]
const router = createRouter({ const router = createRouter({
history: createWebHistory('/ai/'), // 添加基础路径 history: createWebHashHistory('/ai/'), // 使用Hash模式
routes routes
}) })
......
import axios from 'axios'
// 创建axios实例
const instance = axios.create({
baseURL: '/',
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
})
// 请求拦截器 - 添加认证信息
instance.interceptors.request.use(
(config) => {
// 从localStorage获取用户信息
const userData = localStorage.getItem('wechat_user')
const { extMap = {} } = JSON.parse(userData || '{}')
const userToken = extMap.sessionId;
if (userToken) {
try {
config.headers['x-session-id'] = userToken || ''
} catch (error) {
console.warn('解析用户信息失败', error)
}
}
return config
},
(error) => {
return Promise.reject(error)
}
)
import { navigateToLogin } from './router-manager'
// 响应拦截器 - 处理401错误
instance.interceptors.response.use(
(response) => {
return response
},
(error) => {
if (error.response) {
const { status } = error.response
// 处理401未授权错误
if (status === 401) {
// 清除本地存储的用户信息
localStorage.removeItem('wechat_user')
// 使用全局路由管理器跳转
navigateToLogin()
return Promise.reject(new Error('未授权访问,请重新登录'))
}
// 其他错误处理
console.error(`请求失败: ${status}`, error.response.data)
} else if (error.request) {
console.error('网络错误,请求未发送成功', error)
} else {
console.error('请求配置错误', error.message)
}
return Promise.reject(error)
}
)
// 导出get和post方法
export const get = (url, config = {}) => instance.get(url, config)
export const post = (url, data = {}, config = {}) => instance.post(url, data, config)
// 导出实例(可选)
export default instance
\ No newline at end of file
// 全局路由管理器
let routerInstance = null
export const setRouter = (router) => {
routerInstance = router
}
export const getRouter = () => {
return routerInstance
}
export const navigateToLogin = () => {
if (routerInstance) {
routerInstance.push('/login')
} else {
// 备用方案:使用hash跳转
if (window.location.hash) {
window.location.hash = '/login'
} else {
window.location.pathname = '/login'
}
}
}
\ No newline at end of file
// 简化的微信静默登录工具类 // 引入axios
import { post } from './axios.js'
// 企业微信登录工具类 - 简化版本(直接从URL获取code)
class WeChatLogin { class WeChatLogin {
constructor() { constructor() {
this.appId = 'YOUR_WECHAT_APPID' // 替换为你的微信公众号AppID this.corpId = 'ww88c20288b24a8e33' // 企业微信CorpID
this.isWeChat = this.checkWeChatBrowser() this.agentId = '1000002' // 应用AgentId
this.isConfigured = this.appId !== 'YOUR_WECHAT_APPID'
} }
// 检查是否为微信浏览器 // 检查是否为企业微信浏览器
checkWeChatBrowser() { checkWeChatWorkBrowser() {
const ua = navigator.userAgent.toLowerCase() const ua = navigator.userAgent.toLowerCase()
return ua.indexOf('micromessenger') !== -1 return ua.indexOf('wxwork') !== -1
} }
// 简化的静默登录 // 从URL参数获取code
async silentLogin() { getCodeFromURL() {
// 如果未配置appId,使用模拟登录 const urlParams = new URLSearchParams(window.location.search)
if (!this.isConfigured) { return urlParams.get('code')
console.log('使用模拟静默登录')
return this.mockLogin()
}
// 如果是微信浏览器,执行真实静默登录
if (this.isWeChat) {
return this.realWeChatLogin()
}
// 非微信浏览器,使用模拟登录
console.log('非微信浏览器,使用模拟登录')
return this.mockLogin()
} }
// 真实微信静默登录 // 企业微信静默登录 - 核心方法
realWeChatLogin() { async silentLogin() {
return new Promise((resolve, reject) => { try {
// 检查URL中是否已有授权code // 直接从URL获取code
const urlParams = new URLSearchParams(window.location.search) const code = this.getCodeFromURL()
const code = urlParams.get('code') if (!code) {
console.error('未找到code参数,请确保在企业微信内部应用中访问')
if (code) { return {
// 已有code,直接获取用户信息 isLoggedIn: false,
this.getUserInfo(code).then(resolve).catch(reject) message: '未找到code参数,请确保在企业微信内部应用中访问'
} else { }
// 重定向到微信授权页面进行静默授权
this.redirectToWeChat()
} }
})
}
// 重定向到微信授权页面 // 获取用户信息
redirectToWeChat() { const userInfo = await this.getUserInfo(code)
const redirectUri = encodeURIComponent(window.location.origin + window.location.pathname)
const scope = 'snsapi_base' // 静默授权,不弹出授权页面 return {
const state = 'STATE_' + Date.now() isLoggedIn: true,
code: code,
const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${this.appId}&redirect_uri=${redirectUri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect` userInfo: userInfo
}
window.location.href = authUrl } catch (error) {
console.error('登录失败:', error.message)
return {
isLoggedIn: false,
message: error.message || '登录失败'
}
}
} }
// 获取用户信息(简化版) // 获取用户信息 - 使用axios
async getUserInfo(code) { async getUserInfo(code) {
try { try {
// 这里需要调用后端接口来获取用户信息 const response = await post('/pedService/wxcp/auth', {
// 微信不允许前端直接调用获取用户信息的接口 authCode: code
const response = await fetch('/api/wechat/userinfo', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ code })
}) })
if (!response.ok) { const result = response.data
throw new Error('获取用户信息失败')
}
const userInfo = await response.json()
// 保存用户信息到本地存储
localStorage.setItem('wechat_user', JSON.stringify(userInfo))
return { if (result.code === 0) {
isLoggedIn: true, // 保存用户信息
userInfo: userInfo, localStorage.setItem('wechat_user', JSON.stringify(result.data))
message: '微信静默登录成功' return result.data
} else {
throw new Error(result.message || '获取用户信息失败')
} }
} catch (error) { } catch (error) {
console.error('获取用户信息失败:', error) throw new Error(`获取用户信息失败: ${error.message}`)
throw new Error('登录失败,请重试')
} }
} }
// 模拟登录(用于开发和测试)
mockLogin() {
return new Promise((resolve) => {
setTimeout(() => {
const mockUser = {
openid: 'mock_openid_' + Date.now(),
nickname: '测试用户',
headimgurl: '',
isMock: true
}
localStorage.setItem('wechat_user', JSON.stringify(mockUser))
resolve({
isLoggedIn: true,
userInfo: mockUser,
message: '模拟登录成功'
})
}, 1000) // 模拟网络延迟
})
}
// 检查登录状态 // 检查登录状态
checkLoginStatus() { checkLoginStatus() {
const userData = localStorage.getItem('wechat_user') const userData = localStorage.getItem('wechat_user')
if (userData) { if (userData) {
try { try {
const userInfo = JSON.parse(userData)
return { return {
isLoggedIn: true, isLoggedIn: true,
userInfo: userInfo userInfo: JSON.parse(userData)
} }
} catch (error) { } catch (error) {
console.error('解析用户数据失败:', error) localStorage.removeItem('wechat_user')
} }
} }
return { isLoggedIn: false } return { isLoggedIn: false }
} }
...@@ -136,7 +92,7 @@ class WeChatLogin { ...@@ -136,7 +92,7 @@ class WeChatLogin {
localStorage.removeItem('wechat_user') localStorage.removeItem('wechat_user')
} }
// 获取当前用户信息 // 获取当前用户
getCurrentUser() { getCurrentUser() {
const status = this.checkLoginStatus() const status = this.checkLoginStatus()
return status.isLoggedIn ? status.userInfo : null return status.isLoggedIn ? status.userInfo : null
......
...@@ -17,21 +17,22 @@ ...@@ -17,21 +17,22 @@
const apiBaseUrl = '/pedapi'; const apiBaseUrl = '/pedapi';
// 获取token // 获取token
const userToken = '65c76a8b38f350bd1849d41d3185c3eb'; const userInfo = localStorage.getItem('wechat_user')
const {extMap = {}} = JSON.parse(userInfo || '{}')
const userToken = extMap.sessionId;
// 添加APP_CODE配置 // 添加APP_CODE配置
const appCode = 'ped.pc'; const appCode = 'ped.qywx';
const chatParams = { const chatParams = {
appId: '83b2664019a945d0a438abe6339758d8', appId: '83b2664019a945d0a438abe6339758d8',
stage: 'wechat-demo', stage: 'wechat-demo',
}; };
const dialogSessionId = '20251028143404893-00045166'; // const dialogSessionId = '20251028143404893-00045166';
// const dialogSessionId = ''; const dialogSessionId = '';
const detailData = ref({ const detailData = ref({
title: '国械小智', title: '国械小智',
}); });
</script> </script>
<style scoped> <style scoped>
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
<div class="spinner"></div> <div class="spinner"></div>
<p>正在静默登录中...</p> <p>正在静默登录中...</p>
</div> </div>
<div v-else-if="error" class="error"> <div v-else-if="error" class="error">
<p class="error-text">{{ error }}</p> <p class="error-text">{{ error }}</p>
<button @click="retryLogin" class="retry-btn">重试登录</button> <button @click="retryLogin" class="retry-btn">重试登录</button>
...@@ -35,12 +34,9 @@ export default { ...@@ -35,12 +34,9 @@ export default {
if (result.isLoggedIn) { if (result.isLoggedIn) {
// 登录成功,跳转到首页 // 登录成功,跳转到首页
setTimeout(() => { router.replace('/')
router.replace('/')
}, 500)
} }
} catch (err) { } catch (err) {
console.error('登录失败:', err)
error.value = err.message || '登录失败,请重试' error.value = err.message || '登录失败,请重试'
loading.value = false loading.value = false
} }
......
...@@ -81,12 +81,13 @@ ...@@ -81,12 +81,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { EventSourcePolyfill } from 'event-source-polyfill'; import { EventSourcePolyfill } from 'event-source-polyfill';
import { ref, nextTick, onMounted, onBeforeUnmount } from 'vue'; import { ref, reactive, computed, onMounted, onBeforeUnmount, nextTick, watch } from 'vue';
import { SendOutlined, UserOutlined } from '@ant-design/icons-vue';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { post } from '@/utils/axios.js'; // 导入axios的post方法
import tableTemplate from './tableTemplate';
import { SendOutlined, UserOutlined } from '@ant-design/icons-vue';
import defaultAvatar from '@/assets/logo.png'; import defaultAvatar from '@/assets/logo.png';
import ChartComponent from './ChartComponent.vue'; // 导入独立的图表组件 import ChartComponent from './ChartComponent.vue'; // 导入独立的图表组件
import { tableTemplate } from './tableTemplate'; // 导入表格模板工具
// 组件属性 // 组件属性
const props = withDefaults( const props = withDefaults(
...@@ -303,20 +304,18 @@ const sendMessage = async () => { ...@@ -303,20 +304,18 @@ const sendMessage = async () => {
} else { } else {
// 默认的API调用逻辑 // 默认的API调用逻辑
console.log('默认API调用逻辑', dialogSessionId); console.log('默认API调用逻辑', dialogSessionId);
const response = await fetch(`${props.apiBaseUrl}/aiService/ask/app/${props.params?.appId}`, { const response = await post(`${props.apiBaseUrl}/aiService/ask/app/${props.params?.appId}`, {
method: 'POST', question: message,
...props.params,
}, {
headers: { headers: {
'Content-Type': 'application/json',
Token: props.token || '', Token: props.token || '',
'x-session-id': props.token || '', 'x-session-id': props.token || '',
'x-app-code': props.appCode || '', 'x-app-code': props.appCode || '',
}, }
body: JSON.stringify({
question: message,
...props.params,
}),
}); });
const data = await response.json();
const data = response.data;
if (data.code === 0) { if (data.code === 0) {
loading.value = false; loading.value = false;
} }
...@@ -365,19 +364,21 @@ const processSSEMessage = ( ...@@ -365,19 +364,21 @@ const processSSEMessage = (
case 3: // 图表数据 case 3: // 图表数据
if (updatedResponse) { if (updatedResponse) {
const { rows } = messageContent; const { rows } = messageContent;
// 表格数据处理
updatedResponse.contentBlocks.push({ updatedResponse.contentBlocks.push({
content: contentTemplates.table(rows), content: contentTemplates.table(rows),
hasThinkBox: false, hasThinkBox: false,
thinkContent: '', thinkContent: '',
thinkBoxExpanded: false, thinkBoxExpanded: false,
}); });
// 图表数据处理
updatedResponse.contentBlocks.push({ updatedResponse.contentBlocks.push({
content: '', // 图表内容由组件处理,这里留空 content: '',
hasThinkBox: false, hasThinkBox: false,
thinkContent: '', thinkContent: '',
thinkBoxExpanded: false, thinkBoxExpanded: false,
chartData: messageContent, // 添加图表数据 chartData: messageContent, // 添加图表数据
chartType: 3, // 使用object类型 chartType: 3,
}); });
} }
break; break;
...@@ -504,7 +505,7 @@ const reconnectSSE = (newDialogSessionId: string) => { ...@@ -504,7 +505,7 @@ const reconnectSSE = (newDialogSessionId: string) => {
// 添加重连间隔控制,避免频繁重连 // 添加重连间隔控制,避免频繁重连
const reconnectTimeout = setTimeout(() => { const reconnectTimeout = setTimeout(() => {
initSSE(); initSSE();
// 重连完成后重置标志 // 重连完成后重置标志
setTimeout(() => { setTimeout(() => {
isReconnecting.value = false; isReconnecting.value = false;
}, 2000); // 延长重连间隔 }, 2000); // 延长重连间隔
...@@ -755,14 +756,15 @@ const getChatRecord = async (dialogSessionId: string) => { ...@@ -755,14 +756,15 @@ const getChatRecord = async (dialogSessionId: string) => {
messages.value = [...recordList]; messages.value = [...recordList];
} }
} else { } else {
const response = await fetch(`${props.apiBaseUrl}/aiService/ask/list/chat/${dialogSessionId}`, { const response = await post(`${props.apiBaseUrl}/aiService/ask/list/chat/${dialogSessionId}`, {}, {
headers: { headers: {
Token: props.token || '', Token: props.token || '',
'x-session-id': props.token || '', 'x-session-id': props.token || '',
'x-app-code': props.appCode || '', 'x-app-code': props.appCode || '',
}, }
}); });
const data = await response.json();
const data = response.data;
if (data.code === 0) { if (data.code === 0) {
const recordList = processHistoryData(data.data || []); const recordList = processHistoryData(data.data || []);
messages.value = [...recordList]; messages.value = [...recordList];
......
// =============================================
// 全局样式和变量定义
// =============================================
// 颜色变量
@primary-color: #5B8AFE;
@primary-hover: #4a7df5;
@primary-light: #7BA6FF;
@blue-light-1: #f0f5ff;
@blue-light-2: #f8faff;
@blue-light-3: #e0e8ff;
@white: #ffffff;
@gray-1: #f8f9fa;
@gray-2: #f5f5f5;
@gray-3: #e0e0e0;
@gray-4: #cccccc;
@gray-5: #999999;
@gray-6: #666666;
@gray-7: #333333;
@success-color: #52c41a;
@error-color: #f5222d;
@warning-color: #faad14;
// 全局滚动条美化 - 悬浮式不占位滚动条 // 全局滚动条美化 - 悬浮式不占位滚动条
* { * {
padding: 0; padding: 0;
...@@ -11,317 +34,338 @@ ...@@ -11,317 +34,338 @@
} }
} }
p,h1,h2,h3,h4,h5,h6,ul,ol,li{ // 重置基础元素样式
margin:0; p, h1, h2, h3, h4, h5, h6, ul, ol, li {
padding:0; margin: 0;
padding: 0;
} }
// =============================================
// 主容器和布局样式
// =============================================
.chat-container { .chat-container {
background-color: white; background-color: @white;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 8px 30px rgba(91, 138, 254, 0.15); // 修改阴影颜色 box-shadow: 0 8px 30px rgba(91, 138, 254, 0.15);
overflow: hidden; overflow: hidden;
width: 100%; width: 100%;
display: flex;
flex-direction: column;
height: 100vh;
// 居中介绍页面样式
.chat-intro-center {
flex: 1;
display: flex; display: flex;
flex-direction: column; align-items: center;
height: 100vh; justify-content: center;
padding: 40px 20px;
// 居中介绍页面样式
.chat-intro-center { .intro-content {
flex: 1; text-align: center;
display: flex; max-width: 400px;
align-items: center; width: 100%;
justify-content: center;
padding: 40px 20px; .avatar-image {
width: 180px;
height: 180px;
border-radius: 50%;
margin-bottom: 20px;
}
h3 {
font-size: 24px;
color: @gray-7;
margin-bottom: 12px;
font-weight: 600;
}
p {
font-size: 16px;
color: @gray-6;
line-height: 1.5;
margin-bottom: 30px;
}
.start-chat-btn {
background: linear-gradient(135deg, @primary-color 0%, @primary-light 100%);
color: @white;
border: none;
padding: 12px 30px;
border-radius: 25px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(91, 138, 254, 0.3);
.intro-content { &:hover {
text-align: center; transform: translateY(-2px);
max-width: 400px; box-shadow: 0 6px 20px rgba(91, 138, 254, 0.4);
width: 100%;
.avatar-image {
width: 180px;
height: 180px;
border-radius: 50%;
margin-bottom: 20px;
}
h3 {
font-size: 24px;
color: #333;
margin-bottom: 12px;
font-weight: 600;
}
p {
font-size: 16px;
color: #666;
line-height: 1.5;
margin-bottom: 30px;
}
.start-chat-btn {
background: linear-gradient(135deg, #5B8AFE 0%, #7BA6FF 100%);
color: white;
border: none;
padding: 12px 30px;
border-radius: 25px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(91, 138, 254, 0.3);
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(91, 138, 254, 0.4);
}
&:active {
transform: translateY(0);
}
}
} }
&:active {
transform: translateY(0);
}
}
} }
}
// 聊天头部样式保持不变
.chat-header { // 聊天头部样式
display: flex; .chat-header {
align-items: center;
}
// 消息区域样式保持不变
.chat-messages {
flex: 1;
overflow-y: auto;
padding: 12px;
}
// 输入容器保持在底部
.chat-input-container {
padding: 20px;
border-top: 1px solid #e8f2f1;
background: #FCFCFC;
// 确保输入容器始终在底部
flex-shrink: 0;
}
.header-avatar {
width: 45px;
height: 45px;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.2);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center;
font-size: 20px; .header-avatar {
margin-right: 15px; width: 45px;
border: 2px solid rgba(255, 255, 255, 0.3); height: 45px;
img{ border-radius: 50%;
width:100%; background-color: rgba(255, 255, 255, 0.2);
height:auto; display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
margin-right: 15px;
border: 2px solid rgba(255, 255, 255, 0.3);
img {
width: 100%;
height: auto;
}
} }
}
.header-info {
.header-info { flex: 1;
flex: 1; h2 {
h2 { font-size: 18px;
font-size: 18px; }
} }
} }
// 消息区域
.chat-messages { .chat-messages {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
padding:12px; padding: 12px;
} }
.message-time { // 输入容器
color: #88a5d0; // 修改时间颜色为蓝色系 .chat-input-container {
margin-bottom: 6px; padding: 20px;
font-size: 14px; border-top: 1px solid #e8f2f1;
background: #FCFCFC;
flex-shrink: 0;
} }
}
.message { // =============================================
display: flex; // 消息样式
margin-bottom: 20px; // =============================================
flex-direction: column;
align-items: baseline; .message-time {
} color: #88a5d0;
margin-bottom: 6px;
font-size: 14px;
}
.message.sent { .message {
display: flex;
margin-bottom: 20px;
flex-direction: column;
align-items: baseline;
&.sent {
align-items: flex-end; align-items: flex-end;
.message-time { .message-time {
text-align: right; text-align: right;
} }
.avatar-container { .avatar-container {
flex-direction: row-reverse; flex-direction: row-reverse;
justify-content: flex-end; justify-content: flex-end;
} }
} }
.avatar-container { }
display: flex;
align-items: center;
}
.avatar { .avatar-container {
width: 42px; display: flex;
height: 42px; align-items: center;
border-radius: 50%; }
overflow: hidden;
flex-shrink: 0;
background-color: #e0e0e0;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
color: white;
border: 2px solid white;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
img{
width:100%;
height:auto;
}
}
.message.received .avatar { .avatar {
margin-right: 12px; width: 42px;
height: 42px;
border-radius: 50%;
overflow: hidden;
flex-shrink: 0;
background-color: @gray-3;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
color: @white;
border: 2px solid @white;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
img {
width: 100%;
height: auto;
} }
}
.message.sent .avatar { .message.received .avatar {
background: linear-gradient(135deg, #A8C6FF 0%, #C2D6FF 100%); // 修改发送方头像背景为浅蓝色 margin-right: 12px;
margin-left: 12px; }
}
.message.sent .avatar {
background: linear-gradient(135deg, #A8C6FF 0%, #C2D6FF 100%);
margin-left: 12px;
}
.message-content-wrapper { .message-content-wrapper {
max-width: 100%;
margin-top: 8px;
min-width: 150px;
// 当包含图表、表格或iframe时,宽度为100%
&:has(.message-table),
&:has(.message-chart),
&:has(.message-iframe) {
width: 100%;
min-width: 100%;
max-width: 100%; max-width: 100%;
margin-top: 8px;
min-width: 150px;
// 当包含图表、表格或iframe时,宽度为100%
&:has(.message-table),
&:has(.message-chart),
&:has(.message-iframe){
width: 100%;
min-width: 100%;
max-width: 100%;
}
} }
}
.message-content { .message-content {
padding: 10px; padding: 10px;
border-radius: 8px; border-radius: 8px;
line-height: 1.5; line-height: 1.5;
position: relative; position: relative;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
white-space: pre-wrap; white-space: pre-wrap;
.message-inner-box {
font-size: 0; .message-inner-box {
:deep(.message-text) { font-size: 0;
font-size: 14px;
} :deep(.message-text) {
font-size: 14px;
} }
} }
}
.message.received .message-content { .message.received .message-content {
background-color: #f0f5ff; // 修改回复方消息背景为浅蓝色 background-color: @blue-light-1;
border-top-left-radius: 5px; border-top-left-radius: 5px;
color: #333; color: @gray-7;
border: 1px solid #e0e8ff; // 修改边框颜色 border: 1px solid @blue-light-3;
} }
.message.sent .message-content { .message.sent .message-content {
background: linear-gradient(135deg, #5B8AFE 0%, #7BA6FF 100%); // 修改发送方消息背景为#5B8AFE background: linear-gradient(135deg, @primary-color 0%, @primary-light 100%);
border-top-right-radius: 5px; border-top-right-radius: 5px;
color: white; // 修改文字颜色为白色 color: @white;
border: 1px solid #4a7df5; // 修改边框颜色 }
}
:deep(.message-error) { // 错误消息样式
line-height: 1.5; :deep(.message-error) {
color: #c33; line-height: 1.5;
white-space: pre-wrap; color: @error-color;
font-size: 14px; white-space: pre-wrap;
} font-size: 14px;
}
.think-box-wrapper { // 思考框样式
margin: 12px 0; .think-box-wrapper {
padding: 10px 15px; margin: 12px 0;
background-color: #f5f8f7; padding: 10px 15px;
border-radius: 12px; background-color: #f5f8f7;
border: 1px solid #e3ecea; border-radius: 12px;
transition: all 0.3s ease; border: 1px solid #e3ecea;
} transition: all 0.3s ease;
}
:deep(.think-box-toggle) { :deep(.think-box-toggle) {
color: #5B8AFE; // 修改思考框切换按钮颜色 color: @primary-color;
cursor: pointer; cursor: pointer;
font-size: 12px; font-size: 12px;
text-decoration: none; text-decoration: none;
align-items: center; align-items: center;
gap: 4px; gap: 4px;
font-weight: 500; font-weight: 500;
padding: 4px 8px; padding: 4px 8px;
border-radius: 4px; border-radius: 4px;
transition: all 0.2s ease; transition: all 0.2s ease;
} }
:deep(.think-box-content) { :deep(.think-box-content) {
margin-top: 8px; margin-top: 8px;
background-color: #ffffff; background-color: @white;
padding: 12px 16px; padding: 12px 16px;
border-radius: 8px; border-radius: 8px;
border: 1px solid #e9ecef; border: 1px solid #e9ecef;
font-size: 0px; font-size: 0px;
color: #495057; color: #495057;
white-space: pre-wrap; white-space: pre-wrap;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
transition: all 0.3s ease; transition: all 0.3s ease;
animation: fadeIn 0.3s ease-in-out; animation: fadeIn 0.3s ease-in-out;
.think-content {
font-size: 0; .think-content {
.think-line { font-size: 0;
font-size: 13px;
color: #999; .think-line {
font-style: italic; font-size: 13px;
} color: @gray-5;
font-style: italic;
} }
} }
}
.chat-input-container { // =============================================
padding: 20px; // 输入框样式
border-top: 1px solid #e8f2f1; // =============================================
background: #FCFCFC;
}
.chat-input {
display: flex;
align-items: flex-end;
position: relative; // 添加相对定位
}
.chat-input textarea { .chat-input {
display: flex;
align-items: flex-end;
position: relative;
textarea {
flex: 1; flex: 1;
padding: 14px 70px 14px 18px; // 增加右侧内边距为按钮留出更多空间 padding: 14px 70px 14px 18px;
border-radius: 12px; border-radius: 12px;
outline: none; outline: none;
resize: none; resize: none;
height: 52px; height: 52px;
font-size: 15px; font-size: 15px;
transition: border-color 0.3s, box-shadow 0.3s; transition: border-color 0.3s, box-shadow 0.3s;
background-color: #f8faff; background-color: @blue-light-2;
border: 1px solid #E0E0E0; border: 1px solid @gray-3;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
/* 投影/大投影 */
box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.12); box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.12);
&:focus {
border-color: @primary-color;
box-shadow: 0 0 0 2px rgba(91, 138, 254, 0.1);
}
&:disabled {
background-color: @gray-2;
border-color: @gray-3;
color: @gray-5;
cursor: not-allowed;
}
} }
.chat-input button { button {
position: absolute; position: absolute;
right: 12px; right: 12px;
top: 50%; top: 50%;
color: #5B8AFE; color: @primary-color;
background: none; background: none;
border: none; border: none;
width: 40px; width: 40px;
...@@ -334,73 +378,58 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -334,73 +378,58 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
transition: color 0.2s, border-color 0.2s, background-color 0.2s; transition: color 0.2s, border-color 0.2s, background-color 0.2s;
z-index: 10; z-index: 10;
transform: translateY(-50%); transform: translateY(-50%);
}
&:hover {
.chat-input button:hover { color: @primary-hover;
color: #4a7df5; // 悬停时颜色变深 border-color: @primary-hover;
border-color: #4a7df5; // 悬停时边框颜色变深 background-color: rgba(91, 138, 254, 0.05);
background-color: rgba(91, 138, 254, 0.05); // 悬停时添加轻微背景色 }
}
&:active {
.chat-input button:active { background-color: rgba(91, 138, 254, 0.1);
background-color: rgba(91, 138, 254, 0.1); // 点击时背景色加深 transform: translateY(-50%) scale(0.95);
transform: translateY(-50%) scale(0.95); // 保持垂直居中并缩小 }
}
&:disabled {
.chat-input button:disabled { color: @gray-4;
color: #cccccc; // 禁用状态颜色 border-color: @gray-4;
border-color: #cccccc; // 禁用状态边框颜色 background-color: transparent;
background-color: transparent; // 禁用状态背景透明 cursor: not-allowed;
cursor: not-allowed; transform: translateY(-50%);
transform: translateY(-50%); // 保持垂直居中,不移除transform
}
.chat-input textarea:focus {
border-color: #5B8AFE; // 修改输入框焦点边框颜色
box-shadow: 0 0 0 2px rgba(91, 138, 254, 0.1); // 修改输入框焦点阴影
}
.chat-input textarea:disabled {
background-color: #f5f5f5;
border-color: #e0e0e0;
color: #999;
cursor: not-allowed;
}
.operation-box {
margin-top: 6px;
p {
color: #999;
font-size: 12px;
span {
margin-right: 15px;
}
} }
} }
} }
@media (max-width: 600px) { .operation-box {
.header-avatar { margin-top: 6px;
width: 40px;
height: 40px; p {
color: @gray-5;
font-size: 12px;
span {
margin-right: 15px;
} }
} }
}
// =============================================
// 表格消息样式 // 表格消息样式
// =============================================
:deep(.message-table) { :deep(.message-table) {
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
margin: 8px 0; margin: 8px 0;
// 表格容器,用于包裹表格和滚动条 // 表格容器
.table-container { .table-container {
width: 100%; width: 100%;
overflow-x: auto; // 添加水平滚动条支持 overflow-x: auto;
-webkit-overflow-scrolling: touch; // iOS平滑滚动 -webkit-overflow-scrolling: touch;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
// 滚动条样式 // 滚动条样式
&::-webkit-scrollbar { &::-webkit-scrollbar {
height: 8px; height: 8px;
...@@ -420,31 +449,29 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -420,31 +449,29 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
} }
} }
} }
.data-table { .data-table {
width: auto; // 改为自动宽度,允许表格超出容器 width: auto;
min-width: 100%; // 确保表格至少与容器一样宽 min-width: 100%;
border-collapse: collapse; border-collapse: collapse;
background-color: white; background-color: @white;
table-layout: auto; // 改为自动布局,允许列宽自适应内容 table-layout: auto;
// 文字列样式 - 左对齐 // 列类型样式
.text-cell { .text-cell {
text-align: left; text-align: left;
padding-left: 12px; padding-left: 12px;
padding-right: 8px; padding-right: 8px;
} }
// 数字列样式 - 右对齐
.numeric-cell { .numeric-cell {
text-align: right; text-align: right;
padding-left: 8px; padding-left: 8px;
padding-right: 12px; padding-right: 12px;
font-family: 'Courier New', monospace; // 使用等宽字体便于数字对齐 font-family: 'Courier New', monospace;
font-weight: 500; font-weight: 500;
} }
// 趋势列样式 - 居中
.trend-cell { .trend-cell {
text-align: center; text-align: center;
padding-left: 8px; padding-left: 8px;
...@@ -452,8 +479,8 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -452,8 +479,8 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
} }
th { th {
background: linear-gradient(135deg, #5B8AFE 0%, #4a7df5 100%); // 修改表格表头背景 background: linear-gradient(135deg, @primary-color 0%, @primary-hover 100%);
color: white; color: @white;
font-weight: 600; font-weight: 600;
padding: 12px 8px; padding: 12px 8px;
font-size: 14px; font-size: 14px;
...@@ -473,26 +500,26 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -473,26 +500,26 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
padding: 10px 8px; padding: 10px 8px;
font-size: 14px; font-size: 14px;
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0;
color: #333; color: @gray-7;
height: 35px; // 固定单元格高度,替换line-height height: 35px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
vertical-align: middle; // 确保内容垂直居中 vertical-align: middle;
min-width: 80px; // 设置最小列宽,与表头保持一致 min-width: 80px;
} }
// 奇偶行背景色设置移动到tr元素上 // 奇偶行样式
tr:nth-child(odd) td { tr:nth-child(odd) td {
background-color: #f8faff; // 奇数行背景色为浅蓝色 background-color: @blue-light-2;
} }
tr:nth-child(even) td { tr:nth-child(even) td {
background-color: white; // 偶数行背景色为白色 background-color: @white;
} }
tr:hover td { tr:hover td {
background-color: #f0f5ff; // 修改为蓝色系的悬停背景色 background-color: @blue-light-1;
} }
tr:last-child td { tr:last-child td {
...@@ -502,13 +529,13 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -502,13 +529,13 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
// 趋势箭头样式 // 趋势箭头样式
.trend-up { .trend-up {
color: #52c41a; color: @success-color;
font-weight: bold; font-weight: bold;
font-size: 16px; font-size: 16px;
} }
.trend-down { .trend-down {
color: #f5222d; color: @error-color;
font-weight: bold; font-weight: bold;
font-size: 16px; font-size: 16px;
} }
...@@ -516,6 +543,7 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -516,6 +543,7 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
.table-footer { .table-footer {
margin-top: 12px; margin-top: 12px;
font-size: 14px; font-size: 14px;
span { span {
color: #2eb0a1; color: #2eb0a1;
font-weight: bold; font-weight: bold;
...@@ -523,41 +551,10 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -523,41 +551,10 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
} }
} }
// 响应式表格样式 // =============================================
@media (max-width: 768px) { // iframe消息样式
:deep(.message-table) { // =============================================
.data-table {
font-size: 12px;
th, td {
padding: 8px 4px;
height: 30px; // 移动端减小高度
min-width: 60px; // 移动端减小最小列宽
}
}
.table-title {
font-size: 14px;
}
.table-summary {
font-size: 12px;
padding: 8px 10px;
}
}
}
@media (max-width: 480px) {
:deep(.message-table) {
.data-table {
th, td {
min-width: 50px; // 更小屏幕进一步减小最小列宽
height: 28px; // 更小屏幕进一步减小高度
}
}
}
}
// 表格消息样式
:deep(.message-iframe) { :deep(.message-iframe) {
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
...@@ -573,7 +570,7 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -573,7 +570,7 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
min-height: 1800px; min-height: 1800px;
border: none; border: none;
border-radius: 8px; border-radius: 8px;
background-color: #f8f9fa; background-color: @gray-1;
transition: height 0.5s ease-in-out, opacity 0.3s ease; transition: height 0.5s ease-in-out, opacity 0.3s ease;
// 加载状态样式 // 加载状态样式
...@@ -622,8 +619,8 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -622,8 +619,8 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
.loading-spinner { .loading-spinner {
width: 40px; width: 40px;
height: 40px; height: 40px;
border: 4px solid #e0e0e0; border: 4px solid @gray-3;
border-top: 4px solid #5B8AFE; border-top: 4px solid @primary-color;
border-radius: 50%; border-radius: 50%;
animation: spin 1s linear infinite; animation: spin 1s linear infinite;
margin-bottom: 16px; margin-bottom: 16px;
...@@ -631,7 +628,7 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -631,7 +628,7 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
.loading-text { .loading-text {
font-size: 16px; font-size: 16px;
color: #666; color: @gray-6;
margin-bottom: 12px; margin-bottom: 12px;
font-weight: 500; font-weight: 500;
} }
...@@ -639,20 +636,23 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -639,20 +636,23 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
.loading-progress { .loading-progress {
width: 200px; width: 200px;
height: 4px; height: 4px;
background: #e0e0e0; background: @gray-3;
border-radius: 2px; border-radius: 2px;
overflow: hidden; overflow: hidden;
.progress-bar { .progress-bar {
height: 100%; height: 100%;
background: linear-gradient(90deg, #5B8AFE, #7BA6FF); background: linear-gradient(90deg, @primary-color, @primary-light);
width: 30%; width: 30%;
animation: progress 2s ease-in-out infinite; animation: progress 2s ease-in-out infinite;
} }
} }
} }
// 加载动画 // =============================================
// 动画定义
// =============================================
@keyframes loading { @keyframes loading {
0% { 0% {
background-position: 200% 0; background-position: 200% 0;
...@@ -681,4 +681,49 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -681,4 +681,49 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
100% { 100% {
transform: translateX(200%); transform: translateX(200%);
} }
}
// =============================================
// 响应式样式
// =============================================
@media (max-width: 768px) {
:deep(.message-table) {
.data-table {
font-size: 12px;
th, td {
padding: 8px 4px;
height: 30px;
min-width: 60px;
}
}
.table-title {
font-size: 14px;
}
.table-summary {
font-size: 12px;
padding: 8px 10px;
}
}
}
@media (max-width: 480px) {
:deep(.message-table) {
.data-table {
th, td {
min-width: 50px;
height: 28px;
}
}
}
}
@media (max-width: 600px) {
.header-avatar {
width: 40px;
height: 40px;
}
} }
\ No newline at end of file
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'; import { resolve } from 'path';
export default defineConfig({ export default defineConfig({
base: '/ai/', // 添加基础路径前缀 base: '/ai/', // 添加基础路径前缀
plugins: [vue()], plugins: [vue()],
server: { server: {
host: '0.0.0.0', host: '0.0.0.0',
port: 3000, port: 3000,
proxy: { // 添加history fallback配置
historyApiFallback: {
rewrites: [
{ from: /^\/ai\/.*$/, to: '/ai/index.html' }
]
},
proxy: {
'/pedapi': { '/pedapi': {
target: 'http://peddev.cmic.com.cn', target: 'http://peddev.cmic.com.cn',
changeOrigin: true, // 解决跨域问题 changeOrigin: true, // 解决跨域问题
...@@ -33,6 +40,24 @@ export default defineConfig({ ...@@ -33,6 +40,24 @@ export default defineConfig({
console.log('发送请求到:', options.target); console.log('发送请求到:', options.target);
}); });
} }
},
// 修复pedService代理配置
'/pedService': {
target: 'http://10.17.86.37:8630',
changeOrigin: true, // 解决跨域问题
secure: false, // 允许不安全的SSL连接
rewrite: (path) => path.replace(/^\/pedService/, '/pedService'), // 保留前缀
configure: (proxy, options) => {
proxy.on('error', (err, req, res) => {
console.log('pedService代理错误:', err);
});
proxy.on('proxyReq', (proxyReq, req, res) => {
console.log('pedService发送请求到本地服务:', options.target + req.url);
});
proxy.on('proxyRes', (proxyRes, req, res) => {
console.log('pedService收到响应,状态码:', proxyRes.statusCode);
});
}
} }
}, },
}, },
...@@ -44,7 +69,7 @@ export default defineConfig({ ...@@ -44,7 +69,7 @@ export default defineConfig({
resolve: { resolve: {
alias: { alias: {
'@': resolve(__dirname, 'src'), '@': resolve(__dirname, 'src'),
'echarts': 'echarts/dist/echarts.esm.js' // 添加这一行 'echarts': 'echarts/dist/echarts.esm.js'
} }
}, },
}) })
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment