This commit is contained in:
2025-09-15 09:56:34 +08:00
parent f52c0a1123
commit 742abea1f9
4 changed files with 107 additions and 28 deletions

View File

@@ -51,6 +51,11 @@
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="文档名称" align="center" prop="docName" />
<el-table-column label="所属项目" align="center" prop="projectName" />
<el-table-column label="所属模块" align="center">
<template slot-scope="scope">
<span>{{ scope.row.moduleName || (scope.row.kindType === '0' || scope.row.kindType === 0 ? '项目文档' : '-') }}</span>
</template>
</el-table-column>
<el-table-column label="文档类型" align="center">
<template slot-scope="scope">
<span>{{ (scope.row.docType) || (scope.row.docPath ? scope.row.docPath.split('.').pop() : '-') }}</span>
@@ -338,14 +343,23 @@ export default {
this.upload.meta.moduleId = null;
if (!projectId) { this.moduleOptions = []; return; }
try {
const currentUid = String(this.currentUserId)
// 无论角色上传模块文档都只允许当前用户为接取人assignee
// 因此下拉仅展示“我为接取人”的模块,避免误选
let rows = []
if (!this.isProjectAdmin && this.isNormalUser) {
// 从“我的模块”中过滤出所选项目的可见模块
const { rows } = await getMyModules({ pageNum: 1, pageSize: 9999 })
this.moduleOptions = (rows || []).filter(m => String(m.projectId) === String(projectId))
const res = await getMyModules({ pageNum: 1, pageSize: 9999 })
rows = res && Array.isArray(res.rows) ? res.rows : []
} else {
const { rows } = await listModulesByProject(projectId)
this.moduleOptions = rows || []
const res = await listModulesByProject(projectId)
rows = res && Array.isArray(res.rows) ? res.rows : []
}
this.moduleOptions = rows
.filter(m => String(m.projectId) === String(projectId))
.filter(m => (m.assigneeId != null && String(m.assigneeId) === currentUid)
|| (m.assignee && (String(m.assignee) === currentUid
|| m.assignee === (this.$store.getters && this.$store.getters.name)
|| m.assignee === (this.$store.getters && this.$store.getters.nickName))))
} catch (e) {
this.moduleOptions = []
}
@@ -463,11 +477,33 @@ export default {
},
// 文件上传成功处理
handleFileSuccess(response, file, fileList) {
this.upload.open = false;
this.upload.isUploading = false;
this.$refs.upload.clearFiles();
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
this.getList();
// 按后端 code 判断
if (response && typeof response.code !== 'undefined' && Number(response.code) !== 200) {
this.$message.error(response.msg || '上传失败')
return
}
// 统一成功提示
const msg = (response && (response.msg || response.message)) || '上传成功'
this.$message.success(msg)
// 关闭弹窗、清空文件列表
this.uploadOpen = false
this.$nextTick(() => {
try { this.$refs.upload && this.$refs.upload.clearFiles() } catch(e) {}
})
// 同步筛选条件为当前上传目标并即时刷新列表
const { kindType, projectId, moduleId } = this.upload.meta
this.queryParams.kind_type = kindType
if (kindType === 1) {
this.queryParams.moduleId = moduleId
this.queryParams.projectId = null
} else {
this.queryParams.projectId = projectId
this.queryParams.moduleId = null
}
this.queryParams.pageNum = 1
// 即时刷新列表
this.getList()
},
// 文件上传失败处理(网络/后端错误)
handleFileError(err, file, fileList) {
@@ -534,6 +570,8 @@ export default {
this.$modal.msgError('请选择所属模块');
return;
}
// 增加上传中状态,避免重复点击
this.upload.isUploading = true
this.$refs.upload.submit();
}
}

View File

@@ -108,7 +108,7 @@
v-hasPermi="['project:module:claim']"
>接取</el-button>
<el-button
v-if="scope.row.status === '1' && scope.row.assignee === userName"
v-if="scope.row.status === '1' && isSelfAssignee(scope.row)"
size="mini"
type="text"
icon="el-icon-circle-close"
@@ -146,9 +146,7 @@
<el-form-item label="模块描述" prop="description">
<el-input v-model="form.description" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="接取人" prop="assignee" v-if="form.moduleId">
<el-input v-model="form.assignee" placeholder="请输入接取人用户名" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
@@ -162,13 +160,13 @@
<el-form-item label="模块名称">
<el-input v-model="assignForm.moduleName" :disabled="true" />
</el-form-item>
<el-form-item label="指派给" prop="assignee">
<el-select v-model="assignForm.assignee" placeholder="请选择用户" filterable>
<el-form-item label="指派给" prop="designatedUser">
<el-select v-model="assignForm.designatedUser" placeholder="请选择用户" filterable>
<el-option
v-for="item in userOptions"
:key="item.userName"
:key="item.userId"
:label="item.nickName"
:value="item.userName"
:value="item.userId"
/>
</el-select>
</el-form-item>
@@ -241,8 +239,9 @@ export default {
// 指派表单
assignForm: {
moduleId: null,
projectId: null,
moduleName: null,
assignee: null
designatedUser: null
},
// 表单参数
form: {},
@@ -263,6 +262,19 @@ export default {
this.getUserList();
},
methods: {
/** 判断当前用户是否是接取人兼容ID/用户名/昵称) */
isSelfAssignee(row) {
if (!row) return false
// 优先使用后端返回的标准 assigneeId
if (row.assigneeId != null && String(row.assigneeId) === String(this.$store.state.user.id)) return true
const assignee = row.assignee
if (!assignee) return false
const uid = String(this.$store.state.user.id)
if (String(assignee) === uid) return true
const currentUserName = this.$store.getters && this.$store.getters.name
const currentNickName = this.$store.getters && this.$store.getters.nickName
return assignee === currentUserName || assignee === currentNickName
},
/** 查询模块列表 */
getList() {
this.loading = true;
@@ -339,8 +351,9 @@ export default {
handleAssign(row) {
this.assignForm = {
moduleId: row.moduleId,
projectId: row.projectId,
moduleName: row.moduleName,
assignee: null
designatedUser: null
};
this.assignOpen = true;
},
@@ -384,7 +397,7 @@ export default {
},
/** 提交指派 */
submitAssign() {
if (!this.assignForm.assignee) {
if (!this.assignForm.designatedUser) {
this.$modal.msgError("请选择要指派的用户");
return;
}

View File

@@ -88,7 +88,7 @@
>接取</el-button>
<!-- 进行中状态显示放弃完成上传文档按钮 -->
<template v-if="scope.row.status === '1' && (String(scope.row.assignee) === String(userId) || scope.row.assignee === userName)">
<template v-if="scope.row.status === '1' && isSelfAssignee(scope.row)">
<el-button
size="mini"
type="text"
@@ -145,7 +145,7 @@
<!-- 子模块抽屉 -->
<el-drawer :title="currentModule ? ('子模块 - ' + currentModule.moduleName) : '子模块'" :visible.sync="subDrawerOpen" size="60%" append-to-body>
<div>
<el-button type="primary" size="mini" icon="el-icon-plus" @click="handleOpenAddSub" v-if="currentModule && currentModule.status==='1' && (String(currentModule.assignee)===String(userId) || currentModule.assignee===userName)" style="margin-bottom: 12px;">新增子模块</el-button>
<el-button type="primary" size="mini" icon="el-icon-plus" @click="handleOpenAddSub" v-if="currentModule && currentModule.status==='1' && canOperateSub()" style="margin-bottom: 12px;">新增子模块</el-button>
<el-table v-loading="subLoading" :data="subList">
<el-table-column label="子模块名称" prop="subName" />
<el-table-column label="状态" prop="status">
@@ -246,6 +246,21 @@ export default {
this.getList();
},
methods: {
/** 统一判断当前用户是否为模块接取人兼容ID/用户名/昵称) */
isSelfAssignee(row) {
if (!row) return false
// 优先使用后端返回的 assigneeId标准用户ID
if (row.assigneeId != null && String(row.assigneeId) === String(this.userId)) return true
const assignee = row.assignee
const uid = String(this.userId)
if (!assignee) return false
// 精确匹配ID 字符串
if (String(assignee) === uid) return true
// 兼容用户名/昵称(后端展示通过 COALESCE 可能为 nick_name 或 user_name
const currentUserName = this.$store.getters && this.$store.getters.name
const currentNickName = this.$store.getters && this.$store.getters.nickName
return assignee === currentUserName || assignee === currentNickName
},
/** 打开子模块抽屉(统一入口) */
openSubDrawer(row) {
this.currentModule = row
@@ -313,7 +328,17 @@ export default {
/** 可操作判定(仅父模块接取人) */
canOperateSub() {
if (!this.currentModule) return false
return String(this.currentModule.assignee) === String(this.userId) || this.currentModule.assignee === this.userName
// 优先使用后端返回的标准 ID
if (this.currentModule.assigneeId != null && String(this.currentModule.assigneeId) === String(this.userId)) {
return true
}
const assignee = this.currentModule.assignee
if (!assignee) return false
// 兼容旧数据ID字符串/用户名/昵称
if (String(assignee) === String(this.userId)) return true
const currentUserName = this.$store.getters && this.$store.getters.name
const currentNickName = this.$store.getters && this.$store.getters.nickName
return assignee === currentUserName || assignee === currentNickName
},
/** 编辑子模块 */
handleEditSub(row) {

View File

@@ -224,7 +224,7 @@
<!-- 添加或修改项目对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form ref="projectForm" :model="form" :rules="rules" label-width="80px">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="form.projectName" placeholder="请输入项目名称"/>
</el-form-item>
@@ -270,7 +270,7 @@
<!-- 模块添加对话框-->
<el-dialog :title="title" :visible.sync="Models" width="500px" append-to-body>
<el-form ref="form" :model="modelsForm" :rules="rules" label-width="80px">
<el-form ref="moduleForm" :model="modelsForm" :rules="rules" label-width="80px">
<el-form-item label="模块名称" prop="ModelName">
<el-input v-model="modelsForm.moduleName" placeholder="请输入模块名称"/>
</el-form-item>
@@ -583,7 +583,7 @@ export default {
subMitModel() {
this.modelsForm.projectId = this.projectId;
// 表单校验(模块名称、截止日期等必填)
this.$refs["form"].validate(valid => {
this.$refs["moduleForm"].validate(valid => {
if (!valid) {
return;
}
@@ -705,7 +705,7 @@ export default {
deadline: null,
projectLabel: null
}
this.resetForm("form")
this.resetForm("projectForm")
},
/** 搜索按钮操作 */
handleQuery() {
@@ -756,7 +756,7 @@ export default {
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
this.$refs["projectForm"].validate(valid => {
this.finishDialog = false;
if (valid) {
// 运行时校验:起始日期不得晚于截止日期
@@ -775,6 +775,7 @@ export default {
updateProject(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
// 修改后刷新列表,保持当前页
this.getList()
})
} else {
@@ -788,6 +789,8 @@ export default {
addProject(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
// 新增后重置到第一页并刷新,避免需要手动刷新
this.queryParams.pageNum = 1
this.getList()
})
}