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

View File

@@ -108,7 +108,7 @@
v-hasPermi="['project:module:claim']" v-hasPermi="['project:module:claim']"
>接取</el-button> >接取</el-button>
<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" size="mini"
type="text" type="text"
icon="el-icon-circle-close" icon="el-icon-circle-close"
@@ -146,9 +146,7 @@
<el-form-item label="模块描述" prop="description"> <el-form-item label="模块描述" prop="description">
<el-input v-model="form.description" type="textarea" placeholder="请输入内容" /> <el-input v-model="form.description" type="textarea" placeholder="请输入内容" />
</el-form-item> </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> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button> <el-button type="primary" @click="submitForm"> </el-button>
@@ -162,13 +160,13 @@
<el-form-item label="模块名称"> <el-form-item label="模块名称">
<el-input v-model="assignForm.moduleName" :disabled="true" /> <el-input v-model="assignForm.moduleName" :disabled="true" />
</el-form-item> </el-form-item>
<el-form-item label="指派给" prop="assignee"> <el-form-item label="指派给" prop="designatedUser">
<el-select v-model="assignForm.assignee" placeholder="请选择用户" filterable> <el-select v-model="assignForm.designatedUser" placeholder="请选择用户" filterable>
<el-option <el-option
v-for="item in userOptions" v-for="item in userOptions"
:key="item.userName" :key="item.userId"
:label="item.nickName" :label="item.nickName"
:value="item.userName" :value="item.userId"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
@@ -241,8 +239,9 @@ export default {
// 指派表单 // 指派表单
assignForm: { assignForm: {
moduleId: null, moduleId: null,
projectId: null,
moduleName: null, moduleName: null,
assignee: null designatedUser: null
}, },
// 表单参数 // 表单参数
form: {}, form: {},
@@ -263,6 +262,19 @@ export default {
this.getUserList(); this.getUserList();
}, },
methods: { 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() { getList() {
this.loading = true; this.loading = true;
@@ -339,8 +351,9 @@ export default {
handleAssign(row) { handleAssign(row) {
this.assignForm = { this.assignForm = {
moduleId: row.moduleId, moduleId: row.moduleId,
projectId: row.projectId,
moduleName: row.moduleName, moduleName: row.moduleName,
assignee: null designatedUser: null
}; };
this.assignOpen = true; this.assignOpen = true;
}, },
@@ -384,7 +397,7 @@ export default {
}, },
/** 提交指派 */ /** 提交指派 */
submitAssign() { submitAssign() {
if (!this.assignForm.assignee) { if (!this.assignForm.designatedUser) {
this.$modal.msgError("请选择要指派的用户"); this.$modal.msgError("请选择要指派的用户");
return; return;
} }

View File

@@ -88,7 +88,7 @@
>接取</el-button> >接取</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 <el-button
size="mini" size="mini"
type="text" type="text"
@@ -145,7 +145,7 @@
<!-- 子模块抽屉 --> <!-- 子模块抽屉 -->
<el-drawer :title="currentModule ? ('子模块 - ' + currentModule.moduleName) : '子模块'" :visible.sync="subDrawerOpen" size="60%" append-to-body> <el-drawer :title="currentModule ? ('子模块 - ' + currentModule.moduleName) : '子模块'" :visible.sync="subDrawerOpen" size="60%" append-to-body>
<div> <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 v-loading="subLoading" :data="subList">
<el-table-column label="子模块名称" prop="subName" /> <el-table-column label="子模块名称" prop="subName" />
<el-table-column label="状态" prop="status"> <el-table-column label="状态" prop="status">
@@ -246,6 +246,21 @@ export default {
this.getList(); this.getList();
}, },
methods: { 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) { openSubDrawer(row) {
this.currentModule = row this.currentModule = row
@@ -313,7 +328,17 @@ export default {
/** 可操作判定(仅父模块接取人) */ /** 可操作判定(仅父模块接取人) */
canOperateSub() { canOperateSub() {
if (!this.currentModule) return false 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) { handleEditSub(row) {

View File

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