zhangqin 3 tygodni temu
rodzic
commit
e195216c03

+ 35 - 0
src/api/qw/assignRule.js

@@ -0,0 +1,35 @@
+import request from '@/utils/request'
+
+// 查询分配规则列表
+export function listAssignRule(query) {
+  return request({
+    url: '/qwAssignRule/page',
+    method: 'get',
+    params: query
+  })
+}
+
+// 获取分配规则详细
+export function getAssignRule(id) {
+  return request({
+    url: '/qwAssignRule/' + id,
+    method: 'get'
+  })
+}
+
+// 新增或编辑分配规则
+export function addOrUpdateAssignRule(data) {
+  return request({
+    url: '/qwAssignRule/addOrUpdate',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除分配规则
+export function delAssignRule(id) {
+  return request({
+    url: '/qwAssignRule/' + id,
+    method: 'delete'
+  })
+}

+ 0 - 9
src/api/qw/groupActive.js

@@ -1,9 +0,0 @@
-import request from '@/utils/request'
-
-// 查询群活码列表
-export function listGroupActive() {
-  return request({
-    url: '/qw/groupActive/list',
-    method: 'get'
-  })
-}

+ 35 - 0
src/api/qw/groupActual.js

@@ -0,0 +1,35 @@
+import request from '@/utils/request'
+
+// 查询群实际码列表
+export function listGroupActual(query) {
+  return request({
+    url: '/qwGroupActual/page',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询群实际码详细
+export function getGroupActual(id) {
+  return request({
+    url: '/qwGroupActual/' + id,
+    method: 'get'
+  })
+}
+
+// 新增或修改群实际码
+export function addOrUpdateGroupActual(data) {
+  return request({
+    url: '/qwGroupActual/addOrUpdate',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除群实际码
+export function delGroupActual(id) {
+  return request({
+    url: '/qwGroupActual/' + id,
+    method: 'delete'
+  })
+}

+ 35 - 0
src/api/qw/groupLiveCode.js

@@ -0,0 +1,35 @@
+import request from '@/utils/request'
+
+// 查询活码列表
+export function listGroupLiveCode(query) {
+  return request({
+    url: '/qwGroupLiveCode/page',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询活码详细
+export function getGroupLiveCode(id) {
+  return request({
+    url: '/qwGroupLiveCode/' + id,
+    method: 'get'
+  })
+}
+
+// 新增或修改活码
+export function addOrUpdateGroupLiveCode(data) {
+  return request({
+    url: '/qwGroupLiveCode/addOrUpdate',
+    method: 'post',
+    data: data
+  })
+}
+
+// 删除活码
+export function delGroupLiveCode(id) {
+  return request({
+    url: '/qwGroupLiveCode/' + id,
+    method: 'delete'
+  })
+}

+ 1 - 1
src/views/adv/site/index.vue

@@ -544,7 +544,7 @@ import { pageDomain } from "@/api/adv/domain";
 import { pageProject as pageChannel } from "@/api/adv/channel";
 import { pageProject } from "@/api/adv/project";
 import { listAllocationRule } from "@/api/qw/allocationRule";
-import { listGroupActive } from "@/api/qw/groupActive";
+import { listGroupActive } from "@/api/qw/groupActual";
 
 export default {
   name: "Site",

+ 368 - 0
src/views/qw/assignRule/index.vue

@@ -0,0 +1,368 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <el-form-item label="规则名称" prop="ruleName">
+        <el-input
+          v-model="queryParams.ruleName"
+          placeholder="请输入规则名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
+          <el-option label="启用" :value="1" />
+          <el-option label="停用" :value="0" />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @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="mini"
+          @click="handleAdd"
+        >新增</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="assignRuleList" border>
+      <el-table-column label="规则名称" align="center" prop="ruleName" />
+      <el-table-column label="分配类型" align="center" prop="assignType">
+        <template slot-scope="scope">
+          <span v-if="scope.row.assignType === 1">轮询</span>
+          <span v-else-if="scope.row.assignType === 2">依次</span>
+          <span v-else-if="scope.row.assignType === 3">按权重</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="员工数" align="center" prop="personnelCount">
+        <template slot-scope="scope">
+          {{ getPersonnelCount(scope.row) }}
+        </template>
+      </el-table-column>
+      <el-table-column label="状态" align="center" prop="status">
+        <template slot-scope="scope">
+          <el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">
+            {{ scope.row.status === 1 ? '启用' : '停用' }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="280px">
+        <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"
+            @click="handleStatusChange(scope.row)"
+          >{{ scope.row.status === 1 ? '停用' : '启用' }}</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleDetails(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-dialog :title="title" :visible.sync="open" width="700px" append-to-body @close="cancel">
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="规则名称" prop="ruleName">
+          <el-input v-model="form.ruleName" placeholder="请输入规则名称" />
+        </el-form-item>
+        <el-form-item label="分配类型" prop="assignType">
+          <el-radio-group v-model="form.assignType">
+            <el-radio :label="3">按权重</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="选择员工" prop="assignPersonnelJson" style="margin-top: 2%">
+          <div>
+            <el-button
+              size="medium"
+              icon="el-icon-circle-plus-outline"
+              plain
+              @click="handleSelectUser">请选择使用员工</el-button>
+          </div>
+          <div style="margin-top: 10px;">
+            <el-table :data="personnelList" border size="small" style="margin-top: 10px;">
+              <el-table-column label="企微号" align="center" prop="qwUserId" width="120px" />
+              <el-table-column label="企微姓名" align="center" prop="qwUserName" width="120px" />
+              <el-table-column label="权重数" align="center" width="100px">
+                <template slot-scope="scope">
+                  <el-input v-model.number="scope.row.weight" type="number" size="small" />
+                </template>
+              </el-table-column>
+              <el-table-column label="操作" align="center" width="80px">
+                <template slot-scope="scope">
+                  <el-button type="danger" size="mini" icon="el-icon-delete" @click="handleRemovePersonnel(scope.row)"></el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </div>
+        </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>
+
+    <!-- 分配详情对话框 -->
+    <el-dialog title="分配详情" :visible.sync="detailsOpen" width="900px" append-to-body>
+      <el-table :data="detailsPersonnelList" border style="margin-bottom: 20px;">
+        <el-table-column label="企微号" align="center" prop="qwUserId" />
+        <el-table-column label="企微姓名" align="center" prop="qwUserName" />
+        <el-table-column label="权重数" align="center" prop="weight" />
+        <el-table-column label="今日分配数" align="center" prop="assignNumToDay" />
+        <el-table-column label="累积分配数" align="center" prop="assignNumCount" />
+        <el-table-column label="今日添加数" align="center" prop="addNumToDay" />
+        <el-table-column label="累积添加数" align="center" prop="addNumCount" />
+      </el-table>
+    </el-dialog>
+
+    <!-- 选择员工对话框 -->
+    <el-dialog :title="selectUserDialog.title" :visible.sync="selectUserDialog.open" width="1300px" append-to-body>
+      <qwUserList ref="QwUserList" @selectUserList="selectUserList"></qwUserList>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listAssignRule, getAssignRule, addOrUpdateAssignRule } from "@/api/qw/assignRule";
+import qwUserList from '@/views/qw/user/qwUserList.vue'
+
+export default {
+  name: "AssignRule",
+  components: { qwUserList },
+  data() {
+    return {
+      loading: true,
+      showSearch: true,
+      total: 0,
+      assignRuleList: [],
+      title: "",
+      open: false,
+      detailsOpen: false,
+      detailsPersonnelList: [],
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        ruleName: null,
+        status: null,
+      },
+      form: {
+        assignType: 3,
+        assignPersonnelJson: null
+      },
+      personnelList: [],
+      selectUserDialog: {
+        title: "选择员工",
+        open: false
+      },
+      rules: {
+        ruleName: [
+          { required: true, message: "规则名称不能为空", trigger: "blur" }
+        ]
+      },
+
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询分配规则列表 */
+    getList() {
+      this.loading = true;
+      listAssignRule(this.queryParams).then(response => {
+        this.assignRuleList = response.data.records;
+        this.total = response.data.total;
+        this.loading = false;
+      }).catch(() => {
+        this.loading = false;
+      });
+    },
+
+    /** 获取员工数量 */
+    getPersonnelCount(row) {
+      if (row.assignPersonnelJson) {
+        try {
+          const personnel = JSON.parse(row.assignPersonnelJson);
+          return Array.isArray(personnel) ? personnel.length : 0;
+        } catch (e) {
+          return 0;
+        }
+      }
+      return 0;
+    },
+
+    /** 新增按钮 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "新增分配规则";
+    },
+
+    /** 修改按钮 */
+    handleUpdate(row) {
+      this.reset();
+      this.open = true;
+      this.title = "修改分配规则";
+      getAssignRule(row.id).then(response => {
+        this.form = response.data;
+        if (this.form.assignPersonnelJson) {
+          try {
+            this.personnelList = JSON.parse(this.form.assignPersonnelJson);
+          } catch (e) {
+            this.personnelList = [];
+          }
+        }
+      });
+    },
+
+    /** 启用/停用 */
+    handleStatusChange(row) {
+      const status = row.status === 1 ? 0 : 1;
+      const statusText = status === 1 ? "启用" : "停用";
+      this.$confirm(`确认要${statusText}该分配规则吗?`, "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        const data = {
+          id: row.id,
+          status: status
+        };
+        addOrUpdateAssignRule(data).then(response => {
+          this.msgSuccess(`${statusText}成功`);
+          this.getList();
+        });
+      }).catch(() => {});
+    },
+
+    /** 分配详情 */
+    handleDetails(row) {
+      if (row.assignPersonnelJson) {
+        try {
+          this.detailsPersonnelList = JSON.parse(row.assignPersonnelJson);
+        } catch (e) {
+          this.detailsPersonnelList = [];
+        }
+      }
+      this.detailsOpen = true;
+    },
+
+    /** 选择员工 */
+    handleSelectUser() {
+      this.selectUserDialog.open = true;
+      this.$nextTick(() => {
+        this.$refs.QwUserList.getDetails(null, null, null, null);
+      });
+    },
+
+    /** 接收选中的员工 */
+    selectUserList(selectUsers) {
+      this.selectUserDialog.open = false;
+      if (selectUsers && selectUsers.length > 0) {
+        selectUsers.forEach(user => {
+          const exists = this.personnelList.find(p => p.qwUserId === user.qwUserId);
+          if (!exists) {
+            this.personnelList.push({
+              qwUserId: user.qwUserId,
+              qwUserName: user.qwUserName,
+              weight: 1,
+              assignNumToDay: 0,
+              assignNumCount: 0,
+              addNumToDay: 0,
+              addNumCount: 0
+            });
+          }
+        });
+      }
+    },
+
+    /** 移除员工 */
+    handleRemovePersonnel(item) {
+      const index = this.personnelList.findIndex(p => p.qwUserId === item.qwUserId);
+      if (index > -1) {
+        this.personnelList.splice(index, 1);
+      }
+    },
+
+    /** 表单提交 */
+    submitForm() {
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          if (this.personnelList.length === 0) {
+            this.$message.error("请选择至少一个员工");
+            return;
+          }
+          const data = {
+            ...this.form,
+            assignPersonnelJson: JSON.stringify(this.personnelList)
+          };
+          addOrUpdateAssignRule(data).then(response => {
+            this.msgSuccess(this.form.id ? "修改成功" : "新增成功");
+            this.open = false;
+            this.getList();
+          });
+        }
+      });
+    },
+
+    /** 取消 */
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+
+    /** 表单重置 */
+    reset() {
+      this.form = {
+        id: null,
+        ruleName: null,
+        assignType: 3,
+        assignPersonnelJson: null,
+        status: 1
+      };
+      this.personnelList = [];
+      this.resetForm("form");
+    },
+
+    /** 搜索 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+
+    /** 重置 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    }
+  }
+};
+</script>

+ 304 - 0
src/views/qw/groupActual/index.vue

@@ -0,0 +1,304 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="群活码" prop="liveCodeId">
+        <el-select v-model="queryParams.liveCodeId" placeholder="请选择群活码" clearable size="small" @change="handleQuery">
+          <el-option
+            v-for="item in groupLiveCodeList"
+            :key="item.id"
+            :label="item.groupName"
+            :value="item.id"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="群名称" prop="groupName">
+        <el-input
+          v-model="queryParams.groupName"
+          placeholder="请输入群名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
+          <el-option label="启用" :value="1" />
+          <el-option label="停用" :value="0" />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @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="mini"
+          @click="handleAdd"
+        >新增</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="groupActualList" border>
+      <el-table-column label="群名称" align="center" prop="groupName" />
+      <el-table-column label="实际群二维码" align="center" prop="groupUrl">
+        <template slot-scope="scope">
+          <el-image
+            v-if="scope.row.groupUrl"
+            :src="scope.row.groupUrl"
+            :preview-src-list="[scope.row.groupUrl]"
+            style="width: 80px; height: 80px;"
+          />
+          <span v-else>-</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="分配数" align="center" prop="assignNum" />
+      <el-table-column label="状态" align="center" prop="status">
+        <template slot-scope="scope">
+          <el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">
+            {{ scope.row.status === 1 ? '启用' : '停用' }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <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"
+            @click="handleStatusChange(scope.row)"
+          >{{ scope.row.status === 1 ? '停用' : '启用' }}</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-dialog :title="title" :visible.sync="open" width="500px" append-to-body @close="cancel">
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="群活码" prop="liveCodeId">
+          <el-select v-model="form.liveCodeId" placeholder="请选择群活码">
+            <el-option
+              v-for="item in groupLiveCodeList"
+              :key="item.id"
+              :label="item.groupName"
+              :value="item.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="群名称" prop="groupName">
+          <el-input v-model="form.groupName" placeholder="请输入群名称" />
+        </el-form-item>
+        <el-form-item label="群二维码" prop="groupUrl">
+          <image-upload v-model="form.groupUrl" :limit="1" />
+        </el-form-item>
+        <el-form-item label="有效期" prop="efficientTime">
+          <el-date-picker v-model="form.efficientTime" type="date" placeholder="请选择有效期" value-format="yyyy-MM-dd" />
+        </el-form-item>
+        <el-form-item label="分配数" prop="assignNum">
+          <el-input-number v-model="form.assignNum" :min="0" />
+        </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>
+</template>
+
+<script>
+import { listGroupActual, getGroupActual, addOrUpdateGroupActual, delGroupActual } from "@/api/qw/groupActual";
+import { listGroupLiveCode } from "@/api/qw/groupLiveCode";
+import ImageUpload from "@/components/ImageUpload";
+
+export default {
+  name: "GroupActual",
+  components: {
+    ImageUpload
+  },
+  data() {
+    return {
+      loading: true,
+      showSearch: true,
+      total: 0,
+      groupActualList: [],
+      groupLiveCodeList: [],
+      title: "",
+      open: false,
+      liveCodeId: null,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        liveCodeId: null,
+        groupName: null,
+        status: null,
+      },
+      form: {},
+      rules: {
+        groupName: [
+          { required: true, message: "群名称不能为空", trigger: "blur" }
+        ],
+        groupUrl: [
+          { required: true, message: "群二维码不能为空", trigger: "change" }
+        ],
+        liveCodeId: [
+          { required: true, message: "群活码不能为空", trigger: "change" }
+        ]
+      }
+    };
+  },
+  created() {
+    // 从路由参数中获取liveCodeId
+    this.liveCodeId = this.$route.query.liveCodeId;
+    // 如果从群活码页面跳转过来,自动设置筛选条件
+    if (this.liveCodeId) {
+      this.queryParams.liveCodeId = this.liveCodeId;
+    }
+    this.loadGroupLiveCodeList();
+    this.getList();
+  },
+  methods: {
+    /** 查询群实际码列表 */
+    getList() {
+      this.loading = true;
+      const params = { ...this.queryParams };
+      if (this.liveCodeId) {
+        params.liveCodeId = this.liveCodeId;
+      }
+      listGroupActual(params).then(response => {
+        this.groupActualList = response.data.records;
+        this.total = response.data.total;
+        this.loading = false;
+      }).catch(() => {
+        this.loading = false;
+      });
+    },
+
+    /** 新增按钮 */
+    handleAdd() {
+      this.reset();
+      // 如果是从群活码页面跳转过来的,新增时自动带入liveCodeId
+      if (this.liveCodeId) {
+        this.form.liveCodeId = parseInt(this.liveCodeId);
+      }
+      this.loadGroupLiveCodeList();
+      this.open = true;
+      this.title = "新增群实际码";
+    },
+
+    /** 加载群活码列表 */
+    loadGroupLiveCodeList() {
+      listGroupLiveCode({ pageNum: 1, pageSize: 1000 }).then(response => {
+        this.groupLiveCodeList = response.data.records;
+      }).catch(() => {
+        this.groupLiveCodeList = [];
+      });
+    },
+
+    // ... existing code ...
+    handleUpdate(row) {
+      this.reset();
+      this.loadGroupLiveCodeList();
+      this.open = true;
+      this.title = "修改群实际码";
+      getGroupActual(row.id).then(response => {
+        this.form = response.data;
+      });
+    },
+
+    /** 启用/停用 */
+    handleStatusChange(row) {
+      const status = row.status === 1 ? 0 : 1;
+      const statusText = status === 1 ? "启用" : "停用";
+      this.$confirm(`确认要${statusText}该群实际码吗?`, "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        const data = {
+          id: row.id,
+          status: status
+        };
+        addOrUpdateGroupActual(data).then(response => {
+          this.msgSuccess(`${statusText}成功`);
+          this.getList();
+        });
+      }).catch(() => {});
+    },
+
+    /** 表单提交 */
+    submitForm() {
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          const data = { ...this.form };
+          // 有效期处理:剆除时間秘,添加默认时間秘 00:00:00
+          if (data.efficientTime && typeof data.efficientTime === 'string') {
+            data.efficientTime = data.efficientTime + ' 00:00:00';
+          }
+          addOrUpdateGroupActual(data).then(response => {
+            this.msgSuccess(this.form.id ? "修改成功" : "新增成功");
+            this.open = false;
+            this.getList();
+          });
+        }
+      });
+    },
+
+    /** 取消 */
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+
+    /** 表单重置 */
+    reset() {
+      this.form = {
+        id: null,
+        liveCodeId: null,
+        groupName: null,
+        groupUrl: null,
+        efficientTime: null,
+        assignNum: 0,
+        status: 1
+      };
+      this.resetForm("form");
+    },
+
+    /** 搜索 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+
+    /** 重置 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      // 重置时,如果是从群活码页面跳转过来的,保留liveCodeId筛选
+      if (this.liveCodeId) {
+        this.queryParams.liveCodeId = this.liveCodeId;
+      }
+      this.handleQuery();
+    }
+  }
+};
+</script>

+ 263 - 0
src/views/qw/groupLiveCode/index.vue

@@ -0,0 +1,263 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="活码名称" prop="groupName">
+        <el-input
+          v-model="queryParams.groupName"
+          placeholder="请输入活码名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
+          <el-option label="启用" :value="1" />
+          <el-option label="停用" :value="0" />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @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="mini"
+          @click="handleAdd"
+        >新增</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="groupLiveCodeList" border>
+      <el-table-column label="活码名称" align="center" prop="groupName" />
+      <el-table-column label="实际二维码数量" align="center" prop="qrcodeNum" />
+      <el-table-column label="今日加群数" align="center" prop="toDayNum" />
+      <el-table-column label="累计加群数" align="center" prop="countNum" />
+      <el-table-column label="状态" align="center" prop="status">
+        <template slot-scope="scope">
+          <el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">
+            {{ scope.row.status === 1 ? '启用' : '停用' }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <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"
+            @click="handleStatusChange(scope.row)"
+          >{{ scope.row.status === 1 ? '停用' : '启用' }}</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-arrow-right"
+            @click="handleGotoActual(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-dialog :title="title" :visible.sync="open" width="500px" append-to-body @close="cancel">
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="活码名称" prop="groupName">
+          <el-input v-model="form.groupName" placeholder="请输入活码名称" />
+        </el-form-item>
+        <el-form-item label="项目" prop="projectId">
+          <el-select v-model="form.projectId" placeholder="请选择项目" @change="handleProjectChange">
+            <el-option
+              v-for="item in projectList"
+              :key="item.id"
+              :label="item.projectName"
+              :value="item.id"
+            />
+          </el-select>
+        </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>
+</template>
+
+<script>
+import { listGroupLiveCode, getGroupLiveCode, addOrUpdateGroupLiveCode, delGroupLiveCode } from "@/api/qw/groupLiveCode";
+import { pageProject } from "@/api/adv/project";
+
+export default {
+  name: "GroupLiveCode",
+  data() {
+    return {
+      loading: true,
+      showSearch: true,
+      total: 0,
+      groupLiveCodeList: [],
+      projectList: [],
+      title: "",
+      open: false,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        groupName: null,
+        status: null,
+      },
+      form: {},
+      rules: {
+        groupName: [
+          { required: true, message: "活码名称不能为空", trigger: "blur" }
+        ],
+        projectId: [
+          { required: true, message: "项目不能为空", trigger: "change" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询活码列表 */
+    getList() {
+      this.loading = true;
+      listGroupLiveCode(this.queryParams).then(response => {
+        this.groupLiveCodeList = response.data.records;
+        this.total = response.data.total;
+        this.loading = false;
+      }).catch(() => {
+        this.loading = false;
+      });
+    },
+
+    /** 加载项目列表 */
+    loadProjectList() {
+      pageProject({ pageNum: 1, pageSize: 1000 }).then(response => {
+        this.projectList = response.data.records;
+      }).catch(() => {
+        this.projectList = [];
+      });
+    },
+
+    /** 处理项目变更 */
+    handleProjectChange() {
+      const project = this.projectList.find(p => p.id === this.form.projectId);
+      if (project) {
+        this.form.projectName = project.projectName;
+      }
+    },
+
+    /** 新增按钮 */
+    handleAdd() {
+      this.reset();
+      this.loadProjectList();
+      this.open = true;
+      this.title = "新增活码";
+    },
+
+    /** 修改按钮 */
+    handleUpdate(row) {
+      this.reset();
+      this.loadProjectList();
+      this.open = true;
+      this.title = "修改活码";
+      getGroupLiveCode(row.id).then(response => {
+        this.form = response.data;
+      });
+    },
+
+    /** 启用/停用 */
+    handleStatusChange(row) {
+      const status = row.status === 1 ? 0 : 1;
+      const statusText = status === 1 ? "启用" : "停用";
+      this.$confirm(`确认要${statusText}该活码吗?`, "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        const data = {
+          id: row.id,
+          status: status
+        };
+        addOrUpdateGroupLiveCode(data).then(response => {
+          this.msgSuccess(`${statusText}成功`);
+          this.getList();
+        });
+      }).catch(() => {});
+    },
+
+    /** 进入群实际码页面 */
+    handleGotoActual(row) {
+      this.$router.push({
+        path: '/qw/contactWayC/groupActual',
+        query: { liveCodeId: row.id }
+      });
+    },
+
+    /** 表单提交 */
+    submitForm() {
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          addOrUpdateGroupLiveCode(this.form).then(response => {
+            this.msgSuccess(this.form.id ? "修改成功" : "新增成功");
+            this.open = false;
+            this.getList();
+          });
+        }
+      });
+    },
+
+    /** 取消 */
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+
+    /** 表单重置 */
+    reset() {
+      this.form = {
+        id: null,
+        groupName: null,
+        projectId: null,
+        projectName: null,
+        status: 1
+      };
+      this.resetForm("form");
+    },
+
+    /** 搜索 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+
+    /** 重置 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    }
+  }
+};
+</script>