| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672 |
- <template>
- <ContentWrap>
- <div class="tab-header">
- <span class="tab-title">添加规则</span>
- </div>
- <div class="checkContent">
- <section>
- <span>通知规则种类: </span>
- <el-select v-model="noticeData.type" placeholder="请选择" style="width: 260px">
- <el-option
- v-for="dict in getIntDictOptions(DICT_TYPE.NOTICE_RULES_TYPE)"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </el-select>
- </section>
- <section>
- <span>规则:</span>
- <el-select v-model="noticeData.rule" placeholder="请选择" style="width: 260px">
- <!-- 作业通知-->
- <el-option
- v-show="noticeData.type == 1"
- v-for="dict in getStrDictOptions(DICT_TYPE.JOB_NOTICE_RULES)"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- <!-- 操作通知-->
- <el-option
- v-show="noticeData.type == 3"
- v-for="dict in getIntDictOptions(DICT_TYPE.ACTION_NOTICE_RULES)"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- <!-- 提前通知-->
- <el-option
- v-show="noticeData.type == 0"
- v-for="dict in getIntDictOptions(DICT_TYPE.ADVANCE_NOTICE_RULES)"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- <!-- 步骤通知-->
- <el-option
- v-for="item in actionNoticeList"
- :key="item.id"
- :label="item.stepTitleShort"
- :value="item.id"
- v-show="noticeData.type == 2"
- />
- </el-select>
- </section>
- <section>
- <span>通知时间:</span>
- <el-select v-model="noticeData.notifyTimeType" placeholder="请选择" style="width: 260px">
- <el-option
- v-for="dict in getIntDictOptions(DICT_TYPE.NOTICE_TIME_TYPE)"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </el-select>
- <i v-if="noticeData.notifyTimeType == 0 || noticeData.notifyTimeType == 2">
- <el-input-number
- v-model="timeParts.day"
- :min="0"
- :max="10"
- class="mx-4"
- controls-position="right"
- />
- 天
- <el-input-number
- v-model="timeParts.hour"
- :min="0"
- :max="23"
- class="mx-4"
- controls-position="right"
- />
- 时
- <el-input-number
- v-model="timeParts.minute"
- :min="0"
- :max="59"
- class="mx-4"
- controls-position="right"
- />
- 分
- <el-input-number
- v-model="timeParts.second"
- :min="0"
- :max="59"
- class="mx-4"
- controls-position="right"
- />
- 秒
- </i>
- </section>
- <section>
- <span>通知区域:</span>
- <el-tree-select
- style="width: 260px"
- v-model="noticeData.workstationId"
- :data="workstationOptions"
- :props="{ label: 'label', children: 'children', value: 'id' }"
- placeholder="请选择岗位"
- />
- </section>
- </div>
- </ContentWrap>
- <!-- 通知角色与通知模板-->
- <ContentWrap>
- <div class="tab-header">
- <span class="tab-title">通知角色与通知模板</span>
- </div>
- <div class="tableCon">
- <p>
- <span>显示:</span>
- <el-radio-group v-model="status">
- <el-radio label="showAll" :value="0">显示全部</el-radio>
- <el-radio label="showNotice" :value="1">仅显示通知</el-radio>
- </el-radio-group>
- </p>
- <el-table v-loading="loading" :data="filteredTableData" border style="width: 80%">
- <el-table-column prop="roleName" label="角色" width="180" />
- <el-table-column label="是否通知" align="center" width="100">
- <template #default="scope">
- <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0" />
- </template>
- </el-table-column>
- <el-table-column label="仅通知当事人" align="center" width="110">
- <template #default="scope">
- <el-switch v-model="scope.row.isClient" :active-value="1" :inactive-value="0" />
- </template>
- </el-table-column>
- <el-table-column label="通知模板" align="center">
- <template #default="scope">
- <span>{{ scope.row.notifyTemplateName }}</span>
- <i
- style="margin-left: 8px; color: #409eff; cursor: pointer; font-style: normal"
- @click="changeTemplate(scope.row)"
- >
- {{ scope.row.notifyTemplateName ? '更换' : '选择' }}
- </i>
- </template>
- </el-table-column>
- </el-table>
- </div>
- <div class="btnstyle">
- <el-button type="primary" plain @click="submit()" v-if="route.query.type == 'create'"
- >确认
- </el-button>
- <el-button type="primary" plain @click="submitUpdate()" v-else>确认</el-button>
- <el-button plain @click="goBack()">取消</el-button>
- </div>
- </ContentWrap>
- <!-- 选择模板-->
- <el-dialog v-model="templateDialogVisible" title="请选择通知模板" width="80%" center>
- <!-- 搜索工作栏 -->
- <div class="templateSearch">
- <el-form
- class="-mb-15px"
- :model="templateQueryParams"
- ref="queryFormRef"
- :inline="true"
- label-width="68px"
- >
- <el-form-item label="模板名称" prop="name">
- <el-input
- v-model="templateQueryParams.name"
- placeholder="请输入模板名称"
- clearable
- @keyup.enter="handleQuery"
- class="!w-240px"
- />
- </el-form-item>
- <el-form-item label="模板编号" prop="code">
- <el-input
- v-model="templateQueryParams.code"
- placeholder="请输入模版编码"
- clearable
- @keyup.enter="handleQuery"
- class="!w-240px"
- />
- </el-form-item>
- <el-form-item label="状态" prop="status">
- <el-select
- v-model="templateQueryParams.status"
- placeholder="请选择开启状态"
- clearable
- class="!w-240px"
- >
- <el-option
- v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="创建时间" prop="createTime">
- <el-date-picker
- v-model="templateQueryParams.createTime"
- value-format="YYYY-MM-DD HH:mm:ss"
- type="daterange"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
- class="!w-240px"
- />
- </el-form-item>
- <el-form-item>
- <el-button @click="handleQuery">
- <Icon icon="ep:search" class="mr-5px" />
- 搜索
- </el-button>
- <el-button @click="resetQuery">
- <Icon icon="ep:refresh" class="mr-5px" />
- 重置
- </el-button>
- </el-form-item>
- </el-form>
- </div>
- <el-table
- v-loading="loading"
- :data="templateList"
- @current-change="handleCurrentChange"
- highlight-current-row
- :row-class-name="(row) => (row.code == selectedTemplate?.code ? 'selected-row' : '')"
- style="width: 100%; cursor: pointer"
- >
- <!-- 单选通过点击行来实现 -->
- <el-table-column label="模板编码" prop="code" align="center" width="160" fixed />
- <el-table-column label="模板名称" prop="name" width="200" fixed />
- <el-table-column label="通知人姓名" prop="nickname" width="150" fixed />
- <el-table-column
- label="模板内容"
- align="center"
- prop="content"
- width="300"
- :show-overflow-tooltip="true"
- />
- <el-table-column label="类型" align="center" prop="type">
- <template #default="scope">
- <dict-tag :type="DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE" :value="scope.row.type" />
- </template>
- </el-table-column>
- <el-table-column label="开启状态" align="center" prop="status" width="80">
- <template #default="scope">
- <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
- </template>
- </el-table-column>
- <el-table-column label="备注" align="center" prop="remark" />
- <el-table-column
- label="创建时间"
- align="center"
- prop="createTime"
- width="180"
- :formatter="dateFormatter"
- />
- </el-table>
- <!-- 分页 -->
- <Pagination
- style="width: 100%; text-align: right"
- :total="total"
- v-model:page="templateQueryParams.pageNo"
- v-model:limit="templateQueryParams.pageSize"
- @pagination="getTemplateData"
- />
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="templateDialogVisible = false">取消</el-button>
- <el-button type="primary" @click="templateconfirm()"> 确定</el-button>
- </div>
- </template>
- </el-dialog>
- </template>
- <script setup lang="ts">
- import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
- import * as NotificationRules from '@/api/sop/notificationRules'
- import { getRolePage } from '@/api/system/role'
- import { getNotifyTemplatePage } from '@/api/system/notify/template'
- import { handleTree } from '@/utils/tree'
- import { listMarsDept } from '@/api/system/marsdept'
- import { ref } from 'vue'
- import { dateFormatter } from '@/utils/formatTime'
- const router = useRouter()
- const route = useRoute()
- const noticeData = reactive({
- type: '',
- rule: '',
- notifyTimeType: null,
- notifyTime: '',
- workstationId: '',
- sopId: route.query.id
- })
- const timeParts = reactive({
- day: 0,
- hour: 0,
- minute: 1,
- second: 0
- })
- // const templateQueryParams = reactive({
- // pageNo: 1,
- // pageSize: 10
- // })
- // 角色列表参数
- const roleQueryParams = reactive({
- pageNo: 1,
- pageSize: -1
- })
- const workstationOptions = ref([]) // 岗位树选项
- const tableData = ref([])
- const actionNoticeList = ref([])
- const status = ref(0) // 0: 全部, 1: 仅显示通知项
- const templateDialogVisible = ref(false)
- const loading = ref(false)
- const templateList = ref([])
- const selectedTemplate = ref(null) // 当前选中的模板
- const currentTargetRow = ref(null) // 当前要修改的角色行
- const total = ref(0) // 列表的总页数
- const templateQueryParams = reactive({
- pageNo: 1,
- pageSize: 10,
- name: undefined,
- status: undefined,
- code: undefined,
- createTime: []
- })
- const queryFormRef = ref() // 搜索的表单
- const filteredTableData = computed(() => {
- if (status.value == 0) return tableData.value
- return tableData.value.filter((item) => item.status == 1)
- })
- onMounted(() => {
- getActionNoticeData() //步骤操作的规则数据
- getWorkArea() //获取区域数据
- getTableData()
- console.log(route.query.rowId, '是否传递成功')
- })
- // 返回
- const goBack = () => {
- router.go(-1)
- }
- // 获取工作流程list(步骤操作下拉框内容)
- const getActionNoticeData = async () => {
- try {
- const actionNoticesList = await NotificationRules.getSopWorkflowStepList(route.query.id)
- actionNoticeList.value = actionNoticesList
- console.log(actionNoticesList, '是否拿到sop步骤', actionNoticeList.value)
- } catch (err) {}
- }
- // 区域数据
- const getWorkArea = async () => {
- const { list } = await listMarsDept({ pageNo: 1, pageSize: -1 })
- console.log(list, '岗位筛选')
- const targetId = Number(route.query.workstationId)
- // 找到当前节点
- const currentNode = list.find((item) => item.id === targetId)
- if (!currentNode) return
- // 找父级节点
- const parentNode = list.find((item) => item.id === currentNode.parentId)
- // 构建父子结构
- const filteredTree = parentNode
- ? [
- {
- id: parentNode.id,
- label: parentNode.workstationName,
- children: [
- {
- id: currentNode.id,
- label: currentNode.workstationName
- }
- ]
- }
- ]
- : [
- {
- id: currentNode.id,
- label: currentNode.workstationName
- }
- ]
- // 加入“全部”作为独立选项
- workstationOptions.value = [{ id: 0, label: '全部', children: [] }, ...filteredTree]
- }
- // 通知角色模板中表格数据拼接
- const getTableData = async () => {
- if (route.query.type == 'create') {
- // 创建逻辑保持不变
- loading.value = true
- const [roleRes, notifyRes] = await Promise.all([
- getRolePage(roleQueryParams),
- NotificationRules.getNotifyConfigDetailPage()
- ])
- const roles = roleRes?.list || []
- const notifyMap = new Map()
- ;(notifyRes.list || []).forEach((item) => {
- notifyMap.set(item.roleId, item)
- })
- loading.value = false
- tableData.value = roles.map((role) => {
- const notify = notifyMap.get(role.id)
- return {
- id: role.id,
- roleName: role.name,
- status: 0,
- isClient: 0,
- notifyTemplateName: '',
- notifyConfigId: null
- }
- })
- } else if (route.query.type === 'update') {
- loading.value = true
- const [roleRes, notifyRes] = await Promise.all([
- getRolePage(roleQueryParams),
- NotificationRules.selectNotifyConfigById(route.query.rowId)
- ])
- const roles = roleRes?.list || []
- const notifyList = notifyRes.notifyConfigDetailRespVOList || []
- Object.assign(noticeData, notifyRes)
- noticeData.rule = Number(noticeData.rule)
- if (noticeData.notifyTimeType === 0 || noticeData.notifyTimeType === 2) {
- parseNotifyTimeToParts(noticeData.notifyTime)
- }
- const notifyMap = new Map()
- notifyList.forEach((item) => {
- notifyMap.set(item.roleId, item)
- })
- tableData.value = roles.map((role) => {
- const notify = notifyMap.get(role.id)
- return {
- id: role.id,
- roleName: role.name, // ✅ 修复字段
- status: notify?.status ?? 0,
- isClient: notify?.isClient ?? 0,
- notifyTemplateName: notify?.notifyTemplateName || '',
- notifyConfigId: notify?.id ?? null
- }
- })
- loading.value = false
- }
- }
- // 时间处理
- const parseNotifyTimeToParts = (totalSeconds: number) => {
- timeParts.day = Math.floor(totalSeconds / 86400)
- timeParts.hour = Math.floor((totalSeconds % 86400) / 3600)
- timeParts.minute = Math.floor((totalSeconds % 3600) / 60)
- timeParts.second = totalSeconds % 60
- }
- // 选择或更换模板
- const changeTemplate = async (row) => {
- // 这里你可以打开弹窗、弹出菜单或其他方式让用户选模板
- templateDialogVisible.value = true
- currentTargetRow.value = row
- await getTemplateData()
- }
- // 新增确认
- const submit = async () => {
- try {
- let data
- // let successMessage
- // 新增
- console.log(route.query.type, 'ggggdata')
- // 如果是类型 0 或 2,需要做时间转换
- if (noticeData.notifyTimeType == 0 || noticeData.notifyTimeType == 2) {
- const totalSeconds =
- timeParts.day * 86400 + timeParts.hour * 3600 + timeParts.minute * 60 + timeParts.second
- noticeData.notifyTime = totalSeconds
- } else {
- noticeData.notifyTime = 0
- }
- // ✅ Step 1: 遍历 table 中的数据(filteredTableData 是 computed,所以要加 .value)
- const notifyConfigDetailRespVOList = filteredTableData.value.map((item) => ({
- id: item.notifyConfigId ?? null, // 编辑时的 ID,新增为 null
- roleId: item.id, // 角色 ID
- status: item.status, // 是否通知
- isClient: item.isClient, // 是否仅通知当事人
- notifyTemplateCode: item.notifyTemplateCode, // ✅ 这里已经处理好了
- configId: item.notifyConfigId ?? null // 通知配置 ID
- }))
- // ✅ 校验 2:如果 status 或 isClient 为 1,则 notifyTemplateCode 不可为空
- const hasMissingTemplate = notifyConfigDetailRespVOList.some((item) => {
- return (item.status == 1 || item.isClient == 1) && !item.notifyTemplateCode
- })
- if (hasMissingTemplate) {
- ElMessage.warning('存在启用通知或仅通知当事人的角色,但模板未填写')
- return
- }
- // ✅ 合并表单部分数据 noticeData(例如通知名称、类型等)
- const payload = {
- ...noticeData,
- notifyConfigDetailRespVOList
- }
- data = await NotificationRules.insertNotifyConfig(payload)
- console.log(data, '是否正确')
- console.log(tableData.value, 'tableDataValue-赋值之前')
- if (data) {
- goBack()
- }
- ElMessage.success('保存成功')
- } catch (error) {
- console.error('保存失败:', error)
- // message.error('保存失败')
- }
- }
- // 修改确认
- const submitUpdate = async () => {
- if (noticeData.notifyTimeType == 0 || noticeData.notifyTimeType == 2) {
- const totalSeconds =
- timeParts.day * 86400 + timeParts.hour * 3600 + timeParts.minute * 60 + timeParts.second
- noticeData.notifyTime = totalSeconds
- } else {
- noticeData.notifyTime = 0
- }
- // ✅ 包含主表信息 + 详情数组(tableData.value)
- const payload = {
- ...noticeData,
- notifyConfigDetailRespVOList: filteredTableData.value.map((item) => ({
- notifyTemplateCode: item.notifyTemplateCode,
- roleName: item.roleName,
- roleId: item.id,
- status: item.status,
- isClient: item.isClient,
- notifyTemplateName: item.notifyTemplateName,
- id: item.notifyConfigId // 有id则为修改,无id则为新增
- }))
- }
- // const data = await NotificationRules.updateNotifyConfig(payload)
- const data = await NotificationRules.insertNotifyConfig(payload)
- if (data) {
- ElMessage.success('更新成功')
- }
- }
- // 获取模板数据
- const getTemplateData = async () => {
- try {
- const templateData = await getNotifyTemplatePage(templateQueryParams)
- templateList.value = templateData.list
- total.value = templateData.total
- console.log(templateData, '有什么数据', templateList.value)
- } finally {
- loading.value = false
- }
- }
- // 表格中点击行时触发
- const handleCurrentChange = (row) => {
- selectedTemplate.value = row
- }
- // 弹框确认
- const templateconfirm = async () => {
- if (!selectedTemplate.value || !currentTargetRow.value) return
- // ✅ 存 name(用于页面显示)
- currentTargetRow.value.notifyTemplateName = selectedTemplate.value.name
- // ✅ 存 code(用于接口提交)
- currentTargetRow.value.notifyTemplateCode = selectedTemplate.value.code
- templateDialogVisible.value = false
- }
- /** 搜索按钮操作 */
- const handleQuery = () => {
- templateQueryParams.pageNo = 1
- getTemplateData()
- }
- /** 重置按钮操作 */
- const resetQuery = () => {
- queryFormRef.value.resetFields()
- handleQuery()
- }
- </script>
- <style scoped lang="scss">
- .tab-header {
- background-color: #f5f7fa;
- border-bottom: 1px solid #dcdfe6;
- padding: 12px 20px;
- border-radius: 4px 4px 0 0;
- }
- .checkContent {
- width: 95%;
- height: 200px;
- margin: 10px auto;
- section {
- width: 100%;
- height: 49px;
- display: flex;
- //background: #000;
- span {
- display: block;
- padding: 0 5px 0 0;
- width: 120px;
- line-height: 25px;
- text-align: right;
- }
- i {
- font-style: normal;
- }
- }
- }
- .tableCon {
- width: 95%;
- min-height: 300px;
- margin: auto;
- p {
- margin: 20px 0;
- }
- }
- .btnstyle {
- text-align: right;
- }
- .dialog-footer {
- width: 100%;
- text-align: right;
- }
- /* 鼠标悬停时变小手 */
- .el-table__body tr:hover {
- cursor: pointer;
- }
- /* 选中行的背景设为蓝色,文字颜色可选白色以增强对比 */
- .el-table__body .selected-row {
- background-color: #e6f7ff !important; /* 浅蓝色 */
- /* background-color: #409EFF !important; */
- /* 如果你要主色蓝,可以用这个 */
- }
- .templateSearch {
- width: 100%;
- height: 100%;
- margin: 20px auto 30px;
- }
- </style>
|