后台系统: 用户详情页面添加钱包余额显示、用户管理优化记录用户选择币种、 新增广播增加查看按钮内容、及对应跳转对应页面路径 增加帮助中心页面、公告中心页面 完成

This commit is contained in:
2025-07-11 16:33:34 +08:00
parent c6f765f858
commit a0ebd8254a
63 changed files with 5379 additions and 680 deletions

View File

@@ -1,4 +1,5 @@
import { listBroadcast, getAddBroadcast, updateBroadcast, DeleteBroadcast, getBroadcast,dataInfo } from '../../api/broadcast'
import { listBroadcast, getAddBroadcast, updateBroadcast, DeleteBroadcast, getBroadcast, dataInfo } from '../../api/broadcast'
import { isValidPath, getPathSuggestions } from '../../utils/routeUtils'
export default {
data() {
@@ -27,10 +28,14 @@ export default {
},
addParams: {
content: "",
buttonContent: "",
buttonPath: "",
},
editParams: {
content: "",
id: "",
buttonContent: "",
buttonPath: "",
},
dialogVisible: false,
bthLoading: false,
@@ -49,19 +54,19 @@ export default {
let token
try{
token =JSON.parse(localStorage.getItem('token'))
}catch(e){
console.log(e);
try {
token = JSON.parse(localStorage.getItem('token'))
} catch (e) {
console.log(e);
}
if (token) {
this.fetchList(this.listParams);
}
},
methods: {
async fetchList(params) {
this.setLoading('broadcastLoading', true);
const res = await listBroadcast(params)
if (res.code === 200) {
@@ -72,10 +77,18 @@ export default {
},
async addBroadcast(params) {
this.setLoading('bthLoading', true);
// 发送请求前打印参数,用于调试
console.log('发送广播请求的参数:', params);
const res = await getAddBroadcast(params)
if (res.code === 200) {
this.$message.success(this.$t("backendSystem.addSuccess"))
this.dialogVisible = false;
// 清空表单参数
this.addParams.content = ""
this.addParams.buttonContent = ""
this.addParams.buttonPath = ""
this.fetchList(this.listParams);
}
this.setLoading('bthLoading', false);
@@ -84,17 +97,28 @@ export default {
this.setLoading('editLoading', true);
const res = await dataInfo(params)
if (res.code === 200) {
this.editParams = res.data
this.editParams = {
...res.data,
// 确保按钮路径是字符串格式(如果是数组则转换为逗号分隔的字符串)
buttonPath: Array.isArray(res.data.buttonPath)
? res.data.buttonPath.join(',')
: (res.data.buttonPath || '')
};
this.editDialogVisible = true;
}
this.setLoading('editLoading', false);
},
async editBroadcast(params) {
this.setLoading('editLoading', true);
// 发送请求前打印参数,用于调试
console.log('发送编辑广播请求的参数:', params);
const res = await updateBroadcast(params)
if (res.code === 200) {
this.$message.success(this.$t("backendSystem.editSuccess"))
this.editDialogVisible = false;
this.fetchList(this.listParams);
}
this.setLoading('editLoading', false);
@@ -112,25 +136,153 @@ export default {
handleClose() {
this.dialogVisible = false;
this.addParams.content = ""
this.addParams.buttonContent = ""
this.addParams.buttonPath = ""
this.setLoading('bthLoading', false);
},
sureAddBroadcast() {
this.addParams.content = this.addParams.content.trim()
this.addParams.content = this.addParams.content.replace(/[\r\n]/g, '');
this.addParams.buttonPath = this.addParams.buttonPath.trim()
this.addParams.buttonPath = this.addParams.buttonPath.replace(/[\r\n]/g, '');
if (!this.addParams.content) {
this.$message.warning(this.$t("backendSystem.pleaseInputContent"))
return
}
this.addBroadcast(this.addParams);
if ((this.addParams.buttonContent && this.addParams.buttonPath) || (!this.addParams.buttonContent && !this.addParams.buttonPath)) {
if (this.addParams.buttonPath) {
// 兼容中英文逗号分割
let pathArray = this.addParams.buttonPath.split(/[,]/).map(e => e.trim()).filter(e => e);
if (pathArray.length > 5) {
this.$message.warning(this.$t("backendSystem.max5"))
return
} else if (pathArray.length === 0) {
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
return
}
if (this.addParams.buttonContent) {
// 兼容中英文逗号分割
let pathArray2 = this.addParams.buttonContent.split(/[,]/).map(e => e.trim()).filter(e => e);
if (pathArray2.length > 5) {
this.$message.warning(this.$t("backendSystem.max5"))
return
} else if (pathArray2.length === 0) {
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
return
}
if (this.addParams.buttonContent && this.addParams.buttonPath) {
if (pathArray.length !== pathArray2.length) {
this.$message.warning(this.$t("backendSystem.pathNumberNotMatch"))
return
}
}
}
// 验证每个路径是否有效
const invalidPaths = pathArray.filter(path => !isValidPath(path));
if (invalidPaths.length > 0) {
const suggestions = getPathSuggestions(invalidPaths[0]);
this.$message.error(`${this.$t("backendSystem.invalidPath")}: ${invalidPaths.join(', ')}${this.$t("backendSystem.invalidPathSuggestions")}: ${suggestions.slice(0, 3).join(', ')}`);
return
}
// 验证通过,保持字符串格式传给后端(不转换为数组)
// this.addParams.buttonPath 保持原始字符串格式
}
this.addBroadcast(this.addParams);
} else {
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
}
},
sureEditBroadcast() {
this.editParams.content=this.editParams.content.trim()
this.editParams.content = this.editParams.content.trim()
this.editParams.content = this.editParams.content.replace(/[\r\n]/g, '');
let buttonContentArray
let pathArray
if (!this.editParams.content) {
this.$message.warning(this.$t("backendSystem.pleaseInputContent"))
return
}
if (this.editParams.buttonContent) {
this.editParams.buttonContent = this.editParams.buttonContent.trim().replace(/[\r\n]/g, '');
// 验证按钮内容和路径是否匹配
if ((this.editParams.buttonContent && this.editParams.buttonPath) || (!this.editParams.buttonContent && !this.editParams.buttonPath)) {
if (this.editParams.buttonContent) {
// 兼容中英文逗号分割
buttonContentArray = this.editParams.buttonContent.split(/[,]/).map(e => e.trim()).filter(e => e);
if (buttonContentArray.length > 5) {
this.$message.warning(this.$t("backendSystem.max5"))
return
} else if (buttonContentArray.length === 0) {
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
return
}
}
// 如果有按钮路径,进行验证
if (this.editParams.buttonPath) {
this.editParams.buttonPath = this.editParams.buttonPath.trim().replace(/[\r\n]/g, '');
// 验证按钮内容和路径是否匹配
if ((this.editParams.buttonContent && this.editParams.buttonPath) || (!this.editParams.buttonContent && !this.editParams.buttonPath)) {
if (this.editParams.buttonPath) {
// 兼容中英文逗号分割
pathArray = this.editParams.buttonPath.split(/[,]/).map(e => e.trim()).filter(e => e);
if (pathArray.length > 5) {
this.$message.warning(this.$t("backendSystem.max5"))
return
} else if (pathArray.length === 0) {
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
return
}
// 验证每个路径是否有效
const invalidPaths = pathArray.filter(path => !isValidPath(path));
if (invalidPaths.length > 0) {
const suggestions = getPathSuggestions(invalidPaths[0]);
this.$message.error(`${this.$t("backendSystem.invalidPath")}: ${invalidPaths.join(', ')}${this.$t("backendSystem.invalidPathSuggestions")}: ${suggestions.slice(0, 3).join(', ')}`);
return
}
}
} else {
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
return
}
}
if (this.editParams.buttonContent && this.editParams.buttonPath) {
if (buttonContentArray.length !== pathArray.length) {
this.$message.warning(this.$t("backendSystem.pathNumberNotMatch"))
return
}
}
} else {
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
return
}
}
this.editBroadcast(this.editParams);
},
handleEdit(row) {
@@ -140,6 +292,8 @@ export default {
handleEditClose() {
this.editDialogVisible = false;
this.editParams.content = ""
this.editParams.buttonContent = ""
this.editParams.buttonPath = ""
this.setLoading('editLoading', false);
},
handelDelete(row) {
@@ -196,15 +350,73 @@ export default {
this.listParams.pageNum = 1
this.currentPage = 1
this.fetchList(this.listParams);
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`);
this.listParams.pageNum = val
this.fetchList(this.listParams);
console.log(`当前页: ${val}`);
this.listParams.pageNum = val
this.fetchList(this.listParams);
},
/**
* 获取有效路径建议信息
* @returns {Array} 路径建议列表
*/
getValidPathSuggestions() {
return getPathSuggestions('').slice(0, 8); // 返回前8个常用路径
},
/**
* 显示路径使用帮助
*/
showPathHelp() {
const suggestions = this.getValidPathSuggestions();
const helpMessage = `
常用路径示例:
${suggestions.slice(0, 10).join('\n')}
路径规则:
• 多个路径用逗号分隔
• 路径必须以 / 开头
• 支持动态路由参数
• 不要包含域名,只写路径部分
`;
this.$alert(helpMessage, '路径格式说明', {
confirmButtonText: '知道了',
type: 'info',
customClass: 'path-help-dialog'
});
},
/**
* 格式化按钮内容显示
* @param {string} buttonContent - 逗号分隔的按钮内容字符串
* @returns {Array} 按钮内容数组
*/
formatButtonContent(buttonContent) {
if (!buttonContent || typeof buttonContent !== 'string') {
return [];
}
return buttonContent
.split(',')
.map(btn => btn.trim())
.filter(btn => btn);
},
/**
* 格式化按钮路径显示
* @param {string} buttonPath - 逗号分隔的路径字符串
* @returns {Array} 路径数组
*/
formatButtonPath(buttonPath) {
if (!buttonPath || typeof buttonPath !== 'string') {
return [];
}
return buttonPath
.split(',')
.map(path => path.trim())
.filter(path => path);
},
@@ -212,5 +424,5 @@ export default {
},
}

View File

@@ -38,6 +38,48 @@
width="160"
show-overflow-tooltip
/>
<el-table-column
prop="buttonContent"
:label="$t('backendSystem.bthContent2')"
width="200"
show-overflow-tooltip
>
<template slot-scope="scope">
<div v-if="scope.row.buttonContent">
<el-tag
v-for="(button, index) in formatButtonContent(scope.row.buttonContent)"
:key="index"
size="small"
style="margin: 2px;"
>
{{ button }}
</el-tag>
</div>
<span v-else style="color: #999;"></span>
</template>
</el-table-column>
<el-table-column
prop="buttonPath"
:label="$t('backendSystem.bthPath2')"
width="250"
show-overflow-tooltip
>
<template slot-scope="scope">
<div v-if="scope.row.buttonPath">
<div
v-for="(path, index) in formatButtonPath(scope.row.buttonPath)"
:key="index"
class="path-item"
style="font-size: 12px;"
>
{{ index + 1 }}. {{ path }}
</div>
</div>
<span v-else style="color: #999;"></span>
</template>
</el-table-column>
<el-table-column
prop="updateTime"
:label="$t('backendSystem.updateTime')"
@@ -101,9 +143,9 @@
:before-close="handleClose"
:close-on-click-modal="false"
>
<el-form :model="addParams">
<el-form :model="addParams" ref="addForm">
<!-- v-if="isOverLimit" -->
<el-form-item>
<el-form-item :label="$t('backendSystem.broadcastContent')" prop="content">
<el-input
resize="none"
v-model="addParams.content"
@@ -127,6 +169,43 @@
<span> {{ $t("backendSystem.newlineInvalid") }}</span>
</div>
</el-form-item>
<el-form-item :label="$t('backendSystem.bthContent')" prop="buttonContent">
<el-input
resize="none"
v-model="addParams.buttonContent"
type="text"
/>
</el-form-item>
<el-form-item :label="$t('backendSystem.bthPath')" prop="buttonPath">
<el-input
resize="none"
v-model="addParams.buttonPath"
type="textarea"
:rows="2"
/>
<div
style="
color: #999;
font-size: 12px;
margin-top: 4px;
display: flex;
align-items: center;
justify-content: space-between;
"
>
<span v-if="isOverLimit">
{{ $t("backendSystem.exceedingInput") }}</span
>
<span> {{ $t("backendSystem.bthPathStandard") }}</span>
<el-button type="text" size="mini" @click="showPathHelp">
查看路径示例
</el-button>
</div>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose">{{
@@ -140,6 +219,8 @@
>
</div>
</el-dialog>
<!-- 修改广播弹窗 -->
<el-dialog
:title="$t('backendSystem.editContent')"
@@ -149,7 +230,7 @@
:close-on-click-modal="false"
>
<el-form :model="editParams">
<el-form-item>
<el-form-item :label="$t('backendSystem.broadcastContent')">
<el-input
resize="none"
v-model="editParams.content"
@@ -173,6 +254,36 @@
<span> {{ $t("backendSystem.newlineInvalid") }}</span>
</div>
</el-form-item>
<el-form-item :label="$t('backendSystem.bthContent')">
<el-input
v-model="editParams.buttonContent"
type="text"
/>
</el-form-item>
<el-form-item :label="$t('backendSystem.bthPath')">
<el-input
v-model="editParams.buttonPath"
type="textarea"
:rows="2"
/>
<div
style="
color: #999;
font-size: 12px;
margin-top: 4px;
display: flex;
align-items: center;
justify-content: space-between;
"
>
<span>{{ $t("backendSystem.bthPathStandard") }}</span>
<el-button type="text" size="mini" @click="showPathHelp">
查看路径示例
</el-button>
</div>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="handleEditClose">{{
@@ -231,4 +342,41 @@ export default {
border: none;
margin-left: 18px;
}
/* 按钮内容和路径显示优化 */
.el-table .cell {
word-break: break-word;
}
/* 路径帮助弹窗样式 */
::v-deep .path-help-dialog {
.el-message-box__message {
white-space: pre-line;
font-family: 'Courier New', monospace;
font-size: 13px;
line-height: 1.6;
}
}
/* 按钮标签样式优化 */
.el-tag {
max-width: 80px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* 路径显示样式 */
.path-item {
font-family: 'Courier New', monospace;
background: #f5f7fa;
padding: 2px 6px;
border-radius: 3px;
margin: 1px 0;
border-left: 3px solid #409EFF;
}
::v-deep .el-tag{
max-width: 200px !important;
}
</style>