gaoluyang
2026-05-08 d693272409250e5d9afad65e82a8581dc395d7fa
浪潮
1.日志前端页面开发与联调
已修改2个文件
286 ■■■■■ 文件已修改
src/api/collaborativeApproval/journal.js 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/journal/index.vue 268 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/collaborativeApproval/journal.js
@@ -3,7 +3,7 @@
// 查询日志列表
export function listJournal(query) {
  return request({
    url: "/collaborativeApproval/journal/page",
    url: "/sysLogReport/listPage",
    method: "get",
    params: query,
  });
@@ -20,7 +20,7 @@
// 新增日志
export function addJournal(data) {
  return request({
    url: "/collaborativeApproval/journal/add",
    url: "/sysLogReport/add",
    method: "post",
    data: data,
  });
@@ -29,7 +29,7 @@
// 修改日志
export function updateJournal(data) {
  return request({
    url: "/collaborativeApproval/journal/update",
    url: "/sysLogReport/update",
    method: "put",
    data: data,
  });
@@ -38,17 +38,9 @@
// 删除日志
export function delJournal(ids) {
  return request({
    url: "/collaborativeApproval/journal/" + ids,
    url: "/sysLogReport/delete",
    method: "delete",
  });
}
// 推送日志
export function pushJournal(data) {
  return request({
    url: "/collaborativeApproval/journal/push",
    method: "post",
    data: data,
    data: ids,
  });
}
src/views/collaborativeApproval/journal/index.vue
@@ -6,9 +6,6 @@
        <el-form-item label="日志标题">
          <el-input v-model="searchForm.title" placeholder="请输入日志标题" clearable />
        </el-form-item>
        <el-form-item label="创建人">
          <el-input v-model="searchForm.createUserName" placeholder="请输入创建人" clearable />
        </el-form-item>
        <el-form-item label="创建时间">
          <el-date-picker
            v-model="searchForm.dateRange"
@@ -37,7 +34,6 @@
            <span>
              <el-icon><Calendar /></el-icon>
              日报
              <span class="tab-count" v-if="journalCount.daily > 0">({{ journalCount.daily }})</span>
            </span>
          </template>
        </el-tab-pane>
@@ -46,7 +42,6 @@
            <span>
              <el-icon><Document /></el-icon>
              周报
              <span class="tab-count" v-if="journalCount.weekly > 0">({{ journalCount.weekly }})</span>
            </span>
          </template>
        </el-tab-pane>
@@ -55,7 +50,6 @@
            <span>
              <el-icon><DataAnalysis /></el-icon>
              月报
              <span class="tab-count" v-if="journalCount.monthly > 0">({{ journalCount.monthly }})</span>
            </span>
          </template>
        </el-tab-pane>
@@ -64,31 +58,24 @@
      <!-- 日志表格 -->
      <el-table :data="journalList" v-loading="loading" border style="width: 100%">
        <el-table-column type="index" label="序号" width="60" align="center" />
        <el-table-column prop="title" label="日志标题" min-width="200" show-overflow-tooltip>
        <el-table-column prop="title" label="日志标题" show-overflow-tooltip />
        <el-table-column prop="reportType" label="报告类型" width="100" align="center">
          <template #default="scope">
            <el-link type="primary" @click="handleView(scope.row)">{{ scope.row.title }}</el-link>
            <el-tag :type="getTypeTagType(scope.row.reportType)">{{ getTypeText(scope.row.reportType) }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="type" label="日志类型" width="100" align="center">
        <el-table-column prop="logType" label="日志类型" align="center">
          <template #default="scope">
            <el-tag :type="getTypeTagType(scope.row.type)">{{ getTypeText(scope.row.type) }}</el-tag>
            <el-tag>{{ getLogTypeText(scope.row.logType) }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="content" label="日志内容" min-width="300" show-overflow-tooltip />
        <el-table-column prop="createUserName" label="创建人" width="120" align="center" />
        <el-table-column prop="createTime" label="创建时间" width="160" align="center" />
        <el-table-column prop="pushStatus" label="推送状态" width="100" align="center">
          <template #default="scope">
            <el-tag :type="scope.row.pushStatus === 1 ? 'success' : 'info'">
              {{ scope.row.pushStatus === 1 ? '已推送' : '未推送' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="createUserName" label="创建人" align="center" />
        <el-table-column prop="createTime" label="创建时间" align="center" />
        <el-table-column prop="ccUserName" label="抄送人" align="center" />
        <el-table-column label="操作" width="250" align="center" fixed="right">
          <template #default="scope">
            <el-button link type="primary" @click="handleView(scope.row)">查看</el-button>
            <el-button link type="primary" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button link type="success" @click="handlePush(scope.row)" v-if="scope.row.pushStatus !== 1">推送</el-button>
            <el-button link type="primary" @click="handleView(scope.row)">查看</el-button>
            <el-button link type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
          </template>
        </el-table-column>
@@ -98,9 +85,9 @@
      <pagination
        v-show="total > 0"
        :total="total"
        v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize"
        @pagination="getList"
        v-model:page="queryParams.current"
        v-model:limit="queryParams.size"
        @pagination="({ page, limit }) => { queryParams.current = page; queryParams.size = limit; getList(); }"
      />
      <!-- 空状态 -->
@@ -120,8 +107,8 @@
      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="日志类型" prop="type">
              <el-select v-model="form.type" placeholder="请选择日志类型" style="width: 100%">
            <el-form-item label="报告类型">
              <el-select v-model="form.reportType" disabled style="width: 100%">
                <el-option label="日报" value="daily" />
                <el-option label="周报" value="weekly" />
                <el-option label="月报" value="monthly" />
@@ -129,6 +116,18 @@
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日志类型" prop="logType">
              <el-select v-model="form.logType" placeholder="请选择日志类型" style="width: 100%">
                <el-option label="工作" value="work" />
                <el-option label="项目" value="project" />
                <el-option label="问题" value="problem" />
                <el-option label="其他" value="other" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="日志标题" prop="title">
              <el-input v-model="form.title" placeholder="请输入日志标题" />
            </el-form-item>
@@ -150,6 +149,31 @@
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="抄送人" prop="ccUserIds">
              <el-select
                v-model="form.ccUserIds"
                multiple
                filterable
                remote
                reserve-keyword
                placeholder="请输入抄送人名称搜索"
                :remote-method="searchPushUsers"
                :loading="userLoading"
                style="width: 100%"
              >
                <el-option
                  v-for="item in userOptions"
                  :key="item.userId"
                  :label="item.nickName"
                  :value="item.userId"
                >
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="备注">
              <el-input
                v-model="form.remark"
@@ -164,11 +188,8 @@
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">保 存</el-button>
          <el-button type="success" @click="submitAndPushForm">保存并推送</el-button>
          <el-button @click="dialogVisible = false">取 消</el-button>
        </div>
                <el-button type="primary" @click="submitForm">保存</el-button>
                <el-button @click="dialogVisible = false">取 消</el-button>
      </template>
    </el-dialog>
@@ -183,14 +204,15 @@
        <div class="detail-header">
          <h3 class="detail-title">{{ currentJournal.title }}</h3>
          <div class="detail-meta">
            <el-tag :type="getTypeTagType(currentJournal.type)">{{ getTypeText(currentJournal.type) }}</el-tag>
            <el-tag :type="getTypeTagType(currentJournal.reportType)">{{ getTypeText(currentJournal.reportType) }}</el-tag>
            <el-tag>{{ getLogTypeText(currentJournal.logType) }}</el-tag>
            <el-tag :type="currentJournal.pushStatus === 1 ? 'success' : 'info'">
              {{ currentJournal.pushStatus === 1 ? '已推送' : '未推送' }}
            </el-tag>
          </div>
        </div>
        <div class="detail-info">
          <span><el-icon><User /></el-icon> 创建人:{{ currentJournal.createUserName }}</span>
          <span><el-icon><User /></el-icon> 创建人:{{ currentJournal.createUser }}</span>
          <span><el-icon><Timer /></el-icon> 创建时间:{{ currentJournal.createTime }}</span>
        </div>
        <el-divider />
@@ -204,11 +226,9 @@
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="handleEditFromView" v-if="currentJournal.pushStatus !== 1">编 辑</el-button>
          <el-button type="success" @click="handlePushFromView" v-if="currentJournal.pushStatus !== 1">推 送</el-button>
          <el-button @click="viewDialogVisible = false">关 闭</el-button>
        </div>
                <el-button type="primary" @click="handleEditFromView" v-if="currentJournal.pushStatus !== 1">编 辑</el-button>
                <el-button type="success" @click="handlePushFromView" v-if="currentJournal.pushStatus !== 1">推 送</el-button>
                <el-button @click="viewDialogVisible = false">关 闭</el-button>
      </template>
    </el-dialog>
@@ -224,14 +244,14 @@
        <p><strong>日志类型:</strong>{{ getTypeText(currentJournal.type) }}</p>
      </div>
      <el-form ref="pushFormRef" :model="pushForm" :rules="pushRules" label-width="100px">
        <el-form-item label="推送人员" prop="userIds">
        <el-form-item label="抄送人" prop="userIds">
          <el-select
            v-model="pushForm.userIds"
            multiple
            filterable
            remote
            reserve-keyword
            placeholder="请输入用户名搜索"
            placeholder="请输入抄送人名称搜索"
            :remote-method="remoteSearchUser"
            :loading="userLoading"
            style="width: 100%"
@@ -239,11 +259,9 @@
            <el-option
              v-for="item in userOptions"
              :key="item.userId"
              :label="item.userName"
              :label="item.nickName"
              :value="item.userId"
            >
              <span>{{ item.userName }}</span>
              <span style="float: right; color: #8492a6; font-size: 13px">{{ item.deptName }}</span>
            </el-option>
          </el-select>
        </el-form-item>
@@ -273,13 +291,11 @@
import useUserStore from "@/store/modules/user";
import {
  listJournal,
  getJournal,
  addJournal,
  updateJournal,
  delJournal,
  pushJournal,
  listUser
  delJournal
} from "@/api/collaborativeApproval/journal.js";
import { userListNoPage } from "@/api/system/user.js";
import Pagination from "@/components/Pagination/index.vue";
const userStore = useUserStore();
@@ -288,19 +304,23 @@
const data = reactive({
  searchForm: {
    title: "",
    createUserName: "",
    dateRange: []
  },
  form: {
    id: undefined,
    type: "daily",
    reportType: "daily",
    logType: "work",
    title: "",
    content: "",
    remark: "",
    pushStatus: 0
    pushStatus: 0,
    ccUserIds: []
  },
  rules: {
    type: [
    reportType: [
      { required: true, message: "请选择报告类型", trigger: "change" }
    ],
    logType: [
      { required: true, message: "请选择日志类型", trigger: "change" }
    ],
    title: [
@@ -331,8 +351,8 @@
// 查询参数
const queryParams = reactive({
  pageNum: 1,
  pageSize: 10
  current: 1,
  size: 10
});
// 推送表单
@@ -359,16 +379,13 @@
const getList = () => {
  loading.value = true;
  const params = {
    pageNum: queryParams.pageNum,
    pageSize: queryParams.pageSize,
    type: activeJournalType.value
    current: queryParams.current,
    size: queryParams.size,
    reportType: activeJournalType.value
  };
  if (searchForm.value.title) {
    params.title = searchForm.value.title;
  }
  if (searchForm.value.createUserName) {
    params.createUserName = searchForm.value.createUserName;
  }
  if (searchForm.value.dateRange && searchForm.value.dateRange.length === 2) {
    params.startTime = searchForm.value.dateRange[0];
@@ -390,10 +407,10 @@
// 获取所有类型数量
const getAllTypeCounts = () => {
  ['daily', 'weekly', 'monthly'].forEach(type => {
    listJournal({ pageNum: 1, pageSize: 1, type }).then(res => {
  ['daily', 'weekly', 'monthly'].forEach(reportType => {
    listJournal({ current: 1, size: 1, reportType }).then(res => {
      if (res.code === 200) {
        journalCount[type] = res.data.total || 0;
        journalCount[reportType] = res.data.total || 0;
      }
    });
  });
@@ -402,13 +419,13 @@
// Tab切换
const handleTabChange = (tabName) => {
  activeJournalType.value = tabName;
  queryParams.pageNum = 1;
  queryParams.current = 1;
  getList();
};
// 搜索
const handleQuery = () => {
  queryParams.pageNum = 1;
  queryParams.current = 1;
  getList();
};
@@ -416,22 +433,27 @@
const resetQuery = () => {
  searchForm.value = {
    title: "",
    createUserName: "",
    dateRange: []
  };
  handleQuery();
};
// 获取类型文本
const getTypeText = (type) => {
const getTypeText = (reportType) => {
  const typeMap = { daily: "日报", weekly: "周报", monthly: "月报" };
  return typeMap[type] || type;
  return typeMap[reportType] || reportType;
};
// 获取日志类型文本
const getLogTypeText = (logType) => {
  const typeMap = { work: "工作", project: "项目", problem: "问题", other: "其他" };
  return typeMap[logType] || logType;
};
// 获取类型标签样式
const getTypeTagType = (type) => {
const getTypeTagType = (reportType) => {
  const typeMap = { daily: "primary", weekly: "success", monthly: "warning" };
  return typeMap[type] || "";
  return typeMap[reportType] || "";
};
// 打开表单
@@ -440,25 +462,25 @@
    dialogTitle.value = "编写日志";
    form.value = {
      id: undefined,
      type: activeJournalType.value,
      reportType: activeJournalType.value,
      logType: "work",
      title: "",
      content: "",
      remark: "",
      pushStatus: 0
      pushStatus: 0,
      ccUserIds: []
    };
  }
  dialogVisible.value = true;
  loadUserOptions();
};
// 编辑日志
const handleEdit = (row) => {
  if (row.pushStatus === 1) {
    ElMessage.warning("已推送的日志不可编辑");
    return;
  }
  dialogTitle.value = "编辑日志";
  form.value = { ...row };
  form.value = { ...row, ccUserIds: row.ccUserIds || [] };
  dialogVisible.value = true;
  loadUserOptions();
};
// 从查看页面编辑
@@ -469,12 +491,8 @@
// 查看日志
const handleView = (row) => {
  getJournal(row.id).then(res => {
    if (res.code === 200) {
      currentJournal.value = res.data;
      viewDialogVisible.value = true;
    }
  });
  currentJournal.value = { ...row };
  viewDialogVisible.value = true;
};
// 删除日志
@@ -488,11 +506,10 @@
      type: "warning"
    }
  ).then(() => {
    delJournal(id).then(res => {
    delJournal([id]).then(res => {
      if (res.code === 200) {
        ElMessage.success("删除成功");
        getList();
        getAllTypeCounts();
      }
    });
  });
@@ -517,79 +534,39 @@
// 加载用户选项
const loadUserOptions = () => {
  listUser({ pageNum: 1, pageSize: 100 }).then(res => {
  userListNoPage().then(res => {
    if (res.code === 200) {
      userOptions.value = res.data.records || res.data || [];
      userOptions.value = res.data || [];
    }
  });
};
// 远程搜索用户
const remoteSearchUser = (query) => {
  if (query) {
    userLoading.value = true;
    listUser({ userName: query, pageNum: 1, pageSize: 50 }).then(res => {
      if (res.code === 200) {
        userOptions.value = res.data.records || res.data || [];
      }
      userLoading.value = false;
    }).catch(() => {
      userLoading.value = false;
    });
  }
// 远程搜索抄送用户
const searchPushUsers = (query) => {
  userLoading.value = true;
  userListNoPage().then(res => {
    if (res.code === 200) {
      userOptions.value = res.data || [];
    }
    userLoading.value = false;
  }).catch(() => {
    userLoading.value = false;
  });
};
// 提交表单
const submitForm = () => {
  formRef.value.validate((valid) => {
    if (valid) {
      const api = form.value.id ? updateJournal : addJournal;
      api(form.value).then(res => {
      const isEdit = !!form.value.id;
      const api = isEdit ? updateJournal : addJournal;
      const saveData = { ...form.value };
      api(saveData).then(res => {
        if (res.code === 200) {
          ElMessage.success(form.value.id ? "修改成功" : "新增成功");
          ElMessage.success(isEdit ? "修改成功" : "保存成功");
          dialogVisible.value = false;
          getList();
          getAllTypeCounts();
        }
      });
    }
  });
};
// 提交并推送
const submitAndPushForm = () => {
  formRef.value.validate((valid) => {
    if (valid) {
      const api = form.value.id ? updateJournal : addJournal;
      api(form.value).then(res => {
        if (res.code === 200) {
          const journalId = form.value.id || res.data;
          dialogVisible.value = false;
          // 打开推送弹窗
          currentJournal.value = { ...form.value, id: journalId };
          pushForm.journalId = journalId;
          pushForm.userIds = [];
          pushForm.remark = "";
          pushDialogVisible.value = true;
          loadUserOptions();
          getList();
          getAllTypeCounts();
        }
      });
    }
  });
};
// 提交推送
const submitPush = () => {
  pushFormRef.value.validate((valid) => {
    if (valid) {
      pushJournal(pushForm).then(res => {
        if (res.code === 200) {
          ElMessage.success("推送成功");
          pushDialogVisible.value = false;
          getList();
          getAllTypeCounts();
        }
      });
    }
@@ -603,7 +580,6 @@
onMounted(() => {
  getList();
  getAllTypeCounts();
});
</script>