fix(operator): fix operator edit issue
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m51s

This commit is contained in:
sexygoat
2026-04-10 14:00:21 +08:00
parent 9a6f085cde
commit 2b3119c549
53 changed files with 547 additions and 418 deletions

View File

@@ -309,7 +309,7 @@ API Status (2) -> CommonStatus.DISABLED (0)
- **网络错误**axios 拦截器统一捕获,显示通用错误提示 - **网络错误**axios 拦截器统一捕获,显示通用错误提示
- **401 未认证**:自动跳转到登录页面 - **401 未认证**:自动跳转到登录页面
- **403 无权限**:显示权限不足提示,不跳转 - **403 无权限**:显示权限不足提示,不跳转
- **400 业务错误**:根据错误信息显示具体提示(ElMessage.error - **400 业务错误**:根据错误信息显示具体提示()
- **表单验证错误**:在表单字段下显示错误提示 - **表单验证错误**:在表单字段下显示错误提示
**错误提示方式** **错误提示方式**

View File

@@ -101,9 +101,14 @@ export class BaseService {
* 获取单个资源 * 获取单个资源
* @param url 请求URL * @param url 请求URL
* @param params 请求参数 * @param params 请求参数
* @param config 额外配置
*/ */
protected static getOne<T>(url: string, params?: Record<string, any>): Promise<BaseResponse<T>> { protected static getOne<T>(
return this.get<BaseResponse<T>>(url, params) url: string,
params?: Record<string, any>,
config?: Record<string, any>
): Promise<BaseResponse<T>> {
return this.get<BaseResponse<T>>(url, params, config)
} }
/** /**

View File

@@ -38,7 +38,13 @@ export class AssetService extends BaseService {
*/ */
static getRealtimeStatus(identifier: string): Promise<BaseResponse<AssetRealtimeStatusResponse>> { static getRealtimeStatus(identifier: string): Promise<BaseResponse<AssetRealtimeStatusResponse>> {
return this.getOne<AssetRealtimeStatusResponse>( return this.getOne<AssetRealtimeStatusResponse>(
`/api/admin/assets/${identifier}/realtime-status` `/api/admin/assets/${identifier}/realtime-status`,
undefined,
{
requestOptions: {
show404Error: false // 404时不显示错误提示
}
}
) )
} }
@@ -67,7 +73,12 @@ export class AssetService extends BaseService {
): Promise<BaseResponse<AssetPackageListResponse>> { ): Promise<BaseResponse<AssetPackageListResponse>> {
return this.get<BaseResponse<AssetPackageListResponse>>( return this.get<BaseResponse<AssetPackageListResponse>>(
`/api/admin/assets/${identifier}/packages`, `/api/admin/assets/${identifier}/packages`,
params params,
{
requestOptions: {
show404Error: false // 404时不显示错误提示
}
}
) )
} }
@@ -79,7 +90,13 @@ export class AssetService extends BaseService {
*/ */
static getCurrentPackage(identifier: string): Promise<BaseResponse<AssetCurrentPackageResponse>> { static getCurrentPackage(identifier: string): Promise<BaseResponse<AssetCurrentPackageResponse>> {
return this.getOne<AssetCurrentPackageResponse>( return this.getOne<AssetCurrentPackageResponse>(
`/api/admin/assets/${identifier}/current-package` `/api/admin/assets/${identifier}/current-package`,
undefined,
{
requestOptions: {
show404Error: false // 404时不显示错误提示
}
}
) )
} }
@@ -128,7 +145,11 @@ export class AssetService extends BaseService {
* @param identifier 资产标识符ICCID 或 VirtualNo * @param identifier 资产标识符ICCID 或 VirtualNo
*/ */
static getAssetWallet(identifier: string): Promise<BaseResponse<AssetWalletResponse>> { static getAssetWallet(identifier: string): Promise<BaseResponse<AssetWalletResponse>> {
return this.getOne<AssetWalletResponse>(`/api/admin/assets/${identifier}/wallet`) return this.getOne<AssetWalletResponse>(`/api/admin/assets/${identifier}/wallet`, undefined, {
requestOptions: {
show404Error: false // 404时不显示错误提示
}
})
} }
/** /**

View File

@@ -184,7 +184,7 @@
selectOptions.value = options selectOptions.value = options
} catch (error) { } catch (error) {
console.error('远程搜索失败:', error) console.error('远程搜索失败:', error)
ElMessage.error('搜索失败,请重试') console.log('搜索失败,请重试')
} finally { } finally {
selectLoading.value = false selectLoading.value = false
} }

View File

@@ -52,7 +52,7 @@
code = generateEnterpriseCode() code = generateEnterpriseCode()
break break
default: default:
ElMessage.error('未知的编码类型') console.log('未知的编码类型')
return return
} }

View File

@@ -244,7 +244,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取客户账号列表失败') console.log('获取客户账号列表失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -198,13 +198,13 @@
}) })
if (!isValidType) { if (!isValidType) {
ElMessage.error(`只能上传 ${acceptText.value} 格式的文件`) console.log(`只能上传 ${acceptText.value} 格式的文件`)
return false return false
} }
const isLtSize = file.size / 1024 / 1024 < props.maxSize const isLtSize = file.size / 1024 / 1024 < props.maxSize
if (!isLtSize) { if (!isLtSize) {
ElMessage.error(`文件大小不能超过 ${props.maxSize}MB`) console.log(`文件大小不能超过 ${props.maxSize}MB`)
return false return false
} }
@@ -222,7 +222,7 @@
const handleUploadError = () => { const handleUploadError = () => {
uploading.value = false uploading.value = false
ElMessage.error('导入失败') console.log('导入失败')
} }
const handleConfirm = async () => { const handleConfirm = async () => {

View File

@@ -68,7 +68,7 @@
// 上传错误,或者触发 timeout 超时 // 上传错误,或者触发 timeout 超时
onError(file: File, err: any, res: any) { onError(file: File, err: any, res: any) {
console.log(`上传出错`, err, res) console.log(`上传出错`, err, res)
ElMessage.error('图片上传失败') console.log('图片上传失败')
} }
// 注意:返回格式需要按照指定格式返回,才能显示图片 // 注意:返回格式需要按照指定格式返回,才能显示图片
// 上传成功的返回格式: // 上传成功的返回格式:

View File

@@ -330,7 +330,7 @@
console.error('更新store失败:', error) console.error('更新store失败:', error)
} }
} else { } else {
ElMessage.error(t('lockScreen.pwdError')) console.log(t('lockScreen.pwdError'))
} }
} else { } else {
console.error('表单验证失败:', fields) console.error('表单验证失败:', fields)

View File

@@ -38,7 +38,7 @@ export function useAgentManagement() {
setTotal(res.data.total) setTotal(res.data.total)
} catch (error) { } catch (error) {
console.error('获取代理商列表失败:', error) console.error('获取代理商列表失败:', error)
ElMessage.error('获取代理商列表失败') console.log('获取代理商列表失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -54,7 +54,7 @@ export function useAgentManagement() {
treeData.value = res.data treeData.value = res.data
} catch (error) { } catch (error) {
console.error('获取代理商树失败:', error) console.error('获取代理商树失败:', error)
ElMessage.error('获取代理商树失败') console.log('获取代理商树失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -71,7 +71,7 @@ export function useAgentManagement() {
return res.data return res.data
} catch (error) { } catch (error) {
console.error('获取代理商详情失败:', error) console.error('获取代理商详情失败:', error)
ElMessage.error('获取代理商详情失败') console.log('获取代理商详情失败')
return null return null
} finally { } finally {
loading.value = false loading.value = false
@@ -90,7 +90,7 @@ export function useAgentManagement() {
return true return true
} catch (error) { } catch (error) {
console.error('创建失败:', error) console.error('创建失败:', error)
ElMessage.error('创建失败') console.log('创建失败')
return false return false
} finally { } finally {
loading.value = false loading.value = false
@@ -110,7 +110,7 @@ export function useAgentManagement() {
return true return true
} catch (error) { } catch (error) {
console.error('更新失败:', error) console.error('更新失败:', error)
ElMessage.error('更新失败') console.log('更新失败')
return false return false
} finally { } finally {
loading.value = false loading.value = false
@@ -130,7 +130,7 @@ export function useAgentManagement() {
return true return true
} catch (error) { } catch (error) {
console.error('状态更新失败:', error) console.error('状态更新失败:', error)
ElMessage.error('状态更新失败') console.log('状态更新失败')
return false return false
} finally { } finally {
loading.value = false loading.value = false
@@ -148,7 +148,7 @@ export function useAgentManagement() {
return res.data return res.data
} catch (error) { } catch (error) {
console.error('获取下级代理失败:', error) console.error('获取下级代理失败:', error)
ElMessage.error('获取下级代理失败') console.log('获取下级代理失败')
return [] return []
} finally { } finally {
loading.value = false loading.value = false

View File

@@ -40,7 +40,7 @@ export function useCardManagement() {
setTotal(res.data.total) setTotal(res.data.total)
} catch (error) { } catch (error) {
console.error('获取网卡列表失败:', error) console.error('获取网卡列表失败:', error)
ElMessage.error('获取网卡列表失败') console.log('获取网卡列表失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -57,7 +57,7 @@ export function useCardManagement() {
return res.data return res.data
} catch (error) { } catch (error) {
console.error('获取单卡信息失败:', error) console.error('获取单卡信息失败:', error)
ElMessage.error('获取单卡信息失败') console.log('获取单卡信息失败')
return null return null
} finally { } finally {
loading.value = false loading.value = false
@@ -76,7 +76,7 @@ export function useCardManagement() {
return true return true
} catch (error) { } catch (error) {
console.error('操作失败:', error) console.error('操作失败:', error)
ElMessage.error('操作失败') console.log('操作失败')
return false return false
} finally { } finally {
loading.value = false loading.value = false
@@ -96,7 +96,7 @@ export function useCardManagement() {
return true return true
} catch (error) { } catch (error) {
console.error('停机失败:', error) console.error('停机失败:', error)
ElMessage.error('停机失败') console.log('停机失败')
return false return false
} finally { } finally {
loading.value = false loading.value = false
@@ -116,7 +116,7 @@ export function useCardManagement() {
return true return true
} catch (error) { } catch (error) {
console.error('复机失败:', error) console.error('复机失败:', error)
ElMessage.error('复机失败') console.log('复机失败')
return false return false
} finally { } finally {
loading.value = false loading.value = false
@@ -136,7 +136,7 @@ export function useCardManagement() {
return true return true
} catch (error) { } catch (error) {
console.error('导入失败:', error) console.error('导入失败:', error)
ElMessage.error('导入失败') console.log('导入失败')
return false return false
} finally { } finally {
loading.value = false loading.value = false

View File

@@ -133,7 +133,7 @@ export function useLogin() {
const loginResult = mockLogin(formData.username, formData.password) const loginResult = mockLogin(formData.username, formData.password)
if (!loginResult) { if (!loginResult) {
ElMessage.error(t('login.error.invalidCredentials')) console.log(t('login.error.invalidCredentials'))
return return
} }
@@ -144,7 +144,7 @@ export function useLogin() {
const userInfo = mockGetUserInfo(loginResult.access_token) const userInfo = mockGetUserInfo(loginResult.access_token)
if (!userInfo) { if (!userInfo) {
ElMessage.error(t('login.error.getUserInfoFailed')) console.log(t('login.error.getUserInfoFailed'))
return return
} }
@@ -175,19 +175,19 @@ export function useLogin() {
// 检查响应状态 // 检查响应状态
if (response.code !== ApiStatus.success) { if (response.code !== ApiStatus.success) {
ElMessage.error(response.msg || t('login.error.invalidCredentials')) console.log(response.msg || t('login.error.invalidCredentials'))
return return
} }
// 检查返回数据 // 检查返回数据
if (!response.data || !response.data.access_token) { if (!response.data || !response.data.access_token) {
ElMessage.error(t('login.error.loginFailed')) console.log(t('login.error.loginFailed'))
return return
} }
// 检查用户类型 - 禁止企业账号登录 // 检查用户类型 - 禁止企业账号登录
if (response.data.user && response.data.user.user_type === 4) { if (response.data.user && response.data.user.user_type === 4) {
ElMessage.error('企业账号无法登录后台管理系统') console.log('企业账号无法登录后台管理系统')
return return
} }
@@ -199,7 +199,7 @@ export function useLogin() {
userStore.setUserInfo(response.data.user) userStore.setUserInfo(response.data.user)
userStore.setLoginStatus(true) userStore.setLoginStatus(true)
} else { } else {
ElMessage.error(t('login.error.getUserInfoFailed')) console.log(t('login.error.getUserInfoFailed'))
return return
} }

View File

@@ -27,6 +27,8 @@ export interface RequestOptions {
ignoreCancelToken?: boolean ignoreCancelToken?: boolean
// 是否携带token // 是否携带token
withToken?: boolean withToken?: boolean
// 是否显示404错误提示默认false即默认不显示404错误
show404Error?: boolean
} }
// 请求方法类型 // 请求方法类型

View File

@@ -212,13 +212,34 @@ function processRequestConfig(config: ExtendedRequestConfig): AxiosRequestConfig
} }
// 处理错误消息 // 处理错误消息
function handleErrorMessage(error: any, mode: ErrorMessageMode = 'message') { function handleErrorMessage(
error: any,
mode: ErrorMessageMode = 'message',
show404Error: boolean = true
) {
if (mode === 'none') return if (mode === 'none') return
// 优先使用响应中的 msg 字段 const backendMessage = error.response?.data?.msg
const errorMessage = error.response?.data?.msg || error.message const httpStatus = error.response?.status
const message = errorMessage || '请求超时或服务器异常!'
// 如果是404错误且未配置显示404错误则不显示任何提示
if (httpStatus === 404 && !show404Error) {
return
}
// 如果后端返回了错误信息,使用后端信息
if (backendMessage) {
if (mode === 'modal') {
// TODO: 可以使用 ElMessageBox 显示模态框
ElMessage.error(backendMessage)
} else {
ElMessage.error(backendMessage)
}
return
}
// 其他错误显示通用提示
const message = '请求超时或服务器异常!'
if (mode === 'modal') { if (mode === 'modal') {
// TODO: 可以使用 ElMessageBox 显示模态框 // TODO: 可以使用 ElMessageBox 显示模态框
ElMessage.error(message) ElMessage.error(message)
@@ -251,7 +272,10 @@ async function request<T = any>(config: ExtendedRequestConfig): Promise<T> {
if (axios.isAxiosError(e)) { if (axios.isAxiosError(e)) {
// 默认显示错误消息,除非明确设置为 'none' // 默认显示错误消息,除非明确设置为 'none'
const errorMode = config.requestOptions?.errorMessageMode || 'message' const errorMode = config.requestOptions?.errorMessageMode || 'message'
handleErrorMessage(e, errorMode) const show404Error = config.requestOptions?.show404Error !== undefined
? config.requestOptions.show404Error
: true
handleErrorMessage(e, errorMode, show404Error)
} }
return Promise.reject(e) return Promise.reject(e)
} }
@@ -279,14 +303,6 @@ const api = {
} }
} }
// 退出登录(调用接口)
const logOut = () => {
ElMessage.error('登录已过期,请重新登录')
setTimeout(() => {
useUserStore().logOut()
}, 1000)
}
// 仅清理本地状态(不调用接口)- 用于401等情况 // 仅清理本地状态(不调用接口)- 用于401等情况
const clearLocalStateAndRedirect = () => { const clearLocalStateAndRedirect = () => {
ElMessage.error('登录已过期,请重新登录') ElMessage.error('登录已过期,请重新登录')

View File

@@ -40,6 +40,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { ref } from 'vue'
import { useRoute } from 'vue-router'
import { ElCard, ElInput, ElButton } from 'element-plus' import { ElCard, ElInput, ElButton } from 'element-plus'
import { Search, Refresh } from '@element-plus/icons-vue' import { Search, Refresh } from '@element-plus/icons-vue'
import { useAssetFormatters } from '../composables/useAssetFormatters' import { useAssetFormatters } from '../composables/useAssetFormatters'
@@ -47,6 +48,8 @@
// Use formatters // Use formatters
const { formatIccidWithDashes } = useAssetFormatters() const { formatIccidWithDashes } = useAssetFormatters()
const route = useRoute()
// Props // Props
interface Props { interface Props {
hasCardInfo?: boolean hasCardInfo?: boolean
@@ -66,6 +69,26 @@
const searchIccid = ref('') const searchIccid = ref('')
const iccidInputFocused = ref(false) const iccidInputFocused = ref(false)
// 从URL参数中获取初始值
const initializeFromQuery = () => {
const iccid = route.query.iccid as string
const virtualNo = route.query.virtual_no as string
const deviceNo = route.query.device_no as string
const identifier = iccid || virtualNo || deviceNo
if (identifier) {
searchIccid.value = identifier
}
}
// 初始化时从URL参数加载
initializeFromQuery()
// 暴露方法供父组件调用,用于更新搜索框值
const updateSearchValue = (value: string) => {
searchIccid.value = value
}
// Methods // Methods
const handleSearch = () => { const handleSearch = () => {
if (!searchIccid.value.trim()) { if (!searchIccid.value.trim()) {
@@ -77,6 +100,11 @@
const handleRefresh = () => { const handleRefresh = () => {
emit('refresh') emit('refresh')
} }
// 暴露给父组件
defineExpose({
updateSearchValue
})
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@@ -477,9 +477,10 @@
(e: 'resetDevice'): void (e: 'resetDevice'): void
(e: 'showSpeedLimit'): void (e: 'showSpeedLimit'): void
(e: 'showSwitchCard'): void (e: 'showSwitchCard'): void
(e: 'showSetWiFi'): void (e: 'show-set-wifi'): void
(e: 'enableBindingCard', payload: { card: BindingCard }): void (e: 'enableBindingCard', payload: { card: BindingCard }): void
(e: 'disableBindingCard', payload: { card: BindingCard }): void (e: 'disableBindingCard', payload: { card: BindingCard }): void
(e: 'navigateToCard', iccid: string): void
} }
const emit = defineEmits<Emits>() const emit = defineEmits<Emits>()
@@ -528,8 +529,8 @@
// 跳转到卡片信息 // 跳转到卡片信息
const handleNavigateToCardInfo = (iccid: string) => { const handleNavigateToCardInfo = (iccid: string) => {
// 可以通过路由跳转或触发搜索 // 触发搜索事件,让父组件处理
console.log('Navigate to card:', iccid) emit('navigateToCard', iccid)
} }
// 卡操作 // 卡操作
@@ -559,7 +560,7 @@
} }
const handleShowSetWiFi = () => { const handleShowSetWiFi = () => {
emit('showSetWiFi') emit('show-set-wifi')
} }
// 绑定卡操作 // 绑定卡操作

View File

@@ -69,27 +69,27 @@
.wallet-balance-cards { .wallet-balance-cards {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8px; gap: 12px;
.balance-card { .balance-card {
display: flex; display: flex;
gap: 10px; gap: 14px;
align-items: center; align-items: center;
padding: 10px 14px; padding: 16px 18px;
background: var(--el-fill-color-light); background: var(--el-fill-color-light);
border: 1px solid var(--el-border-color-lighter); border: 1px solid var(--el-border-color-lighter);
border-radius: 4px; border-radius: 6px;
transition: all 0.3s ease; transition: all 0.3s ease;
&:hover { &:hover {
border-color: var(--el-color-primary); border-color: var(--el-color-primary);
box-shadow: 0 2px 6px rgb(0 0 0 / 6%); box-shadow: 0 2px 8px rgb(0 0 0 / 8%);
transform: translateX(2px); transform: translateX(2px);
} }
.balance-icon { .balance-icon {
flex-shrink: 0; flex-shrink: 0;
font-size: 20px; font-size: 26px;
line-height: 1; line-height: 1;
} }
@@ -97,16 +97,18 @@
display: flex; display: flex;
flex: 1; flex: 1;
flex-direction: column; flex-direction: column;
gap: 2px; gap: 4px;
.balance-label { .balance-label {
font-size: 12px; font-size: 11px;
font-weight: 500;
color: var(--el-text-color-secondary); color: var(--el-text-color-secondary);
} }
.balance-value { .balance-value {
font-size: 18px; font-size: 20px;
font-weight: 600; font-weight: 600;
line-height: 1.2;
color: var(--el-text-color-primary); color: var(--el-text-color-primary);
} }
} }

View File

@@ -25,10 +25,9 @@
start-placeholder="开始时间" start-placeholder="开始时间"
end-placeholder="结束时间" end-placeholder="结束时间"
style="width: 360px" style="width: 360px"
@change="handleDateChange"
/> />
<ElButton type="primary" @click="handleFilterChange">查询</ElButton> <ElButton type="primary" @click="handleQuery">查询</ElButton>
<ElButton @click="handleResetFilter">重置</ElButton> <ElButton @click="handleReset">重置</ElButton>
</div> </div>
</div> </div>
</template> </template>
@@ -194,28 +193,26 @@
} }
} }
// 处理日期范围变化 // 处理查询按钮点击
const handleDateChange = (value: [Date, Date] | null) => { const handleQuery = () => {
if (value && value.length === 2) { queryParams.value.page = 1
// 转换为 RFC3339 格式 pagination.value.page = 1
queryParams.value.start_time = value[0].toISOString() queryParams.value.transaction_type = filterForm.value.transaction_type
queryParams.value.end_time = value[1].toISOString()
// 处理日期范围
if (filterForm.value.date_range && filterForm.value.date_range.length === 2) {
queryParams.value.start_time = filterForm.value.date_range[0].toISOString()
queryParams.value.end_time = filterForm.value.date_range[1].toISOString()
} else { } else {
queryParams.value.start_time = null queryParams.value.start_time = null
queryParams.value.end_time = null queryParams.value.end_time = null
} }
}
// 处理筛选条件变化
const handleFilterChange = () => {
queryParams.value.page = 1
pagination.value.page = 1
queryParams.value.transaction_type = filterForm.value.transaction_type
loadTransactions() loadTransactions()
} }
// 重置筛选条件 // 处理重置按钮点击
const handleResetFilter = () => { const handleReset = () => {
filterForm.value = { filterForm.value = {
transaction_type: null, transaction_type: null,
date_range: null date_range: null
@@ -254,7 +251,7 @@
(newVal) => { (newVal) => {
if (newVal) { if (newVal) {
// 重置状态 // 重置状态
handleResetFilter() handleReset()
} }
}, },
{ immediate: true } { immediate: true }

View File

@@ -144,7 +144,7 @@
} }
} catch (error) { } catch (error) {
console.error('加载流量详单失败:', error) console.error('加载流量详单失败:', error)
ElMessage.error('加载流量详单失败') console.log('加载流量详单失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -194,7 +194,7 @@
} }
} catch (error: any) { } catch (error: any) {
console.error('加载往期订单失败:', error) console.error('加载往期订单失败:', error)
ElMessage.error(error?.message || '加载往期订单失败') console.log(error?.message || '加载往期订单失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -141,7 +141,7 @@
} }
} catch (error: any) { } catch (error: any) {
console.error('加载套餐列表失败:', error) console.error('加载套餐列表失败:', error)
ElMessage.error(error?.message || '加载套餐列表失败') console.log(error?.message || '加载套餐列表失败')
} finally { } finally {
packageSearchLoading.value = false packageSearchLoading.value = false
} }

View File

@@ -138,7 +138,7 @@
} }
} catch (error) { } catch (error) {
console.error('加载设备绑定卡列表失败:', error) console.error('加载设备绑定卡列表失败:', error)
ElMessage.error('加载卡列表失败') console.log('加载卡列表失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<ElDialog v-model="visible" title="设置WiFi" width="500px"> <ElDialog v-model="visible" title="设置WiFi" width="500px" :append-to-body="true">
<ElForm ref="formRef" :model="form" :rules="rules" label-width="120px"> <ElForm ref="formRef" :model="form" :rules="rules" label-width="120px">
<ElFormItem label="WiFi状态" prop="enabled"> <ElFormItem label="WiFi状态" prop="enabled">
<ElRadioGroup v-model="form.enabled"> <ElRadioGroup v-model="form.enabled">

View File

@@ -6,7 +6,7 @@
import { ref } from 'vue' import { ref } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { AssetService } from '@/api/modules' import { AssetService } from '@/api/modules'
import type { AssetWalletResponse } from '@/types/api' import type { AssetWalletResponse, DeviceGatewayInfo, AssetPackageUsageRecord } from '@/types/api'
/** /**
* 格式化数据大小(MB -> GB/MB) * 格式化数据大小(MB -> GB/MB)
@@ -22,11 +22,11 @@ export function useAssetInfo() {
// 状态管理 // 状态管理
const loading = ref(false) const loading = ref(false)
const cardInfo = ref<any>(null) // 使用 any 以保持与原始实现一致 const cardInfo = ref<any>(null) // 使用 any 以保持与原始实现一致
const deviceRealtime = ref<DeviceRealtimeInfo | null>(null) const deviceRealtime = ref<DeviceGatewayInfo | null>(null)
const currentPackage = ref<PackageInfo | null>(null) const currentPackage = ref<AssetPackageUsageRecord | null>(null)
const currentPackageLoading = ref(false) const currentPackageLoading = ref(false)
const currentPackageErrorMsg = ref('') const currentPackageErrorMsg = ref('')
const packageList = ref<PackageInfo[]>([]) const packageList = ref<AssetPackageUsageRecord[]>([])
const walletInfo = ref<AssetWalletResponse | null>(null) const walletInfo = ref<AssetWalletResponse | null>(null)
const walletLoading = ref(false) const walletLoading = ref(false)
@@ -111,7 +111,7 @@ export function useAssetInfo() {
const assetIdentifier = data.asset_type === 'card' ? data.iccid : data.virtual_no const assetIdentifier = data.asset_type === 'card' ? data.iccid : data.virtual_no
if (assetIdentifier) { if (assetIdentifier) {
// 并行调用多个接口: 当前生效套餐、套餐列表、实时状态、钱包概况 // 并行调用多个接口: 当前生效套餐、套餐列表、实时状态、钱包概况
Promise.all([ await Promise.all([
loadCurrentPackage(assetIdentifier), loadCurrentPackage(assetIdentifier),
loadPackageList(assetIdentifier), loadPackageList(assetIdentifier),
loadRealtimeStatus(assetIdentifier, data.asset_type), loadRealtimeStatus(assetIdentifier, data.asset_type),
@@ -319,11 +319,9 @@ export function useAssetInfo() {
await loadRealtimeStatus(identifier, assetType) await loadRealtimeStatus(identifier, assetType)
} }
} catch (error: any) { } catch (error: any) {
// 检查429错误(冷却期) // 检查 429 错误(冷却期)
if (error?.response?.status === 429) { if (error?.response?.status === 429) {
ElMessage.warning('刷新过于频繁,请稍后再试') ElMessage.warning('刷新过于频繁,请稍后再试')
} else {
ElMessage.error(error?.message || '刷新失败')
} }
throw error throw error
} }

View File

@@ -101,7 +101,7 @@ export function useAssetOperations(cardInfo: Ref<any>, refreshAssetFn?: () => Pr
} catch (error: any) { } catch (error: any) {
if (error !== 'cancel') { if (error !== 'cancel') {
console.error('手动停用失败:', error) console.error('手动停用失败:', error)
ElMessage.error(error?.message || '手动停用失败') console.log(error?.message || '手动停用失败')
} }
} finally { } finally {
manualDeactivateCardLoading.value = false manualDeactivateCardLoading.value = false
@@ -186,7 +186,7 @@ export function useAssetOperations(cardInfo: Ref<any>, refreshAssetFn?: () => Pr
} }
} catch (error: any) { } catch (error: any) {
console.error('设置限速失败:', error) console.error('设置限速失败:', error)
ElMessage.error(error?.message || '设置失败') console.log(error?.message || '设置失败')
return false return false
} finally { } finally {
speedLimitLoading.value = false speedLimitLoading.value = false
@@ -214,7 +214,7 @@ export function useAssetOperations(cardInfo: Ref<any>, refreshAssetFn?: () => Pr
} }
} catch (error: any) { } catch (error: any) {
console.error('切换SIM卡失败:', error) console.error('切换SIM卡失败:', error)
ElMessage.error(error?.message || '切换失败') console.log(error?.message || '切换失败')
return false return false
} finally { } finally {
switchCardLoading.value = false switchCardLoading.value = false
@@ -244,7 +244,7 @@ export function useAssetOperations(cardInfo: Ref<any>, refreshAssetFn?: () => Pr
} }
} catch (error: any) { } catch (error: any) {
console.error('设置WiFi失败:', error) console.error('设置WiFi失败:', error)
ElMessage.error(error?.message || '设置WiFi失败') console.log(error?.message || '设置WiFi失败')
return false return false
} finally { } finally {
setWiFiLoading.value = false setWiFiLoading.value = false
@@ -282,7 +282,7 @@ export function useAssetOperations(cardInfo: Ref<any>, refreshAssetFn?: () => Pr
} }
} catch (error: any) { } catch (error: any) {
console.error('更新轮询状态失败:', error) console.error('更新轮询状态失败:', error)
ElMessage.error(error?.message || '更新轮询状态失败') console.log(error?.message || '更新轮询状态失败')
return false return false
} finally { } finally {
pollingLoading.value = false pollingLoading.value = false

View File

@@ -1,7 +1,12 @@
<template> <template>
<div class="single-card-page"> <div class="single-card-page">
<!-- 资产查询区域 --> <!-- 资产查询区域 -->
<AssetSearchCard :has-card-info="!!cardInfo" @search="handleSearch" @refresh="handleRefresh" /> <AssetSearchCard
ref="assetSearchCardRef"
:has-card-info="!!cardInfo"
@search="handleSearch"
@refresh="handleRefresh"
/>
<!-- 卡片内容区域 --> <!-- 卡片内容区域 -->
<div v-if="cardInfo" class="card-content-area slide-in"> <div v-if="cardInfo" class="card-content-area slide-in">
@@ -21,6 +26,7 @@
@show-set-wifi="showSetWiFiDialog" @show-set-wifi="showSetWiFiDialog"
@enable-binding-card="handleEnableBindingCard" @enable-binding-card="handleEnableBindingCard"
@disable-binding-card="handleDisableBindingCard" @disable-binding-card="handleDisableBindingCard"
@navigate-to-card="handleNavigateToCard"
/> />
</div> </div>
@@ -120,6 +126,9 @@
const route = useRoute() const route = useRoute()
// ========== 组件引用 ==========
const assetSearchCardRef = ref<InstanceType<typeof AssetSearchCard>>()
// ========== 核心数据状态(使用 composable ========== // ========== 核心数据状态(使用 composable ==========
const { const {
cardInfo, cardInfo,
@@ -174,16 +183,11 @@
* 处理资产搜索 * 处理资产搜索
*/ */
const handleSearch = async ({ identifier }: { identifier: string }) => { const handleSearch = async ({ identifier }: { identifier: string }) => {
// 更新搜索框的值
assetSearchCardRef.value?.updateSearchValue(identifier)
// fetchAssetDetail 内部已经会并行加载所有相关数据,不需要重复调用
await fetchAssetDetail(identifier) await fetchAssetDetail(identifier)
if (cardInfo.value) {
// 并行加载相关数据
await Promise.all([
loadPackageList(cardInfo.value.identifier),
loadCurrentPackage(cardInfo.value.identifier),
loadRealtimeStatus(cardInfo.value.identifier, cardInfo.value.asset_type),
loadAssetWallet(cardInfo.value.identifier)
])
}
} }
/** /**
@@ -269,19 +273,35 @@
/** /**
* 绑定卡操作 - 启用绑定卡 * 绑定卡操作 - 启用绑定卡
*/ */
// eslint-disable-next-line @typescript-eslint/no-unused-vars const handleEnableBindingCard = async (payload: { card: any }) => {
const handleEnableBindingCard = async (_card: any) => { const { card } = payload
// TODO: 实现启用绑定卡逻辑 try {
ElMessage.info('启用绑定卡功能待实现') const { CardService } = await import('@/api/modules')
await CardService.enableIotCard(card.iccid)
ElMessage.success('启用成功')
// 刷新资产信息
await handleRefresh()
} catch (error: any) {
console.error('启用绑定卡失败:', error)
ElMessage.error(error?.message || '启用失败')
}
} }
/** /**
* 绑定卡操作 - 停用绑定卡 * 绑定卡操作 - 停用绑定卡
*/ */
// eslint-disable-next-line @typescript-eslint/no-unused-vars const handleDisableBindingCard = async (payload: { card: any }) => {
const handleDisableBindingCard = async (_card: any) => { const { card } = payload
// TODO: 实现停用绑定卡逻辑 try {
ElMessage.info('停用绑定卡功能待实现') const { CardService } = await import('@/api/modules')
await CardService.disableIotCard(card.iccid)
ElMessage.success('停用成功')
// 刷新资产信息
await handleRefresh()
} catch (error: any) {
console.error('停用绑定卡失败:', error)
ElMessage.error(error?.message || '停用失败')
}
} }
/** /**
@@ -314,6 +334,13 @@
dailyRecordsDialogVisible.value = true dailyRecordsDialogVisible.value = true
} }
/**
* 跳转到绑定卡信息
*/
const handleNavigateToCard = async (iccid: string) => {
await handleSearch({ identifier: iccid })
}
/** /**
* URL参数自动加载 * URL参数自动加载
*/ */

View File

@@ -583,7 +583,7 @@
getEnterpriseInfo() getEnterpriseInfo()
getTableData() getTableData()
} else { } else {
ElMessage.error('缺少企业ID') console.log('缺少企业ID')
goBack() goBack()
} }
}) })
@@ -631,7 +631,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取企业卡列表失败') console.log('获取企业卡列表失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -811,7 +811,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取卡列表失败') console.log('获取卡列表失败')
} finally { } finally {
availableCardsLoading.value = false availableCardsLoading.value = false
} }
@@ -889,7 +889,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('授权失败') console.log('授权失败')
} finally { } finally {
allocateLoading.value = false allocateLoading.value = false
} }
@@ -939,7 +939,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('回收失败') console.log('回收失败')
} finally { } finally {
recallLoading.value = false recallLoading.value = false
} }
@@ -1023,7 +1023,7 @@
getTableData() getTableData()
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('停机失败') console.log('停机失败')
} }
}) })
.catch(() => {}) .catch(() => {})
@@ -1043,7 +1043,7 @@
getTableData() getTableData()
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('复机失败') console.log('复机失败')
} }
}) })
.catch(() => {}) .catch(() => {})

View File

@@ -157,11 +157,7 @@
</ElDialog> </ElDialog>
<!-- 结果对话框 --> <!-- 结果对话框 -->
<ElDialog <ElDialog v-model="resultDialogVisible" title="操作结果" width="700px">
v-model="resultDialogVisible"
title="操作结果"
width="700px"
>
<ElDescriptions :column="2" border> <ElDescriptions :column="2" border>
<ElDescriptionsItem label="成功数量"> <ElDescriptionsItem label="成功数量">
<ElTag type="success">{{ operationResult.success_count }}</ElTag> <ElTag type="success">{{ operationResult.success_count }}</ElTag>
@@ -178,11 +174,7 @@
> >
<ElDivider content-position="left">失败项</ElDivider> <ElDivider content-position="left">失败项</ElDivider>
<ElTable :data="operationResult.failed_items" border max-height="300"> <ElTable :data="operationResult.failed_items" border max-height="300">
<ElTableColumn <ElTableColumn prop="virtual_no" label="设备号" width="180" />
prop="virtual_no"
label="设备号"
width="180"
/>
<ElTableColumn prop="reason" label="失败原因" /> <ElTableColumn prop="reason" label="失败原因" />
</ElTable> </ElTable>
</div> </div>
@@ -196,16 +188,8 @@
> >
<ElDivider content-position="left">已授权设备</ElDivider> <ElDivider content-position="left">已授权设备</ElDivider>
<ElTable :data="operationResult.authorized_devices" border max-height="200"> <ElTable :data="operationResult.authorized_devices" border max-height="200">
<ElTableColumn <ElTableColumn prop="virtual_no" label="设备号" width="180" />
prop="virtual_no" <ElTableColumn prop="device_id" label="设备ID" width="100" />
label="设备号"
width="180"
/>
<ElTableColumn
prop="device_id"
label="设备ID"
width="100"
/>
<ElTableColumn label="绑定卡数"> <ElTableColumn label="绑定卡数">
<template #default="{ row }"> <template #default="{ row }">
{{ row.card_count || 0 }} {{ row.card_count || 0 }}
@@ -756,7 +740,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('撤销授权失败') console.logr('撤销授权失败')
} finally { } finally {
recallLoading.value = false recallLoading.value = false
} }

View File

@@ -63,7 +63,9 @@
<p>4. <strong>重要列顺序固定不可调整</strong>系统按位置读取不识别列名</p> <p>4. <strong>重要列顺序固定不可调整</strong>系统按位置读取不识别列名</p>
<p>5. 必填列虚拟号第1列</p> <p>5. 必填列虚拟号第1列</p>
<p <p
>6. 可选列设备名称设备型号设备类型IMEI制造商最大SIM槽数默认4有效范围1-4卡1~卡4 ICCID</p >6.
可选列设备名称设备型号设备类型IMEI制造商最大SIM槽数默认4有效范围1-4卡1~卡4
ICCID</p
> >
</div> </div>
</template> </template>
@@ -566,7 +568,7 @@
}) })
} catch (error: any) { } catch (error: any) {
console.error('设备导入失败:', error) console.error('设备导入失败:', error)
ElMessage.error(error.message || '设备导入失败') console.log(error.message || '设备导入失败')
} finally { } finally {
uploading.value = false uploading.value = false
} }

View File

@@ -775,7 +775,7 @@
}) })
} catch (error: any) { } catch (error: any) {
console.error('IoT卡导入失败:', error) console.error('IoT卡导入失败:', error)
ElMessage.error(error.message || 'IoT卡导入失败') console.log(error.message || 'IoT卡导入失败')
} finally { } finally {
uploading.value = false uploading.value = false
} }

View File

@@ -622,7 +622,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取数据失败') console.log('获取数据失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -736,7 +736,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取佣金明细失败') console.log('获取佣金明细失败')
} finally { } finally {
commissionLoading.value = false commissionLoading.value = false
} }
@@ -773,7 +773,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取提现记录失败') console.log('获取提现记录失败')
} finally { } finally {
withdrawalLoading.value = false withdrawalLoading.value = false
} }
@@ -810,7 +810,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取预充值钱包流水失败') console.log('获取预充值钱包流水失败')
} finally { } finally {
mainWalletLoading.value = false mainWalletLoading.value = false
} }
@@ -878,10 +878,10 @@
resolveFormRef.value?.resetFields() resolveFormRef.value?.resetFields()
// 刷新佣金明细列表 // 刷新佣金明细列表
loadCommissionRecords() await loadCommissionRecords()
} catch (error: any) { } catch (error: any) {
console.error(error) console.error(error)
ElMessage.error(error?.message || `${actionText}失败`) console.log(error?.message || `${actionText}失败`)
} finally { } finally {
resolveSubmitLoading.value = false resolveSubmitLoading.value = false
} }

View File

@@ -429,7 +429,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取账号列表失败') console.log('获取账号列表失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -544,7 +544,7 @@
getTableData() getTableData()
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('添加账号失败') console.log('添加账号失败')
} finally { } finally {
submitLoading.value = false submitLoading.value = false
} }

View File

@@ -13,7 +13,10 @@
</template> </template>
<div class="stats-grid"> <div class="stats-grid">
<div class="stat-card"> <div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%)"> <div
class="stat-icon"
style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%)"
>
<el-icon :size="24"><Document /></el-icon> <el-icon :size="24"><Document /></el-icon>
</div> </div>
<div class="stat-content"> <div class="stat-content">
@@ -22,41 +25,60 @@
</div> </div>
</div> </div>
<div class="stat-card"> <div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%)"> <div
class="stat-icon"
style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%)"
>
<el-icon :size="24"><CircleCheck /></el-icon> <el-icon :size="24"><CircleCheck /></el-icon>
</div> </div>
<div class="stat-content"> <div class="stat-content">
<div class="stat-label">已初始化</div> <div class="stat-label">已初始化</div>
<div class="stat-value"> <div class="stat-value">
{{ overviewStats?.initialized_cards?.toLocaleString() || 0 }} / {{ overviewStats?.total_cards?.toLocaleString() || 0 }} {{ overviewStats?.initialized_cards?.toLocaleString() || 0 }} /
{{ overviewStats?.total_cards?.toLocaleString() || 0 }}
</div> </div>
</div> </div>
</div> </div>
<div class="stat-card"> <div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)"> <div
class="stat-icon"
style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)"
>
<el-icon :size="24"><User /></el-icon> <el-icon :size="24"><User /></el-icon>
</div> </div>
<div class="stat-content"> <div class="stat-content">
<div class="stat-label">实名队列</div> <div class="stat-label">实名队列</div>
<div class="stat-value">{{ overviewStats?.realname_queue_size?.toLocaleString() || 0 }}</div> <div class="stat-value">{{
overviewStats?.realname_queue_size?.toLocaleString() || 0
}}</div>
</div> </div>
</div> </div>
<div class="stat-card"> <div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)"> <div
class="stat-icon"
style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)"
>
<el-icon :size="24"><Box /></el-icon> <el-icon :size="24"><Box /></el-icon>
</div> </div>
<div class="stat-content"> <div class="stat-content">
<div class="stat-label">套餐队列</div> <div class="stat-label">套餐队列</div>
<div class="stat-value">{{ overviewStats?.package_queue_size?.toLocaleString() || 0 }}</div> <div class="stat-value">{{
overviewStats?.package_queue_size?.toLocaleString() || 0
}}</div>
</div> </div>
</div> </div>
<div class="stat-card"> <div class="stat-card">
<div class="stat-icon" style="background: linear-gradient(135deg, #fa709a 0%, #fee140 100%)"> <div
class="stat-icon"
style="background: linear-gradient(135deg, #fa709a 0%, #fee140 100%)"
>
<el-icon :size="24"><DataLine /></el-icon> <el-icon :size="24"><DataLine /></el-icon>
</div> </div>
<div class="stat-content"> <div class="stat-content">
<div class="stat-label">流量队列</div> <div class="stat-label">流量队列</div>
<div class="stat-value">{{ overviewStats?.carddata_queue_size?.toLocaleString() || 0 }}</div> <div class="stat-value">{{
overviewStats?.carddata_queue_size?.toLocaleString() || 0
}}</div>
</div> </div>
</div> </div>
</div> </div>
@@ -82,7 +104,7 @@
const { data } = await PollingMonitorService.getOverviewStats() const { data } = await PollingMonitorService.getOverviewStats()
overviewStats.value = data overviewStats.value = data
} catch (error) { } catch (error) {
ElMessage.error('加载轮询统计失败') console.log('加载轮询统计失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -169,7 +169,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('加载失败') console.log('加载失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -234,7 +234,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取订单详情失败') console.log('获取订单详情失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -284,7 +284,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { h } from 'vue' import { h } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { OrderService, CardService, DeviceService, PackageManageService, StorageService } from '@/api/modules' import {
OrderService,
CardService,
DeviceService,
PackageManageService,
StorageService
} from '@/api/modules'
import { ElMessage, ElMessageBox, ElTag } from 'element-plus' import { ElMessage, ElMessageBox, ElTag } from 'element-plus'
import { Plus } from '@element-plus/icons-vue' import { Plus } from '@element-plus/icons-vue'
import type { FormInstance, FormRules, UploadInstance, UploadFile } from 'element-plus' import type { FormInstance, FormRules, UploadInstance, UploadFile } from 'element-plus'
@@ -477,7 +483,7 @@
ElMessage.success('上传成功') ElMessage.success('上传成功')
} catch (error: any) { } catch (error: any) {
console.error('上传失败:', error) console.error('上传失败:', error)
ElMessage.error(error.message || '上传失败,请重试') console.log(error.message || '上传失败,请重试')
createForm.payment_voucher_key = undefined createForm.payment_voucher_key = undefined
uploadRef.value?.clearFiles() uploadRef.value?.clearFiles()
} }
@@ -733,8 +739,10 @@
purchased_by_platform: 'danger', purchased_by_platform: 'danger',
purchase_for_subordinate: 'info' purchase_for_subordinate: 'info'
} }
return h(ElTag, { type: roleTypeMap[row.purchase_role || ''] || 'info', size: 'small' }, () => return h(
getPurchaseRoleText(row.purchase_role || '') ElTag,
{ type: roleTypeMap[row.purchase_role || ''] || 'info', size: 'small' },
() => getPurchaseRoleText(row.purchase_role || '')
) )
} }
}, },

View File

@@ -242,7 +242,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取详情失败') console.log('获取详情失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -941,7 +941,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取套餐列表失败') console.log('获取套餐列表失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -229,7 +229,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取详情失败') console.log('获取详情失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -751,7 +751,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取套餐系列列表失败') console.log('获取套餐系列列表失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -413,7 +413,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取详情失败') console.log('获取详情失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -535,7 +535,7 @@
await fetchDetail() await fetchDetail()
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error(packageDialogType.value === 'add' ? '添加失败' : '更新失败') console.log(packageDialogType.value === 'add' ? '添加失败' : '更新失败')
} finally { } finally {
submitLoading.value = false submitLoading.value = false
} }
@@ -568,7 +568,7 @@
await fetchDetail() await fetchDetail()
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('删除失败') console.log('删除失败')
} finally { } finally {
submitLoading.value = false submitLoading.value = false
} }

View File

@@ -175,7 +175,11 @@
<ElInputNumber <ElInputNumber
v-model="packageForm.cost_price_yuan" v-model="packageForm.cost_price_yuan"
:min="packageForm.original_cost_price || 0" :min="packageForm.original_cost_price || 0"
:max="packageForm.original_cost_price ? packageForm.original_cost_price * 1.5 : undefined" :max="
packageForm.original_cost_price
? packageForm.original_cost_price * 1.5
: undefined
"
:precision="2" :precision="2"
:step="0.01" :step="0.01"
:controls="false" :controls="false"
@@ -183,8 +187,10 @@
placeholder="请输入成本价" placeholder="请输入成本价"
/> />
<div v-if="packageForm.original_cost_price" class="form-tip"> <div v-if="packageForm.original_cost_price" class="form-tip">
原价: ¥{{ packageForm.original_cost_price.toFixed(2) }}, 原价: ¥{{ packageForm.original_cost_price.toFixed(2) }}, 最高: ¥{{
最高: ¥{{ (packageForm.original_cost_price * 1.5).toFixed(2) }} (50%溢价) (packageForm.original_cost_price * 1.5).toFixed(2)
}}
(50%溢价)
</div> </div>
</ElFormItem> </ElFormItem>
</ElForm> </ElForm>
@@ -312,7 +318,9 @@
<ElInputNumber <ElInputNumber
v-model="pkg.cost_price" v-model="pkg.cost_price"
:min="pkg.original_cost_price || 0" :min="pkg.original_cost_price || 0"
:max="pkg.original_cost_price ? pkg.original_cost_price * 1.5 : undefined" :max="
pkg.original_cost_price ? pkg.original_cost_price * 1.5 : undefined
"
:precision="2" :precision="2"
:step="0.01" :step="0.01"
:controls="false" :controls="false"
@@ -320,7 +328,9 @@
style="width: 150px" style="width: 150px"
/> />
<span v-if="pkg.original_cost_price" class="min-cost-hint"> <span v-if="pkg.original_cost_price" class="min-cost-hint">
(原价: ¥{{ pkg.original_cost_price.toFixed(2) }}, 最高: ¥{{ (pkg.original_cost_price * 1.5).toFixed(2) }}) (原价: ¥{{ pkg.original_cost_price.toFixed(2) }}, 最高: ¥{{
(pkg.original_cost_price * 1.5).toFixed(2)
}})
</span> </span>
</div> </div>
<ElButton type="danger" size="small" @click="removePackage(index)" <ElButton type="danger" size="small" @click="removePackage(index)"
@@ -835,10 +845,22 @@
callback(new Error('请输入成本价')) callback(new Error('请输入成本价'))
} else if (value < 0) { } else if (value < 0) {
callback(new Error('成本价不能小于0')) callback(new Error('成本价不能小于0'))
} else if (packageForm.value.original_cost_price && value < packageForm.value.original_cost_price) { } else if (
callback(new Error(`成本价不能低于原价 ¥${packageForm.value.original_cost_price.toFixed(2)}`)) packageForm.value.original_cost_price &&
} else if (packageForm.value.original_cost_price && value > packageForm.value.original_cost_price * 1.5) { value < packageForm.value.original_cost_price
callback(new Error(`成本价不能高于原价的50%溢价(最高:¥${(packageForm.value.original_cost_price * 1.5).toFixed(2)}`)) ) {
callback(
new Error(`成本价不能低于原价 ¥${packageForm.value.original_cost_price.toFixed(2)}`)
)
} else if (
packageForm.value.original_cost_price &&
value > packageForm.value.original_cost_price * 1.5
) {
callback(
new Error(
`成本价不能高于原价的50%溢价(最高:¥${(packageForm.value.original_cost_price * 1.5).toFixed(2)}`
)
)
} else { } else {
callback() callback()
} }
@@ -1470,7 +1492,9 @@
// 从 availablePackages 中查找选中的套餐 // 从 availablePackages 中查找选中的套餐
const selectedPackage = availablePackages.value.find((p) => p.id === packageId) const selectedPackage = availablePackages.value.find((p) => p.id === packageId)
if (selectedPackage) { if (selectedPackage) {
const originalCostPrice = selectedPackage.cost_price ? selectedPackage.cost_price / 100 : 0 const originalCostPrice = selectedPackage.cost_price
? selectedPackage.cost_price / 100
: 0
packageForm.value.original_cost_price = originalCostPrice packageForm.value.original_cost_price = originalCostPrice
packageForm.value.cost_price_yuan = originalCostPrice packageForm.value.cost_price_yuan = originalCostPrice
} }
@@ -1501,7 +1525,6 @@
} }
} }
// 加载搜索栏系列选项(默认加载10条) // 加载搜索栏系列选项(默认加载10条)
const loadSearchSeriesOptions = async () => { const loadSearchSeriesOptions = async () => {
try { try {
@@ -1661,7 +1684,7 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取系列分配列表失败') console.log('获取系列分配列表失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -1798,7 +1821,7 @@
} }
} catch (error) { } catch (error) {
console.error('获取详情失败:', error) console.error('获取详情失败:', error)
ElMessage.error('获取详情失败') console.log('获取详情失败')
dialogVisible.value = false dialogVisible.value = false
} finally { } finally {
loading.value = false loading.value = false
@@ -1910,7 +1933,9 @@
// 根据佣金类型携带不同参数 // 根据佣金类型携带不同参数
if (form.commission_type === 'fixed') { if (form.commission_type === 'fixed') {
// 固定模式:携带 one_time_commission_amount将元转换为分 // 固定模式:携带 one_time_commission_amount将元转换为分
data.one_time_commission_amount = Math.round((form.one_time_commission_amount || 0) * 100) data.one_time_commission_amount = Math.round(
(form.one_time_commission_amount || 0) * 100
)
} else if (form.commission_type === 'tiered') { } else if (form.commission_type === 'tiered') {
// 梯度模式:携带 commission_tiers将元转换为分 // 梯度模式:携带 commission_tiers将元转换为分
// 注意:请求时不传 operatoroperator 是响应中从 PackageSeries 合并过来的 // 注意:请求时不传 operatoroperator 是响应中从 PackageSeries 合并过来的
@@ -2013,7 +2038,7 @@
} }
} catch (error) { } catch (error) {
console.error('获取套餐列表失败:', error) console.error('获取套餐列表失败:', error)
ElMessage.error('获取套餐列表失败') console.log('获取套餐列表失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -2128,7 +2153,7 @@
await refreshPackageList() await refreshPackageList()
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error(packageDialogType.value === 'add' ? '添加失败' : '更新失败') console.log(packageDialogType.value === 'add' ? '添加失败' : '更新失败')
} finally { } finally {
packageSubmitLoading.value = false packageSubmitLoading.value = false
} }
@@ -2161,7 +2186,7 @@
await refreshPackageList() await refreshPackageList()
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('删除失败') console.log('删除失败')
} finally { } finally {
packageSubmitLoading.value = false packageSubmitLoading.value = false
} }

View File

@@ -231,7 +231,7 @@
tableData.value = data.items tableData.value = data.items
pagination.total = data.total pagination.total = data.total
} catch (error) { } catch (error) {
ElMessage.error('加载告警历史失败') console.log('加载告警历史失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -329,7 +329,7 @@
tableData.value = res.data.items tableData.value = res.data.items
} }
} catch (error) { } catch (error) {
ElMessage.error('加载数据失败') console.log('加载数据失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -384,7 +384,7 @@
}) })
} }
} catch (error) { } catch (error) {
ElMessage.error('获取规则详情失败') console.log('获取规则详情失败')
} }
} }
@@ -410,7 +410,7 @@
} }
} }
} catch (error) { } catch (error) {
ElMessage.error(dialogType.value === 'create' ? '创建失败' : '更新失败') console.log(dialogType.value === 'create' ? '创建失败' : '更新失败')
} }
} }
}) })
@@ -425,7 +425,7 @@
loadData() loadData()
} }
} catch (error) { } catch (error) {
ElMessage.error('操作失败') console.log('操作失败')
} }
} }
@@ -442,7 +442,7 @@
loadData() loadData()
} }
} catch (error) { } catch (error) {
ElMessage.error('删除失败') console.log('删除失败')
} }
}) })
} }

View File

@@ -165,7 +165,7 @@
const { data } = await PollingConcurrencyService.getConcurrencyList() const { data } = await PollingConcurrencyService.getConcurrencyList()
tableData.value = data.items tableData.value = data.items
} catch (error) { } catch (error) {
ElMessage.error('加载并发配置失败') console.log('加载并发配置失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -179,7 +179,7 @@
formData.max_concurrency = data.max_concurrency formData.max_concurrency = data.max_concurrency
dialogVisible.value = true dialogVisible.value = true
} catch (error) { } catch (error) {
ElMessage.error('获取并发配置失败') console.log('获取并发配置失败')
} }
} }
@@ -196,7 +196,7 @@
await loadData() await loadData()
} catch (error) { } catch (error) {
if (error !== 'cancel') { if (error !== 'cancel') {
ElMessage.error('重置失败') console.log('重置失败')
} }
} }
} }
@@ -214,7 +214,7 @@
await loadData() await loadData()
} catch (error) { } catch (error) {
if (error !== 'cancel') { if (error !== 'cancel') {
ElMessage.error('重置失败') console.log('重置失败')
} }
} }
} }
@@ -231,7 +231,7 @@
dialogVisible.value = false dialogVisible.value = false
await loadData() await loadData()
} catch (error) { } catch (error) {
ElMessage.error('修改失败') console.log('修改失败')
} }
}) })
} }

View File

@@ -516,7 +516,7 @@
tableData.value = data.items tableData.value = data.items
pagination.total = data.total pagination.total = data.total
} catch (error) { } catch (error) {
ElMessage.error('加载配置列表失败') console.log('加载配置列表失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -594,7 +594,7 @@
formRef.value?.clearValidate() formRef.value?.clearValidate()
}) })
} catch (error) { } catch (error) {
ElMessage.error('获取配置详情失败') console.log('获取配置详情失败')
} }
} }
@@ -605,7 +605,7 @@
ElMessage.success(newStatus === 1 ? '已启用' : '已禁用') ElMessage.success(newStatus === 1 ? '已启用' : '已禁用')
await loadData() await loadData()
} catch (error) { } catch (error) {
ElMessage.error('状态更新失败') console.log('状态更新失败')
} }
} }
@@ -622,7 +622,7 @@
await loadData() await loadData()
} catch (error) { } catch (error) {
if (error !== 'cancel') { if (error !== 'cancel') {
ElMessage.error('删除失败') console.log('删除失败')
} }
} }
} }
@@ -657,7 +657,7 @@
dialogVisible.value = false dialogVisible.value = false
await loadData() await loadData()
} catch (error) { } catch (error) {
ElMessage.error(dialogType.value === 'create' ? '创建失败' : '更新失败') console.log(dialogType.value === 'create' ? '创建失败' : '更新失败')
} }
}) })
} }

View File

@@ -424,7 +424,6 @@
} }
} catch (error) { } catch (error) {
console.error('获取详情失败:', error) console.error('获取详情失败:', error)
ElMessage.error('获取配置详情失败')
} }
} }

View File

@@ -294,7 +294,6 @@
ManualTriggerHistoryQueryParams, ManualTriggerHistoryQueryParams,
BatchManualTriggerRequest, BatchManualTriggerRequest,
ConditionManualTriggerRequest, ConditionManualTriggerRequest,
SingleManualTriggerRequest,
TaskType TaskType
} from '@/types/api' } from '@/types/api'
import type { SearchFormItem } from '@/types' import type { SearchFormItem } from '@/types'
@@ -510,7 +509,7 @@
tableData.value = data.items tableData.value = data.items
pagination.total = data.total pagination.total = data.total
} catch (error) { } catch (error) {
ElMessage.error('加载触发历史失败') console.log('加载触发历史失败')
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -610,9 +609,9 @@
await ManualTriggerService.batchTrigger(requestData) await ManualTriggerService.batchTrigger(requestData)
ElMessage.success('批量触发成功') ElMessage.success('批量触发成功')
batchDialogVisible.value = false batchDialogVisible.value = false
loadData() await loadData()
} catch (error) { } catch (error) {
ElMessage.error('批量触发失败') console.log('批量触发失败')
} }
}) })
} }
@@ -637,9 +636,9 @@
await ManualTriggerService.conditionTrigger(requestData) await ManualTriggerService.conditionTrigger(requestData)
ElMessage.success('条件触发成功') ElMessage.success('条件触发成功')
conditionDialogVisible.value = false conditionDialogVisible.value = false
loadData() await loadData()
} catch (error) { } catch (error) {
ElMessage.error('条件触发失败') console.log('条件触发失败')
} }
}) })
} }
@@ -656,9 +655,9 @@
}) })
ElMessage.success('单卡触发成功') ElMessage.success('单卡触发成功')
singleDialogVisible.value = false singleDialogVisible.value = false
loadData() await loadData()
} catch (error) { } catch (error) {
ElMessage.error('单卡触发失败') console.log('单卡触发失败')
} }
}) })
} }
@@ -673,15 +672,15 @@
await ManualTriggerService.cancelTrigger({ trigger_id: row.id }) await ManualTriggerService.cancelTrigger({ trigger_id: row.id })
ElMessage.success('任务已取消') ElMessage.success('任务已取消')
loadData() await loadData()
} catch (error) { } catch (error) {
if (error !== 'cancel') { if (error !== 'cancel') {
ElMessage.error('取消任务失败') console.log('取消任务失败')
} }
} }
} }
const handleRowContextMenu = (row: ManualTriggerLog, column: any, event: MouseEvent) => { const handleRowContextMenu = (row: ManualTriggerLog, _column: any, event: MouseEvent) => {
event.preventDefault() event.preventDefault()
event.stopPropagation() event.stopPropagation()
currentClickRow.value = row currentClickRow.value = row

View File

@@ -98,11 +98,7 @@
import { ref, onMounted, onUnmounted } from 'vue' import { ref, onMounted, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { PollingMonitorService } from '@/api/modules' import { PollingMonitorService } from '@/api/modules'
import type { import type { PollingInitProgress, PollingQueueStatus, PollingTaskStats } from '@/types/api'
PollingInitProgress,
PollingQueueStatus,
PollingTaskStats
} from '@/types/api'
import { formatDateTime } from '@/utils/business/format' import { formatDateTime } from '@/utils/business/format'
const initProgress = ref<PollingInitProgress>() const initProgress = ref<PollingInitProgress>()
const queueStatusList = ref<PollingQueueStatus[]>([]) const queueStatusList = ref<PollingQueueStatus[]>([])
@@ -120,9 +116,6 @@
} }
} catch (error) { } catch (error) {
console.error('加载初始化进度失败', error) console.error('加载初始化进度失败', error)
if (showMessage) {
ElMessage.error('加载初始化进度失败')
}
} }
} }
@@ -135,7 +128,7 @@
ElMessage.success('队列状态已刷新') ElMessage.success('队列状态已刷新')
} }
} catch (error) { } catch (error) {
ElMessage.error('加载队列状态失败') console.log('加载队列状态失败')
} }
} }
@@ -148,7 +141,7 @@
ElMessage.success('任务统计已刷新') ElMessage.success('任务统计已刷新')
} }
} catch (error) { } catch (error) {
ElMessage.error('加载任务统计失败') console.log('加载任务统计失败')
} }
} }

View File

@@ -262,7 +262,6 @@
} }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
ElMessage.error('获取支付配置详情失败')
} finally { } finally {
loading.value = false loading.value = false
} }

View File

@@ -19,7 +19,12 @@
@refresh="handleRefresh" @refresh="handleRefresh"
> >
<template #left> <template #left>
<ElButton type="primary" @click="showCreateDialog" v-if="hasAuth('wechat_config:create')">新增支付配置</ElButton> <ElButton
type="primary"
@click="showCreateDialog"
v-if="hasAuth('wechat_config:create')"
>新增支付配置</ElButton
>
</template> </template>
</ArtTableHeader> </ArtTableHeader>
@@ -834,7 +839,6 @@
} }
} catch (error) { } catch (error) {
console.error('获取详情失败:', error) console.error('获取详情失败:', error)
ElMessage.error('获取配置详情失败')
} }
} }

View File

@@ -915,7 +915,6 @@
} }
} catch (error) { } catch (error) {
console.error('获取店铺默认角色失败:', error) console.error('获取店铺默认角色失败:', error)
ElMessage.error('获取店铺默认角色失败')
} finally { } finally {
defaultRolesLoading.value = false defaultRolesLoading.value = false
} }
@@ -944,7 +943,7 @@
} }
} catch (error) { } catch (error) {
console.error('获取角色列表失败:', error) console.error('获取角色列表失败:', error)
ElMessage.error('获取角色列表失败') console.log('获取角色列表失败')
} finally { } finally {
rolesLoading.value = false rolesLoading.value = false
} }

View File

@@ -826,7 +826,6 @@
ElMessage.success('权限添加成功') ElMessage.success('权限添加成功')
} catch (error) { } catch (error) {
console.error('添加权限失败:', error) console.error('添加权限失败:', error)
ElMessage.error('权限添加失败')
} }
} }
@@ -881,7 +880,6 @@
ElMessage.success('权限移除成功') ElMessage.success('权限移除成功')
} catch (error) { } catch (error) {
console.error('移除权限失败:', error) console.error('移除权限失败:', error)
ElMessage.error('权限移除失败')
} }
} }