WXL
2025-08-07 b7f7f38d7ead0939d82a8a0fb301b30b72398acc
测试完成
已添加2个文件
已修改2个文件
2907 ■■■■■ 文件已修改
src/views/knowledge/article/index.vue 486 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/knowledge/drug/index.vue 1072 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/group/index.vue 1343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/knowledge/article/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,486 @@
<template>
  <div class="ArticleManagement">
    <el-row :gutter="20">
      <el-col :span="24" :xs="24">
        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
          <el-form-item label="文章标题" prop="title">
            <el-input
              v-model="queryParams.title"
              placeholder="请输入文章标题"
              clearable
              style="width: 200px"
              @keyup.enter.native="handleQuery"
            />
          </el-form-item>
          <el-form-item label="文章分类" prop="category">
            <el-select v-model="queryParams.category" placeholder="请选择分类" clearable style="width: 200px">
              <el-option
                v-for="item in categoryOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="状态" prop="status">
            <el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width: 200px">
              <el-option
                v-for="item in statusOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="el-icon-search" size="medium" @click="handleQuery">搜索</el-button>
            <el-button icon="el-icon-refresh" size="medium" @click="resetQuery">重置</el-button>
          </el-form-item>
        </el-form>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button
              type="primary"
              plain
              icon="el-icon-plus"
              size="medium"
              @click="handleAdd"
            >新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button
              type="danger"
              plain
              icon="el-icon-delete"
              size="medium"
              :disabled="multiple"
              @click="handleDelete"
            >删除</el-button>
          </el-col>
        </el-row>
        <el-table v-loading="loading" :data="filteredArticleList" @selection-change="handleSelectionChange">
          <el-table-column type="selection" width="50" align="center" />
          <el-table-column label="文章ID" align="center" prop="id" width="80" />
          <el-table-column label="文章标题" align="center" prop="title" :show-overflow-tooltip="true" />
          <el-table-column label="文章分类" align="center" prop="category" width="120">
            <template slot-scope="scope">
              <dict-tag :options="categoryOptions" :value="scope.row.category"/>
            </template>
          </el-table-column>
          <el-table-column label="封面图" align="center" prop="coverImage" width="120">
            <template slot-scope="scope">
              <el-image
                v-if="scope.row.coverImage"
                style="width: 80px; height: 60px"
                :src="scope.row.coverImage"
                :preview-src-list="[scope.row.coverImage]"
                fit="cover"
              />
              <span v-else>无封面</span>
            </template>
          </el-table-column>
          <el-table-column label="作者" align="center" prop="author" width="120" />
          <el-table-column label="发布时间" align="center" prop="publishTime" width="160">
            <template slot-scope="scope">
              <span>{{ parseTime(scope.row.publishTime, '{y}-{m}-{d} {h}:{i}') }}</span>
            </template>
          </el-table-column>
          <el-table-column label="阅读量" align="center" prop="views" width="80" />
          <el-table-column label="状态" align="center" prop="status" width="100">
            <template slot-scope="scope">
              <dict-tag :options="statusOptions" :value="scope.row.status"/>
            </template>
          </el-table-column>
          <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
            <template slot-scope="scope">
              <el-button
                size="mini"
                type="text"
                icon="el-icon-edit"
                @click="handleUpdate(scope.row)"
              >修改</el-button>
              <el-button
                size="mini"
                type="text"
                icon="el-icon-delete"
                @click="handleDelete(scope.row)"
              >删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <pagination
          v-show="total>0"
          :total="total"
          :page.sync="queryParams.pageNum"
          :limit.sync="queryParams.pageSize"
          @pagination="getList"
        />
      </el-col>
    </el-row>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹æ–‡ç« å¯¹è¯æ¡† -->
    <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="文章标题" prop="title">
              <el-input v-model="form.title" placeholder="请输入文章标题" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="文章分类" prop="category">
              <el-select v-model="form.category" placeholder="请选择分类">
                <el-option
                  v-for="item in categoryOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="状态" prop="status">
              <el-radio-group v-model="form.status">
                <el-radio
                  v-for="dict in statusOptions"
                  :key="dict.value"
                  :label="dict.value"
                >{{dict.label}}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="封面图">
              <el-upload
                class="avatar-uploader"
                action="#"
                :show-file-list="false"
                :on-change="handleCoverChange"
                :auto-upload="false">
                <img v-if="form.coverImage" :src="form.coverImage" class="avatar">
                <i v-else class="el-icon-plus avatar-uploader-icon"></i>
              </el-upload>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="文章摘要" prop="summary">
              <el-input
                type="textarea"
                :rows="3"
                v-model="form.summary"
                placeholder="请输入文章摘要"
              />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="文章内容" prop="content">
              <editor v-model="form.content" :min-height="300"/>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">ç¡® å®š</el-button>
        <el-button @click="cancel">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { parseTime } from '@/utils/ruoyi'
export default {
  name: "ArticleManagement",
  dicts: ['sys_normal_disable', 'sys_user_sex'],
  data() {
    return {
      // é®ç½©å±‚
      loading: false,
      // é€‰ä¸­æ•°ç»„
      ids: [],
      // éžå•个禁用
      single: true,
      // éžå¤šä¸ªç¦ç”¨
      multiple: true,
      // æ˜¾ç¤ºæœç´¢æ¡ä»¶
      showSearch: true,
      // æ€»æ¡æ•°
      total: 0,
      // æ–‡ç« è¡¨æ ¼æ•°æ®
      articleList: [
        {
          id: 1,
          title: "如何提高前端开发效率",
          category: "1",
          coverImage: "https://pic.rmb.bdstatic.com/bjh/news/5e5f1b3e7b1a8a7f8a3d6a7d3a6a7d3a.jpeg",
          author: "张三",
          publishTime: "2023-05-10 09:30:00",
          views: 1250,
          status: "1",
          summary: "本文介绍了几种提高前端开发效率的方法和工具",
          content: "<p>前端开发效率的提升对于项目进度至关重要...</p>"
        },
        {
          id: 2,
          title: "Vue3新特性解析",
          category: "2",
          coverImage: "https://pic.rmb.bdstatic.com/bjh/news/8e5f1b3e7b1a8a7f8a3d6a7d3a6a7d3a.jpeg",
          author: "李四",
          publishTime: "2023-05-15 14:20:00",
          views: 3200,
          status: "1",
          summary: "详细解析Vue3的新特性和使用场景",
          content: "<p>Vue3带来了许多令人兴奋的新特性...</p>"
        },
        {
          id: 3,
          title: "Element UI使用技巧",
          category: "3",
          coverImage: "https://pic.rmb.bdstatic.com/bjh/news/9e5f1b3e7b1a8a7f8a3d6a7d3a6a7d3a.jpeg",
          author: "王五",
          publishTime: "2023-05-20 10:15:00",
          views: 890,
          status: "0",
          summary: "分享一些Element UI的高级使用技巧",
          content: "<p>Element UI作为流行的UI框架,有许多实用技巧...</p>"
        },
        {
          id: 4,
          title: "前端性能优化指南",
          category: "1",
          coverImage: "https://pic.rmb.bdstatic.com/bjh/news/7e5f1b3e7b1a8a7f8a3d6a7d3a6a7d3a.jpeg",
          author: "赵六",
          publishTime: "2023-05-25 16:45:00",
          views: 4500,
          status: "1",
          summary: "全面的前端性能优化方法和实践",
          content: "<p>性能优化是前端开发中永恒的话题...</p>"
        },
        {
          id: 5,
          title: "TypeScript入门教程",
          category: "2",
          coverImage: "https://pic.rmb.bdstatic.com/bjh/news/6e5f1b3e7b1a8a7f8a3d6a7d3a6a7d3a.jpeg",
          author: "钱七",
          publishTime: "2023-06-01 11:10:00",
          views: 2100,
          status: "1",
          summary: "从零开始学习TypeScript",
          content: "<p>TypeScript作为JavaScript的超集越来越受欢迎...</p>"
        }
      ],
      // å¼¹å‡ºå±‚标题
      title: "",
      // æ˜¯å¦æ˜¾ç¤ºå¼¹å‡ºå±‚
      open: false,
      // æŸ¥è¯¢å‚æ•°
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        title: undefined,
        category: undefined,
        status: undefined
      },
      // è¡¨å•参数
      form: {},
      // è¡¨å•校验
      rules: {
        title: [
          { required: true, message: "文章标题不能为空", trigger: "blur" }
        ],
        category: [
          { required: true, message: "文章分类不能为空", trigger: "change" }
        ],
        status: [
          { required: true, message: "状态不能为空", trigger: "change" }
        ],
        summary: [
          { required: true, message: "文章摘要不能为空", trigger: "blur" }
        ],
        content: [
          { required: true, message: "文章内容不能为空", trigger: "blur" }
        ]
      },
      // æ–‡ç« åˆ†ç±»é€‰é¡¹
      categoryOptions: [
        { value: "1", label: "技术文章" },
        { value: "2", label: "教程指南" },
        { value: "3", label: "经验分享" },
        { value: "4", label: "行业资讯" }
      ],
      // çŠ¶æ€é€‰é¡¹
      statusOptions: [
        { value: "0", label: "草稿" },
        { value: "1", label: "已发布" },
        { value: "2", label: "已下架" }
      ]
    };
  },
  computed: {
    filteredArticleList() {
      let list = [...this.articleList];
      if (this.queryParams.title) {
        list = list.filter(item =>
          item.title.includes(this.queryParams.title)
        );
      }
      if (this.queryParams.category) {
        list = list.filter(item =>
          item.category === this.queryParams.category
        );
      }
      if (this.queryParams.status) {
        list = list.filter(item =>
          item.status === this.queryParams.status
        );
      }
      return list;
    }
  },
  created() {
    this.total = this.articleList.length;
  },
  methods: {
    // è§£æžæ—¶é—´
    parseTime,
    /** æŸ¥è¯¢æ–‡ç« åˆ—表 */
    getList() {
      this.loading = true;
      setTimeout(() => {
        this.loading = false;
      }, 500);
    },
    /** æœç´¢æŒ‰é’®æ“ä½œ */
    handleQuery() {
      this.queryParams.pageNum = 1;
    },
    /** é‡ç½®æŒ‰é’®æ“ä½œ */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    // å¤šé€‰æ¡†é€‰ä¸­æ•°æ®
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id);
      this.single = selection.length !== 1;
      this.multiple = !selection.length;
    },
    /** æ–°å¢žæŒ‰é’®æ“ä½œ */
    handleAdd() {
      this.reset();
      this.open = true;
      this.title = "添加文章";
    },
    /** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
    handleUpdate(row) {
      this.reset();
      const id = row.id || this.ids;
      const article = this.articleList.find(item => item.id === id);
      this.form = Object.assign({}, article);
      this.open = true;
      this.title = "修改文章";
    },
    /** æäº¤æŒ‰é’® */
    submitForm() {
      this.$refs["form"].validate(valid => {
        if (valid) {
          if (this.form.id != null) {
            // æ¨¡æ‹Ÿä¿®æ”¹æ–‡ç« 
            const index = this.articleList.findIndex(item => item.id === this.form.id);
            if (index !== -1) {
              this.articleList.splice(index, 1, this.form);
            }
            this.$modal.msgSuccess("修改成功");
          } else {
            // æ¨¡æ‹Ÿæ–°å¢žæ–‡ç« 
            this.form.id = Math.max(...this.articleList.map(item => item.id)) + 1;
            this.form.publishTime = new Date().toLocaleString();
            this.form.views = 0;
            this.articleList.unshift(this.form);
            this.total = this.articleList.length;
            this.$modal.msgSuccess("新增成功");
          }
          this.open = false;
        }
      });
    },
    /** åˆ é™¤æŒ‰é’®æ“ä½œ */
    handleDelete(row) {
      const articleIds = row.id || this.ids;
      this.$modal.confirm('是否确认删除文章标题为"' + row.title + '"的数据项?').then(() => {
        // æ¨¡æ‹Ÿåˆ é™¤æ–‡ç« 
        this.articleList = this.articleList.filter(item => item.id !== articleIds);
        this.total = this.articleList.length;
        this.$modal.msgSuccess("删除成功");
      }).catch(() => {});
    },
    /** å–消按钮 */
    cancel() {
      this.open = false;
      this.reset();
    },
    /** è¡¨å•重置 */
    reset() {
      this.form = {
        id: undefined,
        title: undefined,
        category: undefined,
        coverImage: undefined,
        author: "管理员",
        publishTime: undefined,
        views: 0,
        status: "1",
        summary: undefined,
        content: undefined
      };
      this.resetForm("form");
    },
    // å°é¢å›¾ä¸Šä¼ å¤„理
    handleCoverChange(file) {
      const reader = new FileReader();
      reader.onload = (e) => {
        this.form.coverImage = e.target.result;
      };
      reader.readAsDataURL(file.raw);
    }
  }
};
</script>
<style lang="scss" scoped>
.ArticleManagement {
  padding: 20px;
}
.avatar-uploader ::v-deep .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader ::v-deep .el-upload:hover {
  border-color: #409EFF;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>
src/views/knowledge/drug/index.vue
@@ -1,27 +1,1077 @@
<template>
  <div>
药品知识库
  <div class="DrugKnowledgeManagement">
    <!-- å·¦ä¾§æ  -->
    <div class="sidecolumn">
      <div class="sidecolumn-top">
        <div class="top-wj">药品分类</div>
        <div class="top-tj" @click="dialogFormVisible = true">+添加</div>
      </div>
      <div class="center-ss">
        <el-input
          placeholder="请输入内容"
          v-model="sidecolumnval"
          class="input-with-select"
          size="medium">
        </el-input>
      </div>
      <div class="head-container" style="margin-top: 20px">
        <el-tree
          :data="deptOptions"
          :props="defaultProps"
          :expand-on-click-node="false"
          :filter-node-method="filterNode"
          ref="tree"
          node-key="id"
          default-expand-all
          highlight-current
          @node-click="handleNodeClick">
          <span class="custom-tree-node" slot-scope="{ node, data }">
            <span>{{ node.label }}</span>
            <span v-if="data.id > 0">
              <el-button
                type="text"
                icon="el-icon-delete"
                circle
                size="mini"
                @click="() => remove(node, data)">
              </el-button>
            </span>
            <span v-if="data.id > 0">
              <el-button
                type="text"
                circle
                size="mini"
                @click="() => altertag(node, data)">
                <span class="button-textxg"><i class="el-icon-edit-outline"></i></span>
              </el-button>
            </span>
          </span>
        </el-tree>
      </div>
    </div>
    <!-- å³ä¾§æ•°æ® -->
    <div class="leftvlue">
      <div class="leftvlue-bg">
        <el-row :gutter="20">
          <!--药品数据-->
          <el-col :span="24" :xs="24">
            <el-form
              :model="queryParams"
              ref="queryForm"
              size="small"
              :inline="true"
              v-show="showSearch"
              label-width="98px">
              <el-form-item label="药品名称" prop="drugName">
                <el-input
                  v-model="queryParams.drugName"
                  placeholder="请输入"
                  clearable
                  style="width: 200px"
                  @keyup.enter.native="handleQuery"/>
              </el-form-item>
              <el-form-item label="药品分类" prop="categoryId">
                <el-select v-model="queryParams.categoryId" placeholder="请选择">
                  <el-option
                    v-for="item in drugCategories"
                    :key="item.id"
                    :label="item.categoryName"
                    :value="item.id">
                  </el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="药品类型" prop="drugType">
                <el-select v-model="queryParams.drugType" placeholder="请选择">
                  <el-option
                    v-for="item in drugTypes"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value">
                  </el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="是否处方药" prop="isPrescription">
                <el-select v-model="queryParams.isPrescription" placeholder="请选择">
                  <el-option
                    v-for="item in prescriptionOptions"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value">
                  </el-option>
                </el-select>
              </el-form-item>
              <el-form-item>
                <el-button
                  type="primary"
                  icon="el-icon-search"
                  size="medium"
                  @click="handleQuery">搜索</el-button>
                <el-button
                  icon="el-icon-refresh"
                  size="medium"
                  @click="resetQuery">重置</el-button>
              </el-form-item>
            </el-form>
            <el-row :gutter="10" class="mb8">
              <el-col :span="1.5">
                <el-button
                  type="primary"
                  plain
                  icon="el-icon-plus"
                  size="medium"
                  @click="handleAdd">新增</el-button>
              </el-col>
              <el-col :span="1.5">
                <el-button
                  type="danger"
                  plain
                  icon="el-icon-delete"
                  size="medium"
                  :disabled="multiple"
                  @click="handleDelete">删除</el-button>
              </el-col>
            </el-row>
            <el-table
              v-loading="loading"
              :data="filteredDrugList"
              @selection-change="handleSelectionChange">
              <el-table-column type="selection" width="50" align="center" />
              <el-table-column
                label="药品名称"
                fixed
                align="center"
                key="drugName"
                prop="drugName"
                :show-overflow-tooltip="true">
              </el-table-column>
              <el-table-column
                label="通用名"
                align="center"
                key="genericName"
                prop="genericName"
                :show-overflow-tooltip="true"
                width="200"/>
              <el-table-column
                label="药品分类"
                align="center"
                key="categoryName"
                prop="categoryName"
                :show-overflow-tooltip="true"/>
              <el-table-column
                label="药品类型"
                align="center"
                key="drugType"
                prop="drugType">
                <template slot-scope="scope">
                  <dict-tag :options="drugTypes" :value="scope.row.drugType"/>
                </template>
              </el-table-column>
              <el-table-column
                label="是否处方药"
                align="center"
                key="isPrescription"
                prop="isPrescription">
                <template slot-scope="scope">
                  <dict-tag :options="prescriptionOptions" :value="scope.row.isPrescription"/>
                </template>
              </el-table-column>
              <el-table-column
                label="规格"
                align="center"
                key="specification"
                prop="specification"
                width="120"/>
              <el-table-column
                label="单位"
                align="center"
                key="unit"
                prop="unit"
                width="80"/>
              <el-table-column
                label="生产厂家"
                align="center"
                key="manufacturer"
                prop="manufacturer"
                width="150"/>
              <el-table-column
                label="批准文号"
                align="center"
                key="approvalNumber"
                prop="approvalNumber"
                width="150"/>
              <el-table-column
                label="操作"
                fixed="right"
                align="center"
                width="200"
                class-name="small-padding fixed-width">
                <template slot-scope="scope">
                  <el-button
                    size="medium"
                    type="text"
                    @click="handleUpdate(scope.row)">
                    <span class="button-textxg"><i class="el-icon-edit"></i>修改</span>
                  </el-button>
                  <el-button
                    size="medium"
                    type="text"
                    @click="handleDelete(scope.row)">
                    <span class="button-textsc"><i class="el-icon-delete"></i>删除</span>
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
            <pagination
              v-show="total>0"
              :total="total"
              :page.sync="queryParams.pageNum"
              :limit.sync="queryParams.pageSize"
              @pagination="getList"/>
          </el-col>
        </el-row>
        <!-- æ·»åŠ æˆ–ä¿®æ”¹è¯å“å¯¹è¯æ¡† -->
        <el-dialog
          :title="title"
          :visible.sync="drugOpen"
          :close-on-click-modal="false"
          width="900px"
          append-to-body>
          <el-form
            ref="drugForm"
            :model="drugForm"
            :rules="rules"
            label-width="100px">
            <div class="headline">
              <div class="basics">基础信息</div>
            </div>
            <el-divider></el-divider>
            <el-row>
              <el-col :span="12">
                <el-form-item label="药品名称" prop="drugName">
                  <el-input
                    v-model="drugForm.drugName"
                    placeholder="请输入药品名称"
                    maxlength="40"/>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="通用名" prop="genericName">
                  <el-input
                    v-model="drugForm.genericName"
                    placeholder="请输入药品通用名"
                    maxlength="40"/>
                </el-form-item>
              </el-col>
            </el-row>
            <el-row>
              <el-col :span="12">
                <el-form-item label="药品分类" prop="categoryId">
                  <el-select
                    style="width: 300px;"
                    v-model="drugForm.categoryId"
                    size="medium"
                    filterable
                    placeholder="请选择分类">
                    <el-option-group
                      v-for="group in deptOptions"
                      :key="group.id"
                      :label="group.categoryName">
                      <el-option
                        v-for="item in group.children"
                        :key="item.id"
                        :label="item.categoryName"
                        :value="item.id">
                      </el-option>
                    </el-option-group>
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="药品类型" prop="drugType">
                  <el-select v-model="drugForm.drugType" placeholder="请选择药品类型">
                    <el-option
                      v-for="item in drugTypes"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value">
                    </el-option>
                  </el-select>
                </el-form-item>
              </el-col>
            </el-row>
            <el-row>
              <el-col :span="12">
                <el-form-item label="是否处方药" prop="isPrescription">
                  <el-radio-group v-model="drugForm.isPrescription">
                    <el-radio
                      v-for="(item, index) in prescriptionOptions"
                      :label="item.value">{{ item.label }}</el-radio>
                  </el-radio-group>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="批准文号" prop="approvalNumber">
                  <el-input
                    v-model="drugForm.approvalNumber"
                    placeholder="请输入批准文号"
                    maxlength="40"/>
                </el-form-item>
              </el-col>
            </el-row>
            <el-row>
              <el-col :span="12">
                <el-form-item label="规格" prop="specification">
                  <el-input
                    v-model="drugForm.specification"
                    placeholder="请输入药品规格"
                    maxlength="40"/>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="单位" prop="unit">
                  <el-select v-model="drugForm.unit" placeholder="请选择单位">
                    <el-option
                      v-for="item in unitOptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value">
                    </el-option>
                  </el-select>
                </el-form-item>
              </el-col>
            </el-row>
            <el-row>
              <el-col :span="12">
                <el-form-item label="生产厂家" prop="manufacturer">
                  <el-input
                    v-model="drugForm.manufacturer"
                    placeholder="请输入生产厂家"
                    maxlength="100"/>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="条形码" prop="barcode">
                  <el-input
                    v-model="drugForm.barcode"
                    placeholder="请输入条形码"
                    maxlength="40"/>
                </el-form-item>
              </el-col>
            </el-row>
            <div class="headline">
              <div class="basics">药品成分</div>
            </div>
            <el-divider></el-divider>
            <el-form-item prop="ingredients">
              <el-input
                type="textarea"
                :rows="3"
                placeholder="请输入药品主要成分"
                v-model="drugForm.ingredients">
              </el-input>
            </el-form-item>
            <div class="headline">
              <div class="basics">用法用量</div>
            </div>
            <el-divider></el-divider>
            <el-form-item prop="usageDosage">
              <el-input
                type="textarea"
                :rows="3"
                placeholder="请输入用法用量说明"
                v-model="drugForm.usageDosage">
              </el-input>
            </el-form-item>
            <div class="headline">
              <div class="basics">不良反应</div>
            </div>
            <el-divider></el-divider>
            <el-form-item prop="adverseReactions">
              <el-input
                type="textarea"
                :rows="3"
                placeholder="请输入不良反应说明"
                v-model="drugForm.adverseReactions">
              </el-input>
            </el-form-item>
            <div class="headline">
              <div class="basics">禁忌</div>
            </div>
            <el-divider></el-divider>
            <el-form-item prop="contraindications">
              <el-input
                type="textarea"
                :rows="3"
                placeholder="请输入禁忌说明"
                v-model="drugForm.contraindications">
              </el-input>
            </el-form-item>
            <div class="headline">
              <div class="basics">注意事项</div>
            </div>
            <el-divider></el-divider>
            <el-form-item prop="precautions">
              <el-input
                type="textarea"
                :rows="3"
                placeholder="请输入注意事项"
                v-model="drugForm.precautions">
              </el-input>
            </el-form-item>
          </el-form>
          <div slot="footer" class="dialog-footer">
            <el-button type="primary" @click="submitForm">保 å­˜</el-button>
            <el-button @click="cancel">关 é—­</el-button>
          </div>
        </el-dialog>
      </div>
    </div>
    <!-- æ·»åŠ ç±»åˆ«å¼¹æ¡† -->
    <el-dialog title="新增类别" width="30%" :visible.sync="dialogFormVisible">
      <div style="text-align: center; margin-bottom: 20px">
        <el-radio-group v-model="radio">
          <el-radio-button label="主分类"></el-radio-button>
          <el-radio-button label="子分类"></el-radio-button>
        </el-radio-group>
      </div>
      <el-divider></el-divider>
      <el-form :model="classifyform">
        <el-form-item label="请选择药品大类" v-if="radio == '子分类'">
          <el-select v-model="classifyform.pid" placeholder="请选择">
            <el-option
              v-for="item in deptOptions"
              :key="item.id"
              :label="item.categoryName"
              :value="item.id">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="请输入类别名称">
          <el-input
            v-model="classifyform.categoryName"
            autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="getDeptTree()">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="submitsidecolumn">ç¡® å®š</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
export default {
  data () {
  name: "DrugKnowledge",
  dicts: ["sys_normal_disable", "sys_user_sex"],
  data() {
    return {
      // é®ç½©å±‚
      loading: false,
      // é€‰ä¸­æ•°ç»„
      ids: [],
      // éžå•个禁用
      single: true,
      // éžå¤šä¸ªç¦ç”¨
      multiple: true,
      // æ˜¾ç¤ºæœç´¢æ¡ä»¶
      showSearch: true,
      // æ€»æ¡æ•°
      total: 0,
      idds: "",
      classifyform: {  // æ·»åŠ è¿™ä¸ªå¯¹è±¡
        id: undefined,
        pid: undefined,
        categoryName: undefined
      },
      amendtag: false, //是否修改类别
      dialogFormVisible: false, //修改添加类别弹框
      deleteVisible: false, //分类删除弹框
      deletefenl: "高血压", //删除项
      radio: "主分类",
      // è¡¨æ ¼æ•°æ®
      drugList: [
        {
          id: 1,
          drugName: "阿莫西林胶囊",
          genericName: "阿莫西林",
          categoryId: 101,
          categoryName: "抗生素",
          drugType: "1",
          isPrescription: "1",
          specification: "0.25g×24粒",
          unit: "盒",
          manufacturer: "华北制药",
          approvalNumber: "国药准字H13024176",
          barcode: "6923450601234",
          ingredients: "阿莫西林",
          usageDosage: "口服。成人一次0.5g,每6~8小时1次,一日剂量不超过4g。",
          adverseReactions: "1.恶心、呕吐、腹泻及假膜性肠炎等胃肠道反应。2.皮疹、药物热和哮喘等过敏反应。",
          contraindications: "青霉素过敏及青霉素皮肤试验阳性患者禁用。",
          precautions: "1.青霉素类口服药物偶可引起过敏性休克,尤多见于有青霉素或头孢菌素过敏史的患者。2.传染性单核细胞增多症患者应用本品易发生皮疹,应避免使用。"
        },
        {
          id: 2,
          drugName: "板蓝根颗粒",
          genericName: "板蓝根",
          categoryId: 302,
          categoryName: "片剂",
          drugType: "3",
          isPrescription: "0",
          specification: "10g×20袋",
          unit: "盒",
          manufacturer: "白云山制药",
          approvalNumber: "国药准字Z44023445",
          barcode: "6923450605678",
          ingredients: "板蓝根",
          usageDosage: "开水冲服。一次5~10g,一日3~4次。",
          adverseReactions: "尚不明确。",
          contraindications: "尚不明确。",
          precautions: "1.忌烟、酒及辛辣、生冷、油腻食物。2.不宜在服药期间同时服用滋补性中药。"
        },
        {
          id: 3,
          drugName: "复方丹参片",
          genericName: "复方丹参",
          categoryId: 303,
          categoryName: "胶囊",
          drugType: "3",
          isPrescription: "0",
          specification: "60片",
          unit: "瓶",
          manufacturer: "同仁堂",
          approvalNumber: "国药准字Z11020672",
          barcode: "6923450609012",
          ingredients: "丹参、三七、冰片",
          usageDosage: "口服。一次3片,一日3次。",
          adverseReactions: "尚不明确。",
          contraindications: "孕妇禁用。",
          precautions: "1.忌食生冷、辛辣、油腻食物。2.服药期间如有不适,应立即停药并就医。"
        },
        {
          id: 4,
          drugName: "布洛芬缓释胶囊",
          genericName: "布洛芬",
          categoryId: 102,
          categoryName: "解热镇痛药",
          drugType: "1",
          isPrescription: "0",
          specification: "0.3g×20粒",
          unit: "盒",
          manufacturer: "中美史克",
          approvalNumber: "国药准字H10900089",
          barcode: "6923450612345",
          ingredients: "布洛芬",
          usageDosage: "口服。成人一次1粒,一日2次(早晚各一次)。",
          adverseReactions: "1.少数病人可出现恶心、呕吐、胃烧灼感或轻度消化不良、胃肠道溃疡及出血、转氨酶升高、头痛、头晕、耳鸣、视力模糊、精神紧张、嗜睡、下肢水肿或体重骤增。",
          contraindications: "1.对其他非甾体抗炎药过敏者禁用。2.孕妇及哺乳期妇女禁用。3.对阿司匹林过敏的哮喘患者禁用。",
          precautions: "1.本品为对症治疗药,不宜长期或大量使用,用于止痛不得超过5天,用于解热不得超过3天,如症状不缓解,请咨询医师或药师。2.不能同时服用其他含有解热镇痛药的药品(如某些复方抗感冒药)。"
        },
        {
          id: 5,
          drugName: "六味地黄丸",
          genericName: "六味地黄",
          categoryId: 201,
          categoryName: "补益药",
          drugType: "3",
          isPrescription: "0",
          specification: "200丸",
          unit: "瓶",
          manufacturer: "同仁堂",
          approvalNumber: "国药准字Z11020061",
          barcode: "6923450615678",
          ingredients: "熟地黄、酒萸肉、牡丹皮、山药、茯苓、泽泻",
          usageDosage: "口服。一次8丸,一日3次。",
          adverseReactions: "尚不明确。",
          contraindications: "尚不明确。",
          precautions: "1.忌辛辣食物。2.不宜在服药期间服感冒药。3.服药期间出现食欲不振,胃脘不适,大便稀,腹痛等症状时,应去医院就诊。"
        }
      ],
      // å¼¹å‡ºå±‚标题
      title: "",
      // æ˜¯å¦æ˜¾ç¤ºå¼¹å‡ºå±‚
      drugOpen: false,
      // æ—¥æœŸèŒƒå›´
      dateRange: [],
      // è¯å“åˆ†ç±»é€‰é¡¹
      drugCategories: [
        { id: 101, categoryName: "抗生素" },
        { id: 102, categoryName: "解热镇痛药" },
        { id: 103, categoryName: "心血管药物" },
        { id: 201, categoryName: "补益药" },
        { id: 202, categoryName: "清热药" },
        { id: 203, categoryName: "祛湿药" },
        { id: 301, categoryName: "丸剂" },
        { id: 302, categoryName: "片剂" },
        { id: 303, categoryName: "胶囊" }
      ],
      // æ·»åŠ ã€ä¿®æ”¹å‚æ•°
      drugForm: {},
      deptOptions: [
        {
          id: 1,
          categoryName: "西药",
          children: [
            { id: 101, categoryName: "抗生素" },
            { id: 102, categoryName: "解热镇痛药" },
            { id: 103, categoryName: "心血管药物" }
          ]
        },
        {
          id: 2,
          categoryName: "中药",
          children: [
            { id: 201, categoryName: "补益药" },
            { id: 202, categoryName: "清热药" },
            { id: 203, categoryName: "祛湿药" }
          ]
        },
        {
          id: 3,
          categoryName: "中成药",
          children: [
            { id: 301, categoryName: "丸剂" },
            { id: 302, categoryName: "片剂" },
            { id: 303, categoryName: "胶囊" }
          ]
        }
      ],
      defaultProps: {
        children: "children",
        label: "categoryName",
      },
      sidecolumnform: {}, //添加类别表单
      dialogFormVisible: false, //添加类别弹框
      sidecolumnval: "", //类别搜索
      // æŸ¥è¯¢å‚æ•°
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        drugName: undefined,
        categoryId: undefined,
        drugType: undefined,
        isPrescription: undefined
      },
      // è¯å“ç±»åž‹é€‰é¡¹
      drugTypes: [
        { value: "1", label: "西药" },
        { value: "2", label: "中药" },
        { value: "3", label: "中成药" },
        { value: "4", label: "生物制品" },
        { value: "5", label: "其他" }
      ],
      // æ˜¯å¦å¤„方药选项
      prescriptionOptions: [
        { value: "1", label: "处方药" },
        { value: "0", label: "非处方药" }
      ],
      // å•位选项
      unitOptions: [
        { value: "盒", label: "盒" },
        { value: "瓶", label: "瓶" },
        { value: "支", label: "支" },
        { value: "袋", label: "袋" },
        { value: "片", label: "片" },
        { value: "粒", label: "粒" },
        { value: "g", label: "克" },
        { value: "ml", label: "毫升" }
      ],
      // è¡¨å•校验
      rules: {
        drugName: [
          { required: true, message: "药品名称不能为空", trigger: "blur" }
        ],
        genericName: [
          { required: true, message: "通用名不能为空", trigger: "blur" }
        ],
        categoryId: [
          { required: true, message: "药品分类不能为空", trigger: "blur" }
        ],
        drugType: [
          { required: true, message: "药品类型不能为空", trigger: "blur" }
        ],
        isPrescription: [
          { required: true, message: "是否处方药不能为空", trigger: "blur" }
        ],
        specification: [
          { required: true, message: "规格不能为空", trigger: "blur" }
        ],
        unit: [
          { required: true, message: "单位不能为空", trigger: "blur" }
        ],
        approvalNumber: [
          { required: true, message: "批准文号不能为空", trigger: "blur" }
        ],
        manufacturer: [
          { required: true, message: "生产厂家不能为空", trigger: "blur" }
        ]
      }
    };
  },
  computed: {
    filteredDrugList() {
      let list = [...this.drugList];
      if (this.queryParams.drugName) {
        list = list.filter(item =>
          item.drugName.includes(this.queryParams.drugName)
        );
      }
      if (this.queryParams.categoryId) {
        list = list.filter(item =>
          item.categoryId == this.queryParams.categoryId
        );
      }
      if (this.queryParams.drugType) {
        list = list.filter(item =>
          item.drugType == this.queryParams.drugType
        );
      }
      if (this.queryParams.isPrescription) {
        list = list.filter(item =>
          item.isPrescription == this.queryParams.isPrescription
        );
      }
      return list;
    }
  },
  created () {
  watch: {
    // æ ¹æ®åç§°ç­›é€‰éƒ¨é—¨æ ‘
    sidecolumnval(val) {
      this.$refs.tree.filter(val);
    }
  },
  created() {
    // åˆå§‹åŒ–数据
    this.total = this.drugList.length;
  },
  methods: {
    /** æŸ¥è¯¢è¯å“åˆ—表 */
    getList() {
      this.loading = true;
      setTimeout(() => {
        this.loading = false;
      }, 500);
    },
    /** æŸ¥è¯¢è¯å“åˆ†ç±»æ ‘结构 */
    getDeptTree() {
      this.dialogFormVisible = false;
    },
    // ç­›é€‰èŠ‚ç‚¹
    filterNode(value, data) {
      if (!value) return true;
      return data.categoryName.indexOf(value) !== -1;
    },
    // æ·»åŠ ç±»åˆ«æ ‘
    submitsidecolumn() {
      if (this.classifyform.id) {
        // æ¨¡æ‹Ÿä¿®æ”¹åˆ†ç±»
        const category = this.findCategory(this.classifyform.id);
        if (category) {
          category.categoryName = this.classifyform.categoryName;
          if (this.classifyform.pid) {
            category.pid = this.classifyform.pid;
          }
        }
        this.$modal.msgSuccess("修改成功");
        this.classifyform = {};
        this.dialogFormVisible = false;
        return;
      }
      // æ¨¡æ‹Ÿæ–°å¢žåˆ†ç±»
      const newCategory = {
        id: Math.max(...this.deptOptions.flatMap(group =>
          [group.id, ...(group.children || []).map(child => child.id)]
        )) + 1,
        categoryName: this.classifyform.categoryName,
        pid: this.radio === "子分类" ? this.classifyform.pid : null
      };
      if (this.radio === "子分类") {
        const parent = this.findCategory(this.classifyform.pid);
        if (parent) {
          if (!parent.children) parent.children = [];
          parent.children.push(newCategory);
        }
      } else {
        newCategory.children = [];
        this.deptOptions.push(newCategory);
      }
      this.$modal.msgSuccess("新增成功");
      this.classifyform = {};
      this.dialogFormVisible = false;
    },
    findCategory(id) {
      for (const group of this.deptOptions) {
        if (group.id === id) return group;
        if (group.children) {
          for (const child of group.children) {
            if (child.id === id) return child;
          }
        }
      }
      return null;
    },
    remove(a, b) {
      if (b.pid) {
        this.$modal
          .confirm('是否确认删除分类项为"' + b.categoryName + '"的数据项?')
          .then(() => {
            // æ¨¡æ‹Ÿåˆ é™¤å­åˆ†ç±»
            const parent = this.findCategory(b.pid);
            if (parent && parent.children) {
              parent.children = parent.children.filter(child => child.id !== b.id);
            }
            this.$modal.msgSuccess("删除成功");
          })
          .catch(() => {});
      } else {
        this.$modal
          .confirm(
            '是否确认删除一级分类"' +
              b.categoryName +
              '"?删除后其下分类将归类‘未分类’'
          )
          .then(() => {
            // æ¨¡æ‹Ÿåˆ é™¤ä¸»åˆ†ç±»
            this.deptOptions = this.deptOptions.filter(group => group.id !== b.id);
            this.$modal.msgSuccess("删除成功");
          })
          .catch(() => {});
      }
    },
    altertag(a, b) {
      this.dialogFormVisible = true;
      if (!b.pid) {
        this.radio = "主分类";
      } else {
        this.radio = "子分类";
      }
      this.classifyform = JSON.parse(JSON.stringify(b));
      this.dialogFormVisible = true;
    },
    handleNodeClick(data) {
      this.queryParams.categoryId = data.id;
    },
    // å–消按钮
    cancel() {
      this.drugForm = {};
      this.drugOpen = false;
      this.reset();
    },
    // è¡¨å•重置
    reset() {
      this.drugForm = {
        id: undefined,
        drugName: undefined,
        genericName: undefined,
        categoryId: undefined,
        drugType: undefined,
        isPrescription: undefined,
        specification: undefined,
        unit: undefined,
        manufacturer: undefined,
        approvalNumber: undefined,
        barcode: undefined,
        ingredients: undefined,
        usageDosage: undefined,
        adverseReactions: undefined,
        contraindications: undefined,
        precautions: undefined
      };
    },
    /** æœç´¢æŒ‰é’®æ“ä½œ */
    handleQuery() {
      this.queryParams.pageNum = 1;
    },
    /** é‡ç½®æŒ‰é’®æ“ä½œ */
    resetQuery() {
      this.dateRange = [];
      this.resetForm("queryForm");
      this.queryParams = {
        pageNum: 1,
        pageSize: 10,
        drugName: undefined,
        categoryId: undefined,
        drugType: undefined,
        isPrescription: undefined
      };
      this.$refs.tree.setCurrentKey(null);
    },
    // å¤šé€‰æ¡†é€‰ä¸­æ•°æ®
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id);
      this.single = selection.length != 1;
      this.multiple = !selection.length;
    },
    /** æ–°å¢žæŒ‰é’®æ“ä½œ */
    handleAdd() {
      this.reset();
      this.title = "新增药品";
      this.drugForm = {};
      this.drugOpen = true;
    },
    /** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
    handleUpdate(row) {
      this.reset();
      this.title = "修改药品信息";
      this.drugForm = Object.assign({}, row);
      this.drugOpen = true;
    },
    /** æäº¤æŒ‰é’® */
    submitForm: function() {
      this.$refs["drugForm"].validate(valid => {
        if (valid) {
          if (this.drugForm.id != undefined) {
            // æ¨¡æ‹Ÿä¿®æ”¹è¯å“
            const index = this.drugList.findIndex(item => item.id === this.drugForm.id);
            if (index !== -1) {
              this.drugList.splice(index, 1, this.drugForm);
            }
            this.$modal.msgSuccess("修改成功");
          } else {
            // æ¨¡æ‹Ÿæ–°å¢žè¯å“
            this.drugForm.id = Math.max(...this.drugList.map(item => item.id)) + 1;
            this.drugList.unshift(this.drugForm);
            this.total = this.drugList.length;
            this.$modal.msgSuccess("新增成功");
          }
          this.drugOpen = false;
        }
      });
    },
    /** åˆ é™¤æŒ‰é’®æ“ä½œ */
    handleDelete(row) {
      const drugIds = row.id || this.ids;
      this.$modal
        .confirm('是否确认删除药品名称为"' + row.drugName + '"的数据项?')
        .then(() => {
          // æ¨¡æ‹Ÿåˆ é™¤è¯å“
          this.drugList = this.drugList.filter(item => item.id !== drugIds);
          this.total = this.drugList.length;
          this.$modal.msgSuccess("删除成功");
        })
        .catch(() => {});
    }
  }
}
};
</script>
<style lang='scss' scoped>
<style lang="scss" scoped>
.DrugKnowledgeManagement {
  display: flex;
}
.sidecolumn {
  width: 300px;
  min-height: 100vh;
  text-align: center;
  margin-top: 20px;
  margin: 20px;
  padding: 30px;
  background: #fff;
  border: 1px solid #dcdfe6;
  -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12),
    0 0 6px 0 rgba(0, 0, 0, 0.04);
  .sidecolumn-top {
    display: flex;
    justify-content: space-between;
    .top-wj {
      font-size: 20px;
    }
    .top-tj {
      font-size: 18px;
      color: rgb(0, 89, 255);
      cursor: pointer;
    }
  }
  .center-ss {
    margin-top: 30px;
    .input-with-select {
      height: 40px !important;
    }
  }
  .bottom-fl {
    margin-top: 30px;
    display: center !important;
  }
}
.headline {
  display: flex;
  justify-content: space-between;
  font-size: 20px;
  border-left: 4px solid #41a1be;
  padding-left: 5px;
  margin: 15px 0;
}
.leftvlue {
  width: 80%;
  margin-top: 20px;
  padding: 30px;
  background: #ffff;
  border: 1px solid #dcdfe6;
  -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12),
    0 0 6px 0 rgba(0, 0, 0, 0.04);
}
::v-deep .el-tree-node__content {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  height: 46px;
  font-size: 20px;
  cursor: pointer;
}
::v-deep .el-tree {
  position: relative;
  cursor: default;
  border-radius: 5px;
  background: #eff8fe;
  color: #606266;
  border: 1px solid #bbe1fa;
  -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12),
    0 0 6px 0 rgba(0, 0, 0, 0.04);
}
::v-deep
  .el-tree--highlight-current
  .el-tree-node.is-current
  > .el-tree-node__content {
  background-color: #7799fb;
  color: #fff;
}
::v-deep .el-button--mini.is-circle {
  padding: 7px;
  margin: 0;
  color: red;
}
.button-text {
  color: rgb(70, 204, 238);
}
.button-textcs {
  color: rgb(39, 167, 67);
}
.button-textxg {
  color: rgb(35, 81, 233);
}
.button-textsc {
  color: rgb(235, 23, 23);
}
</style>
src/views/login.vue
@@ -136,7 +136,7 @@
        smsCode: "",
        rememberMe: false,
        code: "",
        orgid: "1",
        orgid: "47255004333112711A1001",
      },
      options: [
        { value: "1", label: "景宁畲族自治县人民医院" },
@@ -296,7 +296,7 @@
          const loginData = {
            username: this.loginForm.username,
            orgid: "1",
            orgid: "47255004333112711A1001",
            loginType: this.loginMethod
          };
@@ -311,7 +311,7 @@
          this.$store
            .dispatch("Login", loginData)
            .then(() => {
              this.$router.push({ path: this.redirect || "/" }).catch(() => {});
              this.$router.push({ path: this.redirect || "/followvisit/discharge" }).catch(() => {});
            })
            .catch(() => {
              this.loading = false;
src/views/system/group/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1343 @@
<template>
  <div class="TeamManagement">
    <!-- å›¢é˜Ÿç®¡ç† -->
    <el-tabs v-model="activeTab" type="card">
      <el-tab-pane label="团队管理" name="team">
        <el-row :gutter="20">
          <el-col :span="24" :xs="24">
            <el-form :model="teamQueryParams" ref="teamQueryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
              <el-form-item label="团队名称" prop="name">
                <el-input
                  v-model="teamQueryParams.name"
                  placeholder="请输入团队名称"
                  clearable
                  style="width: 200px"
                  @keyup.enter.native="handleTeamQuery"
                />
              </el-form-item>
              <el-form-item label="团队状态" prop="status">
                <el-select v-model="teamQueryParams.status" placeholder="请选择状态" clearable style="width: 200px">
                  <el-option
                    v-for="item in teamStatusOptions"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
              <el-form-item>
                <el-button type="primary" icon="el-icon-search" size="medium" @click="handleTeamQuery">搜索</el-button>
                <el-button icon="el-icon-refresh" size="medium" @click="resetTeamQuery">重置</el-button>
              </el-form-item>
            </el-form>
            <el-row :gutter="10" class="mb8">
              <el-col :span="1.5">
                <el-button
                  type="primary"
                  plain
                  icon="el-icon-plus"
                  size="medium"
                  @click="handleTeamAdd"
                >新增团队</el-button>
              </el-col>
            </el-row>
            <el-table v-loading="teamLoading" :data="filteredTeamList" @selection-change="handleTeamSelectionChange">
              <el-table-column type="selection" width="50" align="center" />
              <el-table-column label="团队ID" align="center" prop="id" width="80" />
              <el-table-column label="团队名称" align="center" prop="name" :show-overflow-tooltip="true" />
              <el-table-column label="团队组长" align="center" prop="leader" width="120" />
              <el-table-column label="团队成员" align="center" prop="memberCount" width="100">
  <template slot-scope="scope">
    <el-tag>{{ (scope.row.members || []).length }}人</el-tag>
  </template>
</el-table-column>
              <el-table-column label="创建时间" align="center" prop="createTime" width="160">
                <template slot-scope="scope">
                  <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
                </template>
              </el-table-column>
              <el-table-column label="团队状态" align="center" prop="status" width="100">
                <template slot-scope="scope">
                  <dict-tag :options="teamStatusOptions" :value="scope.row.status"/>
                </template>
              </el-table-column>
              <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
                <template slot-scope="scope">
                  <el-button
                    size="mini"
                    type="text"
                    icon="el-icon-view"
                    @click="handleTeamDetail(scope.row)"
                  >详情</el-button>
                  <el-button
                    size="mini"
                    type="text"
                    icon="el-icon-edit"
                    @click="handleTeamUpdate(scope.row)"
                  >编辑</el-button>
                  <el-button
                    size="mini"
                    type="text"
                    icon="el-icon-delete"
                    @click="handleTeamDelete(scope.row)"
                  >删除</el-button>
                </template>
              </el-table-column>
            </el-table>
            <pagination
              v-show="teamTotal>0"
              :total="teamTotal"
              :page.sync="teamQueryParams.pageNum"
              :limit.sync="teamQueryParams.pageSize"
              @pagination="getTeamList"
            />
          </el-col>
        </el-row>
      </el-tab-pane>
      <!-- äººå‘˜åˆ†ç»„ -->
      <el-tab-pane label="人员分组" name="member">
        <el-row :gutter="20">
          <el-col :span="24" :xs="24">
            <el-form :model="memberQueryParams" ref="memberQueryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
              <el-form-item label="成员姓名" prop="name">
                <el-input
                  v-model="memberQueryParams.name"
                  placeholder="请输入成员姓名"
                  clearable
                  style="width: 200px"
                  @keyup.enter.native="handleMemberQuery"
                />
              </el-form-item>
              <el-form-item label="所属团队" prop="teamId">
                <el-select v-model="memberQueryParams.teamId" placeholder="请选择团队" clearable style="width: 200px">
                  <el-option
                    v-for="item in teamList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="成员状态" prop="status">
                <el-select v-model="memberQueryParams.status" placeholder="请选择状态" clearable style="width: 200px">
                  <el-option
                    v-for="item in memberStatusOptions"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
              <el-form-item>
                <el-button type="primary" icon="el-icon-search" size="medium" @click="handleMemberQuery">搜索</el-button>
                <el-button icon="el-icon-refresh" size="medium" @click="resetMemberQuery">重置</el-button>
              </el-form-item>
            </el-form>
            <el-row :gutter="10" class="mb8">
              <el-col :span="1.5">
                <el-button
                  type="primary"
                  plain
                  icon="el-icon-plus"
                  size="medium"
                  @click="handleMemberAdd"
                >新增成员</el-button>
              </el-col>
              <el-col :span="1.5">
                <el-button
                  type="danger"
                  plain
                  icon="el-icon-delete"
                  size="medium"
                  :disabled="multiple"
                  @click="handleMemberDelete"
                >删除</el-button>
              </el-col>
            </el-row>
            <el-table v-loading="memberLoading" :data="filteredMemberList" @selection-change="handleMemberSelectionChange">
              <el-table-column type="selection" width="50" align="center" />
              <el-table-column label="成员ID" align="center" prop="id" width="80" />
              <el-table-column label="成员姓名" align="center" prop="name" :show-overflow-tooltip="true" />
              <el-table-column label="所属团队" align="center" prop="teamName" width="150" />
              <el-table-column label="职位" align="center" prop="position" width="120" />
              <el-table-column label="联系电话" align="center" prop="phone" width="150" />
              <el-table-column label="邮箱" align="center" prop="email" width="200" />
              <el-table-column label="当前工单" align="center" prop="currentWorkOrder" width="120">
                <template slot-scope="scope">
                  <el-tag :type="scope.row.currentWorkOrder ? '' : 'info'">
                    {{ scope.row.currentWorkOrder || '空闲' }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="成员状态" align="center" prop="status" width="100">
                <template slot-scope="scope">
                  <dict-tag :options="memberStatusOptions" :value="scope.row.status"/>
                </template>
              </el-table-column>
              <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
                <template slot-scope="scope">
                  <el-button
                    size="mini"
                    type="text"
                    icon="el-icon-edit"
                    @click="handleMemberUpdate(scope.row)"
                  >编辑</el-button>
                  <el-button
                    size="mini"
                    type="text"
                    icon="el-icon-delete"
                    @click="handleMemberDelete(scope.row)"
                  >删除</el-button>
                </template>
              </el-table-column>
            </el-table>
            <pagination
              v-show="memberTotal>0"
              :total="memberTotal"
              :page.sync="memberQueryParams.pageNum"
              :limit.sync="memberQueryParams.pageSize"
              @pagination="getMemberList"
            />
          </el-col>
        </el-row>
      </el-tab-pane>
      <!-- å·¥å•指派 -->
      <el-tab-pane label="工单指派" name="workOrder">
        <el-row :gutter="20">
          <el-col :span="24" :xs="24">
            <el-form :model="workOrderQueryParams" ref="workOrderQueryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
              <el-form-item label="工单编号" prop="id">
                <el-input
                  v-model="workOrderQueryParams.id"
                  placeholder="请输入工单编号"
                  clearable
                  style="width: 200px"
                  @keyup.enter.native="handleWorkOrderQuery"
                />
              </el-form-item>
              <el-form-item label="工单状态" prop="status">
                <el-select v-model="workOrderQueryParams.status" placeholder="请选择状态" clearable style="width: 200px">
                  <el-option
                    v-for="item in workOrderStatusOptions"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="处理人" prop="assignee">
                <el-select v-model="workOrderQueryParams.assignee" placeholder="请选择处理人" clearable style="width: 200px">
                  <el-option
                    v-for="item in memberList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                  />
                </el-select>
              </el-form-item>
              <el-form-item>
                <el-button type="primary" icon="el-icon-search" size="medium" @click="handleWorkOrderQuery">搜索</el-button>
                <el-button icon="el-icon-refresh" size="medium" @click="resetWorkOrderQuery">重置</el-button>
              </el-form-item>
            </el-form>
            <el-row :gutter="10" class="mb8">
              <el-col :span="1.5">
                <el-button
                  type="primary"
                  plain
                  icon="el-icon-plus"
                  size="medium"
                  @click="handleWorkOrderAdd"
                >新建工单</el-button>
              </el-col>
            </el-row>
            <el-table v-loading="workOrderLoading" :data="filteredWorkOrderList" @selection-change="handleWorkOrderSelectionChange">
              <el-table-column type="selection" width="50" align="center" />
              <el-table-column label="工单编号" align="center" prop="id" width="120" />
              <el-table-column label="工单标题" align="center" prop="title" :show-overflow-tooltip="true" />
              <el-table-column label="优先级" align="center" prop="priority" width="100">
                <template slot-scope="scope">
                  <el-tag :type="scope.row.priority === '1' ? 'danger' : scope.row.priority === '2' ? 'warning' : ''">
                    {{ scope.row.priority === '1' ? '高' : scope.row.priority === '2' ? '中' : '低' }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="创建时间" align="center" prop="createTime" width="160">
                <template slot-scope="scope">
                  <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
                </template>
              </el-table-column>
              <el-table-column label="截止时间" align="center" prop="deadline" width="160">
                <template slot-scope="scope">
                  <span>{{ parseTime(scope.row.deadline, '{y}-{m}-{d}') }}</span>
                </template>
              </el-table-column>
              <el-table-column label="处理人" align="center" prop="assigneeName" width="120" />
              <el-table-column label="工单状态" align="center" prop="status" width="120">
                <template slot-scope="scope">
                  <dict-tag :options="workOrderStatusOptions" :value="scope.row.status"/>
                </template>
              </el-table-column>
              <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
                <template slot-scope="scope">
                  <el-button
                    size="mini"
                    type="text"
                    icon="el-icon-edit"
                    @click="handleWorkOrderUpdate(scope.row)"
                  >编辑</el-button>
                  <el-button
                    size="mini"
                    type="text"
                    icon="el-icon-delete"
                    @click="handleWorkOrderDelete(scope.row)"
                  >删除</el-button>
                  <el-button
                    size="mini"
                    type="text"
                    icon="el-icon-s-promotion"
                    @click="handleAssignWorkOrder(scope.row)"
                    v-if="scope.row.status === '0'"
                  >指派</el-button>
                </template>
              </el-table-column>
            </el-table>
            <pagination
              v-show="workOrderTotal>0"
              :total="workOrderTotal"
              :page.sync="workOrderQueryParams.pageNum"
              :limit.sync="workOrderQueryParams.pageSize"
              @pagination="getWorkOrderList"
            />
          </el-col>
        </el-row>
      </el-tab-pane>
    </el-tabs>
    <!-- å›¢é˜Ÿè¯¦æƒ…对话框 -->
    <el-dialog :title="teamDialogTitle" :visible.sync="teamDialogVisible" width="70%" append-to-body>
      <el-descriptions :column="2" border>
        <el-descriptions-item label="团队ID">{{ currentTeam.id }}</el-descriptions-item>
        <el-descriptions-item label="团队名称">{{ currentTeam.name }}</el-descriptions-item>
        <el-descriptions-item label="团队组长">{{ currentTeam.leader }}</el-descriptions-item>
<el-descriptions-item label="团队成员">{{ (currentTeam.members || []).length }}人</el-descriptions-item>        <el-descriptions-item label="创建时间">{{ parseTime(currentTeam.createTime, '{y}-{m}-{d} {h}:{i}') }}</el-descriptions-item>
        <el-descriptions-item label="团队状态">
          <dict-tag :options="teamStatusOptions" :value="currentTeam.status"/>
        </el-descriptions-item>
        <el-descriptions-item label="团队描述" :span="2">{{ currentTeam.description || '无' }}</el-descriptions-item>
      </el-descriptions>
      <div class="team-members" style="margin-top: 20px;">
        <div class="headline">
          <div class="basics">团队成员</div>
        </div>
        <el-divider></el-divider>
        <el-table :data="currentTeam.members" border style="width: 100%">
          <el-table-column prop="name" label="成员姓名" width="120" />
          <el-table-column prop="position" label="职位" width="120" />
          <el-table-column prop="phone" label="联系电话" width="150" />
          <el-table-column prop="email" label="邮箱" width="200" />
          <el-table-column prop="currentWorkOrder" label="当前工单" width="150">
            <template slot-scope="scope">
              <el-tag :type="scope.row.currentWorkOrder ? '' : 'info'">
                {{ scope.row.currentWorkOrder || '空闲' }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="status" label="成员状态" width="100">
            <template slot-scope="scope">
              <dict-tag :options="memberStatusOptions" :value="scope.row.status"/>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <div class="team-work-orders" style="margin-top: 20px;">
        <div class="headline">
          <div class="basics">团队工单</div>
        </div>
        <el-divider></el-divider>
        <el-table :data="teamWorkOrders" border style="width: 100%">
          <el-table-column prop="id" label="工单编号" width="120" />
          <el-table-column prop="title" label="工单标题" />
          <el-table-column prop="priority" label="优先级" width="100">
            <template slot-scope="scope">
              <el-tag :type="scope.row.priority === '1' ? 'danger' : scope.row.priority === '2' ? 'warning' : ''">
                {{ scope.row.priority === '1' ? '高' : scope.row.priority === '2' ? '中' : '低' }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="assigneeName" label="处理人" width="120" />
          <el-table-column prop="status" label="工单状态" width="120">
            <template slot-scope="scope">
              <dict-tag :options="workOrderStatusOptions" :value="scope.row.status"/>
            </template>
          </el-table-column>
          <el-table-column prop="createTime" label="创建时间" width="160">
            <template slot-scope="scope">
              <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="deadline" label="截止时间" width="160">
            <template slot-scope="scope">
              <span>{{ parseTime(scope.row.deadline, '{y}-{m}-{d}') }}</span>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button @click="teamDialogVisible = false">关 é—­</el-button>
      </div>
    </el-dialog>
    <!-- æ–°å¢ž/编辑团队对话框 -->
    <el-dialog :title="teamFormTitle" :visible.sync="teamFormVisible" width="50%" append-to-body>
      <el-form ref="teamForm" :model="teamForm" :rules="teamRules" label-width="80px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="团队名称" prop="name">
              <el-input v-model="teamForm.name" placeholder="请输入团队名称" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="团队组长" prop="leader">
              <el-select v-model="teamForm.leader" placeholder="请选择团队组长">
                <el-option
                  v-for="item in memberList"
                  :key="item.id"
                  :label="item.name"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="团队状态" prop="status">
              <el-radio-group v-model="teamForm.status">
                <el-radio
                  v-for="dict in teamStatusOptions"
                  :key="dict.value"
                  :label="dict.value"
                >{{dict.label}}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="团队成员" prop="members">
              <el-transfer
                v-model="teamForm.members"
                :data="memberOptions"
                :titles="['可选成员', '团队成员']"
                :props="{
                  key: 'id',
                  label: 'name'
                }"
              />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="团队描述" prop="description">
              <el-input type="textarea" :rows="3" v-model="teamForm.description" placeholder="请输入团队描述" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitTeamForm">ç¡® å®š</el-button>
        <el-button @click="cancelTeamForm">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
    <!-- æ–°å¢ž/编辑成员对话框 -->
    <el-dialog :title="memberFormTitle" :visible.sync="memberFormVisible" width="50%" append-to-body>
      <el-form ref="memberForm" :model="memberForm" :rules="memberRules" label-width="80px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="成员姓名" prop="name">
              <el-input v-model="memberForm.name" placeholder="请输入成员姓名" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="所属团队" prop="teamId">
              <el-select v-model="memberForm.teamId" placeholder="请选择所属团队">
                <el-option
                  v-for="item in teamList"
                  :key="item.id"
                  :label="item.name"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="职位" prop="position">
              <el-input v-model="memberForm.position" placeholder="请输入职位" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="联系电话" prop="phone">
              <el-input v-model="memberForm.phone" placeholder="请输入联系电话" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="邮箱" prop="email">
              <el-input v-model="memberForm.email" placeholder="请输入邮箱" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="成员状态" prop="status">
              <el-radio-group v-model="memberForm.status">
                <el-radio
                  v-for="dict in memberStatusOptions"
                  :key="dict.value"
                  :label="dict.value"
                >{{dict.label}}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitMemberForm">ç¡® å®š</el-button>
        <el-button @click="cancelMemberForm">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
    <!-- æ–°å¢ž/编辑工单对话框 -->
    <el-dialog :title="workOrderFormTitle" :visible.sync="workOrderFormVisible" width="60%" append-to-body>
      <el-form ref="workOrderForm" :model="workOrderForm" :rules="workOrderRules" label-width="80px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="工单标题" prop="title">
              <el-input v-model="workOrderForm.title" placeholder="请输入工单标题" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="优先级" prop="priority">
              <el-select v-model="workOrderForm.priority" placeholder="请选择优先级">
                <el-option
                  v-for="item in priorityOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="截止时间" prop="deadline">
              <el-date-picker
                v-model="workOrderForm.deadline"
                type="datetime"
                placeholder="请选择截止时间"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="工单内容" prop="content">
              <el-input type="textarea" :rows="4" v-model="workOrderForm.content" placeholder="请输入工单内容" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="工单状态" prop="status">
              <el-radio-group v-model="workOrderForm.status">
                <el-radio
                  v-for="dict in workOrderStatusOptions"
                  :key="dict.value"
                  :label="dict.value"
                >{{dict.label}}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="workOrderForm.status === '1'">
            <el-form-item label="处理人" prop="assignee">
              <el-select v-model="workOrderForm.assignee" placeholder="请选择处理人">
                <el-option
                  v-for="item in memberList"
                  :key="item.id"
                  :label="item.name"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitWorkOrderForm">ç¡® å®š</el-button>
        <el-button @click="cancelWorkOrderForm">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
    <!-- æŒ‡æ´¾å·¥å•对话框 -->
    <el-dialog title="指派工单" :visible.sync="assignDialogVisible" width="40%" append-to-body>
      <el-form :model="assignForm" label-width="80px">
        <el-form-item label="工单标题">
          <el-input v-model="assignForm.title" disabled />
        </el-form-item>
        <el-form-item label="处理人" prop="assignee">
          <el-select v-model="assignForm.assignee" placeholder="请选择处理人" style="width: 100%">
            <el-option
              v-for="item in availableMembers"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="优先级" prop="priority">
          <el-select v-model="assignForm.priority" placeholder="请选择优先级" style="width: 100%">
            <el-option
              v-for="item in priorityOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="截止时间" prop="deadline">
          <el-date-picker
            v-model="assignForm.deadline"
            type="datetime"
            placeholder="请选择截止时间"
            value-format="yyyy-MM-dd HH:mm:ss"
            style="width: 100%"
          />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitAssign">ç¡® å®š</el-button>
        <el-button @click="assignDialogVisible = false">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { parseTime } from '@/utils/ruoyi'
export default {
  name: "TeamManagement",
  dicts: ['sys_normal_disable', 'sys_user_sex'],
  data() {
    return {
      // å½“前激活的标签页
      activeTab: 'team',
      // æ˜¾ç¤ºæœç´¢æ¡ä»¶
      showSearch: true,
      // å›¢é˜Ÿç®¡ç†ç›¸å…³æ•°æ®
      teamLoading: false,
       multiple: false, // è¿™é‡Œæ·»åŠ 
      teamList: [
        {
          id: 1,
          name: "前端开发团队",
          leader: "张三",
          members: [
            { id: 1, name: "张三", position: "前端组长", phone: "13800138001", email: "zhangsan@example.com", currentWorkOrder: "WO20230001", status: "1" },
            { id: 2, name: "李四", position: "高级前端", phone: "13800138002", email: "lisi@example.com", currentWorkOrder: "", status: "1" },
            { id: 3, name: "王五", position: "前端开发", phone: "13800138003", email: "wangwu@example.com", currentWorkOrder: "WO20230002", status: "1" }
          ],
          createTime: "2023-01-15 09:30:00",
          status: "1",
          description: "负责公司所有前端项目的开发和维护"
        },
        {
          id: 2,
          name: "后端开发团队",
          leader: "赵六",
          members: [
            { id: 4, name: "赵六", position: "后端组长", phone: "13800138004", email: "zhaoliu@example.com", currentWorkOrder: "WO20230003", status: "1" },
            { id: 5, name: "钱七", position: "高级后端", phone: "13800138005", email: "qianqi@example.com", currentWorkOrder: "", status: "1" },
            { id: 6, name: "孙八", position: "后端开发", phone: "13800138006", email: "sunba@example.com", currentWorkOrder: "", status: "1" }
          ],
          createTime: "2023-01-20 14:20:00",
          status: "1",
          description: "负责公司所有后端服务的开发和维护"
        },
        {
          id: 3,
          name: "测试团队",
          leader: "周九",
          members: [
            { id: 7, name: "周九", position: "测试经理", phone: "13800138007", email: "zhoujiu@example.com", currentWorkOrder: "WO20230004", status: "1" },
            { id: 8, name: "吴十", position: "测试工程师", phone: "13800138008", email: "wushi@example.com", currentWorkOrder: "", status: "1" }
          ],
          createTime: "2023-02-10 10:15:00",
          status: "1",
          description: "负责公司所有项目的测试工作"
        }
      ],
      teamQueryParams: {
        pageNum: 1,
        pageSize: 10,
        name: undefined,
        status: undefined
      },
      teamTotal: 3,
      teamStatusOptions: [
        { value: "0", label: "禁用" },
        { value: "1", label: "启用" }
      ],
      teamDialogVisible: false,
      teamDialogTitle: "",
      currentTeam: {
      id: undefined,
      name: undefined,
      leader: undefined,
      members: [],  // ç¡®ä¿æœ‰é»˜è®¤ç©ºæ•°ç»„
      createTime: undefined,
      status: undefined,
      description: undefined
    },
      teamFormVisible: false,
      teamFormTitle: "",
      teamForm: {
        id: undefined,
        name: undefined,
        leader: undefined,
        members: [],
        status: "1",
        description: undefined
      },
      teamRules: {
        name: [
          { required: true, message: "团队名称不能为空", trigger: "blur" }
        ],
        leader: [
          { required: true, message: "团队组长不能为空", trigger: "change" }
        ],
        status: [
          { required: true, message: "团队状态不能为空", trigger: "change" }
        ]
      },
      // äººå‘˜åˆ†ç»„相关数据
      memberLoading: false,
      memberList: [
        { id: 1, name: "张三", teamId: 1, teamName: "前端开发团队", position: "前端组长", phone: "13800138001", email: "zhangsan@example.com", currentWorkOrder: "WO20230001", status: "1" },
        { id: 2, name: "李四", teamId: 1, teamName: "前端开发团队", position: "高级前端", phone: "13800138002", email: "lisi@example.com", currentWorkOrder: "", status: "1" },
        { id: 3, name: "王五", teamId: 1, teamName: "前端开发团队", position: "前端开发", phone: "13800138003", email: "wangwu@example.com", currentWorkOrder: "WO20230002", status: "1" },
        { id: 4, name: "赵六", teamId: 2, teamName: "后端开发团队", position: "后端组长", phone: "13800138004", email: "zhaoliu@example.com", currentWorkOrder: "WO20230003", status: "1" },
        { id: 5, name: "钱七", teamId: 2, teamName: "后端开发团队", position: "高级后端", phone: "13800138005", email: "qianqi@example.com", currentWorkOrder: "", status: "1" },
        { id: 6, name: "孙八", teamId: 2, teamName: "后端开发团队", position: "后端开发", phone: "13800138006", email: "sunba@example.com", currentWorkOrder: "", status: "1" },
        { id: 7, name: "周九", teamId: 3, teamName: "测试团队", position: "测试经理", phone: "13800138007", email: "zhoujiu@example.com", currentWorkOrder: "WO20230004", status: "1" },
        { id: 8, name: "吴十", teamId: 3, teamName: "测试团队", position: "测试工程师", phone: "13800138008", email: "wushi@example.com", currentWorkOrder: "", status: "1" }
      ],
      memberQueryParams: {
        pageNum: 1,
        pageSize: 10,
        name: undefined,
        teamId: undefined,
        status: undefined
      },
      memberTotal: 8,
      memberStatusOptions: [
        { value: "0", label: "禁用" },
        { value: "1", label: "启用" }
      ],
      memberFormVisible: false,
      memberFormTitle: "",
      memberForm: {
        id: undefined,
        name: undefined,
        teamId: undefined,
        position: undefined,
        phone: undefined,
        email: undefined,
        status: "1"
      },
      memberRules: {
        name: [
          { required: true, message: "成员姓名不能为空", trigger: "blur" }
        ],
        teamId: [
          { required: true, message: "所属团队不能为空", trigger: "change" }
        ],
        position: [
          { required: true, message: "职位不能为空", trigger: "blur" }
        ],
        phone: [
          { required: true, message: "联系电话不能为空", trigger: "blur" }
        ],
        email: [
          { required: true, message: "邮箱不能为空", trigger: "blur" },
          { type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }
        ],
        status: [
          { required: true, message: "成员状态不能为空", trigger: "change" }
        ]
      },
      // å·¥å•指派相关数据
      workOrderLoading: false,
      workOrderList: [
        { id: "WO20230001", title: "首页改版需求开发", priority: "1", createTime: "2023-03-01 09:30:00", deadline: "2023-03-15 18:00:00", assignee: 1, assigneeName: "张三", status: "1", content: "完成首页改版的所有前端开发工作" },
        { id: "WO20230002", title: "用户中心接口开发", priority: "2", createTime: "2023-03-05 14:20:00", deadline: "2023-03-20 18:00:00", assignee: 3, assigneeName: "王五", status: "1", content: "开发用户中心相关接口" },
        { id: "WO20230003", title: "订单系统性能优化", priority: "1", createTime: "2023-03-10 10:15:00", deadline: "2023-03-25 18:00:00", assignee: 4, assigneeName: "赵六", status: "1", content: "优化订单系统性能,提高响应速度" },
        { id: "WO20230004", title: "支付功能测试", priority: "3", createTime: "2023-03-15 16:45:00", deadline: "2023-03-30 18:00:00", assignee: 7, assigneeName: "周九", status: "1", content: "完成支付功能的全面测试" },
        { id: "WO20230005", title: "数据报表开发", priority: "2", createTime: "2023-03-20 11:10:00", deadline: "2023-04-05 18:00:00", assignee: undefined, assigneeName: undefined, status: "0", content: "开发数据统计报表功能" }
      ],
      workOrderQueryParams: {
        pageNum: 1,
        pageSize: 10,
        id: undefined,
        status: undefined,
        assignee: undefined
      },
      workOrderTotal: 5,
      workOrderStatusOptions: [
        { value: "0", label: "待指派" },
        { value: "1", label: "进行中" },
        { value: "2", label: "已完成" },
        { value: "3", label: "已取消" }
      ],
      priorityOptions: [
        { value: "1", label: "高" },
        { value: "2", label: "中" },
        { value: "3", label: "低" }
      ],
      workOrderFormVisible: false,
      workOrderFormTitle: "",
      workOrderForm: {
        id: undefined,
        title: undefined,
        priority: "2",
        createTime: undefined,
        deadline: undefined,
        assignee: undefined,
        status: "0",
        content: undefined
      },
      workOrderRules: {
        title: [
          { required: true, message: "工单标题不能为空", trigger: "blur" }
        ],
        priority: [
          { required: true, message: "优先级不能为空", trigger: "change" }
        ],
        deadline: [
          { required: true, message: "截止时间不能为空", trigger: "change" }
        ],
        content: [
          { required: true, message: "工单内容不能为空", trigger: "blur" }
        ],
        status: [
          { required: true, message: "工单状态不能为空", trigger: "change" }
        ]
      },
      // æŒ‡æ´¾å·¥å•相关数据
      assignDialogVisible: false,
      assignForm: {
        id: undefined,
        title: undefined,
        assignee: undefined,
        priority: "2",
        deadline: undefined
      }
    };
  },
  computed: {
    // å›¢é˜Ÿæˆå‘˜é€‰é¡¹ï¼ˆç”¨äºŽç©¿æ¢­æ¡†ï¼‰
    memberOptions() {
      return this.memberList.map(member => ({
        key: member.id,
        label: member.name,
        disabled: member.status === "0"
      }));
    },
    // è¿‡æ»¤åŽçš„团队列表
    filteredTeamList() {
      let list = [...this.teamList];
      if (this.teamQueryParams.name) {
        list = list.filter(item =>
          item.name.includes(this.teamQueryParams.name)
        );
      }
      if (this.teamQueryParams.status) {
        list = list.filter(item =>
          item.status === this.teamQueryParams.status
        );
      }
      return list;
    },
    // è¿‡æ»¤åŽçš„æˆå‘˜åˆ—表
    filteredMemberList() {
      let list = [...this.memberList];
      if (this.memberQueryParams.name) {
        list = list.filter(item =>
          item.name.includes(this.memberQueryParams.name)
        );
      }
      if (this.memberQueryParams.teamId) {
        list = list.filter(item =>
          item.teamId === this.memberQueryParams.teamId
        );
      }
      if (this.memberQueryParams.status) {
        list = list.filter(item =>
          item.status === this.memberQueryParams.status
        );
      }
      return list;
    },
    // è¿‡æ»¤åŽçš„工单列表
    filteredWorkOrderList() {
      let list = [...this.workOrderList];
      if (this.workOrderQueryParams.id) {
        list = list.filter(item =>
          item.id.includes(this.workOrderQueryParams.id)
        );
      }
      if (this.workOrderQueryParams.status) {
        list = list.filter(item =>
          item.status === this.workOrderQueryParams.status
        );
      }
      if (this.workOrderQueryParams.assignee) {
        list = list.filter(item =>
          item.assignee === this.workOrderQueryParams.assignee
        );
      }
      return list;
    },
    // å›¢é˜Ÿå·¥å•(用于团队详情)
    teamWorkOrders() {
      if (!this.currentTeam.id) return [];
      const teamMemberIds = this.currentTeam.members.map(member => member.id);
      return this.workOrderList.filter(order =>
        teamMemberIds.includes(order.assignee)
      );
    },
    // å¯ç”¨æˆå‘˜ï¼ˆç”¨äºŽå·¥å•指派)
    availableMembers() {
      return this.memberList.filter(member =>
        member.status === "1" && !member.currentWorkOrder
      );
    }
  },
  methods: {
    // è§£æžæ—¶é—´
    parseTime,
    /** å›¢é˜Ÿç®¡ç†ç›¸å…³æ–¹æ³• */
    // æŸ¥è¯¢å›¢é˜Ÿåˆ—表
    getTeamList() {
      this.teamLoading = true;
      setTimeout(() => {
        this.teamLoading = false;
      }, 500);
    },
    // å›¢é˜Ÿæœç´¢
    handleTeamQuery() {
      this.teamQueryParams.pageNum = 1;
    },
    // é‡ç½®å›¢é˜Ÿæœç´¢
    resetTeamQuery() {
      this.resetForm("teamQueryForm");
      this.handleTeamQuery();
    },
    // å›¢é˜Ÿå¤šé€‰
    handleTeamSelectionChange(selection) {
      this.ids = selection.map(item => item.id);
      this.single = selection.length !== 1;
      this.multiple = !selection.length;
    },
    // æŸ¥çœ‹å›¢é˜Ÿè¯¦æƒ…
    handleTeamDetail(row) {
      this.currentTeam = row;
      this.teamDialogTitle = "团队详情 - " + row.name;
      this.teamDialogVisible = true;
    },
    // æ–°å¢žå›¢é˜Ÿ
    handleTeamAdd() {
      this.resetTeamForm();
      this.teamFormTitle = "新增团队";
      this.teamFormVisible = true;
    },
    // ä¿®æ”¹å›¢é˜Ÿ
    handleTeamUpdate(row) {
      this.resetTeamForm();
      const team = this.teamList.find(item => item.id === row.id);
      this.teamForm = Object.assign({}, team);
      this.teamForm.members = team.members.map(member => member.id);
      this.teamFormTitle = "修改团队";
      this.teamFormVisible = true;
    },
    // åˆ é™¤å›¢é˜Ÿ
    handleTeamDelete(row) {
      const teamIds = row.id || this.ids;
      this.$modal.confirm('是否确认删除团队名称为"' + row.name + '"的数据项?').then(() => {
        // æ¨¡æ‹Ÿåˆ é™¤å›¢é˜Ÿ
        this.teamList = this.teamList.filter(item => item.id !== teamIds);
        this.teamTotal = this.teamList.length;
        this.$modal.msgSuccess("删除成功");
      }).catch(() => {});
    },
    // æäº¤å›¢é˜Ÿè¡¨å•
    submitTeamForm() {
      this.$refs["teamForm"].validate(valid => {
        if (valid) {
          if (this.teamForm.id != null) {
            // æ¨¡æ‹Ÿä¿®æ”¹å›¢é˜Ÿ
            const index = this.teamList.findIndex(item => item.id === this.teamForm.id);
            if (index !== -1) {
              const leader = this.memberList.find(member => member.id === this.teamForm.leader);
              const members = this.memberList.filter(member =>
                this.teamForm.members.includes(member.id)
              );
              this.teamList.splice(index, 1, {
                ...this.teamForm,
                leader: leader ? leader.name : '',
                members: members
              });
            }
            this.$modal.msgSuccess("修改成功");
          } else {
            // æ¨¡æ‹Ÿæ–°å¢žå›¢é˜Ÿ
            const newId = Math.max(...this.teamList.map(item => item.id)) + 1;
            const leader = this.memberList.find(member => member.id === this.teamForm.leader);
            const members = this.memberList.filter(member =>
              this.teamForm.members.includes(member.id)
            );
            this.teamList.unshift({
              ...this.teamForm,
              id: newId,
              leader: leader ? leader.name : '',
              members: members,
              createTime: new Date().toLocaleString()
            });
            this.teamTotal = this.teamList.length;
            this.$modal.msgSuccess("新增成功");
          }
          this.teamFormVisible = false;
        }
      });
    },
    // é‡ç½®å›¢é˜Ÿè¡¨å•
    resetTeamForm() {
      this.teamForm = {
        id: undefined,
        name: undefined,
        leader: undefined,
        members: [],
        status: "1",
        description: undefined
      };
      this.resetForm("teamForm");
    },
    // å–消团队表单
    cancelTeamForm() {
      this.teamFormVisible = false;
      this.resetTeamForm();
    },
    /** äººå‘˜åˆ†ç»„相关方法 */
    // æŸ¥è¯¢æˆå‘˜åˆ—表
    getMemberList() {
      this.memberLoading = true;
      setTimeout(() => {
        this.memberLoading = false;
      }, 500);
    },
    // æˆå‘˜æœç´¢
    handleMemberQuery() {
      this.memberQueryParams.pageNum = 1;
    },
    // é‡ç½®æˆå‘˜æœç´¢
    resetMemberQuery() {
      this.resetForm("memberQueryForm");
      this.handleMemberQuery();
    },
    // æˆå‘˜å¤šé€‰
    handleMemberSelectionChange(selection) {
      this.ids = selection.map(item => item.id);
      this.single = selection.length !== 1;
      this.multiple = !selection.length;
    },
    // æ–°å¢žæˆå‘˜
    handleMemberAdd() {
      this.resetMemberForm();
      this.memberFormTitle = "新增成员";
      this.memberFormVisible = true;
    },
    // ä¿®æ”¹æˆå‘˜
    handleMemberUpdate(row) {
      this.resetMemberForm();
      const member = this.memberList.find(item => item.id === row.id);
      this.memberForm = Object.assign({}, member);
      this.memberFormTitle = "修改成员";
      this.memberFormVisible = true;
    },
    // åˆ é™¤æˆå‘˜
    handleMemberDelete(row) {
      const memberIds = row.id || this.ids;
      this.$modal.confirm('是否确认删除成员姓名为"' + row.name + '"的数据项?').then(() => {
        // æ¨¡æ‹Ÿåˆ é™¤æˆå‘˜
        this.memberList = this.memberList.filter(item => item.id !== memberIds);
        this.memberTotal = this.memberList.length;
        this.$modal.msgSuccess("删除成功");
      }).catch(() => {});
    },
    // æäº¤æˆå‘˜è¡¨å•
    submitMemberForm() {
      this.$refs["memberForm"].validate(valid => {
        if (valid) {
          if (this.memberForm.id != null) {
            // æ¨¡æ‹Ÿä¿®æ”¹æˆå‘˜
            const index = this.memberList.findIndex(item => item.id === this.memberForm.id);
            if (index !== -1) {
              const team = this.teamList.find(item => item.id === this.memberForm.teamId);
              this.memberList.splice(index, 1, {
                ...this.memberForm,
                teamName: team ? team.name : ''
              });
            }
            this.$modal.msgSuccess("修改成功");
          } else {
            // æ¨¡æ‹Ÿæ–°å¢žæˆå‘˜
            const newId = Math.max(...this.memberList.map(item => item.id)) + 1;
            const team = this.teamList.find(item => item.id === this.memberForm.teamId);
            this.memberList.unshift({
              ...this.memberForm,
              id: newId,
              teamName: team ? team.name : '',
              currentWorkOrder: ''
            });
            this.memberTotal = this.memberList.length;
            this.$modal.msgSuccess("新增成功");
          }
          this.memberFormVisible = false;
        }
      });
    },
    // é‡ç½®æˆå‘˜è¡¨å•
    resetMemberForm() {
      this.memberForm = {
        id: undefined,
        name: undefined,
        teamId: undefined,
        position: undefined,
        phone: undefined,
        email: undefined,
        status: "1"
      };
      this.resetForm("memberForm");
    },
    // å–消成员表单
    cancelMemberForm() {
      this.memberFormVisible = false;
      this.resetMemberForm();
    },
    /** å·¥å•指派相关方法 */
    // æŸ¥è¯¢å·¥å•列表
    getWorkOrderList() {
      this.workOrderLoading = true;
      setTimeout(() => {
        this.workOrderLoading = false;
      }, 500);
    },
    // å·¥å•搜索
    handleWorkOrderQuery() {
      this.workOrderQueryParams.pageNum = 1;
    },
    // é‡ç½®å·¥å•搜索
    resetWorkOrderQuery() {
      this.resetForm("workOrderQueryForm");
      this.handleWorkOrderQuery();
    },
    // å·¥å•多选
    handleWorkOrderSelectionChange(selection) {
      this.ids = selection.map(item => item.id);
      this.single = selection.length !== 1;
      this.multiple = !selection.length;
    },
    // æ–°å¢žå·¥å•
    handleWorkOrderAdd() {
      this.resetWorkOrderForm();
      this.workOrderFormTitle = "新建工单";
      this.workOrderFormVisible = true;
    },
    // ä¿®æ”¹å·¥å•
    handleWorkOrderUpdate(row) {
      this.resetWorkOrderForm();
      const workOrder = this.workOrderList.find(item => item.id === row.id);
      this.workOrderForm = Object.assign({}, workOrder);
      this.workOrderFormTitle = "编辑工单";
      this.workOrderFormVisible = true;
    },
    // åˆ é™¤å·¥å•
    handleWorkOrderDelete(row) {
      const workOrderIds = row.id || this.ids;
      this.$modal.confirm('是否确认删除工单标题为"' + row.title + '"的数据项?').then(() => {
        // æ¨¡æ‹Ÿåˆ é™¤å·¥å•
        this.workOrderList = this.workOrderList.filter(item => item.id !== workOrderIds);
        this.workOrderTotal = this.workOrderList.length;
        this.$modal.msgSuccess("删除成功");
      }).catch(() => {});
    },
    // æŒ‡æ´¾å·¥å•
    handleAssignWorkOrder(row) {
      this.assignForm = {
        id: row.id,
        title: row.title,
        assignee: undefined,
        priority: row.priority,
        deadline: row.deadline
      };
      this.assignDialogVisible = true;
    },
    // æäº¤å·¥å•表单
    submitWorkOrderForm() {
      this.$refs["workOrderForm"].validate(valid => {
        if (valid) {
          if (this.workOrderForm.id != null) {
            // æ¨¡æ‹Ÿä¿®æ”¹å·¥å•
            const index = this.workOrderList.findIndex(item => item.id === this.workOrderForm.id);
            if (index !== -1) {
              const assignee = this.memberList.find(member => member.id === this.workOrderForm.assignee);
              this.workOrderList.splice(index, 1, {
                ...this.workOrderForm,
                assigneeName: assignee ? assignee.name : undefined
              });
            }
            this.$modal.msgSuccess("修改成功");
          } else {
            // æ¨¡æ‹Ÿæ–°å¢žå·¥å•
            const newId = "WO" + new Date().getFullYear() + (Math.floor(Math.random() * 90000) + 10000);
            const assignee = this.memberList.find(member => member.id === this.workOrderForm.assignee);
            this.workOrderList.unshift({
              ...this.workOrderForm,
              id: newId,
              assigneeName: assignee ? assignee.name : undefined,
              createTime: new Date().toLocaleString()
            });
            this.workOrderTotal = this.workOrderList.length;
            this.$modal.msgSuccess("新增成功");
          }
          this.workOrderFormVisible = false;
        }
      });
    },
    // é‡ç½®å·¥å•表单
    resetWorkOrderForm() {
      this.workOrderForm = {
        id: undefined,
        title: undefined,
        priority: "2",
        createTime: undefined,
        deadline: undefined,
        assignee: undefined,
        status: "0",
        content: undefined
      };
      this.resetForm("workOrderForm");
    },
    // å–消工单表单
    cancelWorkOrderForm() {
      this.workOrderFormVisible = false;
      this.resetWorkOrderForm();
    },
    // æäº¤æŒ‡æ´¾
    submitAssign() {
      if (!this.assignForm.assignee) {
        this.$modal.msgError("请选择处理人");
        return;
      }
      // æ¨¡æ‹ŸæŒ‡æ´¾å·¥å•
      const index = this.workOrderList.findIndex(item => item.id === this.assignForm.id);
      if (index !== -1) {
        const assignee = this.memberList.find(member => member.id === this.assignForm.assignee);
        if (assignee) {
          // æ›´æ–°å·¥å•状态
          this.workOrderList.splice(index, 1, {
            ...this.workOrderList[index],
            assignee: this.assignForm.assignee,
            assigneeName: assignee.name,
            priority: this.assignForm.priority,
            deadline: this.assignForm.deadline,
            status: "1"
          });
          // æ›´æ–°æˆå‘˜å½“前工单
          const memberIndex = this.memberList.findIndex(member => member.id === this.assignForm.assignee);
          if (memberIndex !== -1) {
            this.memberList.splice(memberIndex, 1, {
              ...this.memberList[memberIndex],
              currentWorkOrder: this.assignForm.id
            });
          }
          this.$modal.msgSuccess("指派成功");
          this.assignDialogVisible = false;
        }
      }
    }
  }
};
</script>
<style lang="scss" scoped>
.TeamManagement {
  padding: 20px;
}
.headline {
  display: flex;
  justify-content: space-between;
  font-size: 20px;
  border-left: 4px solid #41a1be;
  padding-left: 5px;
  margin: 15px 0;
}
.avatar-uploader ::v-deep .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader ::v-deep .el-upload:hover {
  border-color: #409EFF;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
.team-members, .team-work-orders {
  margin-top: 20px;
}
</style>