添加搜索
This commit is contained in:
parent
242cc83843
commit
e9c9dcd9c5
|
|
@ -14,4 +14,7 @@ VITE_DEBUG = false
|
||||||
VITE_MQTT_TRANSACTION_HOST=wss://adminapi.apimcapital.top/mqtt
|
VITE_MQTT_TRANSACTION_HOST=wss://adminapi.apimcapital.top/mqtt
|
||||||
|
|
||||||
# exe 下载基础地址
|
# exe 下载基础地址
|
||||||
VITE_EXE_DOWNLOAD_BASE_URL = https://adminh5.apimcapital.top
|
VITE_EXE_DOWNLOAD_BASE_URL = https://adminh5.apimcapital.top
|
||||||
|
|
||||||
|
# config.json 独立部署在 h5 域名下,需要该域名侧配置 CORS
|
||||||
|
VITE_UPDATE_URL = https://adminh5.apimcapital.top/config.json
|
||||||
|
|
@ -14,4 +14,8 @@ VITE_DEBUG = true
|
||||||
VITE_MQTT_TRANSACTION_HOST = wss://adminapi.duxiang.wiki/mqtt
|
VITE_MQTT_TRANSACTION_HOST = wss://adminapi.duxiang.wiki/mqtt
|
||||||
|
|
||||||
# exe 下载基础地址
|
# exe 下载基础地址
|
||||||
VITE_EXE_DOWNLOAD_BASE_URL = https://adminh5.duxiang.wiki
|
VITE_EXE_DOWNLOAD_BASE_URL = https://adminh5.duxiang.wiki
|
||||||
|
|
||||||
|
|
||||||
|
# config.json 独立部署在 h5 域名下,需要该域名侧配置 CORS
|
||||||
|
VITE_UPDATE_URL = https://adminh5.duxiang.wiki/config.json
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import axios from 'axios'
|
||||||
|
import { request as baseRequest } from '@/api'
|
||||||
|
|
||||||
|
// 抑制未使用导入告警
|
||||||
|
void baseRequest
|
||||||
|
|
||||||
|
/**
|
||||||
|
* config.json 中与 ios 相关的配置结构
|
||||||
|
*/
|
||||||
|
export type IosConfig = {
|
||||||
|
/** iOS 下载地址(跳转目标) */
|
||||||
|
upload_url?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /config.json 整体结构(按需扩展字段)
|
||||||
|
*/
|
||||||
|
export type AppConfig = {
|
||||||
|
ios?: IosConfig
|
||||||
|
// 后续若有 android / pc / 版本号等配置也可在此扩展
|
||||||
|
[key: string]: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 静态文件请求专用的 axios 实例:
|
||||||
|
* - 不带 baseURL(绕开 src/api/index.ts 的 VITE_API_BASE_URL)
|
||||||
|
* - 不带业务 token、不触发全局 loading / 错误通知
|
||||||
|
* - 与项目里 request 拦截器彻底解耦
|
||||||
|
*/
|
||||||
|
const staticRequest = axios.create({
|
||||||
|
timeout: 10000,
|
||||||
|
headers: { 'Content-Type': 'application/json;charset=utf-8' },
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前环境下的 config.json
|
||||||
|
*
|
||||||
|
* 关键说明:
|
||||||
|
* 1. 项目里 src/api/index.ts 的 service 默认 baseURL = VITE_API_BASE_URL(业务后端),
|
||||||
|
* 直接 request.get('/config.json') 会请求业务后端下的 /config.json,自然 404。
|
||||||
|
* 2. config.json 通常独立部署在 h5 域名(如 https://adminh5.xxx.com/config.json),
|
||||||
|
* 需要直接请求该地址。这里用 VITE_UPDATE_URL(无协议/域名兜底为 VITE_EXE_DOWNLOAD_BASE_URL)作为基础域名。
|
||||||
|
* 3. 跨域:若管理后台与 config.json 部署不同源,需要 h5 域名侧 Nginx / CDN 配置 CORS 头:
|
||||||
|
* Access-Control-Allow-Origin: <管理后台域名>
|
||||||
|
* Access-Control-Allow-Methods: GET
|
||||||
|
* 否则浏览器会拦截请求。
|
||||||
|
*
|
||||||
|
* @returns Promise<AppConfig> 配置文件内容(业务调用方按需取字段)
|
||||||
|
*/
|
||||||
|
export async function getConfigApi(): Promise<AppConfig> {
|
||||||
|
// 使用相对路径 /config.json:
|
||||||
|
// - 开发环境由 vite.config.ts 的 server.proxy 转发到 h5 域名,避免 CORS
|
||||||
|
// - 生产环境需要运维在 Nginx / 网关上做同等代理(例如把 /config.json 反代到 h5 域名)
|
||||||
|
const url = '/config.json'
|
||||||
|
const sep = url.includes('?') ? '&' : '?'
|
||||||
|
const finalUrl = `${url}${sep}t=${new Date().getTime()}&channel=web`
|
||||||
|
|
||||||
|
const res = await staticRequest.get<AppConfig>(finalUrl)
|
||||||
|
return res.data
|
||||||
|
}
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
<el-button type="primary" :loading="buttonLoading" @click="$emit('search')">
|
<el-button type="primary" :loading="buttonLoading" @click="$emit('search')">
|
||||||
{{ buttonConfig.searchText || '搜索' }}
|
{{ buttonConfig.searchText || '搜索' }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button :loading="buttonLoading" @click="$emit('reset')">
|
<el-button :loading="buttonLoading" @click="$emit('reset')" v-if="isShowReset">
|
||||||
{{ buttonConfig.resetText || '重置' }}
|
{{ buttonConfig.resetText || '重置' }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- 按钮区插槽 -->
|
<!-- 按钮区插槽 -->
|
||||||
|
|
@ -97,6 +97,10 @@ const props = defineProps({
|
||||||
type: Array as () => SearchOption[],
|
type: Array as () => SearchOption[],
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
isShowReset:{
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
buttonConfig: {
|
buttonConfig: {
|
||||||
type: Object as () => ButtonConfig,
|
type: Object as () => ButtonConfig,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="position-stat table_form-container">
|
<div class="position-stat table_form-container">
|
||||||
<!-- 搜索 -->
|
<!-- 搜索 -->
|
||||||
<PositionStatSearch
|
<PositionStatSearch :buttonLoading="loading" :search-form="searchForm" :search-options="searchOptions"
|
||||||
:buttonLoading="loading" :search-form="searchForm" :search-options="searchOptions" @search="handleSearch"
|
@search="handleSearch" @reset="handleReset" :isShowReset="false">
|
||||||
@reset="handleReset">
|
|
||||||
<!-- <template #button="{ form }">-->
|
<!-- <template #button="{ form }">-->
|
||||||
<!-- <el-button type="primary" @click="handleExport()">-->
|
<!-- <el-button type="primary" @click="handleExport()">-->
|
||||||
<!-- 导出-->
|
<!-- 导出-->
|
||||||
|
|
@ -55,6 +54,9 @@ const tableColumnsOptions = ref(tableColumns)
|
||||||
* @description: 定义搜索方法
|
* @description: 定义搜索方法
|
||||||
*/
|
*/
|
||||||
const handleSearch = async () => {
|
const handleSearch = async () => {
|
||||||
|
if (!searchForm.value.account_id) {
|
||||||
|
return ElMessage.warning('请输入账户ID')
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
startLoading()
|
startLoading()
|
||||||
const data = await checkAccountIdIsSonForUser({ account_id: searchForm.value.account_id })
|
const data = await checkAccountIdIsSonForUser({ account_id: searchForm.value.account_id })
|
||||||
|
|
@ -66,6 +68,7 @@ const handleSearch = async () => {
|
||||||
} finally { stopLoading() }
|
} finally { stopLoading() }
|
||||||
}
|
}
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
|
searchForm.value.account_id = ''
|
||||||
console.log('重置搜索')
|
console.log('重置搜索')
|
||||||
}
|
}
|
||||||
const handleExport = () => {
|
const handleExport = () => {
|
||||||
|
|
@ -80,7 +83,7 @@ onMounted(() => {
|
||||||
transactionStore?.disconnect()
|
transactionStore?.disconnect()
|
||||||
transactionStore.initMarketConditionsMQTT()
|
transactionStore.initMarketConditionsMQTT()
|
||||||
})
|
})
|
||||||
onUnmounted(()=>{
|
onUnmounted(() => {
|
||||||
transactionStore?.disconnect()
|
transactionStore?.disconnect()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="download-wrapper table_form-container">
|
<div class="download-wrapper table_formcontainer">
|
||||||
<!-- PC端 -->
|
<!-- PC端 -->
|
||||||
<div class="download-item">
|
<div class="download-item">
|
||||||
<div class="item-left">
|
<div class="item-left">
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- IOS -->
|
<!-- IOS -->
|
||||||
<div class="download-item" v-if="false">
|
<div class="download-item" v-if="iosUploadUrl">
|
||||||
<div class="item-left">
|
<div class="item-left">
|
||||||
<div class="icon-box ios">
|
<div class="icon-box ios">
|
||||||
<svg viewBox="0 0 1024 1024" width="32" height="32">
|
<svg viewBox="0 0 1024 1024" width="32" height="32">
|
||||||
|
|
@ -58,11 +58,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-center">
|
<div class="item-center">
|
||||||
<span class="desc">前往App Store搜索 InTrade 安装</span>
|
<span class="desc">点击跳转至iOS下载页安装</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-right">
|
<div class="item-right">
|
||||||
<el-button type="warning" :icon="Link" @click="handleDownload('ios')">
|
<el-button type="warning" :icon="Link" :loading="iosLoading" @click="handleDownload('ios')">
|
||||||
前往商店
|
前往下载
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -71,6 +71,8 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Monitor, Download, Link } from '@element-plus/icons-vue'
|
import { Monitor, Download, Link } from '@element-plus/icons-vue'
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { getConfigApi } from '@/api/modules/config'
|
||||||
defineOptions({ name: 'Exe' })
|
defineOptions({ name: 'Exe' })
|
||||||
|
|
||||||
type DownloadType = 'pc' | 'android' | 'ios'
|
type DownloadType = 'pc' | 'android' | 'ios'
|
||||||
|
|
@ -86,10 +88,51 @@ const androidApkName = isTestEnv ? 'app-production-debug.apk' : 'app-production-
|
||||||
const downloadUrlMap: Record<DownloadType, string> = {
|
const downloadUrlMap: Record<DownloadType, string> = {
|
||||||
pc: `${exeBaseUrl}/pc/Apim Capital-1.0.27.exe`,
|
pc: `${exeBaseUrl}/pc/Apim Capital-1.0.27.exe`,
|
||||||
android: `${exeBaseUrl}/app/${androidApkName}`,
|
android: `${exeBaseUrl}/app/${androidApkName}`,
|
||||||
ios: `${exeBaseUrl}/app/xxxx.apk`
|
ios: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从 config.json 中动态获取 ios.upload_url
|
||||||
|
// 不同环境部署的 config.json 不同,开发/prod/test 会自动请求对应域名下的 /config.json
|
||||||
|
const iosUploadUrl = ref<string>('')
|
||||||
|
const iosLoading = ref(false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用统一封装在 src/api/modules/config.ts 的接口获取 /config.json,
|
||||||
|
* 从中读取 ios.upload_url 作为 iOS 下载跳转地址。
|
||||||
|
*/
|
||||||
|
const fetchIosUploadUrl = async (): Promise<string> => {
|
||||||
|
try {
|
||||||
|
const data = await getConfigApi()
|
||||||
|
console.log('data:', data);
|
||||||
|
const url = data?.ios?.upload_url
|
||||||
|
if (typeof url === 'string' && url.trim()) {
|
||||||
|
return url.trim()
|
||||||
|
}
|
||||||
|
console.warn('[Exe] /config.json 中未找到 ios.upload_url 字段')
|
||||||
|
return ''
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[Exe] 请求 /config.json 出错:', err)
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
iosLoading.value = true
|
||||||
|
iosUploadUrl.value = await fetchIosUploadUrl()
|
||||||
|
iosLoading.value = false
|
||||||
|
})
|
||||||
|
|
||||||
const handleDownload = (type: DownloadType) => {
|
const handleDownload = (type: DownloadType) => {
|
||||||
|
if (type === 'ios') {
|
||||||
|
if (!iosUploadUrl.value) {
|
||||||
|
// 未拿到地址时静默忽略,避免跳到错误页面
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// iOS 直接新窗口跳转到下载页(App Store / 安装描述文件等)
|
||||||
|
window.open(iosUploadUrl.value, '_blank', 'noopener,noreferrer')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const url: string = downloadUrlMap[type]
|
const url: string = downloadUrlMap[type]
|
||||||
// 使用 window.open 在新页签打开下载链接,
|
// 使用 window.open 在新页签打开下载链接,
|
||||||
// 避免在当前页点击 a.download 时被 SPA 路由拦截跳转到登录页
|
// 避免在当前页点击 a.download 时被 SPA 路由拦截跳转到登录页
|
||||||
|
|
@ -113,7 +156,8 @@ const handleDownload = (type: DownloadType) => {
|
||||||
.download-wrapper {
|
.download-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
|
padding: 10px 20px 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.download-item {
|
.download-item {
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,12 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||||
},
|
},
|
||||||
|
// 将 /config.json 代理到 h5 域名,避免开发环境跨域
|
||||||
|
'/config.json': {
|
||||||
|
target: env.VITE_EXE_DOWNLOAD_BASE_URL || env.VITE_UPDATE_URL,
|
||||||
|
changeOrigin: true,
|
||||||
|
secure: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue