Skip to content

Commit 9765822

Browse files
committed
feat(frontend): 新增单据通知设置页面 #8335
1 parent eae37af commit 9765822

File tree

11 files changed

+357
-1
lines changed

11 files changed

+357
-1
lines changed

dbm-ui/frontend/src/common/const/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export * from './dbTypeInfos';
99
export * from './dbTypes';
1010
export * from './localStorageKeys';
1111
export * from './machineTypes';
12+
export * from './messageTypes';
1213
export * from './occupiedInnerHeight';
1314
export * from './osTypes';
1415
export * from './pipelineStatus';
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* 消息通知类型
3+
*/
4+
5+
export enum MessageTypes {
6+
SMS = 'sms',
7+
WEIXIN = 'weixin',
8+
MAIL = 'mail',
9+
VOICE = 'voice',
10+
RTX = 'rtx',
11+
WECOM_ROBOT = 'wecom_robot',
12+
}
13+
14+
export const InputMessageTypes = [MessageTypes.WECOM_ROBOT] as string[];

dbm-ui/frontend/src/components/auth-component/use-base.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const withBizActionList = [
7171
'biz_ticket_config_set',
7272
'doris_apply',
7373
'biz_assistance_vars_config',
74+
'biz_notify_config',
7475
];
7576

7677
export default function (props: Props) {

dbm-ui/frontend/src/layout/Index.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
'StaffManage',
145145
'TicketFlowSetting',
146146
'TicketCooperationSetting',
147+
'TicketNoticeSetting',
147148
],
148149
[menuEnum.resourceManage]: ['ResourceSpec', 'resourceManage', 'resourcePoolDirtyMachines'],
149150
[menuEnum.platformManage]: [

dbm-ui/frontend/src/layout/components/ConfigManage.vue

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,18 @@
7474
{{ t('单据协作设置') }}
7575
</span>
7676
</BkMenuItem>
77+
<BkMenuItem
78+
key="TicketNoticeSetting"
79+
v-db-console="'bizConfigManage.ticketNoticeSetting'">
80+
<template #icon>
81+
<DbIcon type="note" />
82+
</template>
83+
<span
84+
v-overflow-tips.right
85+
class="text-overflow">
86+
{{ t('单据通知') }}
87+
</span>
88+
</BkMenuItem>
7789
</BkMenuGroup>
7890
<BkMenuGroup :name="t('设置')">
7991
<BkMenuItem

dbm-ui/frontend/src/locales/zh-cn.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3882,6 +3882,9 @@
38823882
"Mongo分片集群": "Mongo 分片集群",
38833883
"sqlserver单节点版": "sqlserver 单节点版",
38843884
"sqlserver主从版": "sqlserver 主从版",
3885+
"审批人": "审批人",
3886+
"协助人": "协助人",
3887+
"单据通知": "单据通知",
38853888
"这行勿动!新增翻译请在上一行添加!": ""
38863889

38873890
}

dbm-ui/frontend/src/router/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import getTicketRoutes from '@views/ticket-center/routes';
3636
import getTicketCooperationSettingRoutes from '@views/ticket-cooperation-setting/routes';
3737
import getTicketFlowSettingBizRoutes from '@views/ticket-flow-setting-biz/routes';
3838
import getTicketFlowSettingGlobalRoutes from '@views/ticket-flow-setting-global/routes';
39+
import getTicketNoticeRoutes from '@views/ticket-notice-setting/routes';
3940
import getVersionFilesRoutes from '@views/version-files/routes';
4041
import getWhitelistRoutes from '@views/whitelist/routes';
4142

@@ -140,6 +141,7 @@ export default () => {
140141
...getTicketCooperationSettingRoutes(),
141142
...getTicketFlowSettingGlobalRoutes(),
142143
...businessModuleList,
144+
...getTicketNoticeRoutes(),
143145
],
144146
},
145147
{

dbm-ui/frontend/src/services/model/function-controller/functionController.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export default class FunctionController {
8383
'bizConfigManage.StaffManage': ControllerItem<string>;
8484
'bizConfigManage.ticketFlowSetting': ControllerItem<string>;
8585
'bizConfigManage.ticketCooperationSetting': ControllerItem<string>;
86+
'bizConfigManage.ticketNoticeSetting': ControllerItem<string>;
8687
databaseManage: ControllerItem<string>;
8788
'databaseManage.missionManage': ControllerItem<string>;
8889
'databaseManage.whitelistManage': ControllerItem<string>;

dbm-ui/frontend/src/services/model/ticket/ticket.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ export default class Ticket<T extends unknown | DetailBase = unknown> {
5656

5757
static statusTextMap = {
5858
[STATUS_APPROVE]: t('待审批'),
59-
[STATUS_INNER_TODO]: t('待继续'),
6059
[STATUS_TODO]: t('待执行'),
6160
[STATUS_RUNNING]: t('执行中'),
6261
[STATUS_RESOURCE_REPLENISH]: t('待补货'),
62+
[STATUS_INNER_TODO]: t('待继续'),
6363
[STATUS_FAILED]: t('已失败'),
6464
[STATUS_SUCCEEDED]: t('已完成'),
6565
[STATUS_TERMINATED]: t('已终止'),
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
<!--
2+
* TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available.
3+
*
4+
* Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved.
5+
*
6+
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License athttps://opensource.org/licenses/MIT
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
10+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for
11+
* the specific language governing permissions and limitations under the License.
12+
-->
13+
14+
<template>
15+
<BkLoading :loading="getBizSettingLoading || groupNotifyLoading">
16+
<SmartAction
17+
class="ticket-notice"
18+
:offset-target="getSmartActionOffsetTarget">
19+
<BkCard
20+
:border="false"
21+
class="mb-32"
22+
:show-header="false">
23+
<DbForm
24+
class="notice-form"
25+
:label-width="100">
26+
<DbFormItem
27+
:label="t('通知方式')"
28+
required>
29+
<BkTable
30+
align="center"
31+
border="full"
32+
class="notice-table"
33+
:columns="columns"
34+
:data="dataList"
35+
header-align="center"
36+
:header-cell-class-name="setHeadCellClassName">
37+
</BkTable>
38+
</DbFormItem>
39+
</DbForm>
40+
</BkCard>
41+
<template #action>
42+
<AuthButton
43+
action-id="biz_notify_config"
44+
class="w-88"
45+
:loading="updateSettingLoading"
46+
:resource="bizId"
47+
theme="primary"
48+
@click="handleSubmit">
49+
{{ t('提交') }}
50+
</AuthButton>
51+
<BkButton
52+
class="ml8 w-88"
53+
:disabled="updateSettingLoading"
54+
@click="handleReset">
55+
{{ t('重置') }}
56+
</BkButton>
57+
</template>
58+
</SmartAction>
59+
</BkLoading>
60+
</template>
61+
<script setup lang="tsx">
62+
import _ from 'lodash';
63+
import { useI18n } from 'vue-i18n';
64+
import { useRequest } from 'vue-request';
65+
66+
import TicketModel from '@services/model/ticket/ticket';
67+
import { getBizSettingList, updateBizSetting } from '@services/source/bizSetting';
68+
import { getAlarmGroupNotifyList } from '@services/source/monitorNoticeGroup';
69+
70+
import { InputMessageTypes, MessageTypes } from '@common/const'
71+
72+
import { messageSuccess } from '@utils';
73+
74+
interface DataRow {
75+
status: string;
76+
statusText: string;
77+
noticeMember: string[];
78+
checkbox: Record<string, boolean>,
79+
input: Record<string, string>,
80+
}
81+
82+
const { t } = useI18n();
83+
84+
const dataList = ref<DataRow[]>([]);
85+
86+
const bizId = window.PROJECT_CONFIG.BIZ_ID
87+
88+
const columns = computed(() => {
89+
const baseColumns = [
90+
{
91+
label: t('单据状态'),
92+
field: 'statusText',
93+
width: 100,
94+
},
95+
{
96+
label: t('通知对象'),
97+
field: 'noticeMember',
98+
width: 200,
99+
render: ({ data } : { data: DataRow }) => data.noticeMember.join('')
100+
},
101+
];
102+
103+
const nofityColumns = (alarmGroupNotifyList.value || []).filter((item) => item.is_active).map(item => {
104+
const isInputType = InputMessageTypes.includes(item.type)
105+
return {
106+
field: item.type,
107+
minWidth: isInputType ? 320 : 120,
108+
showOverflowTooltip: false,
109+
renderHead: () => (
110+
<div class="message-type-head">
111+
<img
112+
height="20"
113+
src={`data:image/png;base64,${item.icon}`}
114+
width="20" />
115+
<span
116+
class="ml-4">
117+
{ item.label }
118+
</span>
119+
</div>
120+
),
121+
render: ({ data } : { data: DataRow }) => {
122+
if (isInputType) {
123+
return (
124+
<bk-input
125+
v-model={data.input[item.type]}
126+
placeholder={t('请输入群ID')}/>
127+
)
128+
}
129+
return <bk-checkbox v-model={data.checkbox[item.type]}/>
130+
}
131+
}
132+
});
133+
134+
return [...baseColumns, ...nofityColumns];
135+
});
136+
137+
const { loading: getBizSettingLoading, data: bizSetting, run: runGetBizSettingList } = useRequest(getBizSettingList, {
138+
manual: true,
139+
});
140+
141+
const { loading: groupNotifyLoading, data: alarmGroupNotifyList, run: runGetAlarmGroupNotifyList } = useRequest(getAlarmGroupNotifyList, {
142+
manual: true,
143+
});
144+
145+
const { loading: updateSettingLoading, run: runUpdateBizSetting } = useRequest(updateBizSetting, {
146+
manual: true,
147+
onSuccess: () => {
148+
messageSuccess(t('保存成功'));
149+
},
150+
});
151+
152+
watch([bizSetting, alarmGroupNotifyList], () => {
153+
if (bizSetting.value && alarmGroupNotifyList.value) {
154+
const activeTypeMap = alarmGroupNotifyList.value.reduce<{
155+
checkbox: Record<string, boolean>,
156+
input: Record<string, string>,
157+
}>((prevMap, item) => {
158+
if (item.is_active) {
159+
if (InputMessageTypes.includes(item.type)) {
160+
Object.assign(prevMap.input, {
161+
[item.type]: ''
162+
})
163+
} else {
164+
Object.assign(prevMap.checkbox, {
165+
[item.type]: false
166+
})
167+
}
168+
}
169+
return prevMap;
170+
}, {
171+
checkbox: {},
172+
input: {}
173+
})
174+
175+
const isBizSettingEmpty = _.isEmpty(bizSetting.value) || _.isEmpty(bizSetting.value.NOTIFY_CONFIG)
176+
const list: DataRow[] = []
177+
178+
Object.entries(TicketModel.statusTextMap).forEach(([status, statusText]) => {
179+
if (![TicketModel.STATUS_RUNNING, TicketModel.STATUS_TIMER].includes(status)) {
180+
const initSetting = _.cloneDeep(activeTypeMap)
181+
if (isBizSettingEmpty) {
182+
[MessageTypes.MAIL, MessageTypes.RTX].forEach(type => {
183+
if (initSetting.checkbox[type] !== undefined) {
184+
initSetting.checkbox[type] = true;
185+
}
186+
});
187+
} else {
188+
const statusBizSetting = bizSetting.value!.NOTIFY_CONFIG[status]
189+
Object.keys(initSetting.checkbox).forEach(initSettingKey => {
190+
initSetting.checkbox[initSettingKey] = statusBizSetting[initSettingKey] || false
191+
})
192+
Object.keys(initSetting.input).forEach(initSettingKey => {
193+
initSetting.input[initSettingKey] = (statusBizSetting[initSettingKey] || []).join(',')
194+
})
195+
}
196+
197+
list.push({
198+
status,
199+
statusText,
200+
noticeMember: status === TicketModel.STATUS_APPROVE ? [t('审批人')] : [t('提单人'), t('协助人')],
201+
checkbox: initSetting.checkbox,
202+
input: initSetting.input
203+
})
204+
}
205+
})
206+
dataList.value = list
207+
}
208+
})
209+
210+
const setHeadCellClassName = ({ columnIndex }: { columnIndex: number }) => columnIndex < 2 ? 'common-head' : ''
211+
212+
const getSmartActionOffsetTarget = () => document.querySelector('.bk-form-content');
213+
214+
const getData = () => {
215+
runGetBizSettingList({
216+
bk_biz_id: bizId,
217+
key: 'NOTIFY_CONFIG',
218+
})
219+
runGetAlarmGroupNotifyList({
220+
bk_biz_id: bizId
221+
})
222+
}
223+
224+
const handleSubmit = () => {
225+
runUpdateBizSetting({
226+
bk_biz_id: bizId,
227+
key: 'NOTIFY_CONFIG',
228+
value: dataList.value.reduce<Record<string, Record<string, boolean | string[]>>>((prevMap, dataItem) => {
229+
const checkboxMap = Object.entries(dataItem.checkbox).reduce<Record<string, boolean>>((prevMap, [key, value])=> {
230+
if (value) {
231+
return Object.assign({}, prevMap, { [key]: value })
232+
}
233+
return prevMap
234+
}, {})
235+
const inputMap = Object.entries(dataItem.input).reduce<Record<string, string[]>>((prevMap, [key, value])=> {
236+
if (value) {
237+
return Object.assign({}, prevMap, { [key]: value.split(',') })
238+
}
239+
return prevMap
240+
}, {})
241+
return Object.assign({}, prevMap, {
242+
[dataItem.status]: {
243+
...checkboxMap,
244+
...inputMap
245+
}
246+
})
247+
}, {})
248+
})
249+
};
250+
251+
const handleReset = () => {
252+
getData()
253+
};
254+
255+
// 初始化查询
256+
getData()
257+
</script>
258+
259+
<style lang="less" scoped>
260+
.ticket-notice {
261+
padding: 20px;
262+
263+
.db-card {
264+
& ~ .db-card {
265+
margin: 20px;
266+
}
267+
}
268+
269+
:deep(.notice-form) {
270+
padding: 24px 0;
271+
272+
.bk-form-label {
273+
font-size: 12px;
274+
}
275+
}
276+
277+
:deep(.notice-table) {
278+
th {
279+
&.common-head {
280+
font-weight: bolder;
281+
}
282+
283+
.message-type-head {
284+
display: flex;
285+
align-items: center;
286+
}
287+
}
288+
}
289+
}
290+
</style>

0 commit comments

Comments
 (0)