Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xyw_asset_console
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DaiJiezhang
xyw_asset_console
Commits
da65cb92
Commit
da65cb92
authored
Jul 03, 2026
by
DaiJiezhang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refine fetch handling and phone workflow
parent
f2fe141d
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
109 additions
and
44 deletions
+109
-44
WxPhoneSaveRequest.java
...in/java/com/xyw/console/phone/dto/WxPhoneSaveRequest.java
+1
-2
WxPhoneEntity.java
...main/java/com/xyw/console/phone/entity/WxPhoneEntity.java
+2
-2
WxPhoneService.java
...in/java/com/xyw/console/phone/service/WxPhoneService.java
+0
-0
phone-add-dialog.js
src/modules/phone/phone-add-dialog.js
+6
-8
phone-list-runtime.js
src/modules/phone/phone-list-runtime.js
+44
-13
phone-api-client.js
src/modules/shared/phone-api-client.js
+28
-8
record-adapters.js
src/modules/shared/record-adapters.js
+1
-3
wechat-api-client.js
src/modules/shared/wechat-api-client.js
+27
-8
No files found.
backend/src/main/java/com/xyw/console/phone/dto/WxPhoneSaveRequest.java
View file @
da65cb92
...
...
@@ -40,6 +40,5 @@ public class WxPhoneSaveRequest {
private
Boolean
numberStatus
;
private
String
linkedWecom
;
private
Boolean
numberRetentionStatus
;
}
backend/src/main/java/com/xyw/console/phone/entity/WxPhoneEntity.java
View file @
da65cb92
...
...
@@ -64,8 +64,7 @@ public class WxPhoneEntity {
@TableField
(
"linked_wecom"
)
private
String
linkedWecom
;
@TableField
(
"number_retention_status"
)
private
Boolean
numberRetentionStatus
;
@TableField
(
exist
=
false
)
private
String
wechatStatus
;
...
...
@@ -73,3 +72,4 @@ public class WxPhoneEntity {
@TableField
(
exist
=
false
)
private
String
outbound
;
}
backend/src/main/java/com/xyw/console/phone/service/WxPhoneService.java
View file @
da65cb92
This diff is collapsed.
Click to expand it.
src/modules/phone/phone-add-dialog.js
View file @
da65cb92
...
...
@@ -23,7 +23,7 @@
channelOperator
:
''
,
numberStatus
:
true
,
linkedWecom
:
''
,
numberRetentionStatus
:
true
,
imageAttachment1
:
''
,
imageAttachment2
:
''
};
...
...
@@ -124,7 +124,7 @@
formData
.
channelOperator
=
record
.
channelOperator
||
record
.
carrier
||
''
;
formData
.
numberStatus
=
record
.
numberStatus
!==
false
;
formData
.
linkedWecom
=
record
.
linkedWecom
||
''
;
formData
.
numberRetentionStatus
=
record
.
numberRetentionStatus
!==
false
;
imageItems
.
value
=
buildImageItemsFromRecord
(
record
);
syncImagesToFormData
();
}
...
...
@@ -347,12 +347,7 @@
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="是否保留号码" prop="numberRetentionStatus">
<el-switch v-model="formData.numberRetentionStatus" active-text="保留" inactive-text="注销"></el-switch>
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="24">
<el-form-item label="可变更 5 元套餐" prop="packageChange5yuan">
<el-switch v-model="formData.packageChange5yuan"></el-switch>
</el-form-item>
...
...
@@ -412,3 +407,6 @@
app
.
use
(
ElementPlus
);
app
.
mount
(
'#phoneDialogRoot'
);
})();
src/modules/phone/phone-list-runtime.js
View file @
da65cb92
...
...
@@ -34,6 +34,17 @@
return
recordTime
>=
startTime
&&
recordTime
<=
endTime
+
24
*
60
*
60
*
1000
-
1
;
}
/**
* 代码作用(白话):把列表里的长文本压成 20 个字符内的单行展示,鼠标悬浮时还能看到完整内容;关联文件:F:/Project/xyw_console/src/modules/phone/phone-list-runtime.js;关联逻辑(调用链/消息链/数据流):表格单元格原始值 -> formatCellText() -> 列表展示/tooltip 提示。
*/
function
formatCellText
(
value
)
{
const
text
=
String
(
value
??
'-'
);
if
(
text
.
length
<=
20
)
{
return
text
;
}
return
`
${
text
.
slice
(
0
,
20
)}
...`
;
}
const
PhoneListTable
=
{
name
:
'PhoneListTable'
,
props
:
{
...
...
@@ -454,9 +465,21 @@
<a href="#" class="domain-link" @click.prevent="focusRow(scope.row.id)">{{ scope.row.phone || '-' }}</a>
</template>
</el-table-column>
<el-table-column property="realPerson" label="真实联系人" min-width="130" />
<el-table-column property="iccid" label="ICCID" min-width="190" />
<el-table-column property="city" label="所在城市" min-width="120" />
<el-table-column label="真实联系人" min-width="150">
<template #default="scope">
<span :title="scope.row.realPerson || '-'" style="display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{ formatCellText(scope.row.realPerson) }}</span>
</template>
</el-table-column>
<el-table-column label="ICCID" min-width="220">
<template #default="scope">
<span :title="scope.row.iccid || '-'" style="display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{ formatCellText(scope.row.iccid) }}</span>
</template>
</el-table-column>
<el-table-column label="所在城市" min-width="140">
<template #default="scope">
<span :title="scope.row.city || '-'" style="display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{ formatCellText(scope.row.city) }}</span>
</template>
</el-table-column>
<el-table-column label="号卡状态" min-width="120">
<template #default="scope">
<span class="status-chip-wrap">
...
...
@@ -464,9 +487,7 @@
<span>{{ scope.row.status }}</span>
</span>
</template>
</el-table-column>
<el-table-column property="cardUsageLocation" label="卡使用地点" min-width="160" />
<el-table-column label="企业微信" min-width="110">
</el-table-column> <el-table-column label="企业微信" min-width="110">
<template #default="scope">{{ formatBooleanText(scope.row.wecom, '已开通', '未开通') }}</template>
</el-table-column>
<el-table-column label="微信" min-width="100">
...
...
@@ -475,20 +496,28 @@
<el-table-column label="可外呼" min-width="100">
<template #default="scope">{{ formatBooleanText(scope.row.outboundCall, '可外呼', '不可外呼') }}</template>
</el-table-column>
<el-table-column property="douyinAccount" label="抖音账号" min-width="160" />
<el-table-column label="抖音账号" min-width="180">
<template #default="scope">
<span :title="scope.row.douyinAccount || '-'" style="display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{ formatCellText(scope.row.douyinAccount) }}</span>
</template>
</el-table-column>
<el-table-column label="小程序备案" min-width="120">
<template #default="scope">{{ formatBooleanText(scope.row.miniProgramFiling, '已备案', '未备案') }}</template>
</el-table-column>
<el-table-column property="channelOperator" label="渠道运营商" min-width="130" />
<el-table-column label="渠道运营商" min-width="150">
<template #default="scope">
<span :title="scope.row.channelOperator || '-'" style="display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{ formatCellText(scope.row.channelOperator) }}</span>
</template>
</el-table-column>
<el-table-column label="手机号状态" min-width="120">
<template #default="scope">{{ formatStatusText(scope.row.numberStatus) }}</template>
</el-table-column>
<el-table-column
property="linkedWecom" label="绑定企业微信" min-width="160" /
>
<el-table-column label="号码保留状态" min-width="130
">
<template #default="scope">{{ formatRetentionText(scope.row.numberRetentionStatus) }}</template
>
</el-table-column
>
<el-table-column label="操作" width="100" fixed="right">
<el-table-column
label="绑定企业微信" min-width="180"
>
<template #default="scope
">
<span :title="scope.row.linkedWecom || '-'" style="display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{ formatCellText(scope.row.linkedWecom) }}</span
>
</template
>
<
/el-table-column> <
el-table-column label="操作" width="100" fixed="right">
<template #default="scope">
<div class="action-cluster" style="display: flex; flex-direction: column; align-items: flex-start; gap: 8px;">
<button class="action-pill action-pill-primary" type="button" @click.stop="handleRowAction('view', scope.row.id)" style="border: none; background: transparent; color: #2563eb; cursor: pointer; padding: 0; font-weight: 600; line-height: 1;">查看</button>
...
...
@@ -544,3 +573,5 @@
src/modules/shared/phone-api-client.js
View file @
da65cb92
...
...
@@ -13,11 +13,33 @@
}
/**
* 代码作用(白话):把浏览器在本地后端没启动时抛出的网络错误翻成稳定中文,避免页面直接展示原始 Failed to fetch;关联文件:F:/Project/xyw_console/src/modules/shared/phone-api-client.js、F:/Project/xyw_console/src/modules/phone/phone-list-runtime.js、F:/Project/xyw_console/src/modules/phone/phone-add-dialog.js;关联逻辑(调用链/消息链/数据流):fetch() 失败 -> requestJson() -> 抛出中文错误 -> 外层 catch -> 页面提示。
*/
function
isFetchUnavailableError
(
error
)
{
const
message
=
String
(
error
?.
message
||
''
).
toLowerCase
();
return
error
instanceof
TypeError
&&
message
.
includes
(
'failed to fetch'
);
}
/**
* 代码作用(白话):先请求接口再统一解析 JSON,并在网络断开或本地后端未启动时返回稳定错误文案;关联文件:F:/Project/xyw_console/src/modules/shared/phone-api-client.js;关联逻辑(调用链/消息链/数据流):listPhones()/savePhone()/deletePhone() -> requestJson() -> parseJsonResponse() -> 外层页面提示。
*/
async
function
requestJson
(
url
,
options
,
networkMessage
)
{
try
{
const
response
=
await
fetch
(
url
,
options
);
return
await
parseJsonResponse
(
response
);
}
catch
(
error
)
{
if
(
isFetchUnavailableError
(
error
))
{
throw
new
Error
(
networkMessage
);
}
throw
error
;
}
}
/**
* 代码作用(白话):从本地手机号接口拉取完整列表,返回后端 data 数组给外层适配;关联文件:F:/Project/xyw_console/app-v2.js、F:/Project/xyw_console/src/modules/phone/phone-list-runtime.js;关联逻辑(调用链/消息链/数据流):phone 页面挂载/刷新 -> listPhones() -> app-v2.js -> normalizePhoneRecord() -> 列表渲染。
*/
async
function
listPhones
()
{
const
response
=
await
fetch
(
BASE_URL
);
const
json
=
await
parseJsonResponse
(
response
);
const
json
=
await
requestJson
(
BASE_URL
,
undefined
,
'手机号服务暂时不可用,请确认本地后端已启动'
);
return
Array
.
isArray
(
json
.
data
)
?
json
.
data
:
[];
}
...
...
@@ -28,12 +50,11 @@
const
payload
=
{
...
record
};
const
isEdit
=
Boolean
(
payload
.
id
);
const
targetUrl
=
isEdit
?
`
${
BASE_URL
}
/
${
payload
.
id
}
`
:
BASE_URL
;
const
response
=
await
fetch
(
targetUrl
,
{
const
json
=
await
requestJson
(
targetUrl
,
{
method
:
isEdit
?
'PUT'
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/json'
},
body
:
JSON
.
stringify
(
payload
)
});
const
json
=
await
parseJsonResponse
(
response
);
},
'手机号保存失败,请确认本地后端已启动'
);
return
json
.
data
||
json
;
}
...
...
@@ -41,10 +62,9 @@
* 代码作用(白话):删除指定手机号记录,并把失败信息统一抛给外层处理;关联文件:F:/Project/xyw_console/app-v2.js、F:/Project/xyw_console/src/modules/phone/phone-list-runtime.js;关联逻辑(调用链/消息链/数据流):手机号列表删除按钮 -> deletePhoneRecord() -> deletePhone() -> 刷新列表或提示失败。
*/
async
function
deletePhone
(
id
)
{
const
response
=
await
fetch
(
`
${
BASE_URL
}
/
${
id
}
`
,
{
const
json
=
await
requestJson
(
`
${
BASE_URL
}
/
${
id
}
`
,
{
method
:
'DELETE'
});
const
json
=
await
parseJsonResponse
(
response
);
},
'手机号删除失败,请确认本地后端已启动'
);
return
json
.
data
||
json
;
}
...
...
src/modules/shared/record-adapters.js
View file @
da65cb92
...
...
@@ -99,7 +99,6 @@
const
miniProgramFiled
=
toBooleanFlag
(
source
.
miniProgramFiling
??
source
.
mini_program_filing
,
false
);
const
packageChangeEnabled
=
toBooleanFlag
(
source
.
packageChange5yuan
??
source
.
package_change_5yuan
,
false
);
const
numberStatus
=
toBooleanFlag
(
source
.
numberStatus
??
source
.
mobile_status
??
source
.
number_status
,
true
);
const
numberRetentionStatus
=
toBooleanFlag
(
source
.
numberRetentionStatus
??
source
.
number_retention_status
,
true
);
const
wechatStatus
=
source
.
wechatStatus
||
(
numberStatus
?
'正常'
:
'异常停机'
);
const
outbound
=
source
.
outbound
||
(
outboundEnabled
?
'可外呼'
:
'不可外呼'
);
const
linkedWecom
=
source
.
linkedWecom
||
source
.
linked_wecom
||
''
;
...
...
@@ -152,8 +151,6 @@
mobile_status
:
numberStatus
,
linkedWecom
,
linked_wecom
:
linkedWecom
,
numberRetentionStatus
,
number_retention_status
:
numberRetentionStatus
};
}
...
...
@@ -162,3 +159,4 @@
normalizePhoneRecord
};
})();
src/modules/shared/wechat-api-client.js
View file @
da65cb92
...
...
@@ -14,11 +14,33 @@
}
/**
* 代码作用(白话):把浏览器在本地后端没启动时抛出的网络错误翻成稳定中文,避免页面直接展示原始 Failed to fetch;关联文件:F:/Project/xyw_console/src/modules/shared/wechat-api-client.js、F:/Project/xyw_console/src/modules/wechat/wechat-list-runtime.js、F:/Project/xyw_console/src/modules/wechat/wechat-add-dialog.js;关联逻辑(调用链/消息链/数据流):fetch() 失败 -> requestJson() -> 抛出中文错误 -> 外层 catch -> 页面提示。
*/
function
isFetchUnavailableError
(
error
)
{
const
message
=
String
(
error
?.
message
||
''
).
toLowerCase
();
return
error
instanceof
TypeError
&&
message
.
includes
(
'failed to fetch'
);
}
/**
* 代码作用(白话):先请求接口再统一解析 JSON,并在网络断开或本地后端未启动时返回稳定错误文案;关联文件:F:/Project/xyw_console/src/modules/shared/wechat-api-client.js;关联逻辑(调用链/消息链/数据流):listWechatRecords()/getWechatRecord()/saveWechatRecord() -> requestJson() -> parseJsonResponse() -> 外层页面提示。
*/
async
function
requestJson
(
url
,
options
,
networkMessage
)
{
try
{
const
response
=
await
fetch
(
url
,
options
);
return
await
parseJsonResponse
(
response
);
}
catch
(
error
)
{
if
(
isFetchUnavailableError
(
error
))
{
throw
new
Error
(
networkMessage
);
}
throw
error
;
}
}
/**
* 代码作用(白话):从后端拉取企微资料全量列表,交给页面继续做本地筛选和分页;关联文件:F:/Project/xyw_console/app-v2.js、F:/Project/xyw_console/src/modules/wechat/wechat-list-runtime.js;关联逻辑(调用链/消息链/数据流):wechat 页面挂载/刷新 -> listWechatRecords() -> app-v2.js -> normalizeWechatRecord() -> 列表渲染。
*/
async
function
listWechatRecords
()
{
const
response
=
await
fetch
(
BASE_URL
);
const
json
=
await
parseJsonResponse
(
response
);
const
json
=
await
requestJson
(
BASE_URL
,
undefined
,
'企微服务暂时不可用,请确认本地后端已启动'
);
return
Array
.
isArray
(
json
.
data
)
?
json
.
data
:
[];
}
...
...
@@ -26,8 +48,7 @@
* 代码作用(白话):按主键读取单条企微资料,让详情抽屉和编辑弹窗拿到数据库最新值;关联文件:F:/Project/xyw_console/app-v2.js、F:/Project/xyw_console/src/modules/wechat/wechat-detail-drawer.js;关联逻辑(调用链/消息链/数据流):查看/编辑按钮 -> getWechatRecord() -> app-v2.js -> 详情抽屉或编辑弹窗打开。
*/
async
function
getWechatRecord
(
id
)
{
const
response
=
await
fetch
(
`
${
BASE_URL
}
/
${
id
}
`
);
const
json
=
await
parseJsonResponse
(
response
);
const
json
=
await
requestJson
(
`
${
BASE_URL
}
/
${
id
}
`
,
undefined
,
'企微详情读取失败,请确认本地后端已启动'
);
return
json
.
data
||
null
;
}
...
...
@@ -41,12 +62,11 @@
if
(
!
isEdit
)
{
delete
payload
.
id
;
}
const
response
=
await
fetch
(
targetUrl
,
{
const
json
=
await
requestJson
(
targetUrl
,
{
method
:
isEdit
?
'PUT'
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/json'
},
body
:
JSON
.
stringify
(
payload
)
});
const
json
=
await
parseJsonResponse
(
response
);
},
'企微保存失败,请确认本地后端已启动'
);
return
json
.
data
||
json
;
}
...
...
@@ -56,4 +76,3 @@
saveWechatRecord
};
})();
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment