程序所在位置
Some checks failed
Some checks failed
This commit is contained in:
parent
104780d195
commit
520712bfab
@ -373,7 +373,7 @@ onMounted(() => {
|
|||||||
loadTodayStats()
|
loadTodayStats()
|
||||||
loadLatestProducts()
|
loadLatestProducts()
|
||||||
loadEmployeeStats()
|
loadEmployeeStats()
|
||||||
// loadStoreInfo()
|
loadStoreInfo()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -25,12 +25,11 @@
|
|||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<el-input v-model="dir" placeholder="如 C:\\verifyTool\\kfz-goods-pricing.exe" clearable @clear="dir = ''" />
|
<el-input v-model="dir" placeholder="如 C:\Users\pc\Desktop\price" />
|
||||||
<input ref="fileInputRef" type="file" accept=".exe" style="display: none" @change="handleFileSelected" />
|
|
||||||
|
|
||||||
<div class="save-bar" style="margin-top: 18px;">
|
<div class="save-bar" style="margin-top: 18px;">
|
||||||
<el-tooltip content="选择本机程序文件" placement="top" trigger="click">
|
<el-tooltip content="保存核价器所在目录" placement="top" trigger="click">
|
||||||
<el-button type="primary" @click="handleBrowseExe" size="small">选择地址</el-button>
|
<el-button type="primary" @click="handleSaveDir" size="small">保存</el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip content="通过自定义协议启动本机程序" placement="top" trigger="click">
|
<el-tooltip content="通过自定义协议启动本机程序" placement="top" trigger="click">
|
||||||
<el-button type="success" @click="handleOpenExe" size="small">打开程序</el-button>
|
<el-button type="success" @click="handleOpenExe" size="small">打开程序</el-button>
|
||||||
@ -281,7 +280,6 @@ import { ref, onMounted } from 'vue'
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Delete, Plus, Setting, User, Link, VideoPlay } from '@element-plus/icons-vue'
|
import { Delete, Plus, Setting, User, Link, VideoPlay } from '@element-plus/icons-vue'
|
||||||
import { ServiceManager } from '@/utils/ServiceManager'
|
|
||||||
import {
|
import {
|
||||||
testConnection,
|
testConnection,
|
||||||
kongfzLogin,
|
kongfzLogin,
|
||||||
@ -409,167 +407,16 @@ export default {
|
|||||||
const bindLoading = ref(false)
|
const bindLoading = ref(false)
|
||||||
const result = ref<{ success: boolean; message: string } | null>(null)
|
const result = ref<{ success: boolean; message: string } | null>(null)
|
||||||
|
|
||||||
/** 通过本地服务管理器启动核价器 exe */
|
/** 保存核价器所在目录到 localStorage */
|
||||||
const fileInputRef = ref(null)
|
const handleSaveDir = () => {
|
||||||
const serviceManager = new ServiceManager('http://127.0.0.1:5000')
|
|
||||||
const SERVICE_ID = 'kfz-goods-pricing'
|
|
||||||
|
|
||||||
const handleBrowseExe = () => {
|
|
||||||
fileInputRef.value?.click()
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleFileSelected = async () => {
|
|
||||||
const input = fileInputRef.value
|
|
||||||
if (!input?.files?.length) return
|
|
||||||
const file = input.files[0]
|
|
||||||
// 优先取完整路径(部分运行环境支持 file.path)
|
|
||||||
let fullPath = (file as any).path || ''
|
|
||||||
// 浏览器只给文件名时,从 ServiceManager 查完整路径
|
|
||||||
if (!fullPath || !(fullPath.includes('\\') || fullPath.includes('/'))) {
|
|
||||||
try {
|
|
||||||
const services = await serviceManager.getServicesStatus()
|
|
||||||
const matched = services.find(s => s.exe_path && s.exe_path.includes(file.name))
|
|
||||||
if (matched) {
|
|
||||||
fullPath = matched.exe_path
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// ServiceManager 不可用,降级用文件名
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dir.value = fullPath || file.name
|
|
||||||
localStorage.setItem(STORAGE_KEY_FILE_DIR, dir.value)
|
localStorage.setItem(STORAGE_KEY_FILE_DIR, dir.value)
|
||||||
|
ElMessage.success({ message: '路径已保存', duration: 1000, customClass: 'scan-success-message' })
|
||||||
// 注册到启动器并启动
|
|
||||||
if (fullPath && (fullPath.includes('\\') || fullPath.includes('/'))) {
|
|
||||||
const exeName = file.name.replace(/\.exe$/i, '')
|
|
||||||
try {
|
|
||||||
await serviceManager.registerService({
|
|
||||||
id: SERVICE_ID,
|
|
||||||
name: '核价器',
|
|
||||||
exe_path: fullPath,
|
|
||||||
})
|
|
||||||
ElMessage.success('已注册到启动器')
|
|
||||||
} catch {
|
|
||||||
// 注册失败不阻塞
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通过 Vite 本地 API 直接启动(优先)
|
|
||||||
try {
|
|
||||||
const resp = await fetch('/api/local/launch-exe', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ exe_path: fullPath })
|
|
||||||
})
|
|
||||||
const result = await resp.json()
|
|
||||||
if (result.code === 0) {
|
|
||||||
ElMessage.success({ message: `核价器已启动 (PID ${result.pid})`, duration: 1000, customClass: 'scan-success-message' })
|
|
||||||
} else {
|
|
||||||
// 降级:通过 ServiceManager 启动
|
|
||||||
await serviceManager.startService(SERVICE_ID)
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// Vite API 不可用,降级 ServiceManager
|
|
||||||
try {
|
|
||||||
await serviceManager.startService(SERVICE_ID)
|
|
||||||
} catch { /* 无法启动 */ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 重置 input 以便重复选择同一文件时仍触发 change 事件
|
|
||||||
input.value = ''
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleOpenExe = async () => {
|
/** 通过自定义协议启动核价器 exe */
|
||||||
if (!dir.value) {
|
const handleOpenExe = () => {
|
||||||
ElMessage.warning({ message: '请先设置程序所在位置', customClass: 'scan-warning-message' })
|
window.location.href = 'kfzprice://launch'
|
||||||
return
|
ElMessage.success({ message: '启动指令已发送', duration: 1000, customClass: 'scan-success-message' })
|
||||||
}
|
|
||||||
|
|
||||||
// 首选:通过 Vite 开发服务器本地 API 直接启动(无需任何外部脚本/服务)
|
|
||||||
try {
|
|
||||||
const resp = await fetch('/api/local/launch-exe', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ exe_path: dir.value })
|
|
||||||
})
|
|
||||||
const result = await resp.json()
|
|
||||||
if (result.code === 0) {
|
|
||||||
ElMessage.success({ message: `核价器已启动 (PID ${result.pid})`, duration: 1000, customClass: 'scan-success-message' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
console.warn('[启动程序] Vite 本地 API 失败:', result.msg)
|
|
||||||
} catch {
|
|
||||||
// Vite API 不可用,继续降级
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 尝试通过服务管理器启动
|
|
||||||
const services = await serviceManager.getServicesStatus()
|
|
||||||
if (services.length > 0) {
|
|
||||||
let target = null
|
|
||||||
// 完整路径:按 exe_path 精确匹配;仅文件名:直接用 SERVICE_ID
|
|
||||||
const isFullPath = dir.value.includes('\\') || dir.value.includes('/')
|
|
||||||
if (isFullPath) {
|
|
||||||
target = services.find(s => s.exe_path && s.exe_path.includes(dir.value))
|
|
||||||
}
|
|
||||||
if (!target) {
|
|
||||||
target = services.find(s => s.id === SERVICE_ID)
|
|
||||||
}
|
|
||||||
if (target) {
|
|
||||||
const ok = await serviceManager.startService(target.id)
|
|
||||||
if (ok) {
|
|
||||||
ElMessage.success({ message: `已启动: ${target.name || target.id}`, duration: 1000, customClass: 'scan-success-message' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 服务管理器不可用或无匹配服务,回退到自定义协议
|
|
||||||
console.warn('[启动程序] 服务管理器不可用,回退到自定义协议')
|
|
||||||
// 分离目录和 exe 文件名
|
|
||||||
const lastSep = Math.max(dir.value.lastIndexOf('\\'), dir.value.lastIndexOf('/'))
|
|
||||||
const dirPath = lastSep > 0 ? dir.value.substring(0, lastSep) : dir.value
|
|
||||||
const exeName = lastSep > 0 ? dir.value.substring(lastSep + 1) : ''
|
|
||||||
|
|
||||||
let launched = false
|
|
||||||
// 1. 尝试 kfzgs:// 协议
|
|
||||||
try {
|
|
||||||
if (exeName) {
|
|
||||||
window.location.href = `kfzgs://launch?dir=${encodeURIComponent(dirPath)}&exe=${encodeURIComponent(exeName)}`
|
|
||||||
} else {
|
|
||||||
window.location.href = `kfzgs://launch?dir=${encodeURIComponent(dirPath)}`
|
|
||||||
}
|
|
||||||
launched = true
|
|
||||||
} catch { /* ignore */ }
|
|
||||||
|
|
||||||
// 2. 降级:file:// 直链 + window.open
|
|
||||||
if (!launched) {
|
|
||||||
const fileUrl = `file:///${dir.value.replace(/\\/g, '/')}`
|
|
||||||
const win = window.open(fileUrl, '_blank')
|
|
||||||
if (!win) {
|
|
||||||
// 弹窗被拦截,用隐藏 a 标签触发
|
|
||||||
const a = document.createElement('a')
|
|
||||||
a.href = fileUrl
|
|
||||||
a.target = '_blank'
|
|
||||||
a.click()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ElMessage.success({ message: '启动指令已发送', duration: 1000, customClass: 'scan-success-message' })
|
|
||||||
} catch (err) {
|
|
||||||
// 服务管理器连接失败,回退到文件协议
|
|
||||||
console.warn('[启动程序] 服务管理器连接失败:', err)
|
|
||||||
try {
|
|
||||||
const fileUrl = `file:///${dir.value.replace(/\\/g, '/')}`
|
|
||||||
const win = window.open(fileUrl, '_blank')
|
|
||||||
if (!win) {
|
|
||||||
const a = document.createElement('a')
|
|
||||||
a.href = fileUrl
|
|
||||||
a.target = '_blank'
|
|
||||||
a.click()
|
|
||||||
}
|
|
||||||
ElMessage.success({ message: '启动指令已发送', duration: 1000, customClass: 'scan-success-message' })
|
|
||||||
} catch (err2) {
|
|
||||||
ElMessage.error({ message: `启动失败: ${err2.message || '未知错误'}`, customClass: 'scan-error-message' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 将单个账号写入已保存列表 */
|
/** 将单个账号写入已保存列表 */
|
||||||
@ -943,9 +790,7 @@ export default {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
dir,
|
dir,
|
||||||
fileInputRef,
|
handleSaveDir,
|
||||||
handleBrowseExe,
|
|
||||||
handleFileSelected,
|
|
||||||
ip,
|
ip,
|
||||||
port,
|
port,
|
||||||
verifyIndex,
|
verifyIndex,
|
||||||
|
|||||||
@ -1,4 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div style="margin-bottom: 16px">
|
||||||
|
<el-steps :active="1" align-center>
|
||||||
|
<el-step title="销售订单" />
|
||||||
|
<el-step title="出库管理" />
|
||||||
|
<el-step title="发货单" />
|
||||||
|
</el-steps>
|
||||||
|
<div style="text-align: right; margin-top: 12px">
|
||||||
|
<el-button type="primary" @click="$router.push('/shipping-order')">下一步</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<el-card class="outbound-manager">
|
<el-card class="outbound-manager">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">出库单管理</div>
|
<div class="card-header">出库单管理</div>
|
||||||
|
|||||||
@ -1,7 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div style="margin-bottom: 16px">
|
||||||
|
<el-steps :active="0" align-center>
|
||||||
|
<el-step title="销售订单" />
|
||||||
|
<el-step title="出库管理" />
|
||||||
|
<el-step title="发货单" />
|
||||||
|
</el-steps>
|
||||||
|
<div style="text-align: right; margin-top: 12px">
|
||||||
|
<el-button type="primary" @click="$router.push('/outbound')">下一步</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<el-card class="sales-order-manager">
|
<el-card class="sales-order-manager">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">销售订单管理</div>
|
<div class="card-header">销售订单管理</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<div class="filter-bar">
|
<div class="filter-bar">
|
||||||
<el-input v-model="searchParams.keyword" placeholder="销售订单号" clearable style="width: 220px"
|
<el-input v-model="searchParams.keyword" placeholder="销售订单号" clearable style="width: 220px"
|
||||||
|
|||||||
@ -1,4 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<el-steps :active="2" align-center style="margin-bottom: 16px">
|
||||||
|
<el-step title="销售订单" />
|
||||||
|
<el-step title="出库管理" />
|
||||||
|
<el-step title="发货单" />
|
||||||
|
</el-steps>
|
||||||
<div class="shipping-order-container">
|
<div class="shipping-order-container">
|
||||||
<!-- 左侧卡片:商品详情 -->
|
<!-- 左侧卡片:商品详情 -->
|
||||||
<el-card class="left-card" shadow="never">
|
<el-card class="left-card" shadow="never">
|
||||||
|
|||||||
11
verifyTool/kfzgs-launcher-start.bat
Normal file
11
verifyTool/kfzgs-launcher-start.bat
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
|
set "LAUNCHER=%~dp0kfzgs-launcher.ps1"
|
||||||
|
|
||||||
|
echo 启动核价器后台服务(端口 5000)...
|
||||||
|
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%LAUNCHER%" 2>&1
|
||||||
|
|
||||||
|
echo 服务已退出
|
||||||
|
pause
|
||||||
188
verifyTool/kfzgs-launcher.ps1
Normal file
188
verifyTool/kfzgs-launcher.ps1
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
# kfzgs-launcher.ps1 - 核价器启动脚本 (便携版)
|
||||||
|
# 用法:
|
||||||
|
# 协议模式: powershell -File kfzgs-launcher.ps1 -url "kfzgs://launch?dir=..."
|
||||||
|
# 服务模式: powershell -File kfzgs-launcher.ps1
|
||||||
|
param([string]$url = "")
|
||||||
|
|
||||||
|
$SERVICE_ID = "kfz-goods-pricing"
|
||||||
|
$HTTP_PORT = 5000
|
||||||
|
$SCRIPT_DIR = Split-Path $MyInvocation.MyCommand.Path -Parent
|
||||||
|
|
||||||
|
# 从同目录下的 config.json 读取 exe 路径,没有则用同目录下默认 exe
|
||||||
|
$CONFIG_FILE = Join-Path $SCRIPT_DIR "launcher-config.json"
|
||||||
|
$DEFAULT_EXE = Join-Path $SCRIPT_DIR "kfz-goods-pricing.exe"
|
||||||
|
|
||||||
|
function Load-Config {
|
||||||
|
if (Test-Path $CONFIG_FILE) {
|
||||||
|
try {
|
||||||
|
$config = Get-Content $CONFIG_FILE -Raw | ConvertFrom-Json
|
||||||
|
if ($config.exe_path) { return $config.exe_path }
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
return $DEFAULT_EXE
|
||||||
|
}
|
||||||
|
|
||||||
|
function Save-Config($exePath) {
|
||||||
|
@{ exe_path = $exePath; id = $SERVICE_ID; name = "核价器" } | ConvertTo-Json | Out-File $CONFIG_FILE -Encoding UTF8
|
||||||
|
}
|
||||||
|
|
||||||
|
$EXE_PATH = Load-Config
|
||||||
|
|
||||||
|
function Parse-KfzgsUrl($rawUrl) {
|
||||||
|
$decoded = [System.Uri]::UnescapeDataString($rawUrl)
|
||||||
|
$stripped = $decoded -replace "^kfzgs://", ""
|
||||||
|
$action = ""
|
||||||
|
$params = @{}
|
||||||
|
if ($stripped -match "^([^?]+)\?(.*)$") {
|
||||||
|
$action = $Matches[1]
|
||||||
|
$query = $Matches[2]
|
||||||
|
$query -split "&" | ForEach-Object {
|
||||||
|
$parts = $_ -split "=", 2
|
||||||
|
if ($parts.Count -eq 2) { $params[$parts[0]] = $parts[1] }
|
||||||
|
}
|
||||||
|
} elseif ($stripped -notmatch "[?]") {
|
||||||
|
$action = $stripped
|
||||||
|
}
|
||||||
|
return @{ action = $action; params = $params }
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-ProtocolHandler($rawUrl) {
|
||||||
|
$parsed = Parse-KfzgsUrl $rawUrl
|
||||||
|
$p = $parsed.params
|
||||||
|
if ($parsed.action -eq "launch") {
|
||||||
|
$dir = $p["dir"] -replace "/", "\"
|
||||||
|
$exeName = $p["exe"]
|
||||||
|
|
||||||
|
if ($exeName) {
|
||||||
|
if ($dir) {
|
||||||
|
if ($dir.EndsWith("\")) { $fullPath = "$dir$exeName" }
|
||||||
|
else { $fullPath = "$dir\$exeName" }
|
||||||
|
} else {
|
||||||
|
$fullPath = Join-Path $SCRIPT_DIR $exeName
|
||||||
|
}
|
||||||
|
} elseif ($dir -and $dir -match "\.exe$") {
|
||||||
|
if (Test-Path $dir) { $fullPath = $dir }
|
||||||
|
else { $fullPath = Join-Path $SCRIPT_DIR $dir }
|
||||||
|
} else { $fullPath = $EXE_PATH }
|
||||||
|
|
||||||
|
if ($fullPath -ne $EXE_PATH) {
|
||||||
|
Save-Config $fullPath
|
||||||
|
$script:EXE_PATH = $fullPath
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path $fullPath) {
|
||||||
|
$parentDir = Split-Path $fullPath -Parent
|
||||||
|
Start-Process -FilePath $fullPath -WorkingDirectory $parentDir -WindowStyle Normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Start-ApiServer {
|
||||||
|
$listener = New-Object System.Net.HttpListener
|
||||||
|
$listener.Prefixes.Add("http://127.0.0.1:$HTTP_PORT/")
|
||||||
|
try { $listener.Start() } catch { exit 1 }
|
||||||
|
|
||||||
|
$services = @{}
|
||||||
|
$services[$SERVICE_ID] = @{
|
||||||
|
id = $SERVICE_ID
|
||||||
|
name = "核价器"
|
||||||
|
exe_path = $EXE_PATH
|
||||||
|
running = $false
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($listener.IsListening) {
|
||||||
|
$context = $listener.GetContext()
|
||||||
|
$request = $context.Request
|
||||||
|
$response = $context.Response
|
||||||
|
|
||||||
|
if ($request.HttpMethod -eq "OPTIONS") {
|
||||||
|
$response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
|
||||||
|
$response.AddHeader("Access-Control-Allow-Headers", "Content-Type")
|
||||||
|
$response.StatusCode = 204
|
||||||
|
$response.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = $request.Url.AbsolutePath
|
||||||
|
$result = @{ code = 0; msg = "ok" }
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($path -eq "/api/services") {
|
||||||
|
if ($request.HttpMethod -eq "GET") {
|
||||||
|
$services[$SERVICE_ID]["exe_path"] = $EXE_PATH
|
||||||
|
$result["data"] = @($services.Values)
|
||||||
|
} elseif ($request.HttpMethod -eq "POST") {
|
||||||
|
$reader = New-Object System.IO.StreamReader($request.InputStream)
|
||||||
|
$body = $reader.ReadToEnd() | ConvertFrom-Json
|
||||||
|
if ($body.id -and $body.exe_path) {
|
||||||
|
$services[$body.id] = @{
|
||||||
|
id = $body.id
|
||||||
|
name = if ($body.name) { $body.name } else { $body.id }
|
||||||
|
exe_path = $body.exe_path
|
||||||
|
running = $false
|
||||||
|
}
|
||||||
|
Save-Config $body.exe_path
|
||||||
|
$script:EXE_PATH = $body.exe_path
|
||||||
|
$result["msg"] = "已注册: $($body.id)"
|
||||||
|
$result["data"] = $services[$body.id]
|
||||||
|
} else {
|
||||||
|
$result["code"] = 1
|
||||||
|
$result["msg"] = "缺少 id 或 exe_path"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($path -match "^/api/services/([^/]+)$" -and $request.HttpMethod -eq "GET") {
|
||||||
|
$sid = $Matches[1]
|
||||||
|
if ($services.ContainsKey($sid)) {
|
||||||
|
$result["data"] = $services[$sid]
|
||||||
|
} else {
|
||||||
|
$result["code"] = 1; $result["msg"] = "未找到"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($path -match "^/api/services/([^/]+)/start$" -and $request.HttpMethod -eq "POST") {
|
||||||
|
$sid = $Matches[1]
|
||||||
|
if ($services.ContainsKey($sid)) {
|
||||||
|
$svc = $services[$sid]
|
||||||
|
$exePath = if ($svc["exe_path"] -and (Test-Path $svc["exe_path"])) { $svc["exe_path"] } else { $EXE_PATH }
|
||||||
|
if (Test-Path $exePath) {
|
||||||
|
$parentDir = Split-Path $exePath -Parent
|
||||||
|
$proc = Start-Process -FilePath $exePath -WorkingDirectory $parentDir -WindowStyle Normal -PassThru
|
||||||
|
$svc["running"] = $true
|
||||||
|
$result["msg"] = "已启动"
|
||||||
|
$result["pid"] = $proc.Id
|
||||||
|
} else { $result["code"] = 1; $result["msg"] = "文件不存在: $exePath" }
|
||||||
|
} else { $result["code"] = 1; $result["msg"] = "未找到" }
|
||||||
|
}
|
||||||
|
elseif ($path -match "^/api/services/([^/]+)/stop$" -and $request.HttpMethod -eq "POST") {
|
||||||
|
$sid = $Matches[1]
|
||||||
|
if ($services.ContainsKey($sid)) {
|
||||||
|
$killed = $false
|
||||||
|
Get-CimInstance Win32_Process | Where-Object { $_.ExecutablePath -eq $services[$sid]["exe_path"] } | ForEach-Object {
|
||||||
|
Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue
|
||||||
|
$killed = $true
|
||||||
|
}
|
||||||
|
$services[$sid]["running"] = $false
|
||||||
|
$result["msg"] = if ($killed) { "已停止" } else { "未在运行" }
|
||||||
|
$result["killed"] = $killed
|
||||||
|
} else { $result["code"] = 1; $result["msg"] = "未找到" }
|
||||||
|
}
|
||||||
|
else { $result["code"] = 404; $result["msg"] = "未知接口" }
|
||||||
|
} catch {
|
||||||
|
$result["code"] = 1; $result["msg"] = $_.Exception.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
$json = $result | ConvertTo-Json -Compress -Depth 3
|
||||||
|
$buffer = [System.Text.Encoding]::UTF8.GetBytes($json)
|
||||||
|
$response.AddHeader("Access-Control-Allow-Origin", "*")
|
||||||
|
$response.ContentType = "application/json; charset=utf-8"
|
||||||
|
$response.ContentLength64 = $buffer.Length
|
||||||
|
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||||
|
$response.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($url -and $url -match "^kfzgs://") {
|
||||||
|
Invoke-ProtocolHandler $url
|
||||||
|
} else {
|
||||||
|
Start-ApiServer
|
||||||
|
}
|
||||||
1
verifyTool/launcher-config.json
Normal file
1
verifyTool/launcher-config.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"exe_path": "D:\\project\\psi_web\\verifyTool\\kfz-goods-pricing.exe","id": "kfz-goods-pricing","name": "核价器"}
|
||||||
47
verifyTool/setup.bat
Normal file
47
verifyTool/setup.bat
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
title 核价器协议注册
|
||||||
|
|
||||||
|
set "PROTOCOL=kfzgs"
|
||||||
|
set "EXE_NAME=kfz-goods-pricing.exe"
|
||||||
|
|
||||||
|
set "SD=%~dp0"
|
||||||
|
set "SD=%SD:~0,-1%"
|
||||||
|
|
||||||
|
set "EXE=%EXE_NAME%"
|
||||||
|
if not "%EXE:~1,2%"==":\" set "EXE=%SD%\%EXE%"
|
||||||
|
|
||||||
|
if not exist "%EXE%" (
|
||||||
|
echo [ERR] 未找到: %EXE%
|
||||||
|
pause
|
||||||
|
goto :eof
|
||||||
|
)
|
||||||
|
|
||||||
|
for %%A in ("%EXE%") do set "EXE_DIR=%%~dpA"
|
||||||
|
set "EXE_DIR=%EXE_DIR:~0,-1%"
|
||||||
|
|
||||||
|
echo ============================================
|
||||||
|
echo 核价器协议注册
|
||||||
|
echo ============================================
|
||||||
|
echo Protocol: %PROTOCOL%://
|
||||||
|
echo EXE: %EXE%
|
||||||
|
echo WorkDir: %EXE_DIR%
|
||||||
|
echo ============================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
reg delete "HKCR\%PROTOCOL%" /f >nul 2>&1
|
||||||
|
reg add "HKCR\%PROTOCOL%" /ve /d "URL:%PROTOCOL% Protocol" /f >nul
|
||||||
|
reg add "HKCR\%PROTOCOL%" /v "URL Protocol" /d "" /f >nul
|
||||||
|
reg add "HKCR\%PROTOCOL%\DefaultIcon" /ve /d "\"%EXE%\",0" /f >nul
|
||||||
|
reg add "HKCR\%PROTOCOL%\shell\open\command" /ve /d "cmd /c start \"\" /D \"%EXE_DIR%\" \"%EXE%\" \"%%1\"" /f >nul
|
||||||
|
|
||||||
|
if !errorlevel! equ 0 (
|
||||||
|
echo [OK] %PROTOCOL%:// 注册成功
|
||||||
|
echo 测试: Win+R ^> %PROTOCOL%://launch
|
||||||
|
) else (
|
||||||
|
echo [FAIL] 请右键以管理员身份运行
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
@ -212,6 +212,22 @@ module.exports = defineConfig({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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 }))
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user