serv\web- 多租户修改

This commit is contained in:
2025-10-29 19:08:22 +08:00
parent c5c134fbb3
commit 82b6f14e64
86 changed files with 4446 additions and 2730 deletions

View File

@@ -76,14 +76,16 @@
<td>{{ formatDate(task.endTime) }}</td>
<td>
<span class="status-tag" :class="getStatusClass(task.status)">
{{ getStatusText(task.status) }}
{{ getStatusText(task.status, task.startTime, task.endTime) }}
</span>
</td>
<td>{{ formatDate(task.createTime) }}</td>
<td class="action-cell">
<button class="btn-link btn-primary" @click="handleView(task)">查看</button>
<button class="btn-link btn-warning" @click="handleEdit(task)" v-if="task.status === 0">编辑</button>
<button class="btn-link btn-success" @click="handlePublish(task)" v-if="task.status === 0">发布</button>
<button class="btn-link btn-success" @click="handleStateChange(task, 'publish')" v-if="task.status !== 1">发布</button>
<button class="btn-link btn-warning" @click="handleStateChange(task, 'unpublish')" v-if="task.status === 1">下架</button>
<button class="btn-link btn-primary" @click="handleStatistics(task)">统计</button>
<button class="btn-link btn-warning" @click="handleUpdateUser(task)" v-if="task.status !== 2">修改人员</button>
<button class="btn-link btn-danger" @click="handleDelete(task)" v-if="task.status === 0">删除</button>
</td>
@@ -184,7 +186,7 @@
<span class="detail-label">任务状态:</span>
<span class="detail-value">
<span class="status-badge" :class="getStatusClass(viewingTask.learningTask.status)">
{{ getStatusText(viewingTask.learningTask.status) }}
{{ getStatusText(viewingTask.learningTask.status, viewingTask.learningTask.startTime, viewingTask.learningTask.endTime) }}
</span>
</span>
</div>
@@ -311,15 +313,18 @@
</div>
<!-- 人员选择器组件 -->
<UserSelect
<GenericSelector
v-model:visible="showUserSelector"
:mode="selectorMode"
:title="selectorMode === 'add' ? '添加人员' : '删除人员'"
:left-title="selectorMode === 'add' ? '可添加人员' : '当前人员'"
:right-title="selectorMode === 'add' ? '待添加人员' : '待删除人员'"
:available-users="selectorMode === 'remove' ? availableUsers : []"
:initial-target-users="[]"
:available-items="selectorMode === 'remove' ? availableUsers : []"
:initial-target-items="[]"
:loading="saving"
:item-config="{ id: 'id', label: 'username', sublabel: 'deptName' }"
unit-name=""
search-placeholder="搜索人员..."
:use-pagination="selectorMode === 'add'"
:fetch-api="selectorMode === 'add' ? userApi.getUserPage : undefined"
:filter-params="userFilterParams"
@@ -335,7 +340,7 @@ import { ref, computed, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { learningTaskApi } from '@/apis/study';
import { userApi } from '@/apis/system';
import { UserSelect } from '@/components';
import { GenericSelector } from '@/components/base';
import type { LearningTask, TaskVO, PageParam, UserVO } from '@/types';
defineOptions({
@@ -518,6 +523,10 @@ function handleEdit(task: LearningTask) {
emit('edit', task);
}
function handleStatistics(task: LearningTask) {
return;
}
// 修改人员 - 显示当前人员列表
async function handleUpdateUser(task: LearningTask) {
managingTask.value = task;
@@ -583,7 +592,7 @@ function closeSelectorModal() {
}
// 处理用户选择器确认事件
async function handleUserSelectConfirm(selectedUsers: UserVO[]) {
async function handleUserSelectConfirm(selectedUsers: any[]) {
if (!managingTask.value || selectedUsers.length === 0) {
ElMessage.warning('请选择要操作的人员');
return;
@@ -602,7 +611,7 @@ async function handleUserSelectConfirm(selectedUsers: UserVO[]) {
ElMessage.success(`成功添加 ${userIds.length} 位人员`);
// 更新当前用户列表
currentUsers.value.push(...selectedUsers);
currentUsers.value.push(...(selectedUsers as UserVO[]));
} else {
// 执行删除操作
for (const userID of userIds) {
@@ -627,21 +636,21 @@ async function handleUserSelectConfirm(selectedUsers: UserVO[]) {
}
// 发布任务
async function handlePublish(task: LearningTask) {
async function handleStateChange(task: LearningTask, state: 'publish' | 'unpublish') {
try {
const res = await learningTaskApi.publishTask({
taskID: task.taskID!,
status: 1
const res = await learningTaskApi.changeTaskStatus({
...task,
status: state === 'publish' ? 1 : 2
});
if (res.success) {
ElMessage.success('任务发布成功');
ElMessage.success('任务状态更新成功');
loadTaskList();
} else {
ElMessage.error(res.message || '发布失败');
ElMessage.error(res.message || '状态更新失败');
}
} catch (error) {
console.error('发布任务失败:', error);
ElMessage.error('发布任务失败');
console.error('状态更新失败:', error);
ElMessage.error('状态更新失败');
}
}
@@ -689,18 +698,27 @@ function getStatusClass(status?: number) {
}
}
// 获取状态文本
function getStatusText(status?: number) {
switch (status) {
case 0:
return '草稿';
case 1:
return '进行中';
case 2:
return '已结束';
default:
return '未知';
function getStatusText(status?: number, startTime?: string, endTime?: string): string {
if (status === 0) {
return '草稿';
}
if (status === 1) {
let now = new Date();
let startTimeDate = new Date(startTime!);
let endTimeDate = new Date(endTime!);
if (now >= startTimeDate && now <= endTimeDate) {
return '进行中';
} else if (now < startTimeDate) {
return '未开始';
} else {
return '已结束';
}
}
if (status === 2) {
return '下架';
}
return '未知';
}
// 格式化日期
@@ -810,28 +828,6 @@ defineExpose({
margin-bottom: 20px;
}
.btn-primary {
padding: 10px 20px;
background: #409eff;
color: #fff;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s;
display: inline-flex;
align-items: center;
gap: 4px;
&:hover {
background: #66b1ff;
}
.icon {
font-size: 18px;
}
}
.task-table-wrapper {
background: #fff;
border-radius: 8px;
@@ -913,46 +909,45 @@ defineExpose({
.action-cell {
display: flex;
gap: 8px;
justify-content: center;
align-items: center;
gap: 6px;
flex-wrap: wrap;
}
.btn-link {
border: none;
padding: 4px 8px;
padding: 6px 12px;
font-size: 13px;
cursor: pointer;
transition: all 0.3s;
border-radius: 4px;
min-width: 64px;
text-align: center;
white-space: nowrap;
&:hover {
opacity: 0.8;
}
&.btn-primary {
&:hover {
background: #ecf5ff;
}
background: #409eff;
color: #ffffff;
}
&.btn-warning {
color: #e6a23c;
&:hover {
background: #fdf6ec;
}
background: #e6a23c;
color: #ffffff;
}
&.btn-success {
color: #67c23a;
&:hover {
background: #f0f9ff;
}
background: #67c23a;
color: #ffffff;
}
&.btn-danger {
background: #f56c6c;
color: #ffffff;
&:hover {
background: #fef0f0;
}
}
}
@@ -1073,9 +1068,11 @@ defineExpose({
}
}
// 通用按钮样式
.btn-default,
.btn-danger {
// 通用按钮样式(排除表格中的 btn-link
.btn-primary:not(.btn-link),
.btn-success:not(.btn-link),
.btn-danger:not(.btn-link),
.btn-default:not(.btn-link) {
padding: 10px 24px;
border-radius: 4px;
font-size: 14px;
@@ -1083,13 +1080,44 @@ defineExpose({
transition: all 0.3s;
border: none;
.icon {
margin-right: 4px;
}
&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
}
.btn-default {
.btn-primary:not(.btn-link) {
background: #409eff;
color: #fff;
&:hover:not(:disabled) {
background: #66b1ff;
}
}
.btn-success:not(.btn-link) {
background: #67c23a;
color: #fff;
&:hover:not(:disabled) {
background: #85ce61;
}
}
.btn-danger:not(.btn-link) {
background: #f56c6c;
color: #fff;
&:hover:not(:disabled) {
background: #f78989;
}
}
.btn-default:not(.btn-link) {
background: #fff;
color: #606266;
border: 1px solid #dcdfe6;
@@ -1100,15 +1128,6 @@ defineExpose({
}
}
.btn-danger {
background: #f56c6c;
color: #fff;
&:hover:not(:disabled) {
background: #f78989;
}
}
// 弹窗样式
.modal-overlay {
position: fixed;
@@ -1300,46 +1319,6 @@ defineExpose({
margin-bottom: 20px;
}
.btn-success,
.btn-danger {
padding: 10px 20px;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s;
display: inline-flex;
align-items: center;
gap: 6px;
.icon {
font-size: 18px;
font-weight: bold;
}
}
.btn-success {
background: #67c23a;
color: #fff;
&:hover {
background: #85ce61;
}
}
.btn-danger {
background: #f56c6c;
color: #fff;
&:hover:not(:disabled) {
background: #f78989;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
.current-user-list {
border: 1px solid #e0e0e0;