Commit 5762c633a1e7de32ec5739bce54dc66553ed4731

Authored by 李宇
1 parent 107c7d61

feat(lqYcsdJsj): 新增成员管理弹窗并优化相关功能

- 添加成员编辑对话框组件 `member-edit-dialog.vue`,支持成员的展示、添加与删除功能
- 在列表页中将“成员数量”列替换为直接操作入口,点击可打开成员管理弹窗
- 引入 `MemberEditDialog` 组件并在页面中控制其显示逻辑
- 默认设置查询月份为当前月份,并在重置时恢复默认值
- 调整部分 UI 文案及结构以提升用户体验和代码一致性
antis-ncc-admin/src/views/lqYcsdJsj/components/member-edit-dialog.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + title="成员管理"
  4 + :visible.sync="visible"
  5 + width="900px"
  6 + :close-on-click-modal="false"
  7 + @close="handleClose">
  8 +
  9 + <div class="member-dialog">
  10 + <!-- 操作栏 -->
  11 + <div class="member-toolbar">
  12 + <el-button type="primary" icon="el-icon-plus" @click="showAddDialog" size="small">添加成员</el-button>
  13 + <el-button type="warning" icon="el-icon-refresh" @click="loadMembers" size="small">刷新</el-button>
  14 + <span class="member-count">共 {{ members.length }} 人</span>
  15 + </div>
  16 +
  17 + <!-- 成员列表 -->
  18 + <el-table :data="members" border style="width: 100%; margin-top: 10px;" v-loading="loading">
  19 + <el-table-column type="index" label="序号" width="60" align="center" />
  20 + <el-table-column prop="userName" label="姓名" min-width="120">
  21 + <template slot-scope="scope">
  22 + <div class="user-name">
  23 + <i class="el-icon-user"></i>
  24 + <span>{{ scope.row.userName || '无' }}</span>
  25 + </div>
  26 + </template>
  27 + </el-table-column>
  28 + <el-table-column prop="userId" label="用户ID" min-width="150">
  29 + <template slot-scope="scope">
  30 + <span>{{ scope.row.userId || '无' }}</span>
  31 + </template>
  32 + </el-table-column>
  33 + <el-table-column label="是否顾问" width="120" align="center">
  34 + <template slot-scope="scope">
  35 + <el-tag :type="scope.row.isLeader === 1 ? 'success' : 'info'" size="small" effect="dark">
  36 + <i class="el-icon-star-on" v-if="scope.row.isLeader === 1"></i>
  37 + <i class="el-icon-star-off" v-else></i>
  38 + {{ scope.row.isLeader === 1 ? '是' : '否' }}
  39 + </el-tag>
  40 + </template>
  41 + </el-table-column>
  42 + <el-table-column prop="status" label="状态" width="100" align="center">
  43 + <template slot-scope="scope">
  44 + <el-tag :type="scope.row.status === 'ACTIVE' ? 'success' : 'info'" size="small" effect="dark">
  45 + {{ scope.row.status === 'ACTIVE' ? '活跃' : '非活跃' }}
  46 + </el-tag>
  47 + </template>
  48 + </el-table-column>
  49 + <el-table-column label="排序" width="100" align="center">
  50 + <template slot-scope="scope">
  51 + <span>{{ scope.row.sortOrder || 0 }}</span>
  52 + </template>
  53 + </el-table-column>
  54 + <el-table-column label="操作" width="100" align="center" fixed="right">
  55 + <template slot-scope="scope">
  56 + <el-button type="danger" icon="el-icon-delete" @click="handleDelete(scope.row)" size="mini" plain>删除</el-button>
  57 + </template>
  58 + </el-table-column>
  59 + </el-table>
  60 + </div>
  61 +
  62 + <!-- 添加成员对话框 -->
  63 + <el-dialog
  64 + title="添加成员"
  65 + :visible.sync="addDialogVisible"
  66 + width="600px"
  67 + append-to-body
  68 + :close-on-click-modal="false">
  69 + <el-form ref="addForm" :model="addForm" label-width="100px" label-position="right" :rules="addFormRules">
  70 + <el-form-item label="用户" prop="userId">
  71 + <el-select
  72 + v-model="addForm.userId"
  73 + placeholder="请选择用户"
  74 + filterable
  75 + style="width: 100%;"
  76 + @change="onUserSelectChange">
  77 + <el-option
  78 + v-for="user in availableUsers"
  79 + :key="user.id"
  80 + :label="user.name"
  81 + :value="user.id">
  82 + </el-option>
  83 + </el-select>
  84 + </el-form-item>
  85 + <el-form-item label="姓名" prop="userName">
  86 + <el-input v-model="addForm.userName" placeholder="请输入姓名" />
  87 + </el-form-item>
  88 + <el-form-item label="是否顾问" prop="isLeader">
  89 + <el-radio-group v-model="addForm.isLeader">
  90 + <el-radio :label="1">是</el-radio>
  91 + <el-radio :label="0">否</el-radio>
  92 + </el-radio-group>
  93 + </el-form-item>
  94 + <!-- <el-form-item label="状态" prop="status">
  95 + <el-select v-model="addForm.status" placeholder="请选择状态" style="width: 100%;">
  96 + <el-option label="活跃" value="ACTIVE"></el-option>
  97 + <el-option label="非活跃" value="INACTIVE"></el-option>
  98 + </el-select>
  99 + </el-form-item> -->
  100 + <el-form-item label="排序" prop="sortOrder">
  101 + <el-input-number
  102 + v-model="addForm.sortOrder"
  103 + :min="1"
  104 + :max="999"
  105 + style="width: 100%;" />
  106 + </el-form-item>
  107 + </el-form>
  108 + <span slot="footer" class="dialog-footer">
  109 + <el-button @click="addDialogVisible = false">取 消</el-button>
  110 + <el-button type="primary" @click="handleAddMember">确 定</el-button>
  111 + </span>
  112 + </el-dialog>
  113 +
  114 + <span slot="footer" class="dialog-footer">
  115 + <el-button @click="handleClose">关 闭</el-button>
  116 + </span>
  117 + </el-dialog>
  118 +</template>
  119 +
  120 +<script>
  121 +import request from '@/utils/request'
  122 +
  123 +export default {
  124 + name: 'MemberEditDialog',
  125 + data() {
  126 + return {
  127 + visible: false,
  128 + loading: false,
  129 + jsjId: '',
  130 + members: [],
  131 + availableUsers: [],
  132 + addDialogVisible: false,
  133 + addForm: {
  134 + userId: '',
  135 + userName: '',
  136 + isLeader: 0,
  137 + status: 'ACTIVE',
  138 + sortOrder: 1
  139 + },
  140 + addFormRules: {
  141 + userId: [
  142 + { required: true, message: '请选择用户', trigger: 'change' }
  143 + ],
  144 + userName: [
  145 + { required: true, message: '请输入姓名', trigger: 'blur' }
  146 + ],
  147 + isLeader: [
  148 + { required: true, message: '请选择是否顾问', trigger: 'change' }
  149 + ],
  150 + status: [
  151 + { required: true, message: '请选择状态', trigger: 'change' }
  152 + ],
  153 + sortOrder: [
  154 + { required: true, message: '请输入排序', trigger: 'blur' }
  155 + ]
  156 + }
  157 + }
  158 + },
  159 + methods: {
  160 + init(jsjId) {
  161 + this.jsjId = jsjId
  162 + this.visible = true
  163 + this.loadMembers()
  164 + this.loadAvailableUsers()
  165 + },
  166 + loadMembers() {
  167 + if (!this.jsjId) return
  168 +
  169 + this.loading = true
  170 + request({
  171 + url: `/api/Extend/LqYcsdJsj/${this.jsjId}/detail`,
  172 + method: 'GET'
  173 + }).then(res => {
  174 + this.members = res.data.members || []
  175 + this.loading = false
  176 + }).catch(() => {
  177 + this.members = []
  178 + this.loading = false
  179 + })
  180 + },
  181 + loadAvailableUsers() {
  182 + // 加载可用用户列表
  183 + request({
  184 + url: '/api/Extend/User/Selector',
  185 + method: 'GET'
  186 + }).then(res => {
  187 + this.availableUsers = res.data.map(item => ({
  188 + id: item.id,
  189 + name: item.realName || item.account
  190 + }))
  191 + }).catch(() => {
  192 + this.availableUsers = []
  193 + })
  194 + },
  195 + showAddDialog() {
  196 + this.addForm = {
  197 + userId: '',
  198 + userName: '',
  199 + isLeader: 0,
  200 + status: 'ACTIVE',
  201 + sortOrder: this.members.length + 1
  202 + }
  203 + this.addDialogVisible = true
  204 + this.$nextTick(() => {
  205 + this.$refs.addForm && this.$refs.addForm.clearValidate()
  206 + })
  207 + },
  208 + onUserSelectChange(userId) {
  209 + // 用户选择变化时自动填充姓名
  210 + const selectedUser = this.availableUsers.find(user => user.id === userId)
  211 + if (selectedUser) {
  212 + this.addForm.userName = selectedUser.name
  213 + }
  214 + },
  215 + handleAddMember() {
  216 + this.$refs.addForm.validate((valid) => {
  217 + if (valid) {
  218 + // 调用新增接口
  219 + request({
  220 + url: '/api/Extend/lqycsdjsj/Actions/AddUserToJsj',
  221 + method: 'POST',
  222 + data: {
  223 + jsjId: this.jsjId,
  224 + userId: this.addForm.userId,
  225 + userName: this.addForm.userName,
  226 + isLeader: this.addForm.isLeader,
  227 + status: this.addForm.status,
  228 + sortOrder: this.addForm.sortOrder
  229 + }
  230 + }).then(res => {
  231 + this.$message({
  232 + type: 'success',
  233 + message: res.msg || '添加成功',
  234 + duration: 1500,
  235 + onClose: () => {
  236 + this.addDialogVisible = false
  237 + this.loadMembers()
  238 + }
  239 + })
  240 + }).catch(err => {
  241 + this.$message({
  242 + type: 'error',
  243 + message: err.msg || '添加失败',
  244 + duration: 1500
  245 + })
  246 + })
  247 + }
  248 + })
  249 + },
  250 + handleDelete(row) {
  251 + if (!row.id) {
  252 + this.$message.error('该成员记录缺少ID,无法删除')
  253 + return
  254 + }
  255 +
  256 + this.$confirm('确定要删除这个成员吗?', '提示', {
  257 + type: 'warning'
  258 + }).then(() => {
  259 + // 调用删除接口
  260 + request({
  261 + url: '/api/Extend/lqycsdjsj/Actions/DeleteJsjUserRelation',
  262 + method: 'POST',
  263 + data: {
  264 + id: row.id
  265 + }
  266 + }).then(res => {
  267 + this.$message({
  268 + type: 'success',
  269 + message: res.msg || '删除成功',
  270 + duration: 1500,
  271 + onClose: () => {
  272 + this.loadMembers()
  273 + }
  274 + })
  275 + }).catch(err => {
  276 + this.$message({
  277 + type: 'error',
  278 + message: err.msg || '删除失败',
  279 + duration: 1500
  280 + })
  281 + })
  282 + }).catch(() => {})
  283 + },
  284 + handleClose() {
  285 + this.visible = false
  286 + this.members = []
  287 + this.$emit('close')
  288 + }
  289 + }
  290 +}
  291 +</script>
  292 +
  293 +<style scoped>
  294 +.member-dialog {
  295 + padding: 10px 0;
  296 +}
  297 +
  298 +.member-toolbar {
  299 + display: flex;
  300 + align-items: center;
  301 + gap: 10px;
  302 + margin-bottom: 10px;
  303 +}
  304 +
  305 +.member-count {
  306 + color: #606266;
  307 + font-size: 14px;
  308 + margin-left: auto;
  309 +}
  310 +
  311 +.user-name {
  312 + display: flex;
  313 + align-items: center;
  314 + gap: 8px;
  315 +}
  316 +
  317 +.user-name i {
  318 + color: #409EFF;
  319 + font-size: 16px;
  320 +}
  321 +
  322 +.el-table {
  323 + margin-top: 10px;
  324 +}
  325 +
  326 +.action-buttons {
  327 + display: flex;
  328 + gap: 8px;
  329 +}
  330 +
  331 +.action-buttons .el-button {
  332 + margin: 0;
  333 +}
  334 +</style>
  335 +
... ...
antis-ncc-admin/src/views/lqYcsdJsj/index.vue
... ... @@ -83,7 +83,7 @@
83 83 </div>
84 84 </template>
85 85 </el-table-column>
86   - <el-table-column label="成员数量" align="center" min-width="120">
  86 + <!-- <el-table-column label="成员数量" align="center" min-width="120">
87 87 <template slot-scope="scope">
88 88 <el-tag v-if="scope.row.memberCount > 0" type="success" size="small" effect="dark">
89 89 <i class="el-icon-user"></i>
... ... @@ -94,11 +94,11 @@
94 94 0人
95 95 </el-tag>
96 96 </template>
97   - </el-table-column>
  97 + </el-table-column> -->
98 98 <el-table-column label="操作" fixed="right" min-width="200">
99 99 <template slot-scope="scope">
100 100 <div class="action-buttons">
101   - <el-button type="primary" icon="el-icon-edit" @click="addOrUpdateHandle(scope.row.id)" size="mini" plain>编辑</el-button>
  101 + <el-button type="primary" icon="el-icon-edit" @click="editMembers(scope.row.id)" size="mini" plain>编辑</el-button>
102 102 <el-button type="info" icon="el-icon-view" @click="viewDetail(scope.row.id)" size="mini" plain>详情</el-button>
103 103 <el-button type="danger" icon="el-icon-delete" @click="handleDel(scope.row.id)" size="mini" plain>删除</el-button>
104 104 </div>
... ... @@ -110,6 +110,7 @@
110 110 </div>
111 111 <NCC-Form v-if="formVisible" ref="NCCForm" @refresh="refresh" />
112 112 <ExportBox v-if="exportBoxVisible" ref="ExportBox" @download="download" />
  113 + <MemberEditDialog v-if="memberDialogVisible" ref="MemberEditDialog" @close="memberDialogVisible = false" />
113 114 </div>
114 115 </template>
115 116  
... ... @@ -218,9 +219,10 @@
218 219 import { getDictionaryDataSelector } from '@/api/systemData/dictionary'
219 220 import NCCForm from './Form'
220 221 import ExportBox from './ExportBox'
  222 + import MemberEditDialog from './components/member-edit-dialog.vue'
221 223 import { previewDataInterface } from '@/api/systemData/dataInterface'
222 224 export default {
223   - components: { NCCForm, ExportBox },
  225 + components: { NCCForm, ExportBox, MemberEditDialog },
224 226 data() {
225 227 return {
226 228 showAll: false,
... ... @@ -244,6 +246,7 @@
244 246 },
245 247 formVisible: false,
246 248 exportBoxVisible: false,
  249 + memberDialogVisible: false,
247 250 columnList: [
248 251 { prop: 'id', label: '主键' },
249 252 { prop: 'yf', label: '月份' },
... ... @@ -254,10 +257,21 @@
254 257 },
255 258 computed: {},
256 259 created() {
  260 + // 设置默认月份为本月
  261 + this.setDefaultMonth()
257 262 this.loadStoreList()
258 263 this.initData()
259 264 },
260 265 methods: {
  266 + setDefaultMonth() {
  267 + // 获取当前月份,格式:yyyyMM
  268 + const now = new Date()
  269 + const year = now.getFullYear()
  270 + const month = String(now.getMonth() + 1).padStart(2, '0')
  271 + const currentMonth = `${year}${month}`
  272 + this.monthQuery = currentMonth
  273 + this.query.yf = currentMonth
  274 + },
261 275 initData() {
262 276 this.listLoading = true;
263 277 let _query = {
... ... @@ -284,7 +298,7 @@
284 298 // 加载门店映射
285 299 this.loadStoreMap()
286 300 // 为每个金三角加载成员数量
287   - this.loadMemberCounts()
  301 + // this.loadMemberCounts()
288 302 })
289 303 },
290 304 handleDel(id) {
... ... @@ -306,6 +320,12 @@
306 320 }).catch(() => {
307 321 });
308 322 },
  323 + editMembers(id) {
  324 + this.memberDialogVisible = true
  325 + this.$nextTick(() => {
  326 + this.$refs.MemberEditDialog.init(id)
  327 + })
  328 + },
309 329 viewDetail(id) {
310 330 this.formVisible = true
311 331 this.$nextTick(() => {
... ... @@ -441,10 +461,10 @@
441 461 if (isrRefresh) this.reset()
442 462 },
443 463 reset() {
444   - for (let key in this.query) {
445   - this.query[key] = undefined
446   - }
447   - this.monthQuery = null
  464 + // 重置时恢复默认月份为本月
  465 + this.setDefaultMonth()
  466 + this.query.md = undefined
  467 + this.query.jsj = undefined
448 468 this.listQuery = {
449 469 currentPage: 1,
450 470 pageSize: 20,
... ...
antis-ncc-admin/src/views/lqYcsdMdmbsd/index.vue
... ... @@ -137,8 +137,8 @@
137 137 </template>
138 138 </el-table-column>
139 139  
140   - <!-- 重大项目部 -->
141   - <el-table-column label="重大项目部" width="140" align="center">
  140 + <!-- 大项目部 -->
  141 + <el-table-column label="大项目部" width="140" align="center">
142 142 <template slot-scope="scope">
143 143 <div class="department-item">
144 144 <i class="el-icon-office-building department-icon"></i>
... ...