daShangDao_psiWebApp/vite.config.js
97694731 fac91a81e2
Some checks failed
CI / build (18.x) (push) Failing after 33m30s
CI / build (20.x) (push) Failing after 1m35s
CI / deploy-preview (push) Has been skipped
CI / lint (push) Failing after 34s
CI / test (push) Failing after 15s
CI / security (push) Failing after 34s
同步列表
2026-06-29 14:52:02 +08:00

262 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { defineConfig } = require('vite')
const vue = require('@vitejs/plugin-vue').default
const path = require('path')
const { spawn } = require('child_process')
// https://vitejs.dev/config/
module.exports = defineConfig({
css: {
preprocessorOptions: {
scss: {
silenceDeprecations: ['legacy-js-api'],
api: 'modern-compiler'
}
}
},
plugins: [
vue(),
// 孔夫子旧书网登录代理(避免浏览器跨域限制)
{
name: 'kongfz-login-proxy',
configureServer(server) {
server.middlewares.use('/kongfz-login', async (req, res) => {
if (req.method !== 'POST') {
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify({ code: 405, message: '仅支持 POST 请求' }))
return
}
let body = ''
req.on('data', chunk => { body += chunk.toString() })
req.on('end', async () => {
try {
const params = new URLSearchParams(body)
const username = params.get('loginName') || ''
const password = params.get('loginPass') || ''
if (!username || !password) {
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify({ code: 400, message: '请输入用户名和密码!' }))
return
}
const https = require('https')
const http = require('http')
function requestWithRedirect(options, bodyData, redirectCount = 0) {
return new Promise((resolve, reject) => {
if (redirectCount > 5) {
reject(new Error('重定向次数过多'))
return
}
const mod = options.port === 443 ? https : http
const req = mod.request(options, (response) => {
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
const redirectUrl = new URL(response.headers.location, `https://${options.hostname}`)
const redirectOpts = {
hostname: redirectUrl.hostname,
port: redirectUrl.port || (redirectUrl.protocol === 'https:' ? 443 : 80),
path: redirectUrl.pathname + redirectUrl.search,
method: 'GET',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
},
timeout: 15000
}
if (response.headers['set-cookie']) {
const cookies = Array.isArray(response.headers['set-cookie'])
? response.headers['set-cookie'].join('; ')
: response.headers['set-cookie']
redirectOpts.headers['Cookie'] = cookies.split(';')[0].trim()
}
resolve(requestWithRedirect(redirectOpts, null, redirectCount + 1))
return
}
let responseData = ''
response.on('data', chunk => { responseData += chunk })
response.on('end', () => resolve({ statusCode: response.statusCode, headers: response.headers, body: responseData }))
})
req.on('error', err => reject(new Error(`登录请求失败: ${err.message}`)))
req.on('timeout', () => { req.destroy(); reject(new Error('登录请求超时')) })
if (bodyData) req.write(bodyData)
req.end()
})
}
const formData = new URLSearchParams()
formData.append('loginName', username)
formData.append('loginPass', password)
formData.append('returnUrl', 'http://user.kongfz.com/')
const formDataStr = formData.toString()
const loginResponse = await requestWithRedirect({
hostname: 'login.kongfz.com',
port: 443,
path: '/Pc/Login/account',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(formDataStr),
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
},
timeout: 15000
}, formDataStr)
if (loginResponse.statusCode !== 200) {
throw new Error(`登录失败(HTTP状态码: ${loginResponse.statusCode})`)
}
const setCookie = loginResponse.headers['set-cookie'] || []
const cookieStr = Array.isArray(setCookie) ? setCookie.join('; ') : setCookie || ''
if (loginResponse.body.includes("window.location.href='https://login.kongfz.cn/Pc/Session/rsync")) {
if (!cookieStr) throw new Error('登录成功但未获取到Cookie')
if (!cookieStr.includes('PHPSESSID=')) throw new Error('登录失败: 未找到 PHPSESSID')
const token = cookieStr.split('PHPSESSID=')[1].split(';')[0]
const userInfoResponse = await requestWithRedirect({
hostname: 'user.kongfz.com',
port: 443,
path: '/User/Index/getUserInfo/',
method: 'GET',
headers: {
'Cookie': `PHPSESSID=${token}`,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8'
},
timeout: 15000
}, null)
let displayName = username
try {
const userJson = JSON.parse(userInfoResponse.body)
if (userJson.status && userJson.data) displayName = userJson.data.nickname || username
} catch { }
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify({
code: 200, message: '登录成功',
data: { token, username: displayName, nickname: displayName }
}))
} else {
try {
const errJson = JSON.parse(loginResponse.body)
if (errJson.errCode === 1001 || errJson.errCode === 1005) throw new Error('账号或密码错误')
throw new Error(errJson.errInfo || '登录失败,未知错误!')
} catch (parseErr) {
if (parseErr instanceof SyntaxError) throw new Error('登录失败,未知错误!')
throw parseErr
}
}
} catch (error) {
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify({ code: 500, message: error.message }))
}
})
})
}
},
// 本地程序启动器(无需协议注册/脚本/额外服务Vite 服务器直接 spawn exe
{
name: 'local-launcher',
configureServer(server) {
server.middlewares.use('/api/local/launch-exe', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
if (req.method === 'OPTIONS') {
res.statusCode = 204
return res.end()
}
if (req.method !== 'POST') {
res.setHeader('Content-Type', 'application/json')
return res.end(JSON.stringify({ code: 405, msg: '仅支持 POST' }))
}
let body = ''
req.on('data', chunk => { body += chunk.toString() })
req.on('end', () => {
try {
const { exe_path } = JSON.parse(body)
if (!exe_path) {
res.setHeader('Content-Type', 'application/json')
return res.end(JSON.stringify({ code: 400, msg: '缺少 exe_path' }))
}
const fs = require('fs')
if (!fs.existsSync(exe_path)) {
res.setHeader('Content-Type', 'application/json')
return res.end(JSON.stringify({ code: 404, msg: `文件不存在: ${exe_path}` }))
}
const exeDir = path.dirname(exe_path)
const proc = spawn(exe_path, [], {
cwd: exeDir,
detached: true,
stdio: 'ignore',
windowsHide: false
})
proc.unref()
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify({ code: 0, msg: '已启动', pid: proc.pid }))
} catch (err) {
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify({ code: 500, msg: err.message }))
}
})
})
server.middlewares.use('/api/local/exe-config', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Content-Type', 'application/json')
if (req.method !== 'GET') return res.end(JSON.stringify({ code: 405 }))
try {
const { execSync } = require('child_process')
const cmd = 'powershell -NoProfile -Command "(Get-ItemProperty -Path \'Registry::HKEY_CLASSES_ROOT\\kfzprice\\shell\\open\\command\' -Name \'(default)\').\'(default)\'"'
const raw = execSync(cmd, { encoding: 'utf8', timeout: 5000 }).trim()
const match = raw.match(/"([^"]+\.exe)"/i)
res.end(JSON.stringify({ code: 0, data: { exe_path: match ? match[1] : '' } }))
} catch (err) {
res.end(JSON.stringify({ code: 500, msg: err.message }))
}
})
}
}
],
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
},
define: {
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false'
},
server: {
port: 5174,
host: '0.0.0.0',
historyApiFallback: true,
proxy: {
'/api': {
// target: 'http://127.0.0.1:9090',
// target: 'http://192.168.101.213:9090',
// target: 'https://psi.api.buzhiyushu.cn',
target: 'http://127.0.0.1:9090',
changeOrigin: true
},
'/api/print': {
// target: 'http://192.168.101.127:8075',
target: 'https://print.buzhiyushu.cn',
changeOrigin: true
}
}
}
})