课程模块部分bug修复
This commit is contained in:
@ -6,7 +6,8 @@ import router from "../router";
|
||||
|
||||
const myAxios = axios.create({
|
||||
withCredentials: true,
|
||||
baseURL:'http://localhost:9091'
|
||||
// baseURL:'http://localhost:9091'
|
||||
baseURL:'http://localhost:9092'
|
||||
// baseURL:'http://1.94.237.210:3457'
|
||||
//baseURL:'http://1.94.237.210:8088'
|
||||
//baseURL:'http://27.30.77.229:9091/'
|
||||
|
@ -76,14 +76,10 @@ const checkLoginStatus = () => {
|
||||
// 检查store中的登录状态
|
||||
if (store.loginUser.userRole === "notLogin") {
|
||||
console.log("未检测到登录状态,跳转到登录页");
|
||||
// 使用replace替换当前路由,禁止返回
|
||||
router.replace({ path: '/' });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 生命周期钩子:在组件挂载前检查登录状态
|
||||
onBeforeMount(() => {
|
||||
checkLoginStatus();
|
||||
});
|
||||
@ -103,7 +99,6 @@ const logout = async () => {
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
|
||||
// 严格遵循接口文档路径大小写
|
||||
const res: any = await myAxios.get(
|
||||
"/userInfo/logout",
|
||||
{
|
||||
|
@ -69,19 +69,18 @@ import {useRoute, useRouter} from "vue-router";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
// 选中侧边栏
|
||||
|
||||
const selectedKeys = ref<string[]>(['/userList']);
|
||||
|
||||
onMounted(() => {
|
||||
setSelectedKey()
|
||||
})
|
||||
|
||||
// 根据路由设置当前选中侧边栏
|
||||
|
||||
const setSelectedKey = () => {
|
||||
selectedKeys.value = [route.path];
|
||||
}
|
||||
|
||||
// 路由跳转
|
||||
const handleClick = (item: any) => {
|
||||
router.push(item.key)
|
||||
}
|
||||
@ -89,7 +88,7 @@ const handleClick = (item: any) => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 全局菜单项样式 */
|
||||
|
||||
:deep(.ant-menu-item),
|
||||
:deep(.ant-menu-submenu-title) {
|
||||
color: rgba(0, 0, 0, 0.85) !important; /* 未选中黑色字体 */
|
||||
@ -97,31 +96,31 @@ const handleClick = (item: any) => {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* 选中项样式 */
|
||||
|
||||
:deep(.ant-menu-item-selected) {
|
||||
background-color: #ffa940 !important;
|
||||
color: white !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
/* 鼠标悬停样式 */
|
||||
|
||||
:deep(.ant-menu-item:hover),
|
||||
:deep(.ant-menu-submenu-title:hover) {
|
||||
background-color: rgba(255, 169, 64, 0.1) !important;
|
||||
}
|
||||
|
||||
/* 子菜单箭头颜色 */
|
||||
|
||||
:deep(.ant-menu-submenu-arrow::before),
|
||||
:deep(.ant-menu-submenu-arrow::after) {
|
||||
background: rgba(0, 0, 0, 0.65) !important;
|
||||
}
|
||||
|
||||
/* 子菜单展开时标题样式 */
|
||||
|
||||
:deep(.ant-menu-submenu-selected .ant-menu-submenu-title) {
|
||||
color: rgba(0, 0, 0, 0.95) !important;
|
||||
}
|
||||
|
||||
/* 折叠状态下选中样式 */
|
||||
|
||||
:deep(.ant-menu-inline-collapsed .ant-menu-item-selected) {
|
||||
background-color: #ffa940 !important;
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ const onLogin = async () => {
|
||||
"/userInfo/login",
|
||||
{
|
||||
userAccount: userAccount.value,
|
||||
userPassword: userPassword.value // 发送加密后的密码
|
||||
userPassword: userPassword.value
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
|
@ -6,43 +6,5 @@
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.search-box {
|
||||
margin-bottom: 20px;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.error-alert {
|
||||
padding: 1rem;
|
||||
background: #ffe3e3;
|
||||
color: #ff4444;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.8rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
display: inline-block;
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
border-radius: 50%;
|
||||
background: #ff4444;
|
||||
color: white;
|
||||
text-align: center;
|
||||
line-height: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
:deep(.ant-table-thead > tr > th) {
|
||||
background-color: #fafafa !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:deep(.ant-table-row:hover) {
|
||||
background-color: #fafafa !important;
|
||||
}
|
||||
</style>
|
@ -68,16 +68,15 @@
|
||||
class="select-field"
|
||||
required
|
||||
>
|
||||
<option value="" disabled>请选择类型</option>
|
||||
<option value="自媒体">自媒体</option>
|
||||
<option value="">请选择课程类型</option>
|
||||
<option value="考公考研">考公考研</option>
|
||||
<option value="自媒体">自媒体</option>
|
||||
<option value="财经">财经</option>
|
||||
</select>
|
||||
<div class="select-arrow">▼</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<label class="input-label">
|
||||
<span class="label-text">课程图片</span>
|
||||
@ -108,6 +107,7 @@
|
||||
class="input-field"
|
||||
required
|
||||
placeholder="请输入原价"
|
||||
@input="validatePrices"
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
@ -122,6 +122,7 @@
|
||||
class="input-field"
|
||||
required
|
||||
placeholder="请输入折扣价"
|
||||
@input="validatePrices"
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
@ -134,11 +135,12 @@
|
||||
<input
|
||||
v-model.number="formData.firstLevelRate"
|
||||
type="number"
|
||||
min="0"
|
||||
max="100"
|
||||
min="1"
|
||||
max="99"
|
||||
class="input-field"
|
||||
required
|
||||
placeholder="0-100"
|
||||
placeholder="1-99"
|
||||
@input="validateRates"
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
@ -149,11 +151,12 @@
|
||||
<input
|
||||
v-model.number="formData.secondLevelRate"
|
||||
type="number"
|
||||
min="0"
|
||||
max="100"
|
||||
min="1"
|
||||
max="99"
|
||||
class="input-field"
|
||||
required
|
||||
placeholder="0-100"
|
||||
placeholder="1-99"
|
||||
@input="validateRates"
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
@ -161,6 +164,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 富文本编辑器区域 - 修改为50%宽度 -->
|
||||
<div class="rich-text-container">
|
||||
<div class="rich-text-columns">
|
||||
<div class="rich-text-group">
|
||||
@ -168,7 +172,7 @@
|
||||
<RichTextEditor
|
||||
v-model="formData.detail"
|
||||
:disable="false"
|
||||
@content-change="(html) => formData.detail = html"
|
||||
@content-change="(html:any) => formData.detail = html"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -177,7 +181,7 @@
|
||||
<RichTextEditor
|
||||
v-model="formData.promoCodeDesc"
|
||||
:disable="false"
|
||||
@content-change="(html) => formData.promoCodeDesc = html"
|
||||
@content-change="(html:any) => formData.promoCodeDesc = html"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -230,7 +234,7 @@ const handleFileUpload = async (event: Event) => {
|
||||
'Authorization': storedToken
|
||||
}
|
||||
});
|
||||
|
||||
console.log(res)
|
||||
if (res.code === 1) {
|
||||
formData.image = res.data;
|
||||
fileName.value = file.name;
|
||||
@ -280,7 +284,41 @@ const encryptValue = (value: any, key: string): any => {
|
||||
}
|
||||
};
|
||||
|
||||
// 验证函数
|
||||
const validatePrices = () => {
|
||||
if (formData.discountPrice >= formData.originPrice) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const validateRates = () => {
|
||||
if (formData.secondLevelRate >= formData.firstLevelRate) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
// 验证价格和佣金比例
|
||||
const isPriceValid = validatePrices();
|
||||
const isRateValid = validateRates();
|
||||
|
||||
let errorMessage = '';
|
||||
|
||||
if (!isPriceValid) {
|
||||
errorMessage += '折扣价必须小于原价\n';
|
||||
}
|
||||
|
||||
if (!isRateValid) {
|
||||
errorMessage += '二级佣金比例必须小于一级佣金比例\n';
|
||||
}
|
||||
|
||||
if (errorMessage) {
|
||||
alert(errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!validateForm()) {
|
||||
alert('请填写所有必填字段');
|
||||
@ -346,6 +384,7 @@ const validateForm = (): boolean => {
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.modern-form {
|
||||
max-width: 90%;
|
||||
@ -458,6 +497,73 @@ const validateForm = (): boolean => {
|
||||
|
||||
.select-wrapper {
|
||||
position: relative;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 0.75rem;
|
||||
transition: all 0.3s ease;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.select-wrapper:hover {
|
||||
border-color: #cbd5e1;
|
||||
}
|
||||
|
||||
.select-wrapper:focus-within {
|
||||
border-color: #6366f1;
|
||||
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
|
||||
}
|
||||
|
||||
.select-field {
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
padding: 0.8rem 1.2rem;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 1rem;
|
||||
color: #4a5568;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
border-radius: 0.75rem;
|
||||
height: 44px; /* 与其他输入框高度一致 */
|
||||
}
|
||||
|
||||
.select-field:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.select-arrow {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #94a3b8;
|
||||
pointer-events: none;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.select-wrapper:focus-within .select-arrow {
|
||||
transform: translateY(-50%) rotate(180deg);
|
||||
}
|
||||
|
||||
/* 下拉选项样式 */
|
||||
.select-field option {
|
||||
padding: 8px 12px;
|
||||
background: white;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
.select-field option:hover {
|
||||
background: #f1f5f9;
|
||||
}
|
||||
|
||||
.select-field option:checked {
|
||||
background: #6366f1;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 当选择框有值时改变样式 */
|
||||
.select-field:not([value=""]) {
|
||||
color: #2c3e50;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.select-field {
|
||||
@ -477,11 +583,6 @@ const validateForm = (): boolean => {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.textarea-field {
|
||||
min-height: 100px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -539,6 +640,7 @@ const validateForm = (): boolean => {
|
||||
|
||||
.rich-text-container {
|
||||
margin-top: 1.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.rich-text-columns {
|
||||
@ -561,6 +663,12 @@ const validateForm = (): boolean => {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.rich-text-columns {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.rich-text-group:focus-within {
|
||||
border-color: #6366f1;
|
||||
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
|
||||
@ -742,4 +850,5 @@ const validateForm = (): boolean => {
|
||||
margin-left: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
</style>
|
@ -108,13 +108,7 @@
|
||||
>
|
||||
编辑
|
||||
</a-button>
|
||||
<a-button
|
||||
size="small"
|
||||
type="link"
|
||||
@click="previewVideo(record.videoView)"
|
||||
>
|
||||
预览
|
||||
</a-button>
|
||||
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
@ -714,7 +708,6 @@ const handleEditChapter = async () => {
|
||||
const storedToken = localStorage.getItem('token');
|
||||
if (!storedToken) throw new Error('未找到登录信息');
|
||||
|
||||
// 准备更新数据,修正字段映射问题
|
||||
const updateData = {
|
||||
id: editForm.value.id,
|
||||
name: editForm.value.name,
|
||||
@ -748,24 +741,15 @@ const handleEditChapter = async () => {
|
||||
};
|
||||
|
||||
|
||||
// 预览视频
|
||||
const previewVideo = (videoView: string) => {
|
||||
previewVideoUrl.value = downLoadImage + videoView;
|
||||
videoPreviewVisible.value = true;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 从路由参数获取课程ID
|
||||
|
||||
courseId.value = route.query.id ? String(route.query.id) : "";
|
||||
|
||||
if (courseId.value) {
|
||||
// 设置章节查询参数中的课程ID
|
||||
searchParams.value.courseId = courseId.value;
|
||||
|
||||
// 获取课程详细信息
|
||||
getCourseDetail();
|
||||
|
||||
// 获取章节列表
|
||||
getChapterList();
|
||||
} else {
|
||||
message.error("未获取到课程ID");
|
||||
|
@ -121,7 +121,6 @@ const handleFileUpload = async (event: Event) => {
|
||||
message.error('文件上传失败');
|
||||
previewImage.value = '';
|
||||
} finally {
|
||||
// 重置文件输入,允许重复上传同一文件
|
||||
if (input) input.value = '';
|
||||
}
|
||||
};
|
||||
@ -250,7 +249,7 @@ const updateCourse = () => {
|
||||
}
|
||||
// 创建编辑数据的深拷贝副本
|
||||
editData.value = JSON.parse(JSON.stringify(courseData.value));
|
||||
previewImage.value = ''; // 进入编辑模式时重置预览图
|
||||
previewImage.value = '';
|
||||
isEditing.value = true;
|
||||
};
|
||||
|
||||
|
@ -92,15 +92,18 @@
|
||||
{{ record.secondLevelRate }}%
|
||||
</template>
|
||||
|
||||
<template v-if="column.key === 'isShelves'">
|
||||
<a-tag :color="record.isShelves ? 'green' : 'red'">
|
||||
{{ record.isShelves ? '已上架' : '已下架' }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<!-- 操作列 -->
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space :size="8">
|
||||
<a-button
|
||||
size="small"
|
||||
:type="record.isShelves ? 'danger' : 'primary'"
|
||||
@click="toggleShelves(record)"
|
||||
>
|
||||
{{ record.isShelves ? '下架' : '上架' }}
|
||||
</a-button>
|
||||
|
||||
<a-button
|
||||
size="small"
|
||||
danger
|
||||
@ -242,21 +245,44 @@ const columns = [
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
{
|
||||
title: '是否上架',
|
||||
dataIndex: 'isShelves',
|
||||
key: 'isShelves',
|
||||
width: 65,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
width: 75,
|
||||
width: 105,
|
||||
align: 'center'
|
||||
}
|
||||
];
|
||||
// 添加上下架切换方法
|
||||
const toggleShelves = async (record: Course) => {
|
||||
Modal.confirm({
|
||||
title: '确认操作',
|
||||
content: `确定要${record.isShelves ? '下架' : '上架'}该课程吗?`,
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
try {
|
||||
const storedToken = localStorage.getItem('token');
|
||||
const res: any = await myAxios.post(
|
||||
"/course/isShelves",
|
||||
{ id: record.id }, // 按照接口要求传递课程ID
|
||||
{ headers: { Authorization: storedToken } }
|
||||
);
|
||||
|
||||
if (res.code === 1) {
|
||||
message.success(`${record.isShelves ? '下架' : '上架'}成功`);
|
||||
// 刷新数据
|
||||
await getCourseList();
|
||||
} else {
|
||||
message.error(res.message || '操作失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('操作失败:', error);
|
||||
message.error(`${record.isShelves ? '下架' : '上架'}操作失败`);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 课程名称搜索方法
|
||||
const handleCourseSearch = async () => {
|
||||
@ -277,7 +303,7 @@ const getCourseList = async () => {
|
||||
const res: any = await myAxios.post("/course/page", searchParams.value,
|
||||
{ headers: { Authorization: storedToken } }
|
||||
);
|
||||
|
||||
console.log(res)
|
||||
if (res.code === 1 && res.data && Array.isArray(res.data.records)) {
|
||||
tableData.value = res.data.records;
|
||||
// 同步总条数到分页组件
|
||||
@ -313,17 +339,13 @@ const handleTableChange = (pag: any, _filters: any, sorter: any) => {
|
||||
|
||||
// 处理排序
|
||||
if (sorter && sorter.field) {
|
||||
// 获取排序字段(使用列的key而不是dataIndex)
|
||||
const sortField = sorter.field;
|
||||
|
||||
// 获取排序方向(ascend/descend)
|
||||
const sortOrder = sorter.order ? sorter.order : '';
|
||||
|
||||
// 更新搜索参数中的排序字段和排序方向
|
||||
searchParams.value.sortField = sortField;
|
||||
searchParams.value.sortOrder = sortOrder;
|
||||
} else {
|
||||
// 如果没有排序信息,重置为默认排序
|
||||
searchParams.value.sortField = "id";
|
||||
searchParams.value.sortOrder = "ascend";
|
||||
}
|
||||
@ -465,7 +487,6 @@ const chapterDetails = (id: string) => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 原有样式保持不变 */
|
||||
.search-box {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
@ -102,7 +102,6 @@ import { onMounted, ref } from "vue";
|
||||
import myAxios from "../../api/myAxios.ts";
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
import {downLoadImage} from "../../api/ImageUrl.ts";
|
||||
import router from "../../router";
|
||||
|
||||
const loading = ref(false);
|
||||
const selectedRowKeys = ref<number[]>([]); // 存储选中的行ID
|
||||
@ -285,7 +284,6 @@ const pagination = ref({
|
||||
pageSizeOptions: ['10', '20', '50', '100']
|
||||
});
|
||||
|
||||
// 处理分页和排序变化
|
||||
// 处理分页和排序变化
|
||||
const handleTableChange = (pag: any, _filters: any, sorter: any) => {
|
||||
searchParams.value.current = pag.current;
|
||||
@ -293,17 +291,14 @@ const handleTableChange = (pag: any, _filters: any, sorter: any) => {
|
||||
|
||||
// 处理排序
|
||||
if (sorter && sorter.field) {
|
||||
// 获取排序字段(使用列的key而不是dataIndex)
|
||||
const sortField = sorter.field;
|
||||
|
||||
// 获取排序方向(ascend/descend)
|
||||
const sortOrder = sorter.order ? sorter.order : '';
|
||||
|
||||
// 更新搜索参数中的排序字段和排序方向
|
||||
searchParams.value.sortField = sortField;
|
||||
searchParams.value.sortOrder = sortOrder;
|
||||
} else {
|
||||
// 如果没有排序信息,重置为默认排序
|
||||
|
||||
searchParams.value.sortField = "id";
|
||||
searchParams.value.sortOrder = "ascend";
|
||||
}
|
||||
|
@ -291,18 +291,16 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
const encryptValue = (value: any, key: string): any => {
|
||||
// 特定字段不加密
|
||||
if (key === 'projectStatus') {
|
||||
return value;
|
||||
}
|
||||
|
||||
// 数值型字段直接返回,不加密
|
||||
if (key === 'projectSettlementCycle' || key === 'maxPromoterCount' || key === 'projectImage' || key === 'projectName') {
|
||||
return value;
|
||||
}
|
||||
|
||||
try {
|
||||
// 将值转换为字符串
|
||||
|
||||
const valueString = typeof value === 'object'
|
||||
? JSON.stringify(value)
|
||||
: String(value);
|
||||
@ -325,12 +323,11 @@ const handleSubmit = async () => {
|
||||
|
||||
const storedToken = localStorage.getItem('token');
|
||||
|
||||
// 创建加密后的表单对象 - 保持原始数据结构
|
||||
const encryptedFormData: Record<string, any> = {};
|
||||
|
||||
console.log("===== 字段Base64编码结果 =====");
|
||||
Object.entries(formData).forEach(([key, value]) => {
|
||||
// 跳过空值字段
|
||||
|
||||
if (value === null || value === undefined || value === '') return;
|
||||
|
||||
// 对字段值进行Base64编码
|
||||
@ -625,16 +622,16 @@ const limitPromoterCount = (event: Event) => {
|
||||
|
||||
.rich-text-columns {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr)); /* 修正列宽分配 */
|
||||
gap: 1rem; /* 减小间距 */
|
||||
align-items: start; /* 顶部对齐 */
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 1rem;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.rich-text-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem; /* 减小标签与编辑器间距 */
|
||||
height: 100%; /* 保持等高布局 */
|
||||
gap: 0.5rem;
|
||||
height: 100%;
|
||||
|
||||
}
|
||||
.rich-text-group:focus-within {
|
||||
@ -652,7 +649,7 @@ const limitPromoterCount = (event: Event) => {
|
||||
|
||||
@media (max-width: 1280px) {
|
||||
.rich-text-columns {
|
||||
grid-template-columns: repeat(2, 1fr); /* 更早切换为2列 */
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 1.2rem;
|
||||
}
|
||||
}
|
||||
@ -672,7 +669,7 @@ const limitPromoterCount = (event: Event) => {
|
||||
min-height: 320px;
|
||||
height: auto;
|
||||
flex-grow: 1;
|
||||
/* 新增焦点状态 */
|
||||
|
||||
&:focus-within {
|
||||
border-color: #6366f1 !important;
|
||||
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
|
||||
@ -680,14 +677,13 @@ const limitPromoterCount = (event: Event) => {
|
||||
}
|
||||
|
||||
|
||||
/* 调整标签与编辑器间距 */
|
||||
.rich-text-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
height: 100%;
|
||||
border-radius: 15px;
|
||||
/* 新增标签焦点状态联动 */
|
||||
|
||||
&:focus-within .label-text {
|
||||
color: #6366f1;
|
||||
transition: color 0.3s ease;
|
||||
@ -695,7 +691,6 @@ const limitPromoterCount = (event: Event) => {
|
||||
}
|
||||
}
|
||||
|
||||
/* 保持与其他输入组件的一致性 */
|
||||
.rich-text-group .label-text {
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
@ -705,7 +700,6 @@ const limitPromoterCount = (event: Event) => {
|
||||
}
|
||||
|
||||
|
||||
/* 手机预览样式 */
|
||||
.phone-preview-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -87,7 +87,7 @@ import RichTextEditor from '../components/RichTextEditor.vue';
|
||||
import {useRoute} from "vue-router";
|
||||
|
||||
function encode64(text: string): string {
|
||||
// 使用_代替未使用的match参数
|
||||
|
||||
return btoa(encodeURIComponent(text).replace(/%([0-9A-F]{2})/g, (_, p1) => {
|
||||
return String.fromCharCode(parseInt(p1, 16));
|
||||
}));
|
||||
@ -102,10 +102,10 @@ interface NotificationForm {
|
||||
const formData = reactive<NotificationForm>({
|
||||
notificationTitle: '',
|
||||
notificationContent: '',
|
||||
projectId: 0 // 初始化值
|
||||
projectId: 0
|
||||
});
|
||||
|
||||
const route = useRoute(); // 获取路由参数
|
||||
const route = useRoute();
|
||||
|
||||
onMounted(() => {
|
||||
// 从路由参数中获取projectId并填充到表单
|
||||
@ -118,7 +118,6 @@ const handleSubmit = async () => {
|
||||
try {
|
||||
const storedToken = localStorage.getItem('token');
|
||||
|
||||
// 创建要发送的数据副本
|
||||
const payload = {
|
||||
...formData,
|
||||
notificationContent: encode64(formData.notificationContent)
|
||||
@ -153,7 +152,6 @@ const handleSubmit = async () => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 保留原有样式,添加富文本编辑器样式 */
|
||||
.phone-notification {
|
||||
padding: 20px;
|
||||
}
|
||||
|
@ -65,22 +65,22 @@ interface ProjectDetail {
|
||||
id: number;
|
||||
projectDetailName: string;
|
||||
projectSettlementPrice: number;
|
||||
projectMinSettlementPrice: number; // 修正接口字段
|
||||
projectMinSettlementPrice: number;
|
||||
maxCommissionRate: number;
|
||||
projectId: number;
|
||||
}
|
||||
|
||||
const route = useRoute();
|
||||
const projectId = ref<string | number>("");
|
||||
const tableData = ref<ProjectDetail[]>([]); // 改为数组存储
|
||||
const tableData = ref<ProjectDetail[]>([]);
|
||||
const loading = ref(false);
|
||||
const error = ref("");
|
||||
const searchId = ref(""); // 新增搜索ID绑定
|
||||
const searchId = ref("");
|
||||
|
||||
|
||||
// 新增变量保存原始数据
|
||||
const originalTableData = ref<ProjectDetail[]>([]);
|
||||
|
||||
// 修改 getMoneyDetail 方法
|
||||
|
||||
const getMoneyDetail = async (id: string | number) => {
|
||||
const storedToken = localStorage.getItem('token');
|
||||
try {
|
||||
@ -98,7 +98,7 @@ const getMoneyDetail = async (id: string | number) => {
|
||||
console.log(response)
|
||||
if (response.code === 1) {
|
||||
tableData.value = response.data;
|
||||
// 保存原始数据
|
||||
|
||||
originalTableData.value = response.data;
|
||||
} else {
|
||||
error.value = "获取项目详情失败";
|
||||
@ -112,10 +112,10 @@ const getMoneyDetail = async (id: string | number) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 修改搜索处理方法 - 前端过滤
|
||||
|
||||
const handleIdSearch = (value: string) => {
|
||||
if (!value.trim()) {
|
||||
// 如果搜索值为空,显示所有数据
|
||||
|
||||
tableData.value = [...originalTableData.value];
|
||||
return;
|
||||
}
|
||||
@ -126,7 +126,7 @@ const handleIdSearch = (value: string) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 前端过滤逻辑
|
||||
|
||||
const filtered = originalTableData.value.filter(item => item.id === id);
|
||||
|
||||
if (filtered.length === 0) {
|
||||
@ -137,10 +137,9 @@ const handleIdSearch = (value: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 修改重置方法
|
||||
|
||||
const reset = () => {
|
||||
searchId.value = "";
|
||||
// 重置时显示所有原始数据
|
||||
tableData.value = [...originalTableData.value];
|
||||
};
|
||||
|
||||
@ -174,7 +173,7 @@ const queryDetailById = async (id: string | number) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化逻辑
|
||||
|
||||
if (typeof route.query.id === "string") {
|
||||
projectId.value = route.query.id;
|
||||
}
|
||||
@ -188,9 +187,9 @@ onMounted(() => {
|
||||
const deleteMoneyDetail = async (id: number) => {
|
||||
try {
|
||||
const storedToken = localStorage.getItem('token');
|
||||
// 修正接口路径为项目明细的删除接口
|
||||
|
||||
const res: any = await myAxios.post(
|
||||
"/projectDetail/delete", // 修改这里
|
||||
"/projectDetail/delete",
|
||||
{ id },
|
||||
{
|
||||
headers: {
|
||||
@ -259,12 +258,12 @@ const formState = reactive({
|
||||
// };
|
||||
//
|
||||
|
||||
// 新增表单相关状态
|
||||
|
||||
const addDrawerVisible = ref(false);
|
||||
const addFormState = reactive({
|
||||
projectDetailName: '',
|
||||
projectSettlementPrice: 0,
|
||||
projectMinSettlementPrice: 0, // 注意字段名称需要与接口一致
|
||||
projectMinSettlementPrice: 0,
|
||||
maxCommissionRate: 0,
|
||||
projectId: 0
|
||||
});
|
||||
@ -352,7 +351,7 @@ const handleSubmit = async () => {
|
||||
const res:any = await myAxios.post(
|
||||
"/projectDetail/update",
|
||||
{
|
||||
// 根据接口文档调整字段映射
|
||||
|
||||
id: formState.id,
|
||||
projectDetailName: formState.projectDetailName,
|
||||
projectSettlementPrice: formState.projectSettlementPrice,
|
||||
@ -368,12 +367,12 @@ const handleSubmit = async () => {
|
||||
}
|
||||
);
|
||||
|
||||
console.log('接口响应:', res); // 添加详细日志
|
||||
console.log('接口响应:', res);
|
||||
|
||||
if (res.code === 1) { // 注意响应结构层级
|
||||
if (res.code === 1) {
|
||||
message.success('更新成功');
|
||||
drawerVisible.value = false;
|
||||
// 根据当前查看模式刷新
|
||||
|
||||
if (searchId.value) {
|
||||
await queryDetailById(formState.id);
|
||||
} else {
|
||||
@ -389,12 +388,10 @@ const handleSubmit = async () => {
|
||||
};
|
||||
|
||||
|
||||
//返回上一级
|
||||
const router = useRouter();
|
||||
|
||||
// 返回上一级方法
|
||||
|
||||
const goBack = () => {
|
||||
// router.go(-1); // 返回上一页
|
||||
router.push('/project')
|
||||
};
|
||||
|
||||
@ -526,7 +523,6 @@ const goBack = () => {
|
||||
</a-form>
|
||||
</a-drawer>
|
||||
|
||||
<!-- 修改新增抽屉的表单项 -->
|
||||
<a-drawer
|
||||
title="新增项目明细"
|
||||
placement="right"
|
||||
@ -625,7 +621,6 @@ const goBack = () => {
|
||||
}
|
||||
|
||||
|
||||
/*橙色按钮*/
|
||||
|
||||
.custom-button {
|
||||
background-color: #ffa940;
|
||||
@ -647,7 +642,6 @@ const goBack = () => {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 危险按钮样式 */
|
||||
.custom-button.ant-btn-dangerous {
|
||||
background-color: #ff4d4f;
|
||||
border-color: #ff4d4f;
|
||||
@ -659,7 +653,6 @@ const goBack = () => {
|
||||
border-color: #ff7875;
|
||||
}
|
||||
|
||||
/* 保持原有的其他样式不变 */
|
||||
.search-box {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@ -675,13 +668,11 @@ const goBack = () => {
|
||||
border-color: #fa8c16;
|
||||
}
|
||||
|
||||
/* 保持输入框原有样式不变 */
|
||||
.custom-search :deep(.ant-input) {
|
||||
border-right-color: #ffa940;
|
||||
}
|
||||
|
||||
|
||||
/* 调整分页器位置 */
|
||||
:deep(.ant-table-pagination.ant-pagination) {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -74,9 +74,9 @@ function decode64(text: string): string {
|
||||
}
|
||||
}
|
||||
interface NotificationDetail {
|
||||
id: string; // 改为 string 类型
|
||||
id: string;
|
||||
notificationTitle: string;
|
||||
projectId: string; // 改为 string 类型
|
||||
projectId: string;
|
||||
createTime: string;
|
||||
notificationContent: string;
|
||||
}
|
||||
@ -99,7 +99,7 @@ const errorMessage = ref("");
|
||||
|
||||
// 进入编辑模式
|
||||
const enterEditMode = () => {
|
||||
// 创建可编辑数据的副本
|
||||
|
||||
editableNotice.value = {
|
||||
...projectNotice.value
|
||||
};
|
||||
@ -140,7 +140,7 @@ const saveNotice = async () => {
|
||||
|
||||
if (res.code === 1) {
|
||||
message.success('更新成功');
|
||||
// 更新本地数据并退出编辑模式 - 使用解码后的内容
|
||||
|
||||
projectNotice.value = {
|
||||
...editableNotice.value, // 这里包含的是用户编辑的原始内容(未编码)
|
||||
};
|
||||
@ -217,7 +217,6 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 基本样式保持不变 */
|
||||
.notification-detail-container {
|
||||
width: 100%;
|
||||
padding: 24px;
|
||||
|
@ -124,14 +124,14 @@ import router from "../../router";
|
||||
const loading = ref(false);
|
||||
const total = ref(0);
|
||||
|
||||
const searchProjectName = ref(""); // 改为项目名称搜索参数
|
||||
const searchProjectName = ref("");
|
||||
const searchParams = ref({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
sortField: "id",
|
||||
sortOrder: "ascend",
|
||||
userRole: null,
|
||||
projectName: "" // 新增项目名称查询参数
|
||||
projectName: ""
|
||||
});
|
||||
|
||||
|
||||
@ -163,8 +163,8 @@ const columns = [
|
||||
key: 'id',
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
|
||||
{
|
||||
@ -189,8 +189,8 @@ const columns = [
|
||||
width: 20,
|
||||
key: 'projectPrice',
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
{
|
||||
title: '当前推广人数',
|
||||
@ -198,8 +198,8 @@ const columns = [
|
||||
width: 20,
|
||||
key: 'currentPromotionCount',
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
{
|
||||
title: '结算周期',
|
||||
@ -207,8 +207,8 @@ const columns = [
|
||||
key: 'projectSettlementCycle',
|
||||
width: 10,
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
{
|
||||
title: '最大推广人数',
|
||||
@ -216,8 +216,8 @@ const columns = [
|
||||
key: 'maxPromoterCount',
|
||||
width: 20,
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
{
|
||||
title: '项目状态',
|
||||
@ -255,9 +255,9 @@ const toggleShelves = async (record: any) => {
|
||||
|
||||
if (res.code === 1) {
|
||||
message.success('状态更新成功');
|
||||
// 使用 Object.assign 触发响应式更新
|
||||
|
||||
Object.assign(record, { isShelves: !record.isShelves });
|
||||
// 或重新获取数据(推荐)
|
||||
|
||||
await getProjectList();
|
||||
}else {
|
||||
message.error(res.message || '操作失败');
|
||||
@ -269,15 +269,14 @@ const toggleShelves = async (record: any) => {
|
||||
};
|
||||
|
||||
interface ProjectRecord {
|
||||
// 这里根据实际数据结构定义属性
|
||||
|
||||
superHostList?: string[];
|
||||
// 其他属性...
|
||||
}
|
||||
// 项目名称搜索方法
|
||||
const handleProjectSearch = async () => {
|
||||
// 将搜索参数同步到分页查询参数
|
||||
|
||||
searchParams.value.projectName = searchProjectName.value;
|
||||
searchParams.value.current = 1; // 重置到第一页
|
||||
searchParams.value.current = 1;
|
||||
await getProjectList();
|
||||
};
|
||||
//用户分页查询
|
||||
@ -287,23 +286,28 @@ const getProjectList = async () => {
|
||||
const storedToken = localStorage.getItem('token');
|
||||
if (!storedToken) throw new Error('未找到登录信息');
|
||||
|
||||
const params = {
|
||||
...searchParams.value,
|
||||
|
||||
fuzzyQuery: true,
|
||||
fuzzyField: 'projectName'
|
||||
};
|
||||
|
||||
const res:any = await myAxios.post("/project/page",
|
||||
{
|
||||
...searchParams.value,
|
||||
projectName: searchParams.value.projectName
|
||||
},
|
||||
params,
|
||||
{ headers: { Authorization: storedToken } }
|
||||
);
|
||||
|
||||
console.log(res)
|
||||
if (res.code === 1 && res.data && Array.isArray(res.data.records)) {
|
||||
tableData.value = res.data.records.map((item: ProjectRecord) => ({
|
||||
...item,
|
||||
superUserList: item.superHostList? item.superHostList.join(', ') : '无'
|
||||
}));
|
||||
// 同步总条数到分页组件
|
||||
|
||||
total.value = res.data.total;
|
||||
pagination.value.total = res.data.total; // 新增此行
|
||||
pagination.value.current = searchParams.value.current; // 同步当前页
|
||||
pagination.value.total = res.data.total;
|
||||
pagination.value.current = searchParams.value.current;
|
||||
} else {
|
||||
message.error(res.message || '请求失败');
|
||||
}
|
||||
@ -318,7 +322,6 @@ const getProjectList = async () => {
|
||||
onMounted(getProjectList);
|
||||
//分页
|
||||
|
||||
// 分页配置
|
||||
const pagination = ref({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
@ -329,9 +332,9 @@ const pagination = ref({
|
||||
pageSizeOptions: ['10', '20', '50', '100']
|
||||
});
|
||||
const handleTableChange = (pag: any, _: any, sorter: any) => {
|
||||
// 处理排序参数
|
||||
let sortField = "id"; // 默认排序字段
|
||||
let sortOrder = "ascend"; // 默认排序方式
|
||||
|
||||
let sortField = "id";
|
||||
let sortOrder = "ascend";
|
||||
if (sorter.field) {
|
||||
sortField = sorter.field;
|
||||
sortOrder = sorter.order;
|
||||
@ -340,11 +343,11 @@ const handleTableChange = (pag: any, _: any, sorter: any) => {
|
||||
...searchParams.value,
|
||||
current: pag.current,
|
||||
pageSize: pag.pageSize,
|
||||
sortField: sortField, // 设置排序字段
|
||||
sortField: sortField,
|
||||
sortOrder: sortOrder
|
||||
};
|
||||
|
||||
// 同步到分页组件
|
||||
|
||||
pagination.value = {
|
||||
...pagination.value,
|
||||
current: pag.current,
|
||||
@ -364,13 +367,13 @@ interface Project {
|
||||
projectStatus: string;
|
||||
projectDescription: string;
|
||||
settlementDesc: string;
|
||||
// 其他可能存在的属性根据实际情况补充
|
||||
|
||||
}
|
||||
|
||||
const tableData = ref<Project[]>([]);
|
||||
|
||||
|
||||
// 删除项目 - 添加确认弹窗
|
||||
// 删除项目
|
||||
const deleteProject = (id: number) => {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
@ -403,7 +406,7 @@ const deleteProject = (id: number) => {
|
||||
}
|
||||
},
|
||||
onCancel() {
|
||||
// 用户点击取消,不做操作
|
||||
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -467,10 +470,8 @@ const promotionCode=(id:number)=>{
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.action-btn {
|
||||
padding: 0 8px;
|
||||
}
|
||||
/* 分割线样式 */
|
||||
|
||||
|
||||
:deep(.ant-divider-vertical) {
|
||||
border-color: rgba(0, 0, 0, 0.15);
|
||||
height: 1.2em;
|
||||
@ -490,8 +491,6 @@ const promotionCode=(id:number)=>{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 角色颜色映射 */
|
||||
:root {
|
||||
--role-user: #87d068;
|
||||
--role-admin: #f50;
|
||||
@ -503,7 +502,6 @@ const promotionCode=(id:number)=>{
|
||||
}
|
||||
|
||||
|
||||
/*橙色按钮*/
|
||||
|
||||
.custom-button {
|
||||
background-color: #ffa940;
|
||||
@ -525,7 +523,7 @@ const promotionCode=(id:number)=>{
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 危险按钮样式 */
|
||||
|
||||
.custom-button.ant-btn-dangerous {
|
||||
background-color: #ff4d4f;
|
||||
border-color: #ff4d4f;
|
||||
@ -537,7 +535,7 @@ const promotionCode=(id:number)=>{
|
||||
border-color: #ff7875;
|
||||
}
|
||||
|
||||
/* 保持原有的其他样式不变 */
|
||||
|
||||
.search-box {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@ -553,7 +551,7 @@ const promotionCode=(id:number)=>{
|
||||
border-color: #fa8c16;
|
||||
}
|
||||
|
||||
/* 保持输入框原有样式不变 */
|
||||
|
||||
.custom-search :deep(.ant-input) {
|
||||
border-right-color: #ffa940;
|
||||
}
|
||||
|
@ -125,7 +125,6 @@ const handleFileUpload = async (event: Event) => {
|
||||
message.error('文件上传失败');
|
||||
previewImage.value = '';
|
||||
} finally {
|
||||
// 重置文件输入,允许重复上传同一文件
|
||||
if (input) input.value = '';
|
||||
}
|
||||
};
|
||||
@ -199,7 +198,7 @@ const finishEditing = async () => {
|
||||
message.error('项目更新失败');
|
||||
} finally {
|
||||
isEditing.value = false;
|
||||
previewImage.value = ''; // 清空预览图
|
||||
previewImage.value = '';
|
||||
}
|
||||
};
|
||||
|
||||
@ -257,9 +256,8 @@ const updateProject = () => {
|
||||
message.warning('项目数据尚未加载完成,请稍后再试');
|
||||
return;
|
||||
}
|
||||
// 创建编辑数据的深拷贝副本
|
||||
editData.value = JSON.parse(JSON.stringify(projectData.value));
|
||||
previewImage.value = ''; // 进入编辑模式时重置预览图
|
||||
previewImage.value = '';
|
||||
isEditing.value = true;
|
||||
};
|
||||
|
||||
@ -279,13 +277,12 @@ const triggerFileInput = () => {
|
||||
const handleNumberInput = (e: KeyboardEvent) => {
|
||||
const allowedKeys = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab'];
|
||||
|
||||
// 只允许数字和控制键
|
||||
if (!allowedKeys.includes(e.key)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
// 添加范围限制方法 - 现在在输入时立即修正
|
||||
|
||||
const limitSettlementCycle = (value: number) => {
|
||||
if (!editData.value) return;
|
||||
|
||||
|
@ -64,7 +64,7 @@ const columns = [
|
||||
}
|
||||
];
|
||||
|
||||
// 修改接口数据类型
|
||||
|
||||
interface ProjectNotification {
|
||||
id: number;
|
||||
notificationTitle: string;
|
||||
@ -75,14 +75,14 @@ interface ProjectNotification {
|
||||
const route = useRoute();
|
||||
const projectId = ref<string | number>("");
|
||||
const originalTableData = ref<ProjectNotification[]>([]);
|
||||
const searchedData = ref<ProjectNotification[]>([]); // 存储搜索结果
|
||||
const displayData = ref<ProjectNotification[]>([]); // 实际显示的数据
|
||||
const searchedData = ref<ProjectNotification[]>([]);
|
||||
const displayData = ref<ProjectNotification[]>([]);
|
||||
|
||||
const loading = ref(false);
|
||||
const error = ref("");
|
||||
const searchId = ref("");
|
||||
|
||||
// 修改搜索处理方法,不再调用后端接口
|
||||
|
||||
const handleIdSearch = () => {
|
||||
const value = searchId.value.trim();
|
||||
|
||||
@ -97,14 +97,14 @@ const handleIdSearch = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 在原始数据中过滤
|
||||
|
||||
const result = originalTableData.value.filter(item => item.id === id);
|
||||
|
||||
if (result.length === 0) {
|
||||
message.warning("未找到匹配的项目通知ID");
|
||||
}
|
||||
|
||||
// 更新显示数据为搜索结果
|
||||
|
||||
searchedData.value = result;
|
||||
displayData.value = result;
|
||||
};
|
||||
@ -208,16 +208,15 @@ const deleteNotification = async (id: number) => {
|
||||
};
|
||||
|
||||
|
||||
// 从路由参数中获取项目ID
|
||||
if (typeof route.query.id === "string") {
|
||||
projectId.value = route.query.id;
|
||||
}
|
||||
|
||||
// 修改新增按钮的路由跳转,传递projectId到新增页面
|
||||
|
||||
const goAddProjectNotice = () => {
|
||||
router.push({
|
||||
path: '/addprojectNotice',
|
||||
query: { projectId: projectId.value } // 传递项目ID到新增页面
|
||||
query: { projectId: projectId.value }
|
||||
});
|
||||
};
|
||||
|
||||
@ -298,8 +297,6 @@ const goBack = () => {
|
||||
}
|
||||
|
||||
|
||||
/*橙色按钮*/
|
||||
|
||||
.custom-button {
|
||||
background-color: #ffa940;
|
||||
border-color: #ffa940;
|
||||
@ -320,7 +317,7 @@ const goBack = () => {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 危险按钮样式 */
|
||||
|
||||
.custom-button.ant-btn-dangerous {
|
||||
background-color: #ff4d4f;
|
||||
border-color: #ff4d4f;
|
||||
@ -332,7 +329,6 @@ const goBack = () => {
|
||||
border-color: #ff7875;
|
||||
}
|
||||
|
||||
/* 保持原有的其他样式不变 */
|
||||
.search-box {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@ -348,13 +344,12 @@ const goBack = () => {
|
||||
border-color: #fa8c16;
|
||||
}
|
||||
|
||||
/* 保持输入框原有样式不变 */
|
||||
|
||||
.custom-search :deep(.ant-input) {
|
||||
border-right-color: #ffa940;
|
||||
}
|
||||
|
||||
|
||||
/* 调整分页器位置 */
|
||||
:deep(.ant-table-pagination.ant-pagination) {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ const columns = [
|
||||
}
|
||||
];
|
||||
|
||||
// 接口数据类型
|
||||
|
||||
interface PromoCode {
|
||||
id: number;
|
||||
promoCodeInfoKey: string;
|
||||
@ -70,14 +70,14 @@ interface PromoCode {
|
||||
|
||||
const route = useRoute();
|
||||
const projectId = ref<string | number>("");
|
||||
const originalTableData = ref<PromoCode[]>([]); // 存储所有原始数据
|
||||
const displayData = ref<PromoCode[]>([]); // 实际显示的数据
|
||||
const originalTableData = ref<PromoCode[]>([]);
|
||||
const displayData = ref<PromoCode[]>([]);
|
||||
const loading = ref(false);
|
||||
const searchId = ref("");
|
||||
const previewVisible = ref(false);
|
||||
const previewImage = ref("");
|
||||
|
||||
// 主查询方法 - 获取项目所有推广码
|
||||
|
||||
const getPromoCodes = async (id: string | number) => {
|
||||
const storedToken = localStorage.getItem('token');
|
||||
try {
|
||||
@ -95,10 +95,9 @@ const getPromoCodes = async (id: string | number) => {
|
||||
console.log(response);
|
||||
|
||||
if (response.code === 1) {
|
||||
// 确保data是数组,即使为null也转为空数组
|
||||
const data = Array.isArray(response.data) ? response.data : [];
|
||||
originalTableData.value = data;
|
||||
displayData.value = data; // 初始显示所有数据
|
||||
displayData.value = data;
|
||||
} else {
|
||||
message.error(response.message || "获取数据失败");
|
||||
originalTableData.value = [];
|
||||
@ -114,7 +113,7 @@ const getPromoCodes = async (id: string | number) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化逻辑
|
||||
|
||||
if (typeof route.query.id === "string") {
|
||||
projectId.value = route.query.id;
|
||||
}
|
||||
@ -125,7 +124,7 @@ onMounted(() => {
|
||||
}
|
||||
});
|
||||
|
||||
// 修改搜索处理 - 前端过滤
|
||||
|
||||
const handleIdSearch = () => {
|
||||
const value = searchId.value.trim();
|
||||
|
||||
@ -140,18 +139,18 @@ const handleIdSearch = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 在前端原始数据中过滤
|
||||
|
||||
const result = originalTableData.value.filter(item => item.id === id);
|
||||
|
||||
if (result.length === 0) {
|
||||
message.warning("未找到匹配的推广码ID");
|
||||
}
|
||||
|
||||
// 更新显示数据
|
||||
|
||||
displayData.value = result;
|
||||
};
|
||||
|
||||
// 重置搜索 - 显示所有数据
|
||||
// 重置搜索
|
||||
const reset = () => {
|
||||
searchId.value = "";
|
||||
displayData.value = originalTableData.value;
|
||||
@ -181,14 +180,13 @@ const openAddDrawer = () => {
|
||||
|
||||
// 提交新增请求
|
||||
const handleAddSubmit = async () => {
|
||||
// 如果有文件需要上传
|
||||
|
||||
if (fileList.value.length > 0) {
|
||||
const imageUrl = await handleUpload();
|
||||
if (!imageUrl) {
|
||||
message.error('图片上传失败,无法提交');
|
||||
return;
|
||||
}
|
||||
// 更新表单中的图片URL
|
||||
addFormState.promoCodeImage = imageUrl;
|
||||
}
|
||||
|
||||
@ -215,7 +213,7 @@ const handleAddSubmit = async () => {
|
||||
message.success('新增成功');
|
||||
addDrawerVisible.value = false;
|
||||
await getPromoCodes(projectId.value);
|
||||
// 重置表单和文件列表
|
||||
|
||||
Object.assign(addFormState, {
|
||||
promoCodeInfoKey: '',
|
||||
promoCodeLink: '',
|
||||
@ -309,14 +307,14 @@ const handleEdit = async (id: number) => {
|
||||
};
|
||||
|
||||
const handleEditSubmit = async () => {
|
||||
// 如果有文件需要上传
|
||||
|
||||
if (fileList.value.length > 0) {
|
||||
const imageUrl = await handleUpload();
|
||||
if (!imageUrl) {
|
||||
message.error('图片上传失败,无法提交');
|
||||
return;
|
||||
}
|
||||
// 更新表单中的图片URL
|
||||
|
||||
editFormState.promoCodeImage = imageUrl;
|
||||
}
|
||||
|
||||
@ -343,7 +341,7 @@ const handleEditSubmit = async () => {
|
||||
message.success('编辑成功');
|
||||
editDrawerVisible.value = false;
|
||||
await getPromoCodes(projectId.value);
|
||||
// 重置文件列表
|
||||
|
||||
fileList.value = [];
|
||||
} else {
|
||||
message.error(res.message || '编辑失败');
|
||||
@ -353,19 +351,19 @@ const handleEditSubmit = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
//返回上一级
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// 返回上一级方法
|
||||
|
||||
const goBack = () => {
|
||||
router.go(-1); // 返回上一页
|
||||
router.go(-1);
|
||||
};
|
||||
|
||||
// 添加文件上传相关状态
|
||||
|
||||
const fileList = ref<any[]>([]);
|
||||
const uploading = ref(false);
|
||||
|
||||
// 图片上传处理
|
||||
|
||||
const handleUpload = async () => {
|
||||
const formData = new FormData();
|
||||
fileList.value.forEach(file => {
|
||||
@ -382,7 +380,7 @@ const handleUpload = async () => {
|
||||
{
|
||||
headers: {
|
||||
'Authorization': storedToken,
|
||||
'AflatScript': 'required', // 添加AflatScript头部
|
||||
'AflatScript': 'required',
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
}
|
||||
@ -390,7 +388,7 @@ const handleUpload = async () => {
|
||||
|
||||
if (res.code === 1) {
|
||||
message.success('上传成功');
|
||||
// 将返回的文件路径保存到表单中
|
||||
|
||||
addFormState.promoCodeImage = res.data;
|
||||
return res.data;
|
||||
} else {
|
||||
@ -405,23 +403,23 @@ const handleUpload = async () => {
|
||||
uploading.value = false;
|
||||
}
|
||||
};
|
||||
// 文件上传前的处理
|
||||
|
||||
const beforeUpload = (file: any) => {
|
||||
// 检查文件类型
|
||||
|
||||
const isImage = file.type.includes('image');
|
||||
if (!isImage) {
|
||||
message.error('只能上传图片文件!');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查文件大小 (限制为5MB)
|
||||
|
||||
const isLt5M = file.size / 1024 / 1024 < 5;
|
||||
if (!isLt5M) {
|
||||
message.error('图片大小不能超过5MB!');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 添加到文件列表
|
||||
|
||||
fileList.value = [file];
|
||||
return false; // 手动上传
|
||||
};
|
||||
@ -466,9 +464,9 @@ const batchDelete = async () => {
|
||||
|
||||
if (res.code === 1) {
|
||||
message.success(`成功删除 ${selectedRowKeys.value.length} 条记录`);
|
||||
// 刷新数据
|
||||
|
||||
await getPromoCodes(projectId.value);
|
||||
// 清空选择
|
||||
|
||||
selectedRowKeys.value = [];
|
||||
} else {
|
||||
message.error(res.message || '批量删除失败');
|
||||
@ -750,26 +748,13 @@ const batchDelete = async () => {
|
||||
background-color: #fafafa !important;
|
||||
}
|
||||
|
||||
/* 新增表格页脚样式 */
|
||||
.table-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
/* 调整分页器位置 */
|
||||
:deep(.ant-table-pagination.ant-pagination) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*橙色按钮*/
|
||||
|
||||
.custom-button {
|
||||
background-color: #ffa940;
|
||||
@ -791,7 +776,7 @@ const batchDelete = async () => {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 危险按钮样式 */
|
||||
|
||||
.custom-button.ant-btn-dangerous {
|
||||
background-color: #ff4d4f;
|
||||
border-color: #ff4d4f;
|
||||
@ -803,7 +788,7 @@ const batchDelete = async () => {
|
||||
border-color: #ff7875;
|
||||
}
|
||||
|
||||
/* 保持原有的其他样式不变 */
|
||||
|
||||
.search-box {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@ -819,7 +804,6 @@ const batchDelete = async () => {
|
||||
border-color: #fa8c16;
|
||||
}
|
||||
|
||||
/* 保持输入框原有样式不变 */
|
||||
.custom-search :deep(.ant-input) {
|
||||
border-right-color: #ffa940;
|
||||
}
|
||||
@ -834,23 +818,5 @@ const batchDelete = async () => {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/*批量删除按钮操作*/
|
||||
.batch-delete-button {
|
||||
margin-left: 10px;
|
||||
background-color: #ff4d4f;
|
||||
border-color: #ff4d4f;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.batch-delete-button:hover {
|
||||
background-color: #ff7875;
|
||||
border-color: #ff7875;
|
||||
}
|
||||
|
||||
/* 添加选择计数样式 */
|
||||
.selection-count {
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
</style>
|
@ -11,7 +11,7 @@
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'projectImage'">
|
||||
<!-- 修复:添加 alt 属性 -->
|
||||
|
||||
<img
|
||||
:src="downLoadImage+record.projectImage"
|
||||
alt="项目图片"
|
||||
@ -19,7 +19,7 @@
|
||||
/>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'projectCodeImage'">
|
||||
<!-- 修复:添加 alt 属性 -->
|
||||
|
||||
<img
|
||||
:src="downLoadImage+record.projectCodeImage"
|
||||
alt="推广码"
|
||||
@ -62,7 +62,7 @@ interface PromoRecord {
|
||||
createTime: string;
|
||||
}
|
||||
|
||||
// 列配置保持不变
|
||||
|
||||
const columns = ref([
|
||||
{
|
||||
title: 'ID',
|
||||
@ -166,7 +166,7 @@ const columns = ref([
|
||||
const dataSource = ref<PromoRecord[]>([]);
|
||||
const loading = ref(false);
|
||||
|
||||
// 添加排序参数
|
||||
|
||||
const sortParams = reactive({
|
||||
sortField: 'id',
|
||||
sortOrder: 'ascend'
|
||||
@ -180,7 +180,7 @@ const pagination = reactive({
|
||||
showTotal: (total: number) => `共 ${total} 条`,
|
||||
});
|
||||
|
||||
// fetchData 方法保持不变
|
||||
|
||||
const fetchData = async () => {
|
||||
const storedToken = localStorage.getItem('token');
|
||||
try {
|
||||
@ -208,7 +208,7 @@ const fetchData = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 修复:简化排序处理逻辑
|
||||
|
||||
const handleTableChange: TableProps['onChange'] = (pag, _, sorter) => {
|
||||
// 处理分页参数
|
||||
if (pag) {
|
||||
@ -216,16 +216,15 @@ const handleTableChange: TableProps['onChange'] = (pag, _, sorter) => {
|
||||
pagination.pageSize = pag.pageSize!;
|
||||
}
|
||||
|
||||
// 修复:简化排序处理
|
||||
if (sorter) {
|
||||
// 处理排序参数(只处理单列排序)
|
||||
|
||||
const { field, order } = sorter as { field?: string; order?: string };
|
||||
|
||||
if (field && order) {
|
||||
sortParams.sortField = field;
|
||||
sortParams.sortOrder = order;
|
||||
} else {
|
||||
// 取消排序时重置
|
||||
|
||||
sortParams.sortField = 'id';
|
||||
sortParams.sortOrder = 'ascend';
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ import { useRoute } from 'vue-router';
|
||||
import router from '../../router';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
// 项目结算记录接口类型
|
||||
|
||||
interface SettlementRecord {
|
||||
id: number;
|
||||
projectDetailName: string;
|
||||
@ -201,7 +201,7 @@ const loading = ref(false);
|
||||
const searchId = ref(''); // 新增搜索ID绑定
|
||||
const originalData = ref<SettlementRecord[]>([]); // 存储原始数据
|
||||
|
||||
// 分页配置
|
||||
|
||||
const pagination = reactive({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
@ -210,13 +210,13 @@ const pagination = reactive({
|
||||
showTotal: (total: number) => `共 ${total} 条`,
|
||||
});
|
||||
|
||||
// 获取路由参数
|
||||
|
||||
const route = useRoute();
|
||||
const idFromRoute = route.query.id as string | undefined;
|
||||
const projectIdFromRoute = route.query.projectId as string | undefined;
|
||||
const userIdFromRoute = route.query.userId as string | undefined;
|
||||
|
||||
// 计算属性:根据分页参数生成表格渲染用的分页数据
|
||||
|
||||
const paginatedData = computed(() => {
|
||||
const start = (pagination.current - 1) * pagination.pageSize;
|
||||
const end = start + pagination.pageSize;
|
||||
@ -232,7 +232,7 @@ const fetchData = async () => {
|
||||
|
||||
const response: any = await myAxios.post(
|
||||
'/projectSettlement/queryByPId',
|
||||
{ id: idFromRoute }, // 使用从路由获取的id
|
||||
{ id: idFromRoute },
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@ -246,7 +246,7 @@ const fetchData = async () => {
|
||||
|
||||
if (response.code === 1) {
|
||||
allData.value = response.data;
|
||||
originalData.value = [...response.data]; // 保存原始数据
|
||||
originalData.value = [...response.data];
|
||||
filteredData.value = [...response.data];
|
||||
pagination.total = response.data.length;
|
||||
} else {
|
||||
@ -272,7 +272,7 @@ const fetchData = async () => {
|
||||
const handleIdSearch = (value: string) => {
|
||||
const idStr = value.trim();
|
||||
if (!idStr) {
|
||||
// 如果搜索值为空,显示所有数据
|
||||
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
@ -283,7 +283,7 @@ const handleIdSearch = (value: string) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 前端过滤 originalData 数据
|
||||
|
||||
const result = originalData.value.filter((record) => record.id === id);
|
||||
|
||||
if (result.length > 0) {
|
||||
@ -302,21 +302,20 @@ const reset = () => {
|
||||
searchId.value = '';
|
||||
filteredData.value = [...originalData.value];
|
||||
pagination.total = originalData.value.length;
|
||||
pagination.current = 1; // 重置页码
|
||||
revenueSourceFilter.value = 'all'; // 重置收益来源筛选
|
||||
pagination.current = 1;
|
||||
revenueSourceFilter.value = 'all';
|
||||
applyFilters();
|
||||
};
|
||||
|
||||
// 表格分页变更处理
|
||||
|
||||
const handleTableChange: TableProps['onChange'] = (pag) => {
|
||||
if (pag) {
|
||||
pagination.current = pag.current!;
|
||||
pagination.pageSize = pag.pageSize!;
|
||||
// 计算属性自动根据 pagination 变化更新,无需额外调用
|
||||
}
|
||||
};
|
||||
|
||||
// 返回按钮(修正拼写,保持语义清晰)
|
||||
|
||||
const goBack = () => {
|
||||
router.push('/applicationRecord');
|
||||
};
|
||||
@ -328,7 +327,7 @@ const deleteRecord = async (id: number) => {
|
||||
try {
|
||||
const response: any = await myAxios.post(
|
||||
'/projectSettlement/delete',
|
||||
{ id }, // 要删除的记录ID
|
||||
{ id },
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@ -342,13 +341,13 @@ const deleteRecord = async (id: number) => {
|
||||
|
||||
if (response.code === 1) {
|
||||
message.success('删除成功');
|
||||
// 重新加载数据
|
||||
|
||||
if (searchId.value) {
|
||||
// 如果当前在搜索状态,重新搜索
|
||||
|
||||
handleIdSearch(searchId.value);
|
||||
} else {
|
||||
// 否则重新获取所有数据
|
||||
await fetchData(); // 异步函数调用加 await
|
||||
|
||||
await fetchData();
|
||||
}
|
||||
} else {
|
||||
message.error(response.message || '删除失败');
|
||||
@ -370,7 +369,7 @@ const form = reactive({
|
||||
settlementRevenue: '',
|
||||
workTime: null,
|
||||
settlementTime: null,
|
||||
// 新增:自动填充路由参数
|
||||
|
||||
promoCodeApplyId: idFromRoute || 0,
|
||||
projectId: projectIdFromRoute || 0,
|
||||
userId: userIdFromRoute || 0,
|
||||
@ -381,7 +380,7 @@ const form = reactive({
|
||||
|
||||
const showModal = () => {
|
||||
visible.value = true;
|
||||
// 重置非路由传递的字段(避免重复填充)
|
||||
|
||||
form.projectDetailName = '';
|
||||
form.settlementQuantity = '';
|
||||
form.settlementRevenue ='';
|
||||
@ -435,13 +434,12 @@ const handleAdd = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const revenueSourceFilter = ref<string | boolean>('all'); // 收益来源筛选值
|
||||
const revenueSourceFilter = ref<string | boolean>('all');
|
||||
|
||||
|
||||
// 应用筛选条件
|
||||
const applyFilters = () => {
|
||||
let result = [...originalData.value];
|
||||
|
||||
// 应用ID筛选
|
||||
if (searchId.value.trim() !== '') {
|
||||
const id = Number(searchId.value.trim());
|
||||
if (!isNaN(id)) {
|
||||
@ -449,7 +447,7 @@ const applyFilters = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 应用收益来源筛选
|
||||
|
||||
if (revenueSourceFilter.value !== 'all') {
|
||||
result = result.filter(record => record.revenueSource === revenueSourceFilter.value);
|
||||
}
|
||||
@ -473,7 +471,7 @@ const applyFilters = () => {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* 橙色按钮样式 */
|
||||
|
||||
.custom-button {
|
||||
background-color: #ffa940;
|
||||
border-color: #ffa940;
|
||||
@ -488,7 +486,7 @@ const applyFilters = () => {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* 表格样式调整 */
|
||||
|
||||
:deep(.ant-table-thead) {
|
||||
background-color: #fafafa;
|
||||
font-weight: 600;
|
||||
@ -498,7 +496,7 @@ const applyFilters = () => {
|
||||
background-color: #f9f9f9 !important;
|
||||
}
|
||||
|
||||
/* 搜索按钮样式 */
|
||||
|
||||
.custom-search :deep(.ant-input-search-button) {
|
||||
background-color: #ffa940;
|
||||
border-color: #ffa940;
|
||||
@ -510,7 +508,7 @@ const applyFilters = () => {
|
||||
border-color: #fa8c16;
|
||||
}
|
||||
|
||||
/* 保持输入框原有样式不变 */
|
||||
|
||||
.custom-search :deep(.ant-input) {
|
||||
border-right-color: #ffa940;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ interface WithdrawalRecord {
|
||||
withdrawalStatus: string;
|
||||
}
|
||||
|
||||
// 修改后的列配置 - 添加排序功能
|
||||
|
||||
const columns = ref([
|
||||
{
|
||||
title: '提现申请记录ID',
|
||||
@ -59,8 +59,8 @@ const columns = ref([
|
||||
width: 80,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
{
|
||||
title: '持卡人',
|
||||
@ -68,8 +68,8 @@ const columns = ref([
|
||||
key: 'cardHolder',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
{
|
||||
title: '身份证号',
|
||||
@ -84,8 +84,8 @@ const columns = ref([
|
||||
key: 'phoneNumber',
|
||||
width: 140,
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
{
|
||||
title: '银行卡号',
|
||||
@ -107,8 +107,8 @@ const columns = ref([
|
||||
key: 'withdrawnAmount',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
{
|
||||
title: '提取状态',
|
||||
@ -129,7 +129,7 @@ const columns = ref([
|
||||
const dataSource = ref<WithdrawalRecord[]>([]);
|
||||
const loading = ref(false);
|
||||
|
||||
// 添加排序参数
|
||||
|
||||
const sortParams = reactive({
|
||||
sortField: 'id',
|
||||
sortOrder: 'ascend'
|
||||
@ -143,7 +143,7 @@ const pagination = reactive({
|
||||
showTotal: (total: number) => `共 ${total} 条`,
|
||||
});
|
||||
|
||||
// 状态映射函数
|
||||
|
||||
const getStatusText = (status: string) => {
|
||||
const statusMap: Record<string, string> = {
|
||||
'processing': '提现中',
|
||||
@ -153,7 +153,7 @@ const getStatusText = (status: string) => {
|
||||
return statusMap[status] || status;
|
||||
};
|
||||
|
||||
// 状态颜色映射函数
|
||||
|
||||
const getStatusColor = (status: string) => {
|
||||
const colorMap: Record<string, string> = {
|
||||
'processing': 'blue',
|
||||
@ -163,7 +163,7 @@ const getStatusColor = (status: string) => {
|
||||
return colorMap[status] || 'default';
|
||||
};
|
||||
|
||||
// 修改后的 fetchData 方法 - 添加排序参数
|
||||
|
||||
const fetchData = async () => {
|
||||
const storedToken = localStorage.getItem('token');
|
||||
try {
|
||||
@ -171,8 +171,8 @@ const fetchData = async () => {
|
||||
const response: any = await myAxios.post('/withdrawalApply/page', {
|
||||
current: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
sortField: sortParams.sortField, // 添加排序字段
|
||||
sortOrder: sortParams.sortOrder, // 添加排序方式
|
||||
sortField: sortParams.sortField,
|
||||
sortOrder: sortParams.sortOrder,
|
||||
withdrawalStatus: 'processing'
|
||||
}, {
|
||||
headers: {
|
||||
@ -193,7 +193,7 @@ const fetchData = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 修改后的 handleTableChange 方法 - 处理排序
|
||||
|
||||
const handleTableChange: TableProps['onChange'] = (pag, _, sorter) => {
|
||||
// 处理分页参数
|
||||
if (pag) {
|
||||
@ -209,7 +209,7 @@ const handleTableChange: TableProps['onChange'] = (pag, _, sorter) => {
|
||||
sortParams.sortField = field;
|
||||
sortParams.sortOrder = order;
|
||||
} else {
|
||||
// 取消排序时重置
|
||||
|
||||
sortParams.sortField = 'id';
|
||||
sortParams.sortOrder = 'ascend';
|
||||
}
|
||||
|
@ -20,11 +20,11 @@
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-button class="custom-button" @click="showModal">新增用户</a-button>
|
||||
<a-button class="custom-button" @click="showModal">新增管理员</a-button>
|
||||
<!--新增用户-->
|
||||
<a-modal
|
||||
v-model:open="openUser"
|
||||
title="新增用户"
|
||||
title="新增管理员"
|
||||
@ok="handleOk"
|
||||
:footer="null"
|
||||
>
|
||||
@ -375,22 +375,22 @@ const beforeUpload: UploadProps['beforeUpload'] = file => {
|
||||
// 自定义上传处理
|
||||
const handleUpload = async ({ file }: { file: File }) => {
|
||||
const form = new FormData();
|
||||
form.append('file', file); // 只保留file字段在formData中
|
||||
form.append('file', file);
|
||||
|
||||
try {
|
||||
uploadLoading.value = true;
|
||||
const storedToken = localStorage.getItem('token');
|
||||
|
||||
// 根据接口文档修改请求地址和参数
|
||||
|
||||
const res:any = await myAxios.post('/file/upload?biz=avatar', form, {
|
||||
headers: {
|
||||
Authorization: storedToken,
|
||||
// 保留由浏览器自动生成的内容类型
|
||||
|
||||
}
|
||||
});
|
||||
console.log(res)
|
||||
// 根据响应结构调整(假设返回data直接是URL)
|
||||
if (res.code === 1) { // 注意文档中响应状态码是200
|
||||
|
||||
if (res.code === 1) {
|
||||
formData.value.userAvatar = res.data;
|
||||
previewImage.value = URL.createObjectURL(file);
|
||||
message.success('上传成功');
|
||||
@ -405,29 +405,29 @@ const handleUpload = async ({ file }: { file: File }) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 编辑表单实时处理函数
|
||||
|
||||
const handleEditNicknameInput = (e: any) => {
|
||||
// 限制最大长度并实时提示
|
||||
|
||||
const trimmedValue = e.target.value.trim().slice(0, 6);
|
||||
editForm.value.nickName = trimmedValue;
|
||||
// 触发表单校验
|
||||
|
||||
editFormRef.value?.validateField('nickName');
|
||||
};
|
||||
|
||||
const handleEditPhoneInput = (e: any) => {
|
||||
// 过滤非数字字符并限制长度
|
||||
|
||||
const numericValue = e.target.value.replace(/\D/g, '').slice(0, 11);
|
||||
editForm.value.phoneNumber = numericValue;
|
||||
// 触发手机号格式校验
|
||||
|
||||
editFormRef.value?.validateField('phoneNumber');
|
||||
};
|
||||
|
||||
const handleEditPasswordInput = (e: any) => {
|
||||
// 限制密码长度
|
||||
|
||||
editForm.value.userPassword = e.target.value.slice(0, 10);
|
||||
};
|
||||
|
||||
// 通用最大长度处理函数
|
||||
|
||||
const handleMaxLength = (max: number) => (e: KeyboardEvent) => {
|
||||
if (e.target instanceof HTMLInputElement && e.target.value.length >= max) {
|
||||
e.preventDefault();
|
||||
@ -516,7 +516,7 @@ const handleSearchPhoneInput = (e: any) => {
|
||||
|
||||
// 新增 onKeyDown 事件处理函数
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
// 允许控制键(如删除、左右方向键等)
|
||||
|
||||
const allowedKeys = [
|
||||
'Backspace',
|
||||
'Delete',
|
||||
@ -525,13 +525,13 @@ const handleKeyDown = (e: KeyboardEvent) => {
|
||||
'Tab',
|
||||
];
|
||||
|
||||
// 阻止非数字和非允许按键
|
||||
|
||||
if (!/[0-9]/.test(e.key) && !allowedKeys.includes(e.key)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
// 实时校验逻辑
|
||||
|
||||
const formData = ref({
|
||||
nickName: '',
|
||||
userAvatar: '',
|
||||
@ -590,8 +590,8 @@ const columns = [
|
||||
key: 'id',
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
|
||||
{
|
||||
@ -630,8 +630,8 @@ const columns = [
|
||||
key: 'phoneNumber',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
{
|
||||
title: '邀请码',
|
||||
@ -639,8 +639,8 @@ const columns = [
|
||||
key: 'invitationCode',
|
||||
width: 70,
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
{
|
||||
title: '上级ID',
|
||||
@ -648,8 +648,8 @@ const columns = [
|
||||
key: 'parentUserId',
|
||||
width: 40,
|
||||
align: 'center',
|
||||
sorter: true, // 添加排序功能
|
||||
sortDirections: ['ascend', 'descend'] // 允许升序降序
|
||||
sorter: true,
|
||||
sortDirections: ['ascend', 'descend']
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
@ -670,7 +670,7 @@ const pagination = ref({
|
||||
pageSizeOptions: ['10', '20', '50', '100']
|
||||
});
|
||||
//编辑用户表单
|
||||
// 新增编辑表单校验规则
|
||||
|
||||
const editFormRules = {
|
||||
nickName: [
|
||||
{
|
||||
@ -721,13 +721,13 @@ const editHasLower = computed(() => /[a-z]/.test(editForm.value.userPassword))
|
||||
const editHasUpper = computed(() => /[A-Z]/.test(editForm.value.userPassword))
|
||||
const editHasNumber = computed(() => /\d/.test(editForm.value.userPassword))
|
||||
|
||||
const editFormRef = ref(); // 添加表单引用
|
||||
const editFormRef = ref();
|
||||
|
||||
// 修改后的分页处理函数
|
||||
const handleTableChange = (pag: any, _: any, sorter: any) => {
|
||||
// 处理排序参数
|
||||
let sortField = "id"; // 默认排序字段
|
||||
let sortOrder = "ascend"; // 默认排序方式
|
||||
|
||||
let sortField = "id";
|
||||
let sortOrder = "ascend";
|
||||
|
||||
if (sorter.field) {
|
||||
sortField = sorter.field;
|
||||
@ -738,8 +738,8 @@ const handleTableChange = (pag: any, _: any, sorter: any) => {
|
||||
...searchParams.value,
|
||||
current: pag.current,
|
||||
pageSize: pag.pageSize,
|
||||
sortField: sortField, // 设置排序字段
|
||||
sortOrder: sortOrder // 设置排序方式
|
||||
sortField: sortField,
|
||||
sortOrder: sortOrder
|
||||
};
|
||||
|
||||
pagination.value.current = pag.current;
|
||||
@ -749,7 +749,7 @@ const handleTableChange = (pag: any, _: any, sorter: any) => {
|
||||
};
|
||||
|
||||
|
||||
// 修改获取用户列表方法
|
||||
|
||||
const getUserList = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
@ -771,7 +771,7 @@ const getUserList = async () => {
|
||||
superUserList: item.superHostList? item.superHostList.join(', ') : '无'
|
||||
};
|
||||
});
|
||||
// 更新分页信息
|
||||
|
||||
pagination.value.total = res.data.total;
|
||||
pagination.value.current = res.data.current;
|
||||
pagination.value.pageSize = res.data.size;
|
||||
@ -796,14 +796,11 @@ interface User {
|
||||
parentUserId:number
|
||||
}
|
||||
|
||||
const tableData = ref<User[]>([]); // 明确元素类型为User[]
|
||||
const tableData = ref<User[]>([]);
|
||||
|
||||
const searchPhone = ref(""); // 手机号搜索参数
|
||||
const searchPhone = ref("");
|
||||
|
||||
// 修改5: 删除原有的searchId变量
|
||||
// const searchId = ref(""); // 删除这行
|
||||
|
||||
// 修改6: 替换原有的handleIdSearch方法
|
||||
const handlePhoneSearch = async () => {
|
||||
if (!searchPhone.value) {
|
||||
message.warning('请输入手机号');
|
||||
@ -821,7 +818,7 @@ const handlePhoneSearch = async () => {
|
||||
const storedToken = localStorage.getItem('token');
|
||||
if (!storedToken) throw new Error('未找到登录信息');
|
||||
|
||||
// 修改7: 使用phoneNumber作为查询参数
|
||||
|
||||
const res: { code: number; data: any; message: any } = await myAxios.post(
|
||||
"/userInfo/page",
|
||||
{
|
||||
@ -857,9 +854,9 @@ const handlePhoneSearch = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 修改8: 更新reset方法
|
||||
|
||||
const reset = () => {
|
||||
searchPhone.value = ""; // 清空手机号搜索
|
||||
searchPhone.value = "";
|
||||
searchParams.value = {
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
@ -868,7 +865,7 @@ const reset = () => {
|
||||
userRole: null,
|
||||
phoneNumber: null
|
||||
};
|
||||
getUserList(); // 重新加载列表
|
||||
getUserList();
|
||||
};
|
||||
|
||||
|
||||
@ -882,13 +879,13 @@ const rowSelection = {
|
||||
selectedRowKeys.value = selectedKeys;
|
||||
},
|
||||
selectedRowKeys: selectedRowKeys,
|
||||
// 添加getCheckboxProps方法,根据用户角色决定是否禁用复选框
|
||||
|
||||
getCheckboxProps: (record: User) => ({
|
||||
disabled: record.userRole !== 'admin', // 只有admin用户可以选择
|
||||
disabled: record.userRole !== 'admin',
|
||||
name: record.id.toString(),
|
||||
}),
|
||||
};
|
||||
// 修改删除用户方法,添加确认弹窗
|
||||
|
||||
const confirmDeleteUser = (id: number) => {
|
||||
Modal.confirm({
|
||||
title: '确认删除用户',
|
||||
@ -897,7 +894,7 @@ const confirmDeleteUser = (id: number) => {
|
||||
okType: 'danger',
|
||||
cancelText: '取消',
|
||||
onOk() {
|
||||
return deleteUser(id); // 调用实际删除方法
|
||||
return deleteUser(id);
|
||||
},
|
||||
onCancel() {
|
||||
console.log('用户取消删除');
|
||||
@ -905,7 +902,7 @@ const confirmDeleteUser = (id: number) => {
|
||||
});
|
||||
};
|
||||
|
||||
// 修改批量删除方法,添加确认弹窗
|
||||
|
||||
const batchDelete = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
message.warning('请先选择要删除的用户');
|
||||
@ -952,7 +949,7 @@ const batchDelete = async () => {
|
||||
});
|
||||
};
|
||||
|
||||
// 原有的deleteUser方法保持不变(执行实际删除操作)
|
||||
|
||||
const deleteUser = async (id: number) => {
|
||||
try {
|
||||
const storedToken = localStorage.getItem('token');
|
||||
@ -1000,13 +997,11 @@ const editForm = ref({
|
||||
SuperUserList: ''
|
||||
});
|
||||
|
||||
// 修改showDrawer方法
|
||||
|
||||
// 编辑状态下的头像上传状态
|
||||
const editUploadLoading = ref(false);
|
||||
const editPreviewImage = ref('');
|
||||
|
||||
// 编辑时的自定义上传处理
|
||||
|
||||
const handleEditUpload = async ({ file }: { file: File }) => {
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
@ -1058,15 +1053,14 @@ const showDrawer = (record: any) => {
|
||||
const toggleEditMode = () => {
|
||||
isEditMode.value = !isEditMode.value;
|
||||
};
|
||||
//保存修改的用户信息
|
||||
//保存修改的用户信息
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
// 检查密码是否修改且符合规则
|
||||
|
||||
if (editForm.value.userPassword) {
|
||||
const password = editForm.value.userPassword;
|
||||
|
||||
// 验证密码规则:必须包含数字、大写字母和小写字母
|
||||
|
||||
const hasNumber = /\d/.test(password);
|
||||
const hasUpperCase = /[A-Z]/.test(password);
|
||||
const hasLowerCase = /[a-z]/.test(password);
|
||||
@ -1080,19 +1074,19 @@ const handleSave = async () => {
|
||||
const storedToken = localStorage.getItem('token');
|
||||
if (!storedToken) throw new Error('未找到登录信息');
|
||||
|
||||
// 处理空值转换
|
||||
|
||||
const processValue = (value: any) => {
|
||||
if (value === "" || value === "无") return null; // 将空字符串和"无"转为null
|
||||
if (value === "" || value === "无") return null;
|
||||
return value;
|
||||
};
|
||||
|
||||
// 处理数字类型字段
|
||||
|
||||
const processNumber = (value: any) => {
|
||||
const num = Number(value);
|
||||
return isNaN(num) ? null : num;
|
||||
};
|
||||
|
||||
// 构建请求体
|
||||
|
||||
const payload = {
|
||||
id: editForm.value.id,
|
||||
nickName: processValue(editForm.value.nickName),
|
||||
@ -1110,7 +1104,7 @@ const handleSave = async () => {
|
||||
: []
|
||||
};
|
||||
|
||||
// 清理undefined字段
|
||||
|
||||
const cleanPayload = Object.fromEntries(
|
||||
Object.entries(payload).filter(([_, v]) => v !== undefined)
|
||||
);
|
||||
@ -1129,7 +1123,7 @@ const handleSave = async () => {
|
||||
await getUserList();
|
||||
const updatedUser = tableData.value.find(item => item.id === editForm.value.id);
|
||||
if (updatedUser) {
|
||||
selectedUser.value = { ...updatedUser }; // 关键更新
|
||||
selectedUser.value = { ...updatedUser };
|
||||
}
|
||||
isEditMode.value = false;
|
||||
} else {
|
||||
@ -1142,7 +1136,7 @@ const handleSave = async () => {
|
||||
};
|
||||
|
||||
|
||||
//新增用户
|
||||
|
||||
const openUser = ref<boolean>(false);
|
||||
const formRef = ref();
|
||||
|
||||
@ -1157,7 +1151,7 @@ const showModal = () => {
|
||||
userAccount: '',
|
||||
userPassword: ''
|
||||
};
|
||||
// 重置预览图片
|
||||
|
||||
previewImage.value = '';
|
||||
};
|
||||
|
||||
@ -1206,12 +1200,12 @@ const handleSubmit = async () => {
|
||||
formRef.value?.resetFields();
|
||||
getUserList();
|
||||
} else {
|
||||
// 使用提取函数处理错误信息
|
||||
|
||||
const errorMsg = extractErrorMessage(res.message);
|
||||
message.error(`${errorMsg}`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
// 使用提取函数处理错误信息
|
||||
|
||||
let errorMsg = error.response?.message || error.message;
|
||||
errorMsg = extractErrorMessage(errorMsg);
|
||||
message.error(`${errorMsg}`);
|
||||
@ -1225,7 +1219,7 @@ const handleSubmit = async () => {
|
||||
.action-btn {
|
||||
padding: 0 8px;
|
||||
}
|
||||
/* 分割线样式 */
|
||||
|
||||
:deep(.ant-divider-vertical) {
|
||||
border-color: rgba(0, 0, 0, 0.15);
|
||||
height: 1.2em;
|
||||
@ -1316,46 +1310,14 @@ const handleSubmit = async () => {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.code {
|
||||
font-family: monospace;
|
||||
background: #f5f5f5;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
|
||||
.role-tag {
|
||||
margin-left: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.relation-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
.relation-icon {
|
||||
font-size: 20px;
|
||||
color: #52c41a;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.relation-group {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.relation-label {
|
||||
display: inline-block;
|
||||
width: 80px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.relation-value {
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 角色颜色映射 */
|
||||
:root {
|
||||
--role-user: #87d068;
|
||||
--role-admin: #f50;
|
||||
@ -1507,7 +1469,7 @@ const handleSubmit = async () => {
|
||||
border-color: #fa8c16;
|
||||
}
|
||||
|
||||
/* 保持输入框原有样式不变 */
|
||||
|
||||
.custom-search :deep(.ant-input) {
|
||||
border-right-color: #ffa940;
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
{"root":["./src/main.ts","./src/vite-env.d.ts","./src/api/imageurl.ts","./src/api/myaxios.ts","./src/router/index.ts","./src/router/routes.ts","./src/store/index.ts","./src/store/userstore.ts","./src/types/wangeditor.d.ts","./src/app.vue","./src/layout/managelayout.vue","./src/layout/manage/manageheader.vue","./src/layout/manage/managesidebar.vue","./src/view/index.vue","./src/view/login.vue","./src/view/test.vue","./src/view/community/community.vue","./src/view/components/richtexteditor.vue","./src/view/course/linkedcourse.vue","./src/view/course/localcurriculum.vue","./src/view/project/addproject.vue","./src/view/project/addprojectnotice.vue","./src/view/project/moneydetail.vue","./src/view/project/noticedetail.vue","./src/view/project/project.vue","./src/view/project/projectdetail.vue","./src/view/project/projectnotice.vue","./src/view/project/promotioncode.vue","./src/view/settlement/applicationrecord.vue","./src/view/settlement/moneyrecord.vue","./src/view/settlement/withdrawalapplicationrecord.vue","./src/view/userlist/userlist.vue","./src/view/work/workdetail.vue","./src/view/work/worklist.vue"],"version":"5.6.3"}
|
||||
{"root":["./src/main.ts","./src/vite-env.d.ts","./src/api/imageurl.ts","./src/api/myaxios.ts","./src/router/index.ts","./src/router/routes.ts","./src/store/index.ts","./src/store/userstore.ts","./src/types/wangeditor.d.ts","./src/app.vue","./src/layout/managelayout.vue","./src/layout/manage/manageheader.vue","./src/layout/manage/managesidebar.vue","./src/view/index.vue","./src/view/login.vue","./src/view/test.vue","./src/view/community/community.vue","./src/view/components/richtexteditor.vue","./src/view/course/addcourse.vue","./src/view/course/chapterdetail.vue","./src/view/course/coursedetail.vue","./src/view/course/coursemanagement.vue","./src/view/course/courseorder.vue","./src/view/project/addproject.vue","./src/view/project/addprojectnotice.vue","./src/view/project/moneydetail.vue","./src/view/project/noticedetail.vue","./src/view/project/project.vue","./src/view/project/projectdetail.vue","./src/view/project/projectnotice.vue","./src/view/project/promotioncode.vue","./src/view/settlement/applicationrecord.vue","./src/view/settlement/moneyrecord.vue","./src/view/settlement/withdrawalapplicationrecord.vue","./src/view/userlist/userlist.vue","./src/view/work/workdetail.vue","./src/view/work/worklist.vue"],"version":"5.6.3"}
|
Reference in New Issue
Block a user