huminmin
2026-05-11 8b1397cf60e69bcc3222a6862e72efc3f95483b0
生产班组
已添加2个文件
435 ■■■■■ 文件已修改
src/api/productionManagement/productionTeam.js 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionTeam/index.vue 382 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/productionManagement/productionTeam.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
import request from "@/utils/request";
// åˆ›å»ºç­ç»„
export function createTeam(data) {
    return request({
        url: "/production_team",
        method: "post",
        data: data,
    });
}
// æ›´æ–°ç­ç»„
export function updateTeam(data) {
    return request({
        url: "/production_team",
        method: "put",
        data: data,
    });
}
// åˆ é™¤ç­ç»„
export function deleteTeam(id) {
    return request({
        url: "/production_team/" + id,
        method: "delete",
    });
}
// æŸ¥è¯¢ç­ç»„详情
export function getTeamDetail(id) {
    return request({
        url: "/production_team/" + id,
        method: "get",
    });
}
// æŸ¥è¯¢ç­ç»„列表
export function getTeamList(query) {
    return request({
        url: "/production_team/list",
        method: "get",
        params: query,
    });
}
// åˆ†é¡µæŸ¥è¯¢ç­ç»„列表
export function getTeamListPage(query) {
    return request({
        url: "/production_team/listPage",
        method: "get",
        params: query,
    });
}
src/views/productionManagement/productionTeam/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,382 @@
<template>
  <div class="app-container">
    <!-- æœç´¢è¡¨å• -->
    <div class="search_form">
      <div class="search-row">
        <div class="search-left">
          <div class="search-item">
            <span class="search_title">班组名称:</span>
            <el-input v-model="searchForm.teamName"
                      style="width: 240px"
                      placeholder="请输入"
                      @change="handleQuery"
                      clearable
                      prefix-icon="Search" />
          </div>
          <div class="search-item">
            <el-button type="primary"
                       @click="handleQuery">搜索</el-button>
          </div>
        </div>
        <div class="search-right">
          <el-button type="primary"
                     @click="handleAdd">新增</el-button>
          <el-button type="danger"
                     plain
                     :disabled="!selectedIds.length"
                     @click="handleBatchDelete">删除</el-button>
        </div>
      </div>
    </div>
    <!-- è¡¨æ ¼æ•°æ® -->
    <div class="table_list">
      <PIMTable rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
                :page="page"
                :tableLoading="tableLoading"
                @pagination="pagination"
                :isSelection="true"
                @selection-change="handleSelectionChange">
        <template #members="{ row }">
          <el-tag
              v-for="member in getNonLeaderMembers(row)"
              :key="member.userId"
              type="info"
              size="small"
              style="margin-right: 4px"
          >{{ member.nickName }}</el-tag>
          <span v-if="!getNonLeaderMembers(row).length" class="text-gray">暂无成员</span>
        </template>
      </PIMTable>
    </div>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹ç­ç»„å¯¹è¯æ¡† -->
    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
      <el-form ref="teamRef" :model="form" :rules="rules" label-width="100px">
        <el-form-item label="班组名称" prop="teamName">
          <el-input v-model="form.teamName" placeholder="请输入班组名称" />
        </el-form-item>
        <el-form-item label="班组长" prop="leaderId">
          <el-select
              v-model="form.leaderId"
              placeholder="请选择班组长"
              style="width: 100%"
              clearable
              filterable
          >
            <el-option
                v-for="user in userList"
                :key="user.userId"
                :label="user.nickName"
                :value="user.userId"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="班组成员" prop="memberIds">
          <el-select
              v-model="form.memberIds"
              placeholder="请选择班组成员(不包含班组长)"
              style="width: 100%"
              multiple
              clearable
              filterable
          >
            <el-option
                v-for="user in availableMembers"
                :key="user.userId"
                :label="user.nickName"
                :value="user.userId"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="备注">
          <el-input v-model="form.remark" type="textarea" placeholder="请输入备注"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="ProductionTeam">
import { ref, reactive, toRefs, onMounted, computed, watch } from "vue";
import {
  createTeam,
  updateTeam,
  deleteTeam,
  getTeamDetail,
  getTeamListPage,
} from "@/api/productionManagement/productionTeam.js";
import { userListNoPageByTenantId } from "@/api/system/user.js";
const { proxy } = getCurrentInstance();
const tableColumn = ref([
  {
    label: "班组名称",
    prop: "teamName",
    width: "150",
  },
  {
    label: "班组长",
    prop: "leaderName",
    width: "120",
  },
  {
    label: "班组成员",
    dataType: "slot",
    slot: "members",
  },
  {
    label: "创建日期",
    prop: "createTime",
    width: "180",
  },
  {
    label: "备注",
    prop: "remark",
  },
  {
    label: "操作",
    width: "180",
    align: "center",
    dataType: "action",
    fixed: "right",
    operation: [
      {
        name: "编辑",
        clickFun: (row) => {
          handleUpdate(row);
        },
      },
      {
        name: "删除",
        clickFun: (row) => {
          handleDelete(row);
        },
      },
    ],
  },
]);
const tableData = ref([]);
const tableLoading = ref(false);
const open = ref(false);
const title = ref("");
const userList = ref([]);
const selectedIds = ref([]);
// å¯é€‰æ‹©çš„æˆå‘˜åˆ—表(排除班组长)
const availableMembers = computed(() => {
  if (!form.value.leaderId) {
    return userList.value;
  }
  return userList.value.filter(user => user.userId !== form.value.leaderId);
});
const page = reactive({
  current: 1,
  size: 10,
  total: 0,
});
const data = reactive({
  form: {},
  searchForm: {
    teamName: "",
  },
  rules: {
    teamName: [{ required: true, message: "班组名称不能为空", trigger: "blur" }],
    leaderId: [{ required: true, message: "请选择班组长", trigger: "blur" }],
  },
});
const { searchForm, form, rules } = toRefs(data);
/** æŸ¥è¯¢ç­ç»„列表 */
function getList() {
  tableLoading.value = true;
  const params = { ...searchForm.value, ...page };
  getTeamListPage(params).then((response) => {
    tableData.value = response.data?.records || response.data || [];
    page.total = response.data?.total || (response.data?.length || 0);
    tableLoading.value = false;
  }).catch(() => {
    tableLoading.value = false;
  });
}
/** æœç´¢æŒ‰é’®æ“ä½œ */
function handleQuery() {
  page.current = 1;
  getList();
}
/** åˆ†é¡µæ“ä½œ */
function pagination(obj) {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
}
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
function handleDelete(row) {
  proxy.$modal.confirm(`是否确认删除班组"${row.teamName}"?`).then(function () {
    return deleteTeam(row.id);
  }).then(() => {
    getList();
    proxy.$modal.msgSuccess("删除成功");
  }).catch(() => {});
}
/** æ‰¹é‡åˆ é™¤ */
function handleBatchDelete() {
  if (!selectedIds.value.length) {
    proxy.$modal.msgWarning("请选择要删除的班组");
    return;
  }
  proxy.$modal.confirm(`是否确认删除选中的${selectedIds.value.length}个班组?`).then(function () {
    // æ‰¹é‡åˆ é™¤ï¼Œä¾æ¬¡åˆ é™¤æ¯ä¸ªID
    const deletePromises = selectedIds.value.map(id => deleteTeam(id));
    return Promise.all(deletePromises);
  }).then(() => {
    getList();
    selectedIds.value = [];
    proxy.$modal.msgSuccess("删除成功");
  }).catch(() => {});
}
/** å¤šé€‰æ¡†é€‰ä¸­æ•°æ® */
function handleSelectionChange(selection) {
  selectedIds.value = selection.map((item) => item.id);
}
/** èŽ·å–éžç­ç»„é•¿çš„æˆå‘˜åˆ—è¡¨ */
function getNonLeaderMembers(row) {
  if (!row.members || !row.leaderId) {
    return row.members || [];
  }
  return row.members.filter(m => m.userId !== row.leaderId);
}
/** èŽ·å–ç”¨æˆ·åˆ—è¡¨ */
function getUserList() {
  userListNoPageByTenantId().then((response) => {
    if (response.code === 200) {
      userList.value = response.data || [];
    }
  });
}
/** é‡ç½®è¡¨å• */
function reset() {
  form.value = {
    id: undefined,
    teamName: undefined,
    leaderId: undefined,
    memberIds: [],
    remark: undefined,
  };
  proxy.resetForm("teamRef");
}
/** æ·»åŠ ç­ç»„ */
function handleAdd() {
  reset();
  open.value = true;
  title.value = "添加班组";
}
/** ä¿®æ”¹ç­ç»„ */
function handleUpdate(row) {
  reset();
  getTeamDetail(row.id).then((response) => {
    form.value = response.data;
    // è¿‡æ»¤æŽ‰ç­ç»„长,只保留普通成员
    form.value.memberIds = response.data.members
      .filter(m => m.userId !== response.data.leaderId)
      .map((m) => m.userId);
    open.value = true;
  });
  title.value = "修改班组";
}
// ç›‘听班组长变化,自动从成员列表中移除班组长
watch(() => form.value.leaderId, (newLeaderId, oldLeaderId) => {
  if (newLeaderId && form.value.memberIds) {
    form.value.memberIds = form.value.memberIds.filter(id => id !== newLeaderId);
  }
});
/** æäº¤æŒ‰é’® */
function submitForm() {
  proxy.$refs["teamRef"].validate((valid) => {
    if (valid) {
      const submitData = {
        id: form.value.id,
        teamName: form.value.teamName,
        leaderId: form.value.leaderId,
        memberIds: form.value.memberIds || [],
        remark: form.value.remark,
      };
      if (form.value.id != undefined) {
        updateTeam(submitData).then((response) => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
          getList();
        });
      } else {
        createTeam(submitData).then((response) => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
        });
      }
    }
  });
}
/** å–消按钮 */
function cancel() {
  open.value = false;
  reset();
}
onMounted(() => {
  getList();
  getUserList();
});
</script>
<style scoped lang="scss">
.search_form {
  margin-bottom: 20px;
  .search-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
  }
  .search-left {
    display: flex;
    gap: 20px;
    align-items: center;
    .search-item {
      display: flex;
      align-items: center;
      gap: 10px;
    }
  }
  .search-right {
    display: flex;
    gap: 10px;
  }
}
</style>