课程模块部分bug修复

This commit is contained in:
2025-07-02 09:43:17 +08:00
parent 927b200cf2
commit 06debc411c
24 changed files with 418 additions and 456 deletions

BIN
dist.zip Normal file

Binary file not shown.

View File

@ -6,7 +6,8 @@ import router from "../router";
const myAxios = axios.create({ const myAxios = axios.create({
withCredentials: true, 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:3457'
//baseURL:'http://1.94.237.210:8088' //baseURL:'http://1.94.237.210:8088'
//baseURL:'http://27.30.77.229:9091/' //baseURL:'http://27.30.77.229:9091/'

View File

@ -76,14 +76,10 @@ const checkLoginStatus = () => {
// 检查store中的登录状态 // 检查store中的登录状态
if (store.loginUser.userRole === "notLogin") { if (store.loginUser.userRole === "notLogin") {
console.log("未检测到登录状态,跳转到登录页"); console.log("未检测到登录状态,跳转到登录页");
// 使用replace替换当前路由禁止返回
router.replace({ path: '/' }); router.replace({ path: '/' });
} }
}; };
// 生命周期钩子:在组件挂载前检查登录状态
onBeforeMount(() => { onBeforeMount(() => {
checkLoginStatus(); checkLoginStatus();
}); });
@ -103,7 +99,6 @@ const logout = async () => {
try { try {
const token = localStorage.getItem('token'); const token = localStorage.getItem('token');
// 严格遵循接口文档路径大小写
const res: any = await myAxios.get( const res: any = await myAxios.get(
"/userInfo/logout", "/userInfo/logout",
{ {

View File

@ -69,19 +69,18 @@ import {useRoute, useRouter} from "vue-router";
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
// 选中侧边栏
const selectedKeys = ref<string[]>(['/userList']); const selectedKeys = ref<string[]>(['/userList']);
onMounted(() => { onMounted(() => {
setSelectedKey() setSelectedKey()
}) })
// 根据路由设置当前选中侧边栏
const setSelectedKey = () => { const setSelectedKey = () => {
selectedKeys.value = [route.path]; selectedKeys.value = [route.path];
} }
// 路由跳转
const handleClick = (item: any) => { const handleClick = (item: any) => {
router.push(item.key) router.push(item.key)
} }
@ -89,7 +88,7 @@ const handleClick = (item: any) => {
</script> </script>
<style scoped> <style scoped>
/* 全局菜单项样式 */
:deep(.ant-menu-item), :deep(.ant-menu-item),
:deep(.ant-menu-submenu-title) { :deep(.ant-menu-submenu-title) {
color: rgba(0, 0, 0, 0.85) !important; /* 未选中黑色字体 */ color: rgba(0, 0, 0, 0.85) !important; /* 未选中黑色字体 */
@ -97,31 +96,31 @@ const handleClick = (item: any) => {
transition: all 0.3s ease; transition: all 0.3s ease;
} }
/* 选中项样式 */
:deep(.ant-menu-item-selected) { :deep(.ant-menu-item-selected) {
background-color: #ffa940 !important; background-color: #ffa940 !important;
color: white !important; color: white !important;
font-weight: 600 !important; font-weight: 600 !important;
} }
/* 鼠标悬停样式 */
:deep(.ant-menu-item:hover), :deep(.ant-menu-item:hover),
:deep(.ant-menu-submenu-title:hover) { :deep(.ant-menu-submenu-title:hover) {
background-color: rgba(255, 169, 64, 0.1) !important; background-color: rgba(255, 169, 64, 0.1) !important;
} }
/* 子菜单箭头颜色 */
:deep(.ant-menu-submenu-arrow::before), :deep(.ant-menu-submenu-arrow::before),
:deep(.ant-menu-submenu-arrow::after) { :deep(.ant-menu-submenu-arrow::after) {
background: rgba(0, 0, 0, 0.65) !important; background: rgba(0, 0, 0, 0.65) !important;
} }
/* 子菜单展开时标题样式 */
:deep(.ant-menu-submenu-selected .ant-menu-submenu-title) { :deep(.ant-menu-submenu-selected .ant-menu-submenu-title) {
color: rgba(0, 0, 0, 0.95) !important; color: rgba(0, 0, 0, 0.95) !important;
} }
/* 折叠状态下选中样式 */
:deep(.ant-menu-inline-collapsed .ant-menu-item-selected) { :deep(.ant-menu-inline-collapsed .ant-menu-item-selected) {
background-color: #ffa940 !important; background-color: #ffa940 !important;
} }

View File

@ -103,7 +103,7 @@ const onLogin = async () => {
"/userInfo/login", "/userInfo/login",
{ {
userAccount: userAccount.value, userAccount: userAccount.value,
userPassword: userPassword.value // 发送加密后的密码 userPassword: userPassword.value
}, },
{ {
headers: { headers: {

View File

@ -6,43 +6,5 @@
</template> </template>
<style scoped> <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> </style>

View File

@ -68,16 +68,15 @@
class="select-field" class="select-field"
required required
> >
<option value="" disabled>请选择类型</option> <option value="">请选择课程类型</option>
<option value="自媒体">自媒体</option>
<option value="考公考研">考公考研</option> <option value="考公考研">考公考研</option>
<option value="自媒体">自媒体</option>
<option value="财经">财经</option> <option value="财经">财经</option>
</select> </select>
<div class="select-arrow"></div> <div class="select-arrow"></div>
</div> </div>
</label> </label>
</div> </div>
<div class="input-group"> <div class="input-group">
<label class="input-label"> <label class="input-label">
<span class="label-text">课程图片</span> <span class="label-text">课程图片</span>
@ -108,6 +107,7 @@
class="input-field" class="input-field"
required required
placeholder="请输入原价" placeholder="请输入原价"
@input="validatePrices"
> >
</label> </label>
</div> </div>
@ -122,6 +122,7 @@
class="input-field" class="input-field"
required required
placeholder="请输入折扣价" placeholder="请输入折扣价"
@input="validatePrices"
> >
</label> </label>
</div> </div>
@ -134,11 +135,12 @@
<input <input
v-model.number="formData.firstLevelRate" v-model.number="formData.firstLevelRate"
type="number" type="number"
min="0" min="1"
max="100" max="99"
class="input-field" class="input-field"
required required
placeholder="0-100" placeholder="1-99"
@input="validateRates"
> >
</label> </label>
</div> </div>
@ -149,11 +151,12 @@
<input <input
v-model.number="formData.secondLevelRate" v-model.number="formData.secondLevelRate"
type="number" type="number"
min="0" min="1"
max="100" max="99"
class="input-field" class="input-field"
required required
placeholder="0-100" placeholder="1-99"
@input="validateRates"
> >
</label> </label>
</div> </div>
@ -161,6 +164,7 @@
</div> </div>
</div> </div>
<!-- 富文本编辑器区域 - 修改为50%宽度 -->
<div class="rich-text-container"> <div class="rich-text-container">
<div class="rich-text-columns"> <div class="rich-text-columns">
<div class="rich-text-group"> <div class="rich-text-group">
@ -168,7 +172,7 @@
<RichTextEditor <RichTextEditor
v-model="formData.detail" v-model="formData.detail"
:disable="false" :disable="false"
@content-change="(html) => formData.detail = html" @content-change="(html:any) => formData.detail = html"
/> />
</div> </div>
@ -177,7 +181,7 @@
<RichTextEditor <RichTextEditor
v-model="formData.promoCodeDesc" v-model="formData.promoCodeDesc"
:disable="false" :disable="false"
@content-change="(html) => formData.promoCodeDesc = html" @content-change="(html:any) => formData.promoCodeDesc = html"
/> />
</div> </div>
</div> </div>
@ -230,7 +234,7 @@ const handleFileUpload = async (event: Event) => {
'Authorization': storedToken 'Authorization': storedToken
} }
}); });
console.log(res)
if (res.code === 1) { if (res.code === 1) {
formData.image = res.data; formData.image = res.data;
fileName.value = file.name; 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 handleSubmit = async () => {
// 验证价格和佣金比例
const isPriceValid = validatePrices();
const isRateValid = validateRates();
let errorMessage = '';
if (!isPriceValid) {
errorMessage += '折扣价必须小于原价\n';
}
if (!isRateValid) {
errorMessage += '二级佣金比例必须小于一级佣金比例\n';
}
if (errorMessage) {
alert(errorMessage);
return;
}
try { try {
if (!validateForm()) { if (!validateForm()) {
alert('请填写所有必填字段'); alert('请填写所有必填字段');
@ -346,6 +384,7 @@ const validateForm = (): boolean => {
}; };
</script> </script>
<style scoped> <style scoped>
.modern-form { .modern-form {
max-width: 90%; max-width: 90%;
@ -458,6 +497,73 @@ const validateForm = (): boolean => {
.select-wrapper { .select-wrapper {
position: relative; 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 { .select-field {
@ -477,11 +583,6 @@ const validateForm = (): boolean => {
pointer-events: none; pointer-events: none;
} }
.textarea-field {
min-height: 100px;
resize: vertical;
}
.submit-button { .submit-button {
display: flex; display: flex;
align-items: center; align-items: center;
@ -539,6 +640,7 @@ const validateForm = (): boolean => {
.rich-text-container { .rich-text-container {
margin-top: 1.5rem; margin-top: 1.5rem;
width: 100%;
} }
.rich-text-columns { .rich-text-columns {
@ -561,6 +663,12 @@ const validateForm = (): boolean => {
flex-grow: 1; flex-grow: 1;
} }
@media (max-width: 768px) {
.rich-text-columns {
grid-template-columns: 1fr;
}
}
.rich-text-group:focus-within { .rich-text-group:focus-within {
border-color: #6366f1; border-color: #6366f1;
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
@ -742,4 +850,5 @@ const validateForm = (): boolean => {
margin-left: 20px; margin-left: 20px;
margin-bottom: 10px; margin-bottom: 10px;
} }
</style> </style>

View File

@ -108,13 +108,7 @@
> >
编辑 编辑
</a-button> </a-button>
<a-button
size="small"
type="link"
@click="previewVideo(record.videoView)"
>
预览
</a-button>
</a-space> </a-space>
</template> </template>
</template> </template>
@ -714,7 +708,6 @@ const handleEditChapter = async () => {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
if (!storedToken) throw new Error('未找到登录信息'); if (!storedToken) throw new Error('未找到登录信息');
// 准备更新数据,修正字段映射问题
const updateData = { const updateData = {
id: editForm.value.id, id: editForm.value.id,
name: editForm.value.name, name: editForm.value.name,
@ -748,24 +741,15 @@ const handleEditChapter = async () => {
}; };
// 预览视频
const previewVideo = (videoView: string) => {
previewVideoUrl.value = downLoadImage + videoView;
videoPreviewVisible.value = true;
};
onMounted(() => { onMounted(() => {
// 从路由参数获取课程ID
courseId.value = route.query.id ? String(route.query.id) : ""; courseId.value = route.query.id ? String(route.query.id) : "";
if (courseId.value) { if (courseId.value) {
// 设置章节查询参数中的课程ID
searchParams.value.courseId = courseId.value; searchParams.value.courseId = courseId.value;
// 获取课程详细信息
getCourseDetail(); getCourseDetail();
// 获取章节列表
getChapterList(); getChapterList();
} else { } else {
message.error("未获取到课程ID"); message.error("未获取到课程ID");

View File

@ -121,7 +121,6 @@ const handleFileUpload = async (event: Event) => {
message.error('文件上传失败'); message.error('文件上传失败');
previewImage.value = ''; previewImage.value = '';
} finally { } finally {
// 重置文件输入,允许重复上传同一文件
if (input) input.value = ''; if (input) input.value = '';
} }
}; };
@ -250,7 +249,7 @@ const updateCourse = () => {
} }
// 创建编辑数据的深拷贝副本 // 创建编辑数据的深拷贝副本
editData.value = JSON.parse(JSON.stringify(courseData.value)); editData.value = JSON.parse(JSON.stringify(courseData.value));
previewImage.value = ''; // 进入编辑模式时重置预览图 previewImage.value = '';
isEditing.value = true; isEditing.value = true;
}; };

View File

@ -92,15 +92,18 @@
{{ record.secondLevelRate }}% {{ record.secondLevelRate }}%
</template> </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'"> <template v-if="column.key === 'action'">
<a-space :size="8"> <a-space :size="8">
<a-button
size="small"
:type="record.isShelves ? 'danger' : 'primary'"
@click="toggleShelves(record)"
>
{{ record.isShelves ? '下架' : '上架' }}
</a-button>
<a-button <a-button
size="small" size="small"
danger danger
@ -242,21 +245,44 @@ const columns = [
sorter: true, sorter: true,
sortDirections: ['ascend', 'descend'] sortDirections: ['ascend', 'descend']
}, },
{
title: '是否上架',
dataIndex: 'isShelves',
key: 'isShelves',
width: 65,
align: 'center'
},
{ {
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 75, width: 105,
align: 'center' 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 () => { const handleCourseSearch = async () => {
@ -277,7 +303,7 @@ const getCourseList = async () => {
const res: any = await myAxios.post("/course/page", searchParams.value, const res: any = await myAxios.post("/course/page", searchParams.value,
{ headers: { Authorization: storedToken } } { headers: { Authorization: storedToken } }
); );
console.log(res)
if (res.code === 1 && res.data && Array.isArray(res.data.records)) { if (res.code === 1 && res.data && Array.isArray(res.data.records)) {
tableData.value = res.data.records; tableData.value = res.data.records;
// 同步总条数到分页组件 // 同步总条数到分页组件
@ -313,17 +339,13 @@ const handleTableChange = (pag: any, _filters: any, sorter: any) => {
// 处理排序 // 处理排序
if (sorter && sorter.field) { if (sorter && sorter.field) {
// 获取排序字段使用列的key而不是dataIndex
const sortField = sorter.field; const sortField = sorter.field;
// 获取排序方向ascend/descend
const sortOrder = sorter.order ? sorter.order : ''; const sortOrder = sorter.order ? sorter.order : '';
// 更新搜索参数中的排序字段和排序方向
searchParams.value.sortField = sortField; searchParams.value.sortField = sortField;
searchParams.value.sortOrder = sortOrder; searchParams.value.sortOrder = sortOrder;
} else { } else {
// 如果没有排序信息,重置为默认排序
searchParams.value.sortField = "id"; searchParams.value.sortField = "id";
searchParams.value.sortOrder = "ascend"; searchParams.value.sortOrder = "ascend";
} }
@ -465,7 +487,6 @@ const chapterDetails = (id: string) => {
</script> </script>
<style scoped> <style scoped>
/* 原有样式保持不变 */
.search-box { .search-box {
margin-bottom: 10px; margin-bottom: 10px;
} }

View File

@ -102,7 +102,6 @@ import { onMounted, ref } from "vue";
import myAxios from "../../api/myAxios.ts"; import myAxios from "../../api/myAxios.ts";
import { message, Modal } from "ant-design-vue"; import { message, Modal } from "ant-design-vue";
import {downLoadImage} from "../../api/ImageUrl.ts"; import {downLoadImage} from "../../api/ImageUrl.ts";
import router from "../../router";
const loading = ref(false); const loading = ref(false);
const selectedRowKeys = ref<number[]>([]); // 存储选中的行ID const selectedRowKeys = ref<number[]>([]); // 存储选中的行ID
@ -285,7 +284,6 @@ const pagination = ref({
pageSizeOptions: ['10', '20', '50', '100'] pageSizeOptions: ['10', '20', '50', '100']
}); });
// 处理分页和排序变化
// 处理分页和排序变化 // 处理分页和排序变化
const handleTableChange = (pag: any, _filters: any, sorter: any) => { const handleTableChange = (pag: any, _filters: any, sorter: any) => {
searchParams.value.current = pag.current; searchParams.value.current = pag.current;
@ -293,17 +291,14 @@ const handleTableChange = (pag: any, _filters: any, sorter: any) => {
// 处理排序 // 处理排序
if (sorter && sorter.field) { if (sorter && sorter.field) {
// 获取排序字段使用列的key而不是dataIndex
const sortField = sorter.field; const sortField = sorter.field;
// 获取排序方向ascend/descend
const sortOrder = sorter.order ? sorter.order : ''; const sortOrder = sorter.order ? sorter.order : '';
// 更新搜索参数中的排序字段和排序方向
searchParams.value.sortField = sortField; searchParams.value.sortField = sortField;
searchParams.value.sortOrder = sortOrder; searchParams.value.sortOrder = sortOrder;
} else { } else {
// 如果没有排序信息,重置为默认排序
searchParams.value.sortField = "id"; searchParams.value.sortField = "id";
searchParams.value.sortOrder = "ascend"; searchParams.value.sortOrder = "ascend";
} }

View File

@ -291,18 +291,16 @@ onMounted(() => {
}); });
const encryptValue = (value: any, key: string): any => { const encryptValue = (value: any, key: string): any => {
// 特定字段不加密
if (key === 'projectStatus') { if (key === 'projectStatus') {
return value; return value;
} }
// 数值型字段直接返回,不加密
if (key === 'projectSettlementCycle' || key === 'maxPromoterCount' || key === 'projectImage' || key === 'projectName') { if (key === 'projectSettlementCycle' || key === 'maxPromoterCount' || key === 'projectImage' || key === 'projectName') {
return value; return value;
} }
try { try {
// 将值转换为字符串
const valueString = typeof value === 'object' const valueString = typeof value === 'object'
? JSON.stringify(value) ? JSON.stringify(value)
: String(value); : String(value);
@ -325,12 +323,11 @@ const handleSubmit = async () => {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
// 创建加密后的表单对象 - 保持原始数据结构
const encryptedFormData: Record<string, any> = {}; const encryptedFormData: Record<string, any> = {};
console.log("===== 字段Base64编码结果 ====="); console.log("===== 字段Base64编码结果 =====");
Object.entries(formData).forEach(([key, value]) => { Object.entries(formData).forEach(([key, value]) => {
// 跳过空值字段
if (value === null || value === undefined || value === '') return; if (value === null || value === undefined || value === '') return;
// 对字段值进行Base64编码 // 对字段值进行Base64编码
@ -625,16 +622,16 @@ const limitPromoterCount = (event: Event) => {
.rich-text-columns { .rich-text-columns {
display: grid; display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr)); /* 修正列宽分配 */ grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 1rem; /* 减小间距 */ gap: 1rem;
align-items: start; /* 顶部对齐 */ align-items: start;
} }
.rich-text-group { .rich-text-group {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.5rem; /* 减小标签与编辑器间距 */ gap: 0.5rem;
height: 100%; /* 保持等高布局 */ height: 100%;
} }
.rich-text-group:focus-within { .rich-text-group:focus-within {
@ -652,7 +649,7 @@ const limitPromoterCount = (event: Event) => {
@media (max-width: 1280px) { @media (max-width: 1280px) {
.rich-text-columns { .rich-text-columns {
grid-template-columns: repeat(2, 1fr); /* 更早切换为2列 */ grid-template-columns: repeat(2, 1fr);
gap: 1.2rem; gap: 1.2rem;
} }
} }
@ -672,7 +669,7 @@ const limitPromoterCount = (event: Event) => {
min-height: 320px; min-height: 320px;
height: auto; height: auto;
flex-grow: 1; flex-grow: 1;
/* 新增焦点状态 */
&:focus-within { &:focus-within {
border-color: #6366f1 !important; border-color: #6366f1 !important;
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
@ -680,14 +677,13 @@ const limitPromoterCount = (event: Event) => {
} }
/* 调整标签与编辑器间距 */
.rich-text-group { .rich-text-group {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.5rem; gap: 0.5rem;
height: 100%; height: 100%;
border-radius: 15px; border-radius: 15px;
/* 新增标签焦点状态联动 */
&:focus-within .label-text { &:focus-within .label-text {
color: #6366f1; color: #6366f1;
transition: color 0.3s ease; transition: color 0.3s ease;
@ -695,7 +691,6 @@ const limitPromoterCount = (event: Event) => {
} }
} }
/* 保持与其他输入组件的一致性 */
.rich-text-group .label-text { .rich-text-group .label-text {
font-size: 0.95rem; font-size: 0.95rem;
font-weight: 600; font-weight: 600;
@ -705,7 +700,6 @@ const limitPromoterCount = (event: Event) => {
} }
/* 手机预览样式 */
.phone-preview-container { .phone-preview-container {
display: flex; display: flex;
justify-content: center; justify-content: center;

View File

@ -87,7 +87,7 @@ import RichTextEditor from '../components/RichTextEditor.vue';
import {useRoute} from "vue-router"; import {useRoute} from "vue-router";
function encode64(text: string): string { function encode64(text: string): string {
// 使用_代替未使用的match参数
return btoa(encodeURIComponent(text).replace(/%([0-9A-F]{2})/g, (_, p1) => { return btoa(encodeURIComponent(text).replace(/%([0-9A-F]{2})/g, (_, p1) => {
return String.fromCharCode(parseInt(p1, 16)); return String.fromCharCode(parseInt(p1, 16));
})); }));
@ -102,10 +102,10 @@ interface NotificationForm {
const formData = reactive<NotificationForm>({ const formData = reactive<NotificationForm>({
notificationTitle: '', notificationTitle: '',
notificationContent: '', notificationContent: '',
projectId: 0 // 初始化值 projectId: 0
}); });
const route = useRoute(); // 获取路由参数 const route = useRoute();
onMounted(() => { onMounted(() => {
// 从路由参数中获取projectId并填充到表单 // 从路由参数中获取projectId并填充到表单
@ -118,7 +118,6 @@ const handleSubmit = async () => {
try { try {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
// 创建要发送的数据副本
const payload = { const payload = {
...formData, ...formData,
notificationContent: encode64(formData.notificationContent) notificationContent: encode64(formData.notificationContent)
@ -153,7 +152,6 @@ const handleSubmit = async () => {
</script> </script>
<style scoped> <style scoped>
/* 保留原有样式,添加富文本编辑器样式 */
.phone-notification { .phone-notification {
padding: 20px; padding: 20px;
} }

View File

@ -65,22 +65,22 @@ interface ProjectDetail {
id: number; id: number;
projectDetailName: string; projectDetailName: string;
projectSettlementPrice: number; projectSettlementPrice: number;
projectMinSettlementPrice: number; // 修正接口字段 projectMinSettlementPrice: number;
maxCommissionRate: number; maxCommissionRate: number;
projectId: number; projectId: number;
} }
const route = useRoute(); const route = useRoute();
const projectId = ref<string | number>(""); const projectId = ref<string | number>("");
const tableData = ref<ProjectDetail[]>([]); // 改为数组存储 const tableData = ref<ProjectDetail[]>([]);
const loading = ref(false); const loading = ref(false);
const error = ref(""); const error = ref("");
const searchId = ref(""); // 新增搜索ID绑定 const searchId = ref("");
// 新增变量保存原始数据
const originalTableData = ref<ProjectDetail[]>([]); const originalTableData = ref<ProjectDetail[]>([]);
// 修改 getMoneyDetail 方法
const getMoneyDetail = async (id: string | number) => { const getMoneyDetail = async (id: string | number) => {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
try { try {
@ -98,7 +98,7 @@ const getMoneyDetail = async (id: string | number) => {
console.log(response) console.log(response)
if (response.code === 1) { if (response.code === 1) {
tableData.value = response.data; tableData.value = response.data;
// 保存原始数据
originalTableData.value = response.data; originalTableData.value = response.data;
} else { } else {
error.value = "获取项目详情失败"; error.value = "获取项目详情失败";
@ -112,10 +112,10 @@ const getMoneyDetail = async (id: string | number) => {
} }
}; };
// 修改搜索处理方法 - 前端过滤
const handleIdSearch = (value: string) => { const handleIdSearch = (value: string) => {
if (!value.trim()) { if (!value.trim()) {
// 如果搜索值为空,显示所有数据
tableData.value = [...originalTableData.value]; tableData.value = [...originalTableData.value];
return; return;
} }
@ -126,7 +126,7 @@ const handleIdSearch = (value: string) => {
return; return;
} }
// 前端过滤逻辑
const filtered = originalTableData.value.filter(item => item.id === id); const filtered = originalTableData.value.filter(item => item.id === id);
if (filtered.length === 0) { if (filtered.length === 0) {
@ -137,10 +137,9 @@ const handleIdSearch = (value: string) => {
} }
}; };
// 修改重置方法
const reset = () => { const reset = () => {
searchId.value = ""; searchId.value = "";
// 重置时显示所有原始数据
tableData.value = [...originalTableData.value]; tableData.value = [...originalTableData.value];
}; };
@ -174,7 +173,7 @@ const queryDetailById = async (id: string | number) => {
} }
}; };
// 初始化逻辑
if (typeof route.query.id === "string") { if (typeof route.query.id === "string") {
projectId.value = route.query.id; projectId.value = route.query.id;
} }
@ -188,9 +187,9 @@ onMounted(() => {
const deleteMoneyDetail = async (id: number) => { const deleteMoneyDetail = async (id: number) => {
try { try {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
// 修正接口路径为项目明细的删除接口
const res: any = await myAxios.post( const res: any = await myAxios.post(
"/projectDetail/delete", // 修改这里 "/projectDetail/delete",
{ id }, { id },
{ {
headers: { headers: {
@ -259,12 +258,12 @@ const formState = reactive({
// }; // };
// //
// 新增表单相关状态
const addDrawerVisible = ref(false); const addDrawerVisible = ref(false);
const addFormState = reactive({ const addFormState = reactive({
projectDetailName: '', projectDetailName: '',
projectSettlementPrice: 0, projectSettlementPrice: 0,
projectMinSettlementPrice: 0, // 注意字段名称需要与接口一致 projectMinSettlementPrice: 0,
maxCommissionRate: 0, maxCommissionRate: 0,
projectId: 0 projectId: 0
}); });
@ -352,7 +351,7 @@ const handleSubmit = async () => {
const res:any = await myAxios.post( const res:any = await myAxios.post(
"/projectDetail/update", "/projectDetail/update",
{ {
// 根据接口文档调整字段映射
id: formState.id, id: formState.id,
projectDetailName: formState.projectDetailName, projectDetailName: formState.projectDetailName,
projectSettlementPrice: formState.projectSettlementPrice, 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('更新成功'); message.success('更新成功');
drawerVisible.value = false; drawerVisible.value = false;
// 根据当前查看模式刷新
if (searchId.value) { if (searchId.value) {
await queryDetailById(formState.id); await queryDetailById(formState.id);
} else { } else {
@ -389,12 +388,10 @@ const handleSubmit = async () => {
}; };
//返回上一级
const router = useRouter(); const router = useRouter();
// 返回上一级方法
const goBack = () => { const goBack = () => {
// router.go(-1); // 返回上一页
router.push('/project') router.push('/project')
}; };
@ -526,7 +523,6 @@ const goBack = () => {
</a-form> </a-form>
</a-drawer> </a-drawer>
<!-- 修改新增抽屉的表单项 -->
<a-drawer <a-drawer
title="新增项目明细" title="新增项目明细"
placement="right" placement="right"
@ -625,7 +621,6 @@ const goBack = () => {
} }
/*橙色按钮*/
.custom-button { .custom-button {
background-color: #ffa940; background-color: #ffa940;
@ -647,7 +642,6 @@ const goBack = () => {
color: #fff; color: #fff;
} }
/* 危险按钮样式 */
.custom-button.ant-btn-dangerous { .custom-button.ant-btn-dangerous {
background-color: #ff4d4f; background-color: #ff4d4f;
border-color: #ff4d4f; border-color: #ff4d4f;
@ -659,7 +653,6 @@ const goBack = () => {
border-color: #ff7875; border-color: #ff7875;
} }
/* 保持原有的其他样式不变 */
.search-box { .search-box {
margin-bottom: 10px; margin-bottom: 10px;
} }
@ -675,13 +668,11 @@ const goBack = () => {
border-color: #fa8c16; border-color: #fa8c16;
} }
/* 保持输入框原有样式不变 */
.custom-search :deep(.ant-input) { .custom-search :deep(.ant-input) {
border-right-color: #ffa940; border-right-color: #ffa940;
} }
/* 调整分页器位置 */
:deep(.ant-table-pagination.ant-pagination) { :deep(.ant-table-pagination.ant-pagination) {
margin: 0; margin: 0;
} }

View File

@ -74,9 +74,9 @@ function decode64(text: string): string {
} }
} }
interface NotificationDetail { interface NotificationDetail {
id: string; // 改为 string 类型 id: string;
notificationTitle: string; notificationTitle: string;
projectId: string; // 改为 string 类型 projectId: string;
createTime: string; createTime: string;
notificationContent: string; notificationContent: string;
} }
@ -99,7 +99,7 @@ const errorMessage = ref("");
// 进入编辑模式 // 进入编辑模式
const enterEditMode = () => { const enterEditMode = () => {
// 创建可编辑数据的副本
editableNotice.value = { editableNotice.value = {
...projectNotice.value ...projectNotice.value
}; };
@ -140,7 +140,7 @@ const saveNotice = async () => {
if (res.code === 1) { if (res.code === 1) {
message.success('更新成功'); message.success('更新成功');
// 更新本地数据并退出编辑模式 - 使用解码后的内容
projectNotice.value = { projectNotice.value = {
...editableNotice.value, // 这里包含的是用户编辑的原始内容(未编码) ...editableNotice.value, // 这里包含的是用户编辑的原始内容(未编码)
}; };
@ -217,7 +217,6 @@ onMounted(() => {
</script> </script>
<style scoped> <style scoped>
/* 基本样式保持不变 */
.notification-detail-container { .notification-detail-container {
width: 100%; width: 100%;
padding: 24px; padding: 24px;

View File

@ -124,14 +124,14 @@ import router from "../../router";
const loading = ref(false); const loading = ref(false);
const total = ref(0); const total = ref(0);
const searchProjectName = ref(""); // 改为项目名称搜索参数 const searchProjectName = ref("");
const searchParams = ref({ const searchParams = ref({
current: 1, current: 1,
pageSize: 10, pageSize: 10,
sortField: "id", sortField: "id",
sortOrder: "ascend", sortOrder: "ascend",
userRole: null, userRole: null,
projectName: "" // 新增项目名称查询参数 projectName: ""
}); });
@ -163,8 +163,8 @@ const columns = [
key: 'id', key: 'id',
fixed: 'left', fixed: 'left',
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
@ -189,8 +189,8 @@ const columns = [
width: 20, width: 20,
key: 'projectPrice', key: 'projectPrice',
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
title: '当前推广人数', title: '当前推广人数',
@ -198,8 +198,8 @@ const columns = [
width: 20, width: 20,
key: 'currentPromotionCount', key: 'currentPromotionCount',
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
title: '结算周期', title: '结算周期',
@ -207,8 +207,8 @@ const columns = [
key: 'projectSettlementCycle', key: 'projectSettlementCycle',
width: 10, width: 10,
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
title: '最大推广人数', title: '最大推广人数',
@ -216,8 +216,8 @@ const columns = [
key: 'maxPromoterCount', key: 'maxPromoterCount',
width: 20, width: 20,
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
title: '项目状态', title: '项目状态',
@ -255,9 +255,9 @@ const toggleShelves = async (record: any) => {
if (res.code === 1) { if (res.code === 1) {
message.success('状态更新成功'); message.success('状态更新成功');
// 使用 Object.assign 触发响应式更新
Object.assign(record, { isShelves: !record.isShelves }); Object.assign(record, { isShelves: !record.isShelves });
// 或重新获取数据(推荐)
await getProjectList(); await getProjectList();
}else { }else {
message.error(res.message || '操作失败'); message.error(res.message || '操作失败');
@ -269,15 +269,14 @@ const toggleShelves = async (record: any) => {
}; };
interface ProjectRecord { interface ProjectRecord {
// 这里根据实际数据结构定义属性
superHostList?: string[]; superHostList?: string[];
// 其他属性...
} }
// 项目名称搜索方法 // 项目名称搜索方法
const handleProjectSearch = async () => { const handleProjectSearch = async () => {
// 将搜索参数同步到分页查询参数
searchParams.value.projectName = searchProjectName.value; searchParams.value.projectName = searchProjectName.value;
searchParams.value.current = 1; // 重置到第一页 searchParams.value.current = 1;
await getProjectList(); await getProjectList();
}; };
//用户分页查询 //用户分页查询
@ -287,23 +286,28 @@ const getProjectList = async () => {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
if (!storedToken) throw new Error('未找到登录信息'); if (!storedToken) throw new Error('未找到登录信息');
const res:any = await myAxios.post("/project/page", const params = {
{
...searchParams.value, ...searchParams.value,
projectName: searchParams.value.projectName
}, fuzzyQuery: true,
fuzzyField: 'projectName'
};
const res:any = await myAxios.post("/project/page",
params,
{ headers: { Authorization: storedToken } } { headers: { Authorization: storedToken } }
); );
console.log(res) console.log(res)
if (res.code === 1 && res.data && Array.isArray(res.data.records)) { if (res.code === 1 && res.data && Array.isArray(res.data.records)) {
tableData.value = res.data.records.map((item: ProjectRecord) => ({ tableData.value = res.data.records.map((item: ProjectRecord) => ({
...item, ...item,
superUserList: item.superHostList? item.superHostList.join(', ') : '无' superUserList: item.superHostList? item.superHostList.join(', ') : '无'
})); }));
// 同步总条数到分页组件
total.value = res.data.total; total.value = res.data.total;
pagination.value.total = res.data.total; // 新增此行 pagination.value.total = res.data.total;
pagination.value.current = searchParams.value.current; // 同步当前页 pagination.value.current = searchParams.value.current;
} else { } else {
message.error(res.message || '请求失败'); message.error(res.message || '请求失败');
} }
@ -318,7 +322,6 @@ const getProjectList = async () => {
onMounted(getProjectList); onMounted(getProjectList);
//分页 //分页
// 分页配置
const pagination = ref({ const pagination = ref({
current: 1, current: 1,
pageSize: 10, pageSize: 10,
@ -329,9 +332,9 @@ const pagination = ref({
pageSizeOptions: ['10', '20', '50', '100'] pageSizeOptions: ['10', '20', '50', '100']
}); });
const handleTableChange = (pag: any, _: any, sorter: any) => { const handleTableChange = (pag: any, _: any, sorter: any) => {
// 处理排序参数
let sortField = "id"; // 默认排序字段 let sortField = "id";
let sortOrder = "ascend"; // 默认排序方式 let sortOrder = "ascend";
if (sorter.field) { if (sorter.field) {
sortField = sorter.field; sortField = sorter.field;
sortOrder = sorter.order; sortOrder = sorter.order;
@ -340,11 +343,11 @@ const handleTableChange = (pag: any, _: any, sorter: any) => {
...searchParams.value, ...searchParams.value,
current: pag.current, current: pag.current,
pageSize: pag.pageSize, pageSize: pag.pageSize,
sortField: sortField, // 设置排序字段 sortField: sortField,
sortOrder: sortOrder sortOrder: sortOrder
}; };
// 同步到分页组件
pagination.value = { pagination.value = {
...pagination.value, ...pagination.value,
current: pag.current, current: pag.current,
@ -364,13 +367,13 @@ interface Project {
projectStatus: string; projectStatus: string;
projectDescription: string; projectDescription: string;
settlementDesc: string; settlementDesc: string;
// 其他可能存在的属性根据实际情况补充
} }
const tableData = ref<Project[]>([]); const tableData = ref<Project[]>([]);
// 删除项目 - 添加确认弹窗 // 删除项目
const deleteProject = (id: number) => { const deleteProject = (id: number) => {
Modal.confirm({ Modal.confirm({
title: '确认删除', title: '确认删除',
@ -403,7 +406,7 @@ const deleteProject = (id: number) => {
} }
}, },
onCancel() { onCancel() {
// 用户点击取消,不做操作
}, },
}); });
}; };
@ -467,10 +470,8 @@ const promotionCode=(id:number)=>{
</script> </script>
<style scoped> <style scoped>
.action-btn {
padding: 0 8px;
}
/* 分割线样式 */
:deep(.ant-divider-vertical) { :deep(.ant-divider-vertical) {
border-color: rgba(0, 0, 0, 0.15); border-color: rgba(0, 0, 0, 0.15);
height: 1.2em; height: 1.2em;
@ -490,8 +491,6 @@ const promotionCode=(id:number)=>{
} }
/* 角色颜色映射 */
:root { :root {
--role-user: #87d068; --role-user: #87d068;
--role-admin: #f50; --role-admin: #f50;
@ -503,7 +502,6 @@ const promotionCode=(id:number)=>{
} }
/*橙色按钮*/
.custom-button { .custom-button {
background-color: #ffa940; background-color: #ffa940;
@ -525,7 +523,7 @@ const promotionCode=(id:number)=>{
color: #fff; color: #fff;
} }
/* 危险按钮样式 */
.custom-button.ant-btn-dangerous { .custom-button.ant-btn-dangerous {
background-color: #ff4d4f; background-color: #ff4d4f;
border-color: #ff4d4f; border-color: #ff4d4f;
@ -537,7 +535,7 @@ const promotionCode=(id:number)=>{
border-color: #ff7875; border-color: #ff7875;
} }
/* 保持原有的其他样式不变 */
.search-box { .search-box {
margin-bottom: 10px; margin-bottom: 10px;
} }
@ -553,7 +551,7 @@ const promotionCode=(id:number)=>{
border-color: #fa8c16; border-color: #fa8c16;
} }
/* 保持输入框原有样式不变 */
.custom-search :deep(.ant-input) { .custom-search :deep(.ant-input) {
border-right-color: #ffa940; border-right-color: #ffa940;
} }

View File

@ -125,7 +125,6 @@ const handleFileUpload = async (event: Event) => {
message.error('文件上传失败'); message.error('文件上传失败');
previewImage.value = ''; previewImage.value = '';
} finally { } finally {
// 重置文件输入,允许重复上传同一文件
if (input) input.value = ''; if (input) input.value = '';
} }
}; };
@ -199,7 +198,7 @@ const finishEditing = async () => {
message.error('项目更新失败'); message.error('项目更新失败');
} finally { } finally {
isEditing.value = false; isEditing.value = false;
previewImage.value = ''; // 清空预览图 previewImage.value = '';
} }
}; };
@ -257,9 +256,8 @@ const updateProject = () => {
message.warning('项目数据尚未加载完成,请稍后再试'); message.warning('项目数据尚未加载完成,请稍后再试');
return; return;
} }
// 创建编辑数据的深拷贝副本
editData.value = JSON.parse(JSON.stringify(projectData.value)); editData.value = JSON.parse(JSON.stringify(projectData.value));
previewImage.value = ''; // 进入编辑模式时重置预览图 previewImage.value = '';
isEditing.value = true; isEditing.value = true;
}; };
@ -279,13 +277,12 @@ const triggerFileInput = () => {
const handleNumberInput = (e: KeyboardEvent) => { const handleNumberInput = (e: KeyboardEvent) => {
const allowedKeys = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab']; const allowedKeys = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab'];
// 只允许数字和控制键
if (!allowedKeys.includes(e.key)) { if (!allowedKeys.includes(e.key)) {
e.preventDefault(); e.preventDefault();
} }
}; };
// 添加范围限制方法 - 现在在输入时立即修正
const limitSettlementCycle = (value: number) => { const limitSettlementCycle = (value: number) => {
if (!editData.value) return; if (!editData.value) return;

View File

@ -64,7 +64,7 @@ const columns = [
} }
]; ];
// 修改接口数据类型
interface ProjectNotification { interface ProjectNotification {
id: number; id: number;
notificationTitle: string; notificationTitle: string;
@ -75,14 +75,14 @@ interface ProjectNotification {
const route = useRoute(); const route = useRoute();
const projectId = ref<string | number>(""); const projectId = ref<string | number>("");
const originalTableData = ref<ProjectNotification[]>([]); const originalTableData = ref<ProjectNotification[]>([]);
const searchedData = ref<ProjectNotification[]>([]); // 存储搜索结果 const searchedData = ref<ProjectNotification[]>([]);
const displayData = ref<ProjectNotification[]>([]); // 实际显示的数据 const displayData = ref<ProjectNotification[]>([]);
const loading = ref(false); const loading = ref(false);
const error = ref(""); const error = ref("");
const searchId = ref(""); const searchId = ref("");
// 修改搜索处理方法,不再调用后端接口
const handleIdSearch = () => { const handleIdSearch = () => {
const value = searchId.value.trim(); const value = searchId.value.trim();
@ -97,14 +97,14 @@ const handleIdSearch = () => {
return; return;
} }
// 在原始数据中过滤
const result = originalTableData.value.filter(item => item.id === id); const result = originalTableData.value.filter(item => item.id === id);
if (result.length === 0) { if (result.length === 0) {
message.warning("未找到匹配的项目通知ID"); message.warning("未找到匹配的项目通知ID");
} }
// 更新显示数据为搜索结果
searchedData.value = result; searchedData.value = result;
displayData.value = result; displayData.value = result;
}; };
@ -208,16 +208,15 @@ const deleteNotification = async (id: number) => {
}; };
// 从路由参数中获取项目ID
if (typeof route.query.id === "string") { if (typeof route.query.id === "string") {
projectId.value = route.query.id; projectId.value = route.query.id;
} }
// 修改新增按钮的路由跳转传递projectId到新增页面
const goAddProjectNotice = () => { const goAddProjectNotice = () => {
router.push({ router.push({
path: '/addprojectNotice', path: '/addprojectNotice',
query: { projectId: projectId.value } // 传递项目ID到新增页面 query: { projectId: projectId.value }
}); });
}; };
@ -298,8 +297,6 @@ const goBack = () => {
} }
/*橙色按钮*/
.custom-button { .custom-button {
background-color: #ffa940; background-color: #ffa940;
border-color: #ffa940; border-color: #ffa940;
@ -320,7 +317,7 @@ const goBack = () => {
color: #fff; color: #fff;
} }
/* 危险按钮样式 */
.custom-button.ant-btn-dangerous { .custom-button.ant-btn-dangerous {
background-color: #ff4d4f; background-color: #ff4d4f;
border-color: #ff4d4f; border-color: #ff4d4f;
@ -332,7 +329,6 @@ const goBack = () => {
border-color: #ff7875; border-color: #ff7875;
} }
/* 保持原有的其他样式不变 */
.search-box { .search-box {
margin-bottom: 10px; margin-bottom: 10px;
} }
@ -348,13 +344,12 @@ const goBack = () => {
border-color: #fa8c16; border-color: #fa8c16;
} }
/* 保持输入框原有样式不变 */
.custom-search :deep(.ant-input) { .custom-search :deep(.ant-input) {
border-right-color: #ffa940; border-right-color: #ffa940;
} }
/* 调整分页器位置 */
:deep(.ant-table-pagination.ant-pagination) { :deep(.ant-table-pagination.ant-pagination) {
margin: 0; margin: 0;
} }

View File

@ -58,7 +58,7 @@ const columns = [
} }
]; ];
// 接口数据类型
interface PromoCode { interface PromoCode {
id: number; id: number;
promoCodeInfoKey: string; promoCodeInfoKey: string;
@ -70,14 +70,14 @@ interface PromoCode {
const route = useRoute(); const route = useRoute();
const projectId = ref<string | number>(""); const projectId = ref<string | number>("");
const originalTableData = ref<PromoCode[]>([]); // 存储所有原始数据 const originalTableData = ref<PromoCode[]>([]);
const displayData = ref<PromoCode[]>([]); // 实际显示的数据 const displayData = ref<PromoCode[]>([]);
const loading = ref(false); const loading = ref(false);
const searchId = ref(""); const searchId = ref("");
const previewVisible = ref(false); const previewVisible = ref(false);
const previewImage = ref(""); const previewImage = ref("");
// 主查询方法 - 获取项目所有推广码
const getPromoCodes = async (id: string | number) => { const getPromoCodes = async (id: string | number) => {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
try { try {
@ -95,10 +95,9 @@ const getPromoCodes = async (id: string | number) => {
console.log(response); console.log(response);
if (response.code === 1) { if (response.code === 1) {
// 确保data是数组即使为null也转为空数组
const data = Array.isArray(response.data) ? response.data : []; const data = Array.isArray(response.data) ? response.data : [];
originalTableData.value = data; originalTableData.value = data;
displayData.value = data; // 初始显示所有数据 displayData.value = data;
} else { } else {
message.error(response.message || "获取数据失败"); message.error(response.message || "获取数据失败");
originalTableData.value = []; originalTableData.value = [];
@ -114,7 +113,7 @@ const getPromoCodes = async (id: string | number) => {
} }
}; };
// 初始化逻辑
if (typeof route.query.id === "string") { if (typeof route.query.id === "string") {
projectId.value = route.query.id; projectId.value = route.query.id;
} }
@ -125,7 +124,7 @@ onMounted(() => {
} }
}); });
// 修改搜索处理 - 前端过滤
const handleIdSearch = () => { const handleIdSearch = () => {
const value = searchId.value.trim(); const value = searchId.value.trim();
@ -140,18 +139,18 @@ const handleIdSearch = () => {
return; return;
} }
// 在前端原始数据中过滤
const result = originalTableData.value.filter(item => item.id === id); const result = originalTableData.value.filter(item => item.id === id);
if (result.length === 0) { if (result.length === 0) {
message.warning("未找到匹配的推广码ID"); message.warning("未找到匹配的推广码ID");
} }
// 更新显示数据
displayData.value = result; displayData.value = result;
}; };
// 重置搜索 - 显示所有数据 // 重置搜索
const reset = () => { const reset = () => {
searchId.value = ""; searchId.value = "";
displayData.value = originalTableData.value; displayData.value = originalTableData.value;
@ -181,14 +180,13 @@ const openAddDrawer = () => {
// 提交新增请求 // 提交新增请求
const handleAddSubmit = async () => { const handleAddSubmit = async () => {
// 如果有文件需要上传
if (fileList.value.length > 0) { if (fileList.value.length > 0) {
const imageUrl = await handleUpload(); const imageUrl = await handleUpload();
if (!imageUrl) { if (!imageUrl) {
message.error('图片上传失败,无法提交'); message.error('图片上传失败,无法提交');
return; return;
} }
// 更新表单中的图片URL
addFormState.promoCodeImage = imageUrl; addFormState.promoCodeImage = imageUrl;
} }
@ -215,7 +213,7 @@ const handleAddSubmit = async () => {
message.success('新增成功'); message.success('新增成功');
addDrawerVisible.value = false; addDrawerVisible.value = false;
await getPromoCodes(projectId.value); await getPromoCodes(projectId.value);
// 重置表单和文件列表
Object.assign(addFormState, { Object.assign(addFormState, {
promoCodeInfoKey: '', promoCodeInfoKey: '',
promoCodeLink: '', promoCodeLink: '',
@ -309,14 +307,14 @@ const handleEdit = async (id: number) => {
}; };
const handleEditSubmit = async () => { const handleEditSubmit = async () => {
// 如果有文件需要上传
if (fileList.value.length > 0) { if (fileList.value.length > 0) {
const imageUrl = await handleUpload(); const imageUrl = await handleUpload();
if (!imageUrl) { if (!imageUrl) {
message.error('图片上传失败,无法提交'); message.error('图片上传失败,无法提交');
return; return;
} }
// 更新表单中的图片URL
editFormState.promoCodeImage = imageUrl; editFormState.promoCodeImage = imageUrl;
} }
@ -343,7 +341,7 @@ const handleEditSubmit = async () => {
message.success('编辑成功'); message.success('编辑成功');
editDrawerVisible.value = false; editDrawerVisible.value = false;
await getPromoCodes(projectId.value); await getPromoCodes(projectId.value);
// 重置文件列表
fileList.value = []; fileList.value = [];
} else { } else {
message.error(res.message || '编辑失败'); message.error(res.message || '编辑失败');
@ -353,19 +351,19 @@ const handleEditSubmit = async () => {
} }
}; };
//返回上一级
const router = useRouter(); const router = useRouter();
// 返回上一级方法
const goBack = () => { const goBack = () => {
router.go(-1); // 返回上一页 router.go(-1);
}; };
// 添加文件上传相关状态
const fileList = ref<any[]>([]); const fileList = ref<any[]>([]);
const uploading = ref(false); const uploading = ref(false);
// 图片上传处理
const handleUpload = async () => { const handleUpload = async () => {
const formData = new FormData(); const formData = new FormData();
fileList.value.forEach(file => { fileList.value.forEach(file => {
@ -382,7 +380,7 @@ const handleUpload = async () => {
{ {
headers: { headers: {
'Authorization': storedToken, 'Authorization': storedToken,
'AflatScript': 'required', // 添加AflatScript头部 'AflatScript': 'required',
'Content-Type': 'multipart/form-data' 'Content-Type': 'multipart/form-data'
} }
} }
@ -390,7 +388,7 @@ const handleUpload = async () => {
if (res.code === 1) { if (res.code === 1) {
message.success('上传成功'); message.success('上传成功');
// 将返回的文件路径保存到表单中
addFormState.promoCodeImage = res.data; addFormState.promoCodeImage = res.data;
return res.data; return res.data;
} else { } else {
@ -405,23 +403,23 @@ const handleUpload = async () => {
uploading.value = false; uploading.value = false;
} }
}; };
// 文件上传前的处理
const beforeUpload = (file: any) => { const beforeUpload = (file: any) => {
// 检查文件类型
const isImage = file.type.includes('image'); const isImage = file.type.includes('image');
if (!isImage) { if (!isImage) {
message.error('只能上传图片文件!'); message.error('只能上传图片文件!');
return false; return false;
} }
// 检查文件大小 (限制为5MB)
const isLt5M = file.size / 1024 / 1024 < 5; const isLt5M = file.size / 1024 / 1024 < 5;
if (!isLt5M) { if (!isLt5M) {
message.error('图片大小不能超过5MB!'); message.error('图片大小不能超过5MB!');
return false; return false;
} }
// 添加到文件列表
fileList.value = [file]; fileList.value = [file];
return false; // 手动上传 return false; // 手动上传
}; };
@ -466,9 +464,9 @@ const batchDelete = async () => {
if (res.code === 1) { if (res.code === 1) {
message.success(`成功删除 ${selectedRowKeys.value.length} 条记录`); message.success(`成功删除 ${selectedRowKeys.value.length} 条记录`);
// 刷新数据
await getPromoCodes(projectId.value); await getPromoCodes(projectId.value);
// 清空选择
selectedRowKeys.value = []; selectedRowKeys.value = [];
} else { } else {
message.error(res.message || '批量删除失败'); message.error(res.message || '批量删除失败');
@ -750,26 +748,13 @@ const batchDelete = async () => {
background-color: #fafafa !important; 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) { :deep(.ant-table-pagination.ant-pagination) {
margin: 0; margin: 0;
} }
/*橙色按钮*/
.custom-button { .custom-button {
background-color: #ffa940; background-color: #ffa940;
@ -791,7 +776,7 @@ const batchDelete = async () => {
color: #fff; color: #fff;
} }
/* 危险按钮样式 */
.custom-button.ant-btn-dangerous { .custom-button.ant-btn-dangerous {
background-color: #ff4d4f; background-color: #ff4d4f;
border-color: #ff4d4f; border-color: #ff4d4f;
@ -803,7 +788,7 @@ const batchDelete = async () => {
border-color: #ff7875; border-color: #ff7875;
} }
/* 保持原有的其他样式不变 */
.search-box { .search-box {
margin-bottom: 10px; margin-bottom: 10px;
} }
@ -819,7 +804,6 @@ const batchDelete = async () => {
border-color: #fa8c16; border-color: #fa8c16;
} }
/* 保持输入框原有样式不变 */
.custom-search :deep(.ant-input) { .custom-search :deep(.ant-input) {
border-right-color: #ffa940; border-right-color: #ffa940;
} }
@ -834,23 +818,5 @@ const batchDelete = async () => {
color: #666; 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> </style>

View File

@ -11,7 +11,7 @@
> >
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'projectImage'"> <template v-if="column.dataIndex === 'projectImage'">
<!-- 修复添加 alt 属性 -->
<img <img
:src="downLoadImage+record.projectImage" :src="downLoadImage+record.projectImage"
alt="项目图片" alt="项目图片"
@ -19,7 +19,7 @@
/> />
</template> </template>
<template v-if="column.dataIndex === 'projectCodeImage'"> <template v-if="column.dataIndex === 'projectCodeImage'">
<!-- 修复添加 alt 属性 -->
<img <img
:src="downLoadImage+record.projectCodeImage" :src="downLoadImage+record.projectCodeImage"
alt="推广码" alt="推广码"
@ -62,7 +62,7 @@ interface PromoRecord {
createTime: string; createTime: string;
} }
// 列配置保持不变
const columns = ref([ const columns = ref([
{ {
title: 'ID', title: 'ID',
@ -166,7 +166,7 @@ const columns = ref([
const dataSource = ref<PromoRecord[]>([]); const dataSource = ref<PromoRecord[]>([]);
const loading = ref(false); const loading = ref(false);
// 添加排序参数
const sortParams = reactive({ const sortParams = reactive({
sortField: 'id', sortField: 'id',
sortOrder: 'ascend' sortOrder: 'ascend'
@ -180,7 +180,7 @@ const pagination = reactive({
showTotal: (total: number) => `${total}`, showTotal: (total: number) => `${total}`,
}); });
// fetchData 方法保持不变
const fetchData = async () => { const fetchData = async () => {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
try { try {
@ -208,7 +208,7 @@ const fetchData = async () => {
} }
}; };
// 修复:简化排序处理逻辑
const handleTableChange: TableProps['onChange'] = (pag, _, sorter) => { const handleTableChange: TableProps['onChange'] = (pag, _, sorter) => {
// 处理分页参数 // 处理分页参数
if (pag) { if (pag) {
@ -216,16 +216,15 @@ const handleTableChange: TableProps['onChange'] = (pag, _, sorter) => {
pagination.pageSize = pag.pageSize!; pagination.pageSize = pag.pageSize!;
} }
// 修复:简化排序处理
if (sorter) { if (sorter) {
// 处理排序参数(只处理单列排序)
const { field, order } = sorter as { field?: string; order?: string }; const { field, order } = sorter as { field?: string; order?: string };
if (field && order) { if (field && order) {
sortParams.sortField = field; sortParams.sortField = field;
sortParams.sortOrder = order; sortParams.sortOrder = order;
} else { } else {
// 取消排序时重置
sortParams.sortField = 'id'; sortParams.sortField = 'id';
sortParams.sortOrder = 'ascend'; sortParams.sortOrder = 'ascend';
} }

View File

@ -124,7 +124,7 @@ import { useRoute } from 'vue-router';
import router from '../../router'; import router from '../../router';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
// 项目结算记录接口类型
interface SettlementRecord { interface SettlementRecord {
id: number; id: number;
projectDetailName: string; projectDetailName: string;
@ -201,7 +201,7 @@ const loading = ref(false);
const searchId = ref(''); // 新增搜索ID绑定 const searchId = ref(''); // 新增搜索ID绑定
const originalData = ref<SettlementRecord[]>([]); // 存储原始数据 const originalData = ref<SettlementRecord[]>([]); // 存储原始数据
// 分页配置
const pagination = reactive({ const pagination = reactive({
current: 1, current: 1,
pageSize: 10, pageSize: 10,
@ -210,13 +210,13 @@ const pagination = reactive({
showTotal: (total: number) => `${total}`, showTotal: (total: number) => `${total}`,
}); });
// 获取路由参数
const route = useRoute(); const route = useRoute();
const idFromRoute = route.query.id as string | undefined; const idFromRoute = route.query.id as string | undefined;
const projectIdFromRoute = route.query.projectId as string | undefined; const projectIdFromRoute = route.query.projectId as string | undefined;
const userIdFromRoute = route.query.userId as string | undefined; const userIdFromRoute = route.query.userId as string | undefined;
// 计算属性:根据分页参数生成表格渲染用的分页数据
const paginatedData = computed(() => { const paginatedData = computed(() => {
const start = (pagination.current - 1) * pagination.pageSize; const start = (pagination.current - 1) * pagination.pageSize;
const end = start + pagination.pageSize; const end = start + pagination.pageSize;
@ -232,7 +232,7 @@ const fetchData = async () => {
const response: any = await myAxios.post( const response: any = await myAxios.post(
'/projectSettlement/queryByPId', '/projectSettlement/queryByPId',
{ id: idFromRoute }, // 使用从路由获取的id { id: idFromRoute },
{ {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -246,7 +246,7 @@ const fetchData = async () => {
if (response.code === 1) { if (response.code === 1) {
allData.value = response.data; allData.value = response.data;
originalData.value = [...response.data]; // 保存原始数据 originalData.value = [...response.data];
filteredData.value = [...response.data]; filteredData.value = [...response.data];
pagination.total = response.data.length; pagination.total = response.data.length;
} else { } else {
@ -272,7 +272,7 @@ const fetchData = async () => {
const handleIdSearch = (value: string) => { const handleIdSearch = (value: string) => {
const idStr = value.trim(); const idStr = value.trim();
if (!idStr) { if (!idStr) {
// 如果搜索值为空,显示所有数据
reset(); reset();
return; return;
} }
@ -283,7 +283,7 @@ const handleIdSearch = (value: string) => {
return; return;
} }
// 前端过滤 originalData 数据
const result = originalData.value.filter((record) => record.id === id); const result = originalData.value.filter((record) => record.id === id);
if (result.length > 0) { if (result.length > 0) {
@ -302,21 +302,20 @@ const reset = () => {
searchId.value = ''; searchId.value = '';
filteredData.value = [...originalData.value]; filteredData.value = [...originalData.value];
pagination.total = originalData.value.length; pagination.total = originalData.value.length;
pagination.current = 1; // 重置页码 pagination.current = 1;
revenueSourceFilter.value = 'all'; // 重置收益来源筛选 revenueSourceFilter.value = 'all';
applyFilters(); applyFilters();
}; };
// 表格分页变更处理
const handleTableChange: TableProps['onChange'] = (pag) => { const handleTableChange: TableProps['onChange'] = (pag) => {
if (pag) { if (pag) {
pagination.current = pag.current!; pagination.current = pag.current!;
pagination.pageSize = pag.pageSize!; pagination.pageSize = pag.pageSize!;
// 计算属性自动根据 pagination 变化更新,无需额外调用
} }
}; };
// 返回按钮(修正拼写,保持语义清晰)
const goBack = () => { const goBack = () => {
router.push('/applicationRecord'); router.push('/applicationRecord');
}; };
@ -328,7 +327,7 @@ const deleteRecord = async (id: number) => {
try { try {
const response: any = await myAxios.post( const response: any = await myAxios.post(
'/projectSettlement/delete', '/projectSettlement/delete',
{ id }, // 要删除的记录ID { id },
{ {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -342,13 +341,13 @@ const deleteRecord = async (id: number) => {
if (response.code === 1) { if (response.code === 1) {
message.success('删除成功'); message.success('删除成功');
// 重新加载数据
if (searchId.value) { if (searchId.value) {
// 如果当前在搜索状态,重新搜索
handleIdSearch(searchId.value); handleIdSearch(searchId.value);
} else { } else {
// 否则重新获取所有数据
await fetchData(); // 异步函数调用加 await await fetchData();
} }
} else { } else {
message.error(response.message || '删除失败'); message.error(response.message || '删除失败');
@ -370,7 +369,7 @@ const form = reactive({
settlementRevenue: '', settlementRevenue: '',
workTime: null, workTime: null,
settlementTime: null, settlementTime: null,
// 新增:自动填充路由参数
promoCodeApplyId: idFromRoute || 0, promoCodeApplyId: idFromRoute || 0,
projectId: projectIdFromRoute || 0, projectId: projectIdFromRoute || 0,
userId: userIdFromRoute || 0, userId: userIdFromRoute || 0,
@ -381,7 +380,7 @@ const form = reactive({
const showModal = () => { const showModal = () => {
visible.value = true; visible.value = true;
// 重置非路由传递的字段(避免重复填充)
form.projectDetailName = ''; form.projectDetailName = '';
form.settlementQuantity = ''; form.settlementQuantity = '';
form.settlementRevenue =''; form.settlementRevenue ='';
@ -435,13 +434,12 @@ const handleAdd = async () => {
} }
}; };
const revenueSourceFilter = ref<string | boolean>('all'); // 收益来源筛选值 const revenueSourceFilter = ref<string | boolean>('all');
// 应用筛选条件
const applyFilters = () => { const applyFilters = () => {
let result = [...originalData.value]; let result = [...originalData.value];
// 应用ID筛选
if (searchId.value.trim() !== '') { if (searchId.value.trim() !== '') {
const id = Number(searchId.value.trim()); const id = Number(searchId.value.trim());
if (!isNaN(id)) { if (!isNaN(id)) {
@ -449,7 +447,7 @@ const applyFilters = () => {
} }
} }
// 应用收益来源筛选
if (revenueSourceFilter.value !== 'all') { if (revenueSourceFilter.value !== 'all') {
result = result.filter(record => record.revenueSource === revenueSourceFilter.value); 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); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
} }
/* 橙色按钮样式 */
.custom-button { .custom-button {
background-color: #ffa940; background-color: #ffa940;
border-color: #ffa940; border-color: #ffa940;
@ -488,7 +486,7 @@ const applyFilters = () => {
opacity: 0.9; opacity: 0.9;
} }
/* 表格样式调整 */
:deep(.ant-table-thead) { :deep(.ant-table-thead) {
background-color: #fafafa; background-color: #fafafa;
font-weight: 600; font-weight: 600;
@ -498,7 +496,7 @@ const applyFilters = () => {
background-color: #f9f9f9 !important; background-color: #f9f9f9 !important;
} }
/* 搜索按钮样式 */
.custom-search :deep(.ant-input-search-button) { .custom-search :deep(.ant-input-search-button) {
background-color: #ffa940; background-color: #ffa940;
border-color: #ffa940; border-color: #ffa940;
@ -510,7 +508,7 @@ const applyFilters = () => {
border-color: #fa8c16; border-color: #fa8c16;
} }
/* 保持输入框原有样式不变 */
.custom-search :deep(.ant-input) { .custom-search :deep(.ant-input) {
border-right-color: #ffa940; border-right-color: #ffa940;
} }

View File

@ -50,7 +50,7 @@ interface WithdrawalRecord {
withdrawalStatus: string; withdrawalStatus: string;
} }
// 修改后的列配置 - 添加排序功能
const columns = ref([ const columns = ref([
{ {
title: '提现申请记录ID', title: '提现申请记录ID',
@ -59,8 +59,8 @@ const columns = ref([
width: 80, width: 80,
fixed: 'left', fixed: 'left',
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
title: '持卡人', title: '持卡人',
@ -68,8 +68,8 @@ const columns = ref([
key: 'cardHolder', key: 'cardHolder',
width: 120, width: 120,
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
title: '身份证号', title: '身份证号',
@ -84,8 +84,8 @@ const columns = ref([
key: 'phoneNumber', key: 'phoneNumber',
width: 140, width: 140,
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
title: '银行卡号', title: '银行卡号',
@ -107,8 +107,8 @@ const columns = ref([
key: 'withdrawnAmount', key: 'withdrawnAmount',
width: 120, width: 120,
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
title: '提取状态', title: '提取状态',
@ -129,7 +129,7 @@ const columns = ref([
const dataSource = ref<WithdrawalRecord[]>([]); const dataSource = ref<WithdrawalRecord[]>([]);
const loading = ref(false); const loading = ref(false);
// 添加排序参数
const sortParams = reactive({ const sortParams = reactive({
sortField: 'id', sortField: 'id',
sortOrder: 'ascend' sortOrder: 'ascend'
@ -143,7 +143,7 @@ const pagination = reactive({
showTotal: (total: number) => `${total}`, showTotal: (total: number) => `${total}`,
}); });
// 状态映射函数
const getStatusText = (status: string) => { const getStatusText = (status: string) => {
const statusMap: Record<string, string> = { const statusMap: Record<string, string> = {
'processing': '提现中', 'processing': '提现中',
@ -153,7 +153,7 @@ const getStatusText = (status: string) => {
return statusMap[status] || status; return statusMap[status] || status;
}; };
// 状态颜色映射函数
const getStatusColor = (status: string) => { const getStatusColor = (status: string) => {
const colorMap: Record<string, string> = { const colorMap: Record<string, string> = {
'processing': 'blue', 'processing': 'blue',
@ -163,7 +163,7 @@ const getStatusColor = (status: string) => {
return colorMap[status] || 'default'; return colorMap[status] || 'default';
}; };
// 修改后的 fetchData 方法 - 添加排序参数
const fetchData = async () => { const fetchData = async () => {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
try { try {
@ -171,8 +171,8 @@ const fetchData = async () => {
const response: any = await myAxios.post('/withdrawalApply/page', { const response: any = await myAxios.post('/withdrawalApply/page', {
current: pagination.current, current: pagination.current,
pageSize: pagination.pageSize, pageSize: pagination.pageSize,
sortField: sortParams.sortField, // 添加排序字段 sortField: sortParams.sortField,
sortOrder: sortParams.sortOrder, // 添加排序方式 sortOrder: sortParams.sortOrder,
withdrawalStatus: 'processing' withdrawalStatus: 'processing'
}, { }, {
headers: { headers: {
@ -193,7 +193,7 @@ const fetchData = async () => {
} }
}; };
// 修改后的 handleTableChange 方法 - 处理排序
const handleTableChange: TableProps['onChange'] = (pag, _, sorter) => { const handleTableChange: TableProps['onChange'] = (pag, _, sorter) => {
// 处理分页参数 // 处理分页参数
if (pag) { if (pag) {
@ -209,7 +209,7 @@ const handleTableChange: TableProps['onChange'] = (pag, _, sorter) => {
sortParams.sortField = field; sortParams.sortField = field;
sortParams.sortOrder = order; sortParams.sortOrder = order;
} else { } else {
// 取消排序时重置
sortParams.sortField = 'id'; sortParams.sortField = 'id';
sortParams.sortOrder = 'ascend'; sortParams.sortOrder = 'ascend';
} }

View File

@ -20,11 +20,11 @@
/> />
</a-form-item> </a-form-item>
<a-button class="custom-button" @click="showModal">新增用户</a-button> <a-button class="custom-button" @click="showModal">新增管理员</a-button>
<!--新增用户--> <!--新增用户-->
<a-modal <a-modal
v-model:open="openUser" v-model:open="openUser"
title="新增用户" title="新增管理员"
@ok="handleOk" @ok="handleOk"
:footer="null" :footer="null"
> >
@ -375,22 +375,22 @@ const beforeUpload: UploadProps['beforeUpload'] = file => {
// 自定义上传处理 // 自定义上传处理
const handleUpload = async ({ file }: { file: File }) => { const handleUpload = async ({ file }: { file: File }) => {
const form = new FormData(); const form = new FormData();
form.append('file', file); // 只保留file字段在formData中 form.append('file', file);
try { try {
uploadLoading.value = true; uploadLoading.value = true;
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
// 根据接口文档修改请求地址和参数
const res:any = await myAxios.post('/file/upload?biz=avatar', form, { const res:any = await myAxios.post('/file/upload?biz=avatar', form, {
headers: { headers: {
Authorization: storedToken, Authorization: storedToken,
// 保留由浏览器自动生成的内容类型
} }
}); });
console.log(res) console.log(res)
// 根据响应结构调整假设返回data直接是URL
if (res.code === 1) { // 注意文档中响应状态码是200 if (res.code === 1) {
formData.value.userAvatar = res.data; formData.value.userAvatar = res.data;
previewImage.value = URL.createObjectURL(file); previewImage.value = URL.createObjectURL(file);
message.success('上传成功'); message.success('上传成功');
@ -405,29 +405,29 @@ const handleUpload = async ({ file }: { file: File }) => {
} }
}; };
// 编辑表单实时处理函数
const handleEditNicknameInput = (e: any) => { const handleEditNicknameInput = (e: any) => {
// 限制最大长度并实时提示
const trimmedValue = e.target.value.trim().slice(0, 6); const trimmedValue = e.target.value.trim().slice(0, 6);
editForm.value.nickName = trimmedValue; editForm.value.nickName = trimmedValue;
// 触发表单校验
editFormRef.value?.validateField('nickName'); editFormRef.value?.validateField('nickName');
}; };
const handleEditPhoneInput = (e: any) => { const handleEditPhoneInput = (e: any) => {
// 过滤非数字字符并限制长度
const numericValue = e.target.value.replace(/\D/g, '').slice(0, 11); const numericValue = e.target.value.replace(/\D/g, '').slice(0, 11);
editForm.value.phoneNumber = numericValue; editForm.value.phoneNumber = numericValue;
// 触发手机号格式校验
editFormRef.value?.validateField('phoneNumber'); editFormRef.value?.validateField('phoneNumber');
}; };
const handleEditPasswordInput = (e: any) => { const handleEditPasswordInput = (e: any) => {
// 限制密码长度
editForm.value.userPassword = e.target.value.slice(0, 10); editForm.value.userPassword = e.target.value.slice(0, 10);
}; };
// 通用最大长度处理函数
const handleMaxLength = (max: number) => (e: KeyboardEvent) => { const handleMaxLength = (max: number) => (e: KeyboardEvent) => {
if (e.target instanceof HTMLInputElement && e.target.value.length >= max) { if (e.target instanceof HTMLInputElement && e.target.value.length >= max) {
e.preventDefault(); e.preventDefault();
@ -516,7 +516,7 @@ const handleSearchPhoneInput = (e: any) => {
// 新增 onKeyDown 事件处理函数 // 新增 onKeyDown 事件处理函数
const handleKeyDown = (e: KeyboardEvent) => { const handleKeyDown = (e: KeyboardEvent) => {
// 允许控制键(如删除、左右方向键等)
const allowedKeys = [ const allowedKeys = [
'Backspace', 'Backspace',
'Delete', 'Delete',
@ -525,13 +525,13 @@ const handleKeyDown = (e: KeyboardEvent) => {
'Tab', 'Tab',
]; ];
// 阻止非数字和非允许按键
if (!/[0-9]/.test(e.key) && !allowedKeys.includes(e.key)) { if (!/[0-9]/.test(e.key) && !allowedKeys.includes(e.key)) {
e.preventDefault(); e.preventDefault();
} }
}; };
// 实时校验逻辑
const formData = ref({ const formData = ref({
nickName: '', nickName: '',
userAvatar: '', userAvatar: '',
@ -590,8 +590,8 @@ const columns = [
key: 'id', key: 'id',
fixed: 'left', fixed: 'left',
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
@ -630,8 +630,8 @@ const columns = [
key: 'phoneNumber', key: 'phoneNumber',
width: 80, width: 80,
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
title: '邀请码', title: '邀请码',
@ -639,8 +639,8 @@ const columns = [
key: 'invitationCode', key: 'invitationCode',
width: 70, width: 70,
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
title: '上级ID', title: '上级ID',
@ -648,8 +648,8 @@ const columns = [
key: 'parentUserId', key: 'parentUserId',
width: 40, width: 40,
align: 'center', align: 'center',
sorter: true, // 添加排序功能 sorter: true,
sortDirections: ['ascend', 'descend'] // 允许升序降序 sortDirections: ['ascend', 'descend']
}, },
{ {
title: '操作', title: '操作',
@ -670,7 +670,7 @@ const pagination = ref({
pageSizeOptions: ['10', '20', '50', '100'] pageSizeOptions: ['10', '20', '50', '100']
}); });
//编辑用户表单 //编辑用户表单
// 新增编辑表单校验规则
const editFormRules = { const editFormRules = {
nickName: [ nickName: [
{ {
@ -721,13 +721,13 @@ const editHasLower = computed(() => /[a-z]/.test(editForm.value.userPassword))
const editHasUpper = 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 editHasNumber = computed(() => /\d/.test(editForm.value.userPassword))
const editFormRef = ref(); // 添加表单引用 const editFormRef = ref();
// 修改后的分页处理函数 // 修改后的分页处理函数
const handleTableChange = (pag: any, _: any, sorter: any) => { const handleTableChange = (pag: any, _: any, sorter: any) => {
// 处理排序参数
let sortField = "id"; // 默认排序字段 let sortField = "id";
let sortOrder = "ascend"; // 默认排序方式 let sortOrder = "ascend";
if (sorter.field) { if (sorter.field) {
sortField = sorter.field; sortField = sorter.field;
@ -738,8 +738,8 @@ const handleTableChange = (pag: any, _: any, sorter: any) => {
...searchParams.value, ...searchParams.value,
current: pag.current, current: pag.current,
pageSize: pag.pageSize, pageSize: pag.pageSize,
sortField: sortField, // 设置排序字段 sortField: sortField,
sortOrder: sortOrder // 设置排序方式 sortOrder: sortOrder
}; };
pagination.value.current = pag.current; pagination.value.current = pag.current;
@ -749,7 +749,7 @@ const handleTableChange = (pag: any, _: any, sorter: any) => {
}; };
// 修改获取用户列表方法
const getUserList = async () => { const getUserList = async () => {
loading.value = true; loading.value = true;
try { try {
@ -771,7 +771,7 @@ const getUserList = async () => {
superUserList: item.superHostList? item.superHostList.join(', ') : '无' superUserList: item.superHostList? item.superHostList.join(', ') : '无'
}; };
}); });
// 更新分页信息
pagination.value.total = res.data.total; pagination.value.total = res.data.total;
pagination.value.current = res.data.current; pagination.value.current = res.data.current;
pagination.value.pageSize = res.data.size; pagination.value.pageSize = res.data.size;
@ -796,14 +796,11 @@ interface User {
parentUserId:number 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 () => { const handlePhoneSearch = async () => {
if (!searchPhone.value) { if (!searchPhone.value) {
message.warning('请输入手机号'); message.warning('请输入手机号');
@ -821,7 +818,7 @@ const handlePhoneSearch = async () => {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
if (!storedToken) throw new Error('未找到登录信息'); if (!storedToken) throw new Error('未找到登录信息');
// 修改7: 使用phoneNumber作为查询参数
const res: { code: number; data: any; message: any } = await myAxios.post( const res: { code: number; data: any; message: any } = await myAxios.post(
"/userInfo/page", "/userInfo/page",
{ {
@ -857,9 +854,9 @@ const handlePhoneSearch = async () => {
} }
}; };
// 修改8: 更新reset方法
const reset = () => { const reset = () => {
searchPhone.value = ""; // 清空手机号搜索 searchPhone.value = "";
searchParams.value = { searchParams.value = {
current: 1, current: 1,
pageSize: 10, pageSize: 10,
@ -868,7 +865,7 @@ const reset = () => {
userRole: null, userRole: null,
phoneNumber: null phoneNumber: null
}; };
getUserList(); // 重新加载列表 getUserList();
}; };
@ -882,13 +879,13 @@ const rowSelection = {
selectedRowKeys.value = selectedKeys; selectedRowKeys.value = selectedKeys;
}, },
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
// 添加getCheckboxProps方法根据用户角色决定是否禁用复选框
getCheckboxProps: (record: User) => ({ getCheckboxProps: (record: User) => ({
disabled: record.userRole !== 'admin', // 只有admin用户可以选择 disabled: record.userRole !== 'admin',
name: record.id.toString(), name: record.id.toString(),
}), }),
}; };
// 修改删除用户方法,添加确认弹窗
const confirmDeleteUser = (id: number) => { const confirmDeleteUser = (id: number) => {
Modal.confirm({ Modal.confirm({
title: '确认删除用户', title: '确认删除用户',
@ -897,7 +894,7 @@ const confirmDeleteUser = (id: number) => {
okType: 'danger', okType: 'danger',
cancelText: '取消', cancelText: '取消',
onOk() { onOk() {
return deleteUser(id); // 调用实际删除方法 return deleteUser(id);
}, },
onCancel() { onCancel() {
console.log('用户取消删除'); console.log('用户取消删除');
@ -905,7 +902,7 @@ const confirmDeleteUser = (id: number) => {
}); });
}; };
// 修改批量删除方法,添加确认弹窗
const batchDelete = async () => { const batchDelete = async () => {
if (selectedRowKeys.value.length === 0) { if (selectedRowKeys.value.length === 0) {
message.warning('请先选择要删除的用户'); message.warning('请先选择要删除的用户');
@ -952,7 +949,7 @@ const batchDelete = async () => {
}); });
}; };
// 原有的deleteUser方法保持不变执行实际删除操作
const deleteUser = async (id: number) => { const deleteUser = async (id: number) => {
try { try {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
@ -1000,13 +997,11 @@ const editForm = ref({
SuperUserList: '' SuperUserList: ''
}); });
// 修改showDrawer方法
// 编辑状态下的头像上传状态
const editUploadLoading = ref(false); const editUploadLoading = ref(false);
const editPreviewImage = ref(''); const editPreviewImage = ref('');
// 编辑时的自定义上传处理
const handleEditUpload = async ({ file }: { file: File }) => { const handleEditUpload = async ({ file }: { file: File }) => {
const form = new FormData(); const form = new FormData();
form.append('file', file); form.append('file', file);
@ -1058,15 +1053,14 @@ const showDrawer = (record: any) => {
const toggleEditMode = () => { const toggleEditMode = () => {
isEditMode.value = !isEditMode.value; isEditMode.value = !isEditMode.value;
}; };
//保存修改的用户信息
//保存修改的用户信息
const handleSave = async () => { const handleSave = async () => {
try { try {
// 检查密码是否修改且符合规则
if (editForm.value.userPassword) { if (editForm.value.userPassword) {
const password = editForm.value.userPassword; const password = editForm.value.userPassword;
// 验证密码规则:必须包含数字、大写字母和小写字母
const hasNumber = /\d/.test(password); const hasNumber = /\d/.test(password);
const hasUpperCase = /[A-Z]/.test(password); const hasUpperCase = /[A-Z]/.test(password);
const hasLowerCase = /[a-z]/.test(password); const hasLowerCase = /[a-z]/.test(password);
@ -1080,19 +1074,19 @@ const handleSave = async () => {
const storedToken = localStorage.getItem('token'); const storedToken = localStorage.getItem('token');
if (!storedToken) throw new Error('未找到登录信息'); if (!storedToken) throw new Error('未找到登录信息');
// 处理空值转换
const processValue = (value: any) => { const processValue = (value: any) => {
if (value === "" || value === "无") return null; // 将空字符串和"无"转为null if (value === "" || value === "无") return null;
return value; return value;
}; };
// 处理数字类型字段
const processNumber = (value: any) => { const processNumber = (value: any) => {
const num = Number(value); const num = Number(value);
return isNaN(num) ? null : num; return isNaN(num) ? null : num;
}; };
// 构建请求体
const payload = { const payload = {
id: editForm.value.id, id: editForm.value.id,
nickName: processValue(editForm.value.nickName), nickName: processValue(editForm.value.nickName),
@ -1110,7 +1104,7 @@ const handleSave = async () => {
: [] : []
}; };
// 清理undefined字段
const cleanPayload = Object.fromEntries( const cleanPayload = Object.fromEntries(
Object.entries(payload).filter(([_, v]) => v !== undefined) Object.entries(payload).filter(([_, v]) => v !== undefined)
); );
@ -1129,7 +1123,7 @@ const handleSave = async () => {
await getUserList(); await getUserList();
const updatedUser = tableData.value.find(item => item.id === editForm.value.id); const updatedUser = tableData.value.find(item => item.id === editForm.value.id);
if (updatedUser) { if (updatedUser) {
selectedUser.value = { ...updatedUser }; // 关键更新 selectedUser.value = { ...updatedUser };
} }
isEditMode.value = false; isEditMode.value = false;
} else { } else {
@ -1142,7 +1136,7 @@ const handleSave = async () => {
}; };
//新增用户
const openUser = ref<boolean>(false); const openUser = ref<boolean>(false);
const formRef = ref(); const formRef = ref();
@ -1157,7 +1151,7 @@ const showModal = () => {
userAccount: '', userAccount: '',
userPassword: '' userPassword: ''
}; };
// 重置预览图片
previewImage.value = ''; previewImage.value = '';
}; };
@ -1206,12 +1200,12 @@ const handleSubmit = async () => {
formRef.value?.resetFields(); formRef.value?.resetFields();
getUserList(); getUserList();
} else { } else {
// 使用提取函数处理错误信息
const errorMsg = extractErrorMessage(res.message); const errorMsg = extractErrorMessage(res.message);
message.error(`${errorMsg}`); message.error(`${errorMsg}`);
} }
} catch (error: any) { } catch (error: any) {
// 使用提取函数处理错误信息
let errorMsg = error.response?.message || error.message; let errorMsg = error.response?.message || error.message;
errorMsg = extractErrorMessage(errorMsg); errorMsg = extractErrorMessage(errorMsg);
message.error(`${errorMsg}`); message.error(`${errorMsg}`);
@ -1225,7 +1219,7 @@ const handleSubmit = async () => {
.action-btn { .action-btn {
padding: 0 8px; padding: 0 8px;
} }
/* 分割线样式 */
:deep(.ant-divider-vertical) { :deep(.ant-divider-vertical) {
border-color: rgba(0, 0, 0, 0.15); border-color: rgba(0, 0, 0, 0.15);
height: 1.2em; height: 1.2em;
@ -1316,46 +1310,14 @@ const handleSubmit = async () => {
color: #1890ff; color: #1890ff;
} }
.code {
font-family: monospace;
background: #f5f5f5;
padding: 2px 6px;
border-radius: 4px;
}
.role-tag { .role-tag {
margin-left: 8px; margin-left: 8px;
font-size: 12px; 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 { :root {
--role-user: #87d068; --role-user: #87d068;
--role-admin: #f50; --role-admin: #f50;
@ -1507,7 +1469,7 @@ const handleSubmit = async () => {
border-color: #fa8c16; border-color: #fa8c16;
} }
/* 保持输入框原有样式不变 */
.custom-search :deep(.ant-input) { .custom-search :deep(.ant-input) {
border-right-color: #ffa940; border-right-color: #ffa940;
} }

View File

@ -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"}