mirror of
https://gitee.com/pnoker/iot-dc3.git
synced 2026-09-19 02:04:37 +08:00
feat: add alarm/command/event types, i18n entries, shared styles, and thingModel format utilities
This commit is contained in:
+33
-37
@@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { httpGet, httpPost } from '@/api/common';
|
||||
import { crudAdd, crudDelete, crudGetById, crudList, crudUpdate } from '@/api/common';
|
||||
import { API_DATA_BASE } from '@/config/constant/api';
|
||||
import type { PageQuery, PageResult } from '@/config/types';
|
||||
import type { PageQuery } from '@/config/types';
|
||||
import type {
|
||||
MessageRecord,
|
||||
NotifyChannelBindRecord,
|
||||
@@ -37,45 +37,41 @@ const endpoints = {
|
||||
history: `${API_DATA_BASE}/notify/history`,
|
||||
} as const;
|
||||
|
||||
const add = <T>(base: string, payload: T) => httpPost(`${base}/add`, payload);
|
||||
const update = <T>(base: string, payload: T) => httpPost(`${base}/update`, payload);
|
||||
const remove = (base: string, id: string) => httpPost(`${base}/delete`, undefined, { params: { id } });
|
||||
const selectById = <T>(base: string, id: string) => httpGet<R<T>>(`${base}/get_by_id`, { params: { id } });
|
||||
const list = <T>(base: string, query: PageQuery) => httpPost<R<PageResult<T>>>(`${base}/list`, query);
|
||||
export const addRule = (payload: Partial<RuleRecord>) => crudAdd(endpoints.rule, payload);
|
||||
export const updateRule = (payload: Partial<RuleRecord>) => crudUpdate(endpoints.rule, payload);
|
||||
export const deleteRule = (id: string) => crudDelete(endpoints.rule, id);
|
||||
export const getRuleById = (id: string) => crudGetById<RuleRecord>(endpoints.rule, id);
|
||||
export const listRule = (query: PageQuery) => crudList<RuleRecord>(endpoints.rule, query);
|
||||
|
||||
export const addRule = (payload: Partial<RuleRecord>) => add(endpoints.rule, payload);
|
||||
export const updateRule = (payload: Partial<RuleRecord>) => update(endpoints.rule, payload);
|
||||
export const deleteRule = (id: string) => remove(endpoints.rule, id);
|
||||
export const getRuleById = (id: string) => selectById<RuleRecord>(endpoints.rule, id);
|
||||
export const listRule = (query: PageQuery) => list<RuleRecord>(endpoints.rule, query);
|
||||
export const addNotify = (payload: Partial<NotifyRecord>) => crudAdd(endpoints.notify, payload);
|
||||
export const updateNotify = (payload: Partial<NotifyRecord>) => crudUpdate(endpoints.notify, payload);
|
||||
export const deleteNotify = (id: string) => crudDelete(endpoints.notify, id);
|
||||
export const getNotifyById = (id: string) => crudGetById<NotifyRecord>(endpoints.notify, id);
|
||||
export const listNotify = (query: PageQuery) => crudList<NotifyRecord>(endpoints.notify, query);
|
||||
|
||||
export const addNotify = (payload: Partial<NotifyRecord>) => add(endpoints.notify, payload);
|
||||
export const updateNotify = (payload: Partial<NotifyRecord>) => update(endpoints.notify, payload);
|
||||
export const deleteNotify = (id: string) => remove(endpoints.notify, id);
|
||||
export const getNotifyById = (id: string) => selectById<NotifyRecord>(endpoints.notify, id);
|
||||
export const listNotify = (query: PageQuery) => list<NotifyRecord>(endpoints.notify, query);
|
||||
export const addMessage = (payload: Partial<MessageRecord>) => crudAdd(endpoints.message, payload);
|
||||
export const updateMessage = (payload: Partial<MessageRecord>) => crudUpdate(endpoints.message, payload);
|
||||
export const deleteMessage = (id: string) => crudDelete(endpoints.message, id);
|
||||
export const getMessageById = (id: string) => crudGetById<MessageRecord>(endpoints.message, id);
|
||||
export const listMessage = (query: PageQuery) => crudList<MessageRecord>(endpoints.message, query);
|
||||
|
||||
export const addMessage = (payload: Partial<MessageRecord>) => add(endpoints.message, payload);
|
||||
export const updateMessage = (payload: Partial<MessageRecord>) => update(endpoints.message, payload);
|
||||
export const deleteMessage = (id: string) => remove(endpoints.message, id);
|
||||
export const getMessageById = (id: string) => selectById<MessageRecord>(endpoints.message, id);
|
||||
export const listMessage = (query: PageQuery) => list<MessageRecord>(endpoints.message, query);
|
||||
export const addNotifyChannel = (payload: Partial<NotifyChannelRecord>) => crudAdd(endpoints.channel, payload);
|
||||
export const updateNotifyChannel = (payload: Partial<NotifyChannelRecord>) => crudUpdate(endpoints.channel, payload);
|
||||
export const deleteNotifyChannel = (id: string) => crudDelete(endpoints.channel, id);
|
||||
export const getNotifyChannelById = (id: string) => crudGetById<NotifyChannelRecord>(endpoints.channel, id);
|
||||
export const listNotifyChannel = (query: PageQuery) => crudList<NotifyChannelRecord>(endpoints.channel, query);
|
||||
|
||||
export const addNotifyChannel = (payload: Partial<NotifyChannelRecord>) => add(endpoints.channel, payload);
|
||||
export const updateNotifyChannel = (payload: Partial<NotifyChannelRecord>) => update(endpoints.channel, payload);
|
||||
export const deleteNotifyChannel = (id: string) => remove(endpoints.channel, id);
|
||||
export const getNotifyChannelById = (id: string) => selectById<NotifyChannelRecord>(endpoints.channel, id);
|
||||
export const listNotifyChannel = (query: PageQuery) => list<NotifyChannelRecord>(endpoints.channel, query);
|
||||
|
||||
export const addNotifyChannelBind = (payload: Partial<NotifyChannelBindRecord>) => add(endpoints.channelBind, payload);
|
||||
export const addNotifyChannelBind = (payload: Partial<NotifyChannelBindRecord>) =>
|
||||
crudAdd(endpoints.channelBind, payload);
|
||||
export const updateNotifyChannelBind = (payload: Partial<NotifyChannelBindRecord>) =>
|
||||
update(endpoints.channelBind, payload);
|
||||
export const deleteNotifyChannelBind = (id: string) => remove(endpoints.channelBind, id);
|
||||
export const getNotifyChannelBindById = (id: string) => selectById<NotifyChannelBindRecord>(endpoints.channelBind, id);
|
||||
export const listNotifyChannelBind = (query: PageQuery) => list<NotifyChannelBindRecord>(endpoints.channelBind, query);
|
||||
crudUpdate(endpoints.channelBind, payload);
|
||||
export const deleteNotifyChannelBind = (id: string) => crudDelete(endpoints.channelBind, id);
|
||||
export const getNotifyChannelBindById = (id: string) => crudGetById<NotifyChannelBindRecord>(endpoints.channelBind, id);
|
||||
export const listNotifyChannelBind = (query: PageQuery) =>
|
||||
crudList<NotifyChannelBindRecord>(endpoints.channelBind, query);
|
||||
|
||||
export const getRuleStateById = (id: string) => selectById<RuleStateRecord>(endpoints.state, id);
|
||||
export const listRuleState = (query: PageQuery) => list<RuleStateRecord>(endpoints.state, query);
|
||||
export const getRuleStateById = (id: string) => crudGetById<RuleStateRecord>(endpoints.state, id);
|
||||
export const listRuleState = (query: PageQuery) => crudList<RuleStateRecord>(endpoints.state, query);
|
||||
|
||||
export const getNotifyHistoryById = (id: string) => selectById<NotifyHistoryRecord>(endpoints.history, id);
|
||||
export const listNotifyHistory = (query: PageQuery) => list<NotifyHistoryRecord>(endpoints.history, query);
|
||||
export const getNotifyHistoryById = (id: string) => crudGetById<NotifyHistoryRecord>(endpoints.history, id);
|
||||
export const listNotifyHistory = (query: PageQuery) => crudList<NotifyHistoryRecord>(endpoints.history, query);
|
||||
|
||||
+20
-15
@@ -14,33 +14,38 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { httpGet, httpPost } from '@/api/common';
|
||||
import { crudAdd, crudDelete, crudGetById, crudList, crudUpdate, httpGet, httpPost } from '@/api/common';
|
||||
import { API_DATA_BASE, API_MANAGER_BASE } from '@/config/constant/api';
|
||||
import type { PageQuery, PageResult } from '@/config/types';
|
||||
import type { CommandHistory, CommandRecord } from '@/config/types/command';
|
||||
import type { CommandHistory, CommandParamRecord, CommandRecord } from '@/config/types/command';
|
||||
|
||||
const endpoints = {
|
||||
command: `${API_MANAGER_BASE}/command`,
|
||||
commandParam: `${API_MANAGER_BASE}/command_param`,
|
||||
commandHistory: `${API_DATA_BASE}/command_history`,
|
||||
} as const;
|
||||
|
||||
const add = <T>(base: string, payload: T) => httpPost(`${base}/add`, payload);
|
||||
const update = <T>(base: string, payload: T) => httpPost(`${base}/update`, payload);
|
||||
const remove = (base: string, id: string) => httpPost(`${base}/delete`, undefined, { params: { id } });
|
||||
const selectById = <T>(base: string, id: string) => httpGet<R<T>>(`${base}/get_by_id`, { params: { id } });
|
||||
const list = <T>(base: string, query: PageQuery) => httpPost<R<PageResult<T>>>(`${base}/list`, query);
|
||||
// Command Definition CRUD
|
||||
|
||||
// ─── Command Definition CRUD ─────────────────────────────────────────
|
||||
|
||||
export const addCommand = (payload: Partial<CommandRecord>) => add(endpoints.command, payload);
|
||||
export const updateCommand = (payload: Partial<CommandRecord>) => update(endpoints.command, payload);
|
||||
export const deleteCommand = (id: string) => remove(endpoints.command, id);
|
||||
export const getCommandById = (id: string) => selectById<CommandRecord>(endpoints.command, id);
|
||||
export const listCommand = (query: PageQuery) => list<CommandRecord>(endpoints.command, query);
|
||||
export const addCommand = (payload: Partial<CommandRecord>) => crudAdd(endpoints.command, payload);
|
||||
export const updateCommand = (payload: Partial<CommandRecord>) => crudUpdate(endpoints.command, payload);
|
||||
export const deleteCommand = (id: string) => crudDelete(endpoints.command, id);
|
||||
export const getCommandById = (id: string) => crudGetById<CommandRecord>(endpoints.command, id);
|
||||
export const listCommand = (query: PageQuery) => crudList<CommandRecord>(endpoints.command, query);
|
||||
export const listCommandByProfileId = (profileId: string) =>
|
||||
httpGet<R<CommandRecord[]>>(`${endpoints.command}/list_by_profile_id`, { params: { profile_id: profileId } });
|
||||
|
||||
// ─── Command History Queries ──────────────────────────────────────────
|
||||
// Command Param CRUD
|
||||
|
||||
export const addCommandParam = (payload: Partial<CommandParamRecord>) => crudAdd(endpoints.commandParam, payload);
|
||||
export const updateCommandParam = (payload: Partial<CommandParamRecord>) => crudUpdate(endpoints.commandParam, payload);
|
||||
export const deleteCommandParam = (id: string) => crudDelete(endpoints.commandParam, id);
|
||||
export const listCommandParamByCommandId = (commandId: string) =>
|
||||
httpGet<R<CommandParamRecord[]>>(`${endpoints.commandParam}/list_by_command_id`, {
|
||||
params: { command_id: commandId },
|
||||
});
|
||||
|
||||
// Command History Queries
|
||||
|
||||
export const getCommandHistoryById = (recordId: string) =>
|
||||
httpGet<R<CommandHistory>>(`${endpoints.commandHistory}/${recordId}`);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import request from '@/config/axios';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
import type { PageQuery, PageResult } from '@/config/types';
|
||||
|
||||
/**
|
||||
* Shared HTTP helpers so every `src/api/*.ts` module stays a one-liner per
|
||||
@@ -28,3 +29,18 @@ export const httpGet = <T = R>(url: string, config?: AxiosRequestConfig) =>
|
||||
|
||||
export const httpPost = <T = R, D = unknown>(url: string, data?: D, config?: AxiosRequestConfig) =>
|
||||
request<T>({ ...config, url, method: 'post', data });
|
||||
|
||||
export const crudAdd = <TPayload, TResponse = string>(base: string, payload: TPayload) =>
|
||||
httpPost<R<TResponse>, TPayload>(`${base}/add`, payload);
|
||||
|
||||
export const crudUpdate = <TPayload, TResponse = string>(base: string, payload: TPayload) =>
|
||||
httpPost<R<TResponse>, TPayload>(`${base}/update`, payload);
|
||||
|
||||
export const crudDelete = (base: string, id: string) =>
|
||||
httpPost<R<string>>(`${base}/delete`, undefined, { params: { id } });
|
||||
|
||||
export const crudGetById = <TRecord>(base: string, id: string) =>
|
||||
httpGet<R<TRecord>>(`${base}/get_by_id`, { params: { id } });
|
||||
|
||||
export const crudList = <TRecord>(base: string, query: PageQuery) =>
|
||||
httpPost<R<PageResult<TRecord>>, PageQuery>(`${base}/list`, query);
|
||||
|
||||
+18
-15
@@ -14,33 +14,36 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { httpGet, httpPost } from '@/api/common';
|
||||
import { crudAdd, crudDelete, crudGetById, crudList, crudUpdate, httpGet, httpPost } from '@/api/common';
|
||||
import { API_DATA_BASE, API_MANAGER_BASE } from '@/config/constant/api';
|
||||
import type { PageQuery, PageResult } from '@/config/types';
|
||||
import type { EventHistory, EventRecord } from '@/config/types/event';
|
||||
import type { EventHistory, EventParamRecord, EventRecord } from '@/config/types/event';
|
||||
|
||||
const endpoints = {
|
||||
event: `${API_MANAGER_BASE}/event`,
|
||||
eventParam: `${API_MANAGER_BASE}/event_param`,
|
||||
eventHistory: `${API_DATA_BASE}/event_history`,
|
||||
} as const;
|
||||
|
||||
const add = <T>(base: string, payload: T) => httpPost(`${base}/add`, payload);
|
||||
const update = <T>(base: string, payload: T) => httpPost(`${base}/update`, payload);
|
||||
const remove = (base: string, id: string) => httpPost(`${base}/delete`, undefined, { params: { id } });
|
||||
const selectById = <T>(base: string, id: string) => httpGet<R<T>>(`${base}/get_by_id`, { params: { id } });
|
||||
const list = <T>(base: string, query: PageQuery) => httpPost<R<PageResult<T>>>(`${base}/list`, query);
|
||||
// Event Definition CRUD
|
||||
|
||||
// ─── Event Definition CRUD ────────────────────────────────────────────
|
||||
|
||||
export const addEvent = (payload: Partial<EventRecord>) => add(endpoints.event, payload);
|
||||
export const updateEvent = (payload: Partial<EventRecord>) => update(endpoints.event, payload);
|
||||
export const deleteEvent = (id: string) => remove(endpoints.event, id);
|
||||
export const getEventById = (id: string) => selectById<EventRecord>(endpoints.event, id);
|
||||
export const listEvent = (query: PageQuery) => list<EventRecord>(endpoints.event, query);
|
||||
export const addEvent = (payload: Partial<EventRecord>) => crudAdd(endpoints.event, payload);
|
||||
export const updateEvent = (payload: Partial<EventRecord>) => crudUpdate(endpoints.event, payload);
|
||||
export const deleteEvent = (id: string) => crudDelete(endpoints.event, id);
|
||||
export const getEventById = (id: string) => crudGetById<EventRecord>(endpoints.event, id);
|
||||
export const listEvent = (query: PageQuery) => crudList<EventRecord>(endpoints.event, query);
|
||||
export const listEventByProfileId = (profileId: string) =>
|
||||
httpGet<R<EventRecord[]>>(`${endpoints.event}/list_by_profile_id`, { params: { profile_id: profileId } });
|
||||
|
||||
// ─── Event History Queries ────────────────────────────────────────────
|
||||
// Event Param CRUD
|
||||
|
||||
export const addEventParam = (payload: Partial<EventParamRecord>) => crudAdd(endpoints.eventParam, payload);
|
||||
export const updateEventParam = (payload: Partial<EventParamRecord>) => crudUpdate(endpoints.eventParam, payload);
|
||||
export const deleteEventParam = (id: string) => crudDelete(endpoints.eventParam, id);
|
||||
export const listEventParamByEventId = (eventId: string) =>
|
||||
httpGet<R<EventParamRecord[]>>(`${endpoints.eventParam}/list_by_event_id`, { params: { event_id: eventId } });
|
||||
|
||||
// Event History Queries
|
||||
|
||||
export const getEventHistoryById = (recordId: string) =>
|
||||
httpGet<R<EventHistory>>(`${endpoints.eventHistory}/${recordId}`);
|
||||
|
||||
+8
-4
@@ -19,16 +19,20 @@ import { API_AUTH_BASE } from '@/config/constant/api';
|
||||
import type { PageQuery, PageResult } from '@/config/types';
|
||||
import type { ResourceForm, ResourceRecord } from '@/config/types/auth';
|
||||
|
||||
export const addResource = (resource: ResourceForm) => httpPost(`${API_AUTH_BASE}/resource/add`, resource);
|
||||
export const addResource = (resource: ResourceForm) =>
|
||||
httpPost<R<ResourceRecord>>(`${API_AUTH_BASE}/resource/add`, resource);
|
||||
|
||||
export const deleteResource = (id: string) =>
|
||||
httpPost(`${API_AUTH_BASE}/resource/delete`, undefined, { params: { id } });
|
||||
|
||||
export const updateResource = (resource: ResourceForm) => httpPost(`${API_AUTH_BASE}/resource/update`, resource);
|
||||
export const updateResource = (resource: ResourceForm) =>
|
||||
httpPost<R<ResourceRecord>>(`${API_AUTH_BASE}/resource/update`, resource);
|
||||
|
||||
export const getResourceById = (id: string) => httpGet(`${API_AUTH_BASE}/resource/get_by_id`, { params: { id } });
|
||||
export const getResourceById = (id: string) =>
|
||||
httpGet<R<ResourceRecord>>(`${API_AUTH_BASE}/resource/get_by_id`, { params: { id } });
|
||||
|
||||
export const listResource = <T = R<PageResult<ResourceRecord>>>(query: PageQuery) =>
|
||||
httpPost<T>(`${API_AUTH_BASE}/resource/list`, query);
|
||||
|
||||
export const listResourceTree = (query: PageQuery = {}) => httpPost(`${API_AUTH_BASE}/resource/list_tree`, query);
|
||||
export const listResourceTree = (query: PageQuery = {}) =>
|
||||
httpPost<R<ResourceRecord[]>>(`${API_AUTH_BASE}/resource/list_tree`, query);
|
||||
|
||||
@@ -745,7 +745,7 @@
|
||||
try {
|
||||
await agenticStore.uploadAttachment(file);
|
||||
} catch (error) {
|
||||
ElMessage.error(error instanceof Error ? error.message : 'Upload failed');
|
||||
ElMessage.error(error instanceof Error ? error.message : t('agentic.uploadFailed'));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -757,12 +757,12 @@
|
||||
cancelButtonText: t('agentic.dialogCancel'),
|
||||
});
|
||||
await agenticStore.confirmAction(actionId);
|
||||
ElMessage.success('Action confirmed');
|
||||
ElMessage.success(t('agentic.actionConfirmed'));
|
||||
};
|
||||
|
||||
const handleRejectAction = async (actionId: string) => {
|
||||
await agenticStore.rejectAction(actionId);
|
||||
ElMessage.success('Action rejected');
|
||||
ElMessage.success(t('agentic.actionRejected'));
|
||||
};
|
||||
|
||||
const handleCopyMessage = async (message: AgenticMessage) => {
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
margin-top: 2px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
border-top: 1px solid #dcdfe6;
|
||||
border-top: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
.things-card-footer-operation {
|
||||
|
||||
@@ -247,13 +247,13 @@
|
||||
|
||||
.dashboard-card__title-text {
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.dashboard-card__subtitle {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
color: #909399;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
|
||||
// Badge sits inline with the title — override the default floating
|
||||
@@ -332,7 +332,7 @@
|
||||
|
||||
// ---- footer ----------------------------------------------------------
|
||||
// Opt-in bar beneath the body. Matches LiveFeed's "updated at + rows"
|
||||
// look: 8/16 padding, 12px/#909399 text, light top border, #fafafa bg.
|
||||
// look: 8/16 padding, secondary text, light top border and subtle bg.
|
||||
// Consumers lay out content with a pair of <span>s — flex space-between
|
||||
// handles the rest.
|
||||
.dashboard-card__footer {
|
||||
@@ -342,9 +342,9 @@
|
||||
gap: 8px;
|
||||
padding: 8px 16px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
color: var(--el-text-color-secondary);
|
||||
border-top: 1px solid var(--el-border-color-lighter);
|
||||
background: #fafafa;
|
||||
background: var(--el-fill-color-lighter);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
line-height: 48px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
color: var(--el-text-color-primary);
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
@@ -72,7 +72,7 @@
|
||||
width: 200px;
|
||||
|
||||
&:hover {
|
||||
color: #1890ff;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,10 +89,10 @@
|
||||
}
|
||||
|
||||
.header-enable {
|
||||
border-bottom: 1px solid #c2e7b0;
|
||||
border-bottom: 1px solid var(--el-color-success-light-5);
|
||||
}
|
||||
|
||||
.header-disable {
|
||||
border-bottom: 1px solid #fbc4c4;
|
||||
border-bottom: 1px solid var(--el-color-danger-light-5);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
width: 100%;
|
||||
height: 55px;
|
||||
display: flex;
|
||||
border-bottom: 1px solid #dcdfe6;
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
.skeleton-card-icon {
|
||||
@@ -152,7 +152,7 @@
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
border-top: 1px solid #dcdfe6;
|
||||
border-top: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
.skeleton-card-operation {
|
||||
|
||||
@@ -118,19 +118,19 @@
|
||||
// --stat-card-accent values declared in the scoped styles below so a
|
||||
// palette change only needs updating in one place conceptually.
|
||||
const TONE_ACCENT: Record<string, string> = {
|
||||
blue: '#409eff',
|
||||
green: '#67c23a',
|
||||
orange: '#e6a23c',
|
||||
blue: 'var(--el-color-primary)',
|
||||
green: 'var(--el-color-success)',
|
||||
orange: 'var(--el-color-warning)',
|
||||
purple: '#9059f6',
|
||||
red: '#f56c6c',
|
||||
red: 'var(--el-color-danger)',
|
||||
};
|
||||
const accentColor = computed(() => TONE_ACCENT[props.tone] || TONE_ACCENT.blue);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.stat-card {
|
||||
--stat-card-accent: #409eff;
|
||||
--stat-card-bg: rgba(64, 158, 255, 0.08);
|
||||
--stat-card-accent: var(--el-color-primary);
|
||||
--stat-card-bg: var(--el-color-primary-light-9);
|
||||
cursor: pointer;
|
||||
transition: transform 0.15s ease;
|
||||
height: 100%;
|
||||
@@ -149,24 +149,24 @@
|
||||
}
|
||||
|
||||
&--blue {
|
||||
--stat-card-accent: #409eff;
|
||||
--stat-card-bg: rgba(64, 158, 255, 0.1);
|
||||
--stat-card-accent: var(--el-color-primary);
|
||||
--stat-card-bg: var(--el-color-primary-light-9);
|
||||
}
|
||||
&--green {
|
||||
--stat-card-accent: #67c23a;
|
||||
--stat-card-bg: rgba(103, 194, 58, 0.1);
|
||||
--stat-card-accent: var(--el-color-success);
|
||||
--stat-card-bg: var(--el-color-success-light-9);
|
||||
}
|
||||
&--orange {
|
||||
--stat-card-accent: #e6a23c;
|
||||
--stat-card-bg: rgba(230, 162, 60, 0.1);
|
||||
--stat-card-accent: var(--el-color-warning);
|
||||
--stat-card-bg: var(--el-color-warning-light-9);
|
||||
}
|
||||
&--purple {
|
||||
--stat-card-accent: #9059f6;
|
||||
--stat-card-bg: rgba(144, 89, 246, 0.1);
|
||||
}
|
||||
&--red {
|
||||
--stat-card-accent: #f56c6c;
|
||||
--stat-card-bg: rgba(245, 108, 108, 0.1);
|
||||
--stat-card-accent: var(--el-color-danger);
|
||||
--stat-card-bg: var(--el-color-danger-light-9);
|
||||
}
|
||||
|
||||
:deep(.el-card__body) {
|
||||
@@ -211,7 +211,7 @@
|
||||
|
||||
.stat-card__title {
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
.stat-card__value-text {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.stat-card__trend {
|
||||
@@ -236,18 +236,18 @@
|
||||
}
|
||||
|
||||
.stat-card__trend--up {
|
||||
color: #67c23a;
|
||||
color: var(--el-color-success);
|
||||
}
|
||||
.stat-card__trend--down {
|
||||
color: #f56c6c;
|
||||
color: var(--el-color-danger);
|
||||
}
|
||||
.stat-card__trend--flat {
|
||||
color: #909399;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
|
||||
.stat-card__subtitle {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
/** Accent colour for the line stroke and the gradient's inner stop. */
|
||||
color: {
|
||||
type: String,
|
||||
default: '#409eff',
|
||||
default: 'var(--el-color-primary)',
|
||||
},
|
||||
/** Chart height in px. Container is stretched to the parent width. */
|
||||
height: {
|
||||
@@ -71,6 +71,13 @@
|
||||
const containerRef = ref<HTMLElement>();
|
||||
let chart: Chart | undefined;
|
||||
|
||||
const resolveCssColor = (color: string) => {
|
||||
const match = color.match(/^var\((--[^),]+)(?:,[^)]+)?\)$/);
|
||||
const token = match?.[1];
|
||||
if (!token) return color;
|
||||
return getComputedStyle(document.documentElement).getPropertyValue(token).trim() || color;
|
||||
};
|
||||
|
||||
const draw = (attempt = 0) => {
|
||||
const el = containerRef.value;
|
||||
if (!el || !props.data || props.data.length === 0) return;
|
||||
@@ -98,7 +105,8 @@
|
||||
paddingRight: 2,
|
||||
});
|
||||
|
||||
const fillGradient = `linear-gradient(90deg, rgba(255,255,255,0) 0%, ${props.color} 100%)`;
|
||||
const color = resolveCssColor(props.color);
|
||||
const fillGradient = `linear-gradient(90deg, rgba(255,255,255,0) 0%, ${color} 100%)`;
|
||||
|
||||
const area = chart
|
||||
.area()
|
||||
@@ -132,7 +140,7 @@
|
||||
.encode('x', 'x')
|
||||
.encode('y', 'y')
|
||||
.encode('shape', 'smooth')
|
||||
.style('stroke', props.color)
|
||||
.style('stroke', color)
|
||||
.style('lineWidth', 2)
|
||||
.axis(false)
|
||||
.legend(false);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { isEnabledFlag } from '@/utils/thingModelFormatUtil';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -36,10 +37,5 @@
|
||||
);
|
||||
|
||||
const { t } = useI18n();
|
||||
const enabled = computed(() => {
|
||||
if (props.value === true) return true;
|
||||
if (props.value === false) return false;
|
||||
const value = String(props.value ?? '').toUpperCase();
|
||||
return value === 'ENABLE' || value === 'ENABLED' || value === 'TRUE' || value === '0';
|
||||
});
|
||||
const enabled = computed(() => isEnabledFlag(props.value));
|
||||
</script>
|
||||
|
||||
@@ -136,6 +136,12 @@ export const CALL_TYPE_OPTIONS: EnumOption[] = [
|
||||
{ label: 'ASYNC', value: 'ASYNC' },
|
||||
];
|
||||
|
||||
// Backend: ParamDirectionFlagEnum
|
||||
export const PARAM_DIRECTION_OPTIONS: EnumOption[] = [
|
||||
{ label: 'INPUT', value: 'INPUT' },
|
||||
{ label: 'OUTPUT', value: 'OUTPUT' },
|
||||
];
|
||||
|
||||
// Backend: EventTypeFlagEnum
|
||||
export const EVENT_TYPE_OPTIONS: EnumOption[] = [
|
||||
{ label: 'INFO', value: 'INFO' },
|
||||
|
||||
@@ -474,11 +474,62 @@ export default {
|
||||
commandName: 'Command Name',
|
||||
commandNamePlaceholder: 'Enter command name',
|
||||
},
|
||||
form: {
|
||||
addTitle: 'Add Command',
|
||||
editTitle: 'Edit Command',
|
||||
code: 'Code',
|
||||
commandType: 'Command Type',
|
||||
callType: 'Call Type',
|
||||
timeout: 'Timeout (s)',
|
||||
params: 'Command Params',
|
||||
direction: 'Direction',
|
||||
type: 'Type',
|
||||
required: 'Required',
|
||||
defaultValue: 'Default',
|
||||
enabled: 'Enabled',
|
||||
nameRequired: 'Command name is required',
|
||||
codeRequired: 'Command code is required',
|
||||
paramRequired: 'Command param name, code, direction, and type are required.',
|
||||
paramCodeUnique: 'Command param code must be unique.',
|
||||
},
|
||||
detail: {
|
||||
title: 'Command Detail',
|
||||
code: 'Code',
|
||||
commandType: 'Command Type',
|
||||
callType: 'Call Type',
|
||||
timeout: 'Timeout (s)',
|
||||
profileId: 'Profile ID',
|
||||
tenantId: 'Tenant ID',
|
||||
},
|
||||
history: {
|
||||
detailTitle: 'Command Record Detail',
|
||||
recordId: 'Record ID',
|
||||
deviceId: 'Device ID',
|
||||
commandId: 'Command ID',
|
||||
commandCode: 'Command Code',
|
||||
status: 'Status',
|
||||
error: 'Error',
|
||||
errorCode: 'Error Code',
|
||||
errorMessage: 'Error Message',
|
||||
source: 'Source',
|
||||
sourceUserId: 'Source User ID',
|
||||
paramValues: 'Param Values',
|
||||
resultValues: 'Result Values',
|
||||
configSnapshot: 'Config Snapshot',
|
||||
occurTime: 'Occur Time',
|
||||
sendTime: 'Send Time',
|
||||
finishTime: 'Finish Time',
|
||||
expireTime: 'Expire Time',
|
||||
},
|
||||
errors: {
|
||||
idNotReturned: 'Command ID was not returned.',
|
||||
idMissing: 'Command ID is missing.',
|
||||
},
|
||||
card: {
|
||||
code: 'Command Code',
|
||||
type: 'Command Type',
|
||||
callType: 'Call Type',
|
||||
timeout: 'Timeout',
|
||||
timeout: 'Timeout (s)',
|
||||
remarkTitle: 'Command description',
|
||||
confirmDisable: 'Are you sure to disable this command? This action cannot be undone!',
|
||||
confirmEnable: 'Are you sure to enable this command?',
|
||||
@@ -491,6 +542,32 @@ export default {
|
||||
eventName: 'Event Name',
|
||||
eventNamePlaceholder: 'Enter event name',
|
||||
},
|
||||
form: {
|
||||
addTitle: 'Add Event',
|
||||
editTitle: 'Edit Event',
|
||||
code: 'Code',
|
||||
eventType: 'Event Type',
|
||||
eventLevel: 'Event Level',
|
||||
params: 'Event Params',
|
||||
type: 'Type',
|
||||
enabled: 'Enabled',
|
||||
nameRequired: 'Event name is required',
|
||||
codeRequired: 'Event code is required',
|
||||
paramRequired: 'Event param name, code, and type are required.',
|
||||
paramCodeUnique: 'Event param code must be unique.',
|
||||
},
|
||||
detail: {
|
||||
title: 'Event Detail',
|
||||
code: 'Code',
|
||||
eventType: 'Event Type',
|
||||
eventLevel: 'Event Level',
|
||||
profileId: 'Profile ID',
|
||||
tenantId: 'Tenant ID',
|
||||
},
|
||||
errors: {
|
||||
idNotReturned: 'Event ID was not returned.',
|
||||
idMissing: 'Event ID is missing.',
|
||||
},
|
||||
card: {
|
||||
code: 'Event Code',
|
||||
type: 'Event Type',
|
||||
@@ -502,6 +579,24 @@ export default {
|
||||
},
|
||||
empty: 'No event data!',
|
||||
},
|
||||
eventHistory: {
|
||||
detailTitle: 'Event History Detail',
|
||||
recordId: 'Record ID',
|
||||
deviceId: 'Device ID',
|
||||
eventId: 'Event ID',
|
||||
eventCode: 'Event Code',
|
||||
type: 'Type',
|
||||
level: 'Level',
|
||||
ack: 'Ack',
|
||||
message: 'Message',
|
||||
paramValues: 'Param Values',
|
||||
configSnapshot: 'Config Snapshot',
|
||||
occurTime: 'Occur Time',
|
||||
receiveTime: 'Receive Time',
|
||||
acknowledgeFlag: 'Acknowledge Flag',
|
||||
acknowledgeUserId: 'Acknowledge User ID',
|
||||
acknowledgeTime: 'Acknowledge Time',
|
||||
},
|
||||
point: {
|
||||
tool: {
|
||||
pointName: 'Point Name',
|
||||
@@ -588,6 +683,7 @@ export default {
|
||||
card: {
|
||||
pointValueId: 'Point Value ID',
|
||||
rwType: 'R/W Type',
|
||||
write: 'Write',
|
||||
processedValue: 'Processed Value',
|
||||
rawValue: 'Raw Value',
|
||||
device: 'Device',
|
||||
@@ -596,10 +692,9 @@ export default {
|
||||
saveTime: 'Save Time',
|
||||
noLatestValue: 'No Value',
|
||||
noHistory: 'No History',
|
||||
confirmDelete: 'Are you sure to delete this point value? This action cannot be undone!',
|
||||
},
|
||||
edit: {
|
||||
title: 'Edit Point Value',
|
||||
title: 'Write Point Value',
|
||||
pointValue: 'Point Value',
|
||||
description: 'Description',
|
||||
pointValuePlaceholder: 'Enter point value',
|
||||
@@ -1103,6 +1198,9 @@ export default {
|
||||
dialogDeleteConfirm: 'Delete this conversation?',
|
||||
attachAnalyze: 'Please analyze the attached files.',
|
||||
canceled: 'Canceled.',
|
||||
uploadFailed: 'Upload failed.',
|
||||
actionConfirmed: 'Action confirmed.',
|
||||
actionRejected: 'Action rejected.',
|
||||
requestFailed: 'Request failed.',
|
||||
failedStream: 'Agentic chat failed.',
|
||||
failedContext: 'Missing conversation context.',
|
||||
|
||||
@@ -473,11 +473,62 @@ export default {
|
||||
commandName: '指令名称',
|
||||
commandNamePlaceholder: '请输入指令名称',
|
||||
},
|
||||
form: {
|
||||
addTitle: '新增指令',
|
||||
editTitle: '编辑指令',
|
||||
code: '标识',
|
||||
commandType: '指令类型',
|
||||
callType: '调用类型',
|
||||
timeout: '超时时间(s)',
|
||||
params: '指令参数',
|
||||
direction: '方向',
|
||||
type: '类型',
|
||||
required: '必填',
|
||||
defaultValue: '默认值',
|
||||
enabled: '启用',
|
||||
nameRequired: '指令名称不能为空',
|
||||
codeRequired: '指令标识不能为空',
|
||||
paramRequired: '指令参数名称、标识、方向和类型不能为空。',
|
||||
paramCodeUnique: '指令参数标识不能重复。',
|
||||
},
|
||||
detail: {
|
||||
title: '指令详情',
|
||||
code: '标识',
|
||||
commandType: '指令类型',
|
||||
callType: '调用类型',
|
||||
timeout: '超时时间(s)',
|
||||
profileId: '模板 ID',
|
||||
tenantId: '租户 ID',
|
||||
},
|
||||
history: {
|
||||
detailTitle: '指令调用记录详情',
|
||||
recordId: '记录 ID',
|
||||
deviceId: '设备 ID',
|
||||
commandId: '指令 ID',
|
||||
commandCode: '指令标识',
|
||||
status: '状态',
|
||||
error: '错误',
|
||||
errorCode: '错误码',
|
||||
errorMessage: '错误信息',
|
||||
source: '来源',
|
||||
sourceUserId: '来源用户 ID',
|
||||
paramValues: '参数值',
|
||||
resultValues: '结果值',
|
||||
configSnapshot: '配置快照',
|
||||
occurTime: '发生时间',
|
||||
sendTime: '发送时间',
|
||||
finishTime: '完成时间',
|
||||
expireTime: '过期时间',
|
||||
},
|
||||
errors: {
|
||||
idNotReturned: '后端未返回指令 ID。',
|
||||
idMissing: '指令 ID 缺失。',
|
||||
},
|
||||
card: {
|
||||
code: '指令标识',
|
||||
type: '指令类型',
|
||||
callType: '调用类型',
|
||||
timeout: '超时时间',
|
||||
timeout: '超时时间(s)',
|
||||
remarkTitle: '指令描述信息',
|
||||
confirmDisable: '是否确定停用该指令? 该操作不可恢复!',
|
||||
confirmEnable: '是否确定启用该指令?',
|
||||
@@ -490,6 +541,32 @@ export default {
|
||||
eventName: '事件名称',
|
||||
eventNamePlaceholder: '请输入事件名称',
|
||||
},
|
||||
form: {
|
||||
addTitle: '新增事件',
|
||||
editTitle: '编辑事件',
|
||||
code: '标识',
|
||||
eventType: '事件类型',
|
||||
eventLevel: '事件等级',
|
||||
params: '事件参数',
|
||||
type: '类型',
|
||||
enabled: '启用',
|
||||
nameRequired: '事件名称不能为空',
|
||||
codeRequired: '事件标识不能为空',
|
||||
paramRequired: '事件参数名称、标识和类型不能为空。',
|
||||
paramCodeUnique: '事件参数标识不能重复。',
|
||||
},
|
||||
detail: {
|
||||
title: '事件详情',
|
||||
code: '标识',
|
||||
eventType: '事件类型',
|
||||
eventLevel: '事件等级',
|
||||
profileId: '模板 ID',
|
||||
tenantId: '租户 ID',
|
||||
},
|
||||
errors: {
|
||||
idNotReturned: '后端未返回事件 ID。',
|
||||
idMissing: '事件 ID 缺失。',
|
||||
},
|
||||
card: {
|
||||
code: '事件标识',
|
||||
type: '事件类型',
|
||||
@@ -501,6 +578,24 @@ export default {
|
||||
},
|
||||
empty: '暂无事件数据!',
|
||||
},
|
||||
eventHistory: {
|
||||
detailTitle: '事件上报记录详情',
|
||||
recordId: '记录 ID',
|
||||
deviceId: '设备 ID',
|
||||
eventId: '事件 ID',
|
||||
eventCode: '事件标识',
|
||||
type: '类型',
|
||||
level: '等级',
|
||||
ack: '确认',
|
||||
message: '消息',
|
||||
paramValues: '参数值',
|
||||
configSnapshot: '配置快照',
|
||||
occurTime: '发生时间',
|
||||
receiveTime: '接收时间',
|
||||
acknowledgeFlag: '确认标识',
|
||||
acknowledgeUserId: '确认用户 ID',
|
||||
acknowledgeTime: '确认时间',
|
||||
},
|
||||
point: {
|
||||
tool: {
|
||||
pointName: '位号名称',
|
||||
@@ -587,6 +682,7 @@ export default {
|
||||
card: {
|
||||
pointValueId: '位号值ID',
|
||||
rwType: '读写标识',
|
||||
write: '写入',
|
||||
processedValue: '处理值',
|
||||
rawValue: '原始值',
|
||||
device: '所属设备',
|
||||
@@ -595,10 +691,9 @@ export default {
|
||||
saveTime: '保存日期',
|
||||
noLatestValue: '暂无值',
|
||||
noHistory: '暂无历史',
|
||||
confirmDelete: '是否确定删除该位号值? 该操作不可恢复!',
|
||||
},
|
||||
edit: {
|
||||
title: '编辑位号值',
|
||||
title: '写入位号值',
|
||||
pointValue: '位号值',
|
||||
description: '操作描述',
|
||||
pointValuePlaceholder: '请输入位号值',
|
||||
@@ -1103,6 +1198,9 @@ export default {
|
||||
dialogDeleteConfirm: '确定删除该对话?',
|
||||
attachAnalyze: '请分析附件内容。',
|
||||
canceled: '已取消。',
|
||||
uploadFailed: '上传失败。',
|
||||
actionConfirmed: '操作已确认。',
|
||||
actionRejected: '操作已拒绝。',
|
||||
requestFailed: '请求失败。',
|
||||
failedStream: 'AI 对话失败。',
|
||||
failedContext: '缺少对话上下文。',
|
||||
|
||||
@@ -14,41 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Element Plus form component size variables
|
||||
* Used to define consistent widths for form inputs and selects
|
||||
*/
|
||||
|
||||
// Form size widths
|
||||
// Element Plus form component size tokens. Keep this file token-only because
|
||||
// Vite injects it into every SCSS block via additionalData.
|
||||
$form-width-small: 120px;
|
||||
$form-width-medium: 150px;
|
||||
$form-width-default: 250px;
|
||||
$form-width-special: 300px;
|
||||
$form-width-large: 500px;
|
||||
|
||||
// Small form elements
|
||||
.el-select.edit-form-small,
|
||||
.el-input.edit-form-small {
|
||||
width: $form-width-small;
|
||||
}
|
||||
|
||||
// Medium form elements
|
||||
.el-select.edit-form-medium {
|
||||
width: $form-width-medium;
|
||||
}
|
||||
|
||||
// Default form elements
|
||||
.el-select.edit-form-default {
|
||||
width: $form-width-default;
|
||||
}
|
||||
|
||||
// Special form elements
|
||||
.el-select.edit-form-special,
|
||||
.el-input.edit-form-special {
|
||||
width: $form-width-special;
|
||||
}
|
||||
|
||||
// Large form elements
|
||||
.el-select.edit-form-large {
|
||||
width: $form-width-large;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
import type { App } from 'vue';
|
||||
import * as ElementIcons from '@element-plus/icons-vue';
|
||||
import 'element-plus/dist/index.css';
|
||||
import './element-variables.scss';
|
||||
|
||||
/**
|
||||
* Registers every icon exported by `@element-plus/icons-vue` globally so
|
||||
|
||||
@@ -53,6 +53,22 @@ export interface CommandForm {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface CommandParamRecord {
|
||||
id?: string;
|
||||
paramName?: string;
|
||||
paramCode?: string;
|
||||
paramDirectionFlag?: string | number;
|
||||
paramTypeFlag?: string | number;
|
||||
requiredFlag?: boolean;
|
||||
defaultValue?: string;
|
||||
paramExt?: Record<string, unknown>;
|
||||
commandId?: string;
|
||||
enableFlag?: string | number;
|
||||
signature?: string;
|
||||
version?: number;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command call history (dc3_command_history).
|
||||
*/
|
||||
|
||||
@@ -51,6 +51,19 @@ export interface EventForm {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface EventParamRecord {
|
||||
id?: string;
|
||||
paramName?: string;
|
||||
paramCode?: string;
|
||||
paramTypeFlag?: string | number;
|
||||
paramExt?: Record<string, unknown>;
|
||||
eventId?: string;
|
||||
enableFlag?: string | number;
|
||||
signature?: string;
|
||||
version?: number;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event report history (dc3_event_history).
|
||||
*/
|
||||
|
||||
@@ -56,8 +56,8 @@ export type {
|
||||
AlarmEntityRecord,
|
||||
} from './alarm';
|
||||
|
||||
export type { CommandRecord, CommandForm, CommandHistory } from './command';
|
||||
export type { EventRecord, EventForm, EventHistory } from './event';
|
||||
export type { CommandRecord, CommandForm, CommandParamRecord, CommandHistory } from './command';
|
||||
export type { EventRecord, EventForm, EventParamRecord, EventHistory } from './event';
|
||||
|
||||
export type {
|
||||
UserForm,
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@use '@/styles/things-dialog.scss';
|
||||
@use '@/styles/things-card.scss';
|
||||
|
||||
// 真正的全局样式,在 main.ts 里一次性 import。
|
||||
// 不能放到 element-variables.scss 里,因为后者是 Vite additionalData,
|
||||
// 会被预置到每个 scoped <style> 块,所有选择器都会被附加 scope hash,
|
||||
@@ -25,6 +28,50 @@ body {
|
||||
min-height: 768px;
|
||||
}
|
||||
|
||||
// Form width helper classes are real CSS, so they live in the one-time global
|
||||
// stylesheet. The Sass variables behind them are still injected everywhere for
|
||||
// token reuse.
|
||||
.el-select.edit-form-small,
|
||||
.el-input.edit-form-small {
|
||||
width: $form-width-small;
|
||||
}
|
||||
|
||||
.el-select.edit-form-medium {
|
||||
width: $form-width-medium;
|
||||
}
|
||||
|
||||
.el-select.edit-form-default {
|
||||
width: $form-width-default;
|
||||
}
|
||||
|
||||
.el-select.edit-form-special,
|
||||
.el-input.edit-form-special {
|
||||
width: $form-width-special;
|
||||
}
|
||||
|
||||
.el-select.edit-form-large {
|
||||
width: $form-width-large;
|
||||
}
|
||||
|
||||
.settings-table {
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.json-preview {
|
||||
max-height: 220px;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
overflow: auto;
|
||||
border-radius: 4px;
|
||||
background: var(--el-fill-color-light);
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
// el-popconfirm 的 popper 也通过 teleport 挂到 body,作用域外样式必须放在全局。
|
||||
// Element Plus 默认 popconfirm 只按文字宽度撑开,文字 + 两个按钮常常挤在一行,
|
||||
// 视觉上又窄又紧。这里统一:
|
||||
|
||||
@@ -15,9 +15,7 @@
|
||||
*/
|
||||
|
||||
// Vertically centre things-dialog + cap its height so tall forms scroll
|
||||
// inside the dialog rather than bleed past the viewport bottom. Applied
|
||||
// via the wrapper .el-overlay-dialog because el-dialog teleports to body
|
||||
// and its direct container controls vertical alignment.
|
||||
// inside the dialog rather than bleed past the viewport bottom.
|
||||
.el-overlay-dialog:has(.things-dialog) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -35,8 +33,13 @@
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
overflow-y: auto;
|
||||
flex: 1 1 auto;
|
||||
padding: 30px 30px 15px 30px;
|
||||
overflow-y: auto;
|
||||
|
||||
pre {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// Opt-in helper: put `class="things-dialog things-dialog--wide"` on a
|
||||
@@ -101,6 +104,17 @@
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.param-editor {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.param-editor__toolbar {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.things-dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
@@ -111,14 +125,6 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
padding: 30px 30px 15px 30px;
|
||||
|
||||
pre {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.el-form-item__content {
|
||||
width: 100%;
|
||||
|
||||
|
||||
@@ -36,6 +36,11 @@ export const timestampColumn = (_row: unknown, _col: unknown, cellValue: unknown
|
||||
return timestamp(String(cellValue));
|
||||
};
|
||||
|
||||
export const timestampLabel = (value: unknown, fallback = '-'): string => {
|
||||
if (value == null || value === '') return fallback;
|
||||
return timestamp(String(value)) || fallback;
|
||||
};
|
||||
|
||||
/**
|
||||
* Format date to string
|
||||
*
|
||||
|
||||
@@ -14,23 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { defineComponent, ref } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PointValueDetail',
|
||||
props: {
|
||||
detailData: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const detailVisible = ref(false);
|
||||
|
||||
return {
|
||||
detailVisible,
|
||||
};
|
||||
},
|
||||
});
|
||||
export const prettyJson = (value: unknown, fallback = '-'): string => {
|
||||
if (value == null || value === '') return fallback;
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
return JSON.stringify(JSON.parse(value), null, 2);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return JSON.stringify(value, null, 2);
|
||||
};
|
||||
@@ -14,7 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
type FlagValue = string | number | null | undefined;
|
||||
type FlagValue = string | number | boolean | null | undefined;
|
||||
type TimeoutValue = string | number | null | undefined;
|
||||
|
||||
const LEGACY_TIMEOUT_MILLISECONDS_THRESHOLD = 1000;
|
||||
const MILLISECONDS_PER_SECOND = 1000;
|
||||
|
||||
const COMMAND_TYPE_BY_INDEX: Record<string, string> = {
|
||||
'0': 'CUSTOM',
|
||||
@@ -27,6 +31,22 @@ const CALL_TYPE_BY_INDEX: Record<string, string> = {
|
||||
'1': 'ASYNC',
|
||||
};
|
||||
|
||||
const PARAM_DIRECTION_BY_INDEX: Record<string, string> = {
|
||||
'0': 'INPUT',
|
||||
'1': 'OUTPUT',
|
||||
};
|
||||
|
||||
const POINT_TYPE_BY_INDEX: Record<string, string> = {
|
||||
'0': 'STRING',
|
||||
'1': 'BYTE',
|
||||
'2': 'SHORT',
|
||||
'3': 'INT',
|
||||
'4': 'LONG',
|
||||
'5': 'FLOAT',
|
||||
'6': 'DOUBLE',
|
||||
'7': 'BOOLEAN',
|
||||
};
|
||||
|
||||
const EVENT_TYPE_BY_INDEX: Record<string, string> = {
|
||||
'0': 'INFO',
|
||||
'1': 'ALERT',
|
||||
@@ -41,6 +61,11 @@ const EVENT_LEVEL_BY_INDEX: Record<string, string> = {
|
||||
'3': 'CRITICAL',
|
||||
};
|
||||
|
||||
const ENABLE_FLAG_BY_INDEX: Record<string, string> = {
|
||||
'0': 'ENABLE',
|
||||
'1': 'DISABLE',
|
||||
};
|
||||
|
||||
function normalizeFlag(value: FlagValue, indexMap: Record<string, string>): string {
|
||||
if (value === null || value === undefined || value === '') {
|
||||
return '-';
|
||||
@@ -50,26 +75,63 @@ function normalizeFlag(value: FlagValue, indexMap: Record<string, string>): stri
|
||||
return indexMap[raw] ?? raw.toUpperCase();
|
||||
}
|
||||
|
||||
function normalizeFormFlag(value: FlagValue, indexMap: Record<string, string>, fallback: string): string {
|
||||
const normalized = normalizeFlag(value, indexMap);
|
||||
return normalized === '-' ? fallback : normalized;
|
||||
}
|
||||
|
||||
export function isEnabledFlag(value: FlagValue): boolean {
|
||||
return String(value).toUpperCase() === 'ENABLE' || Number(value) === 0;
|
||||
if (value === true) return true;
|
||||
if (value === false || value === null || value === undefined || value === '') return false;
|
||||
|
||||
const normalized = String(value).trim().toUpperCase();
|
||||
return normalized === 'ENABLE' || normalized === 'ENABLED' || normalized === 'TRUE' || normalized === '0';
|
||||
}
|
||||
|
||||
export function enableFlagValue(value: FlagValue, fallback = 'ENABLE'): string {
|
||||
return normalizeFormFlag(value, ENABLE_FLAG_BY_INDEX, fallback);
|
||||
}
|
||||
|
||||
export function commandTypeLabel(value: FlagValue): string {
|
||||
return normalizeFlag(value, COMMAND_TYPE_BY_INDEX);
|
||||
}
|
||||
|
||||
export function commandTypeValue(value: FlagValue, fallback = 'CUSTOM'): string {
|
||||
return normalizeFormFlag(value, COMMAND_TYPE_BY_INDEX, fallback);
|
||||
}
|
||||
|
||||
export function callTypeLabel(value: FlagValue): string {
|
||||
return normalizeFlag(value, CALL_TYPE_BY_INDEX);
|
||||
}
|
||||
|
||||
export function callTypeValue(value: FlagValue, fallback = 'SYNC'): string {
|
||||
return normalizeFormFlag(value, CALL_TYPE_BY_INDEX, fallback);
|
||||
}
|
||||
|
||||
export function paramDirectionValue(value: FlagValue, fallback = 'INPUT'): string {
|
||||
return normalizeFormFlag(value, PARAM_DIRECTION_BY_INDEX, fallback);
|
||||
}
|
||||
|
||||
export function pointTypeValue(value: FlagValue, fallback = 'STRING'): string {
|
||||
return normalizeFormFlag(value, POINT_TYPE_BY_INDEX, fallback);
|
||||
}
|
||||
|
||||
export function eventTypeLabel(value: FlagValue): string {
|
||||
return normalizeFlag(value, EVENT_TYPE_BY_INDEX);
|
||||
}
|
||||
|
||||
export function eventTypeValue(value: FlagValue, fallback = 'INFO'): string {
|
||||
return normalizeFormFlag(value, EVENT_TYPE_BY_INDEX, fallback);
|
||||
}
|
||||
|
||||
export function eventLevelLabel(value: FlagValue): string {
|
||||
return normalizeFlag(value, EVENT_LEVEL_BY_INDEX);
|
||||
}
|
||||
|
||||
export function eventLevelValue(value: FlagValue, fallback = 'LOW'): string {
|
||||
return normalizeFormFlag(value, EVENT_LEVEL_BY_INDEX, fallback);
|
||||
}
|
||||
|
||||
export function eventLevelTag(value: FlagValue): 'success' | 'warning' | 'danger' | 'info' {
|
||||
const level = eventLevelLabel(value);
|
||||
if (level === 'CRITICAL') return 'danger';
|
||||
@@ -77,3 +139,24 @@ export function eventLevelTag(value: FlagValue): 'success' | 'warning' | 'danger
|
||||
if (level === 'MEDIUM') return 'success';
|
||||
return 'info';
|
||||
}
|
||||
|
||||
export function normalizeCommandTimeoutSeconds(value: TimeoutValue): number | undefined {
|
||||
if (value === null || value === undefined || value === '') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const timeout = Number(value);
|
||||
if (!Number.isFinite(timeout) || timeout <= 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (timeout >= LEGACY_TIMEOUT_MILLISECONDS_THRESHOLD && timeout % MILLISECONDS_PER_SECOND === 0) {
|
||||
return timeout / MILLISECONDS_PER_SECOND;
|
||||
}
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
||||
export function commandTimeoutLabel(value: TimeoutValue): string {
|
||||
return normalizeCommandTimeoutSeconds(value)?.toString() ?? '-';
|
||||
}
|
||||
|
||||
@@ -347,5 +347,3 @@
|
||||
|
||||
list();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
<div class="things-dialog-footer">
|
||||
<slot name="footer">
|
||||
<el-button @click="cancel">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button type="primary" @click="addThing">{{ $t('common.confirm') }}</el-button>
|
||||
</slot>
|
||||
</div>
|
||||
@@ -238,7 +238,3 @@
|
||||
addThing,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<el-card shadow="hover">
|
||||
<div class="things-card-content">
|
||||
<things-card-header
|
||||
:enabled="data.enableFlag === 'ENABLE'"
|
||||
:enabled="enabled"
|
||||
:icon="icon"
|
||||
:name="data.deviceName"
|
||||
:status-title="$t('common.enableFlag')"
|
||||
@@ -59,7 +59,7 @@
|
||||
:delete-title="$t('device.card.confirmDelete')"
|
||||
:disable-title="$t('device.card.confirmDisable')"
|
||||
:enable-title="$t('device.card.confirmEnable')"
|
||||
:enabled="data.enableFlag === 'ENABLE'"
|
||||
:enabled="enabled"
|
||||
@delete="emitDelete"
|
||||
@detail="detail"
|
||||
@disable="emitToggle('disable-thing')"
|
||||
@@ -72,12 +72,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue';
|
||||
import { computed, type PropType } from 'vue';
|
||||
import { Edit, Promotion, Sunset } from '@element-plus/icons-vue';
|
||||
import router from '@/config/router';
|
||||
import { copy } from '@/utils/commonUtil';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { successMessage } from '@/utils/notificationUtil';
|
||||
import { isEnabledFlag } from '@/utils/thingModelFormatUtil';
|
||||
import ThingsCardHeader from '@/components/card/header/ThingsCardHeader.vue';
|
||||
import ThingsCardActions from '@/components/card/actions/ThingsCardActions.vue';
|
||||
|
||||
@@ -90,6 +91,7 @@
|
||||
});
|
||||
|
||||
const emit = defineEmits(['disable-thing', 'enable-thing', 'delete-thing']);
|
||||
const enabled = computed(() => isEnabledFlag(props.data.enableFlag));
|
||||
|
||||
const emitToggle = (name: 'disable-thing' | 'enable-thing') => {
|
||||
emit(name, props.data.id, props.data.driverId, () => successMessage());
|
||||
@@ -111,7 +113,3 @@
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
</style>
|
||||
|
||||
@@ -202,7 +202,3 @@
|
||||
device();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
</style>
|
||||
|
||||
@@ -96,9 +96,9 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item class="edit-form-button">
|
||||
<el-button :icon="Back" plain type="success" @click="done">{{ $t('common.return') }}</el-button>
|
||||
<el-button :icon="Back" plain @click="done">{{ $t('common.return') }}</el-button>
|
||||
<el-button :icon="RefreshLeft" @click="deviceReset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button :icon="Right" plain type="warning" @click="next">{{ $t('common.next') }}</el-button>
|
||||
<el-button :icon="Right" plain type="primary" @click="next">{{ $t('common.next') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
@@ -155,11 +155,11 @@
|
||||
</el-form>
|
||||
<el-empty v-else :description="$t('device.edit.driverConfigEmpty')" />
|
||||
<el-form-item class="edit-form-button">
|
||||
<el-button :icon="Back" plain type="success" @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Back" plain @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button v-if="hasDriverAttributes" :icon="RefreshLeft" @click="driverInfoReset">
|
||||
{{ $t('common.reset') }}
|
||||
</el-button>
|
||||
<el-button :icon="Right" plain type="warning" @click="next">{{ $t('common.next') }}</el-button>
|
||||
<el-button :icon="Right" plain type="primary" @click="next">{{ $t('common.next') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-card>
|
||||
|
||||
@@ -297,8 +297,8 @@
|
||||
</el-table>
|
||||
|
||||
<el-form-item class="edit-form-button">
|
||||
<el-button :icon="Back" plain type="success" @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Right" :loading="reactiveData.pointSaving" plain type="warning" @click="next">
|
||||
<el-button :icon="Back" plain @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Right" :loading="reactiveData.pointSaving" plain type="primary" @click="next">
|
||||
{{ $t('common.next') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
@@ -436,8 +436,8 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-form-item class="edit-form-button">
|
||||
<el-button :icon="Back" plain type="success" @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Right" :loading="reactiveData.commandSaving" plain type="warning" @click="next">
|
||||
<el-button :icon="Back" plain @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Right" :loading="reactiveData.commandSaving" plain type="primary" @click="next">
|
||||
{{ $t('common.next') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
@@ -575,8 +575,8 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-form-item class="edit-form-button">
|
||||
<el-button :icon="Back" plain type="success" @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Right" :loading="reactiveData.eventSaving" plain type="warning" @click="next">
|
||||
<el-button :icon="Back" plain @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Right" :loading="reactiveData.eventSaving" plain type="primary" @click="next">
|
||||
{{ $t('common.next') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
<div class="things-dialog-footer">
|
||||
<slot name="footer">
|
||||
<el-button @click="cancel">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button plain type="warning" @click="importTemplate">{{ $t('device.import.template') }}</el-button>
|
||||
<el-button type="primary" @click="importThing">{{ $t('common.confirm') }}</el-button>
|
||||
</slot>
|
||||
@@ -293,7 +293,3 @@
|
||||
importThing,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -156,5 +156,3 @@
|
||||
|
||||
list();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<el-card shadow="hover">
|
||||
<div class="things-card-content">
|
||||
<things-card-header
|
||||
:enabled="data.enableFlag === 'ENABLE'"
|
||||
:enabled="enabled"
|
||||
:icon="icon"
|
||||
:name="data.driverName"
|
||||
:status-title="$t('common.name')"
|
||||
@@ -71,6 +71,7 @@
|
||||
import router from '@/config/router';
|
||||
import { copy } from '@/utils/commonUtil';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { isEnabledFlag } from '@/utils/thingModelFormatUtil';
|
||||
import ThingsCardHeader from '@/components/card/header/ThingsCardHeader.vue';
|
||||
|
||||
const props = defineProps({
|
||||
@@ -81,6 +82,7 @@
|
||||
});
|
||||
|
||||
defineEmits(['select-change']);
|
||||
const enabled = computed(() => isEnabledFlag(props.data.enableFlag));
|
||||
|
||||
const status = computed(() => {
|
||||
const id = props.data.id;
|
||||
@@ -112,7 +114,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
@use '@/views/driver/card/style.scss';
|
||||
|
||||
// DriverCard 的 footer 只有单个 detail 按钮,不使用 ThingsCardActions,在此补齐样式。
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
<div class="things-dialog-footer">
|
||||
<slot name="footer">
|
||||
<el-button @click="cancel">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button type="primary" @click="addThing">{{ $t('common.confirm') }}</el-button>
|
||||
</slot>
|
||||
</div>
|
||||
@@ -230,7 +230,3 @@
|
||||
addThing,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<el-card shadow="hover">
|
||||
<div class="things-card-content">
|
||||
<things-card-header
|
||||
:enabled="data.enableFlag === 'ENABLE'"
|
||||
:enabled="enabled"
|
||||
:icon="icon"
|
||||
:name="data.pointName"
|
||||
:status-title="$t('common.name')"
|
||||
@@ -103,7 +103,7 @@
|
||||
:delete-title="$t('point.card.confirmDelete')"
|
||||
:disable-title="$t('point.card.confirmDisable')"
|
||||
:enable-title="$t('point.card.confirmEnable')"
|
||||
:enabled="data.enableFlag === 'ENABLE'"
|
||||
:enabled="enabled"
|
||||
detail-disabled
|
||||
@delete="emitDelete"
|
||||
@detail="detail"
|
||||
@@ -117,13 +117,14 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue';
|
||||
import { computed, type PropType } from 'vue';
|
||||
import { Edit, List, Location, Sunset } from '@element-plus/icons-vue';
|
||||
import router from '@/config/router';
|
||||
import { copy } from '@/utils/commonUtil';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { successMessage } from '@/utils/notificationUtil';
|
||||
import { pointTypeKey, rwFlagKey } from '@/utils/pointFormatUtil';
|
||||
import { isEnabledFlag } from '@/utils/thingModelFormatUtil';
|
||||
import ThingsCardHeader from '@/components/card/header/ThingsCardHeader.vue';
|
||||
import ThingsCardActions from '@/components/card/actions/ThingsCardActions.vue';
|
||||
|
||||
@@ -135,6 +136,7 @@
|
||||
});
|
||||
|
||||
const emit = defineEmits(['disable-thing', 'enable-thing', 'delete-thing']);
|
||||
const enabled = computed(() => isEnabledFlag(props.data.enableFlag));
|
||||
|
||||
const emitToggle = (name: 'disable-thing' | 'enable-thing') => {
|
||||
emit(name, props.data.id, props.data.profileId, () => successMessage());
|
||||
@@ -163,8 +165,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
|
||||
// PointCard 用双栏列表展示字段,200px 固定宽度是为了和卡片尺寸匹配。
|
||||
.things-body-content-item-column-2 {
|
||||
width: 200px;
|
||||
|
||||
@@ -63,7 +63,3 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts" />
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
</style>
|
||||
|
||||
@@ -105,9 +105,9 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item class="edit-form-button">
|
||||
<el-button :icon="Back" plain type="success" @click="done">{{ $t('common.return') }}</el-button>
|
||||
<el-button :icon="Back" plain @click="done">{{ $t('common.return') }}</el-button>
|
||||
<el-button :icon="RefreshLeft" @click="pointReset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button :icon="Right" plain type="warning" @click="next">{{ $t('common.next') }}</el-button>
|
||||
<el-button :icon="Right" plain type="primary" @click="next">{{ $t('common.next') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
@@ -79,8 +79,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
|
||||
// PointInfoCard 内联了一个简化的 header(无状态标签),不使用 ThingsCardHeader,在此补齐样式。
|
||||
|
||||
.cursor-pointer {
|
||||
@@ -110,15 +108,15 @@
|
||||
line-height: 48px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.header-enable {
|
||||
border-bottom: 1px solid #c2e7b0;
|
||||
border-bottom: 1px solid var(--el-color-success-light-5);
|
||||
}
|
||||
|
||||
.header-disable {
|
||||
border-bottom: 1px solid #fbc4c4;
|
||||
border-bottom: 1px solid var(--el-color-danger-light-5);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -72,12 +72,12 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-if="pre || next" #buttons="{ search, reset }">
|
||||
<el-button v-if="pre" :icon="Back" plain type="success" @click="$emit('pre-handle')">
|
||||
<el-button v-if="pre" :icon="Back" plain @click="$emit('pre-handle')">
|
||||
{{ $t('common.previous') }}
|
||||
</el-button>
|
||||
<el-button :icon="Search" type="primary" @click="search">{{ $t('common.search') }}</el-button>
|
||||
<el-button :icon="RefreshLeft" @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button v-if="next" :icon="Check" plain type="warning" @click="$emit('next-handle')">
|
||||
<el-button v-if="next" :icon="Check" plain type="primary" @click="$emit('next-handle')">
|
||||
{{ $t('common.next') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
@@ -43,22 +43,29 @@
|
||||
:embedded="embedded"
|
||||
:point="reactiveData.pointTable[data.pointId]"
|
||||
:unit="reactiveData.unitTable[data.pointId]"
|
||||
@detail-thing="openDetail"
|
||||
@write-thing="openWrite"
|
||||
></point-value-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</blank-card>
|
||||
|
||||
<point-value-edit-form ref="editRef" @update-thing="writeValue" />
|
||||
<point-value-detail ref="detailRef" :detail-data="reactiveData.detailData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, reactive } from 'vue';
|
||||
import { getPointByIds, getPointUnit, getPointValueLatest, listPointValue } from '@/api/point';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { getPointByIds, getPointUnit, getPointValueLatest, listPointValue, writePointValue } from '@/api/point';
|
||||
import { listDeviceByIds } from '@/api/device';
|
||||
|
||||
import blankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import skeletonCard from '@/components/card/skeleton/SkeletonCard.vue';
|
||||
import pointValueTool from './tool/PointValueTool.vue';
|
||||
import pointValueCard from './card/PointValueCard.vue';
|
||||
import pointValueEditForm from './edit/PointValueEditForm.vue';
|
||||
import pointValueDetail from './detail/PointValueDetail.vue';
|
||||
|
||||
import { isNull } from '@/utils/validationUtil';
|
||||
|
||||
@@ -83,6 +90,7 @@
|
||||
pointTable: {} as Record<string, any>,
|
||||
unitTable: {} as Record<string, any>,
|
||||
listData: [] as any[],
|
||||
detailData: {} as Record<string, unknown>,
|
||||
query: {},
|
||||
page: {
|
||||
total: 0,
|
||||
@@ -91,6 +99,9 @@
|
||||
},
|
||||
});
|
||||
|
||||
const editRef = ref<InstanceType<typeof pointValueEditForm>>();
|
||||
const detailRef = ref<InstanceType<typeof pointValueDetail>>();
|
||||
|
||||
const hasData = computed(() => {
|
||||
return !reactiveData.loading && reactiveData.listData?.length < 1;
|
||||
});
|
||||
@@ -199,6 +210,40 @@
|
||||
list();
|
||||
};
|
||||
|
||||
const openWrite = (row: Record<string, unknown>) => {
|
||||
editRef.value?.show({
|
||||
...row,
|
||||
value: String(row.calValue ?? ''),
|
||||
});
|
||||
};
|
||||
|
||||
const writeValue = (formData: Record<string, unknown>, done: () => void) => {
|
||||
writePointValue({
|
||||
deviceId: formData.deviceId,
|
||||
pointId: formData.pointId,
|
||||
value: String(formData.value ?? ''),
|
||||
})
|
||||
.then(() => {
|
||||
refresh();
|
||||
done();
|
||||
})
|
||||
.catch(() => {
|
||||
// handled globally
|
||||
});
|
||||
};
|
||||
|
||||
const openDetail = (row: Record<string, unknown>) => {
|
||||
const deviceId = String(row.deviceId || '');
|
||||
const pointId = String(row.pointId || '');
|
||||
reactiveData.detailData = {
|
||||
...row,
|
||||
device: reactiveData.deviceTable[deviceId],
|
||||
point: reactiveData.pointTable[pointId],
|
||||
unit: reactiveData.unitTable[pointId],
|
||||
};
|
||||
detailRef.value?.show();
|
||||
};
|
||||
|
||||
const sizeChange = (size: number) => {
|
||||
reactiveData.page.size = size;
|
||||
list();
|
||||
@@ -218,5 +263,3 @@
|
||||
list,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -95,25 +95,19 @@
|
||||
:height="80"
|
||||
:tooltip-unit="unit"
|
||||
animate
|
||||
color="#409eff"
|
||||
color="var(--el-color-primary)"
|
||||
/>
|
||||
<div v-else class="point-value-empty-chart">{{ $t('pointValue.card.noHistory') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="embedded == ''" class="things-card__footer">
|
||||
<div class="things-card-footer-operation">
|
||||
<el-popconfirm
|
||||
:icon="CircleClose"
|
||||
:title="$t('pointValue.card.confirmDelete')"
|
||||
icon-color="#f56c6c"
|
||||
placement="top"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button link type="primary">{{ $t('common.delete') }}</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
<el-button link type="primary">{{ $t('common.edit') }}</el-button>
|
||||
<el-button link type="primary">{{ $t('common.detail') }}</el-button>
|
||||
<el-button :disabled="writeDisabled" link type="primary" @click="$emit('write-thing', data)">
|
||||
{{ $t('pointValue.card.write') }}
|
||||
</el-button>
|
||||
<el-button link type="primary" @click="$emit('detail-thing', data)">
|
||||
{{ $t('common.detail') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -123,7 +117,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
import { CircleClose, Edit, Management, Sunrise, Sunset, Timer } from '@element-plus/icons-vue';
|
||||
import { Edit, Management, Sunrise, Sunset, Timer } from '@element-plus/icons-vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import MiniAreaChart from '@/components/chart/MiniAreaChart.vue';
|
||||
@@ -168,6 +162,8 @@
|
||||
},
|
||||
});
|
||||
|
||||
defineEmits(['write-thing', 'detail-thing']);
|
||||
|
||||
const copyValue = (data: any) => {
|
||||
const content = {
|
||||
deviceId: data.deviceId,
|
||||
@@ -189,6 +185,7 @@
|
||||
const displayDelay = computed(() => {
|
||||
return typeof props.data?.interval === 'number' ? `${props.data.interval} ms` : '--';
|
||||
});
|
||||
const writeDisabled = computed(() => !['W', 'RW'].includes(String(props.data?.rwFlag || '').toUpperCase()));
|
||||
|
||||
const displayTime = (value: string | null | undefined) => {
|
||||
if (!hasLatestValue.value || !value) {
|
||||
@@ -241,8 +238,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
|
||||
// PointValueCard 内联了 header / footer / 实时数值展示区,不使用 ThingsCardHeader / ThingsCardActions,
|
||||
// 因此在此补齐对应样式。`header-enable` / `header-disable` 语义不同:基于 data.interval 表示延时是否正常。
|
||||
|
||||
@@ -269,11 +264,11 @@
|
||||
line-height: 48px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
color: var(--el-text-color-primary);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #1890ff;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,15 +289,15 @@
|
||||
}
|
||||
|
||||
.header-enable {
|
||||
border-bottom: 1px solid #c2e7b0;
|
||||
border-bottom: 1px solid var(--el-color-success-light-5);
|
||||
}
|
||||
|
||||
.header-disable {
|
||||
border-bottom: 1px solid #fbc4c4;
|
||||
border-bottom: 1px solid var(--el-color-danger-light-5);
|
||||
}
|
||||
|
||||
.header-missing {
|
||||
border-bottom: 1px solid #dcdfe6;
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
.things-card__body {
|
||||
@@ -326,7 +321,7 @@
|
||||
}
|
||||
|
||||
.value-missing {
|
||||
color: #909399;
|
||||
color: var(--el-text-color-secondary);
|
||||
animation: none;
|
||||
}
|
||||
|
||||
@@ -342,7 +337,7 @@
|
||||
.point-value-empty-chart {
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
color: #909399;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
@@ -353,7 +348,7 @@
|
||||
margin-top: 2px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
border-top: 1px solid #dcdfe6;
|
||||
border-top: 1px solid var(--el-border-color);
|
||||
|
||||
.things-card-footer-operation {
|
||||
height: 35px;
|
||||
@@ -363,13 +358,13 @@
|
||||
|
||||
@keyframes hue {
|
||||
0% {
|
||||
color: #409eff;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
50% {
|
||||
color: #f3f4fe;
|
||||
color: var(--el-color-primary-light-9);
|
||||
}
|
||||
100% {
|
||||
color: #409eff;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -23,10 +23,27 @@
|
||||
direction="rtl"
|
||||
size="40%"
|
||||
>
|
||||
<pre v-highlightjs>
|
||||
<code class="json">{{ detailData }}</code>
|
||||
</pre>
|
||||
<pre class="json-preview">{{ formatJson(detailData) }}</pre>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts" />
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
import { prettyJson } from '@/utils/jsonUtil';
|
||||
|
||||
defineProps({
|
||||
detailData: {
|
||||
type: Object as PropType<Record<string, unknown>>,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const detailVisible = ref(false);
|
||||
const formatJson = (value: unknown) => prettyJson(value);
|
||||
const show = () => {
|
||||
detailVisible.value = true;
|
||||
};
|
||||
|
||||
defineExpose({ show });
|
||||
</script>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<div class="things-dialog-footer">
|
||||
<slot name="footer">
|
||||
<el-button @click="cancel">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button type="primary" @click="updateThing">{{ $t('common.confirm') }}</el-button>
|
||||
</slot>
|
||||
</div>
|
||||
@@ -100,12 +100,12 @@
|
||||
],
|
||||
});
|
||||
|
||||
const syncFormData = () => {
|
||||
reactiveData.formData = { ...props.formData };
|
||||
const syncFormData = (value = props.formData) => {
|
||||
reactiveData.formData = { ...value };
|
||||
};
|
||||
|
||||
const show = () => {
|
||||
syncFormData();
|
||||
const show = (value?: PointValueFormData) => {
|
||||
syncFormData(value);
|
||||
reactiveData.formVisible = true;
|
||||
};
|
||||
|
||||
@@ -143,7 +143,3 @@
|
||||
updateThing,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -224,5 +224,3 @@
|
||||
|
||||
list();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<div class="things-dialog-footer">
|
||||
<slot name="footer">
|
||||
<el-button @click="cancel">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button type="primary" @click="addThing">{{ $t('common.confirm') }}</el-button>
|
||||
</slot>
|
||||
</div>
|
||||
@@ -122,7 +122,3 @@
|
||||
addThing,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<el-card shadow="hover">
|
||||
<div class="things-card-content">
|
||||
<things-card-header
|
||||
:enabled="data.enableFlag === 'ENABLE'"
|
||||
:enabled="enabled"
|
||||
:icon="icon"
|
||||
:name="data.profileName"
|
||||
:status-title="$t('common.name')"
|
||||
@@ -49,7 +49,7 @@
|
||||
:delete-title="$t('profile.card.confirmDelete')"
|
||||
:disable-title="$t('profile.card.confirmDisable')"
|
||||
:enable-title="$t('profile.card.confirmEnable')"
|
||||
:enabled="data.enableFlag === 'ENABLE'"
|
||||
:enabled="enabled"
|
||||
@delete="emitAction('delete-thing')"
|
||||
@detail="detail"
|
||||
@disable="emitAction('disable-thing')"
|
||||
@@ -62,12 +62,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue';
|
||||
import { computed, type PropType } from 'vue';
|
||||
import { Edit, Sunset } from '@element-plus/icons-vue';
|
||||
import router from '@/config/router';
|
||||
import { copy } from '@/utils/commonUtil';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { successMessage } from '@/utils/notificationUtil';
|
||||
import { isEnabledFlag } from '@/utils/thingModelFormatUtil';
|
||||
import ThingsCardHeader from '@/components/card/header/ThingsCardHeader.vue';
|
||||
import ThingsCardActions from '@/components/card/actions/ThingsCardActions.vue';
|
||||
|
||||
@@ -78,6 +79,7 @@
|
||||
});
|
||||
|
||||
const emit = defineEmits(['disable-thing', 'enable-thing', 'delete-thing']);
|
||||
const enabled = computed(() => isEnabledFlag(props.data.enableFlag));
|
||||
|
||||
const emitAction = (name: 'disable-thing' | 'enable-thing' | 'delete-thing') => {
|
||||
emit(name, props.data.id, () => successMessage());
|
||||
@@ -95,7 +97,3 @@
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
</style>
|
||||
|
||||
@@ -63,7 +63,3 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts" />
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
</style>
|
||||
|
||||
@@ -53,9 +53,9 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item class="edit-form-button">
|
||||
<el-button :icon="Back" plain type="success" @click="done">{{ $t('common.return') }}</el-button>
|
||||
<el-button :icon="Back" plain @click="done">{{ $t('common.return') }}</el-button>
|
||||
<el-button :icon="RefreshLeft" @click="profileReset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button :icon="Right" plain type="warning" @click="next">{{ $t('common.next') }}</el-button>
|
||||
<el-button :icon="Right" plain type="primary" @click="next">{{ $t('common.next') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
@@ -63,24 +63,24 @@
|
||||
<el-divider content-position="left">{{ $t('profile.edit.pointConfig') }}</el-divider>
|
||||
<point :embedded="'edit'" :profile-id="reactiveData.id"></point>
|
||||
<el-form-item class="edit-form-button">
|
||||
<el-button :icon="Back" plain type="success" @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Right" plain type="warning" @click="next">{{ $t('common.next') }}</el-button>
|
||||
<el-button :icon="Back" plain @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Right" plain type="primary" @click="next">{{ $t('common.next') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-card>
|
||||
<el-card v-if="reactiveData.active === 2" shadow="hover">
|
||||
<el-divider content-position="left">{{ $t('profile.edit.commandConfig') }}</el-divider>
|
||||
<command-list :embedded="'edit'" :profile-id="reactiveData.id"></command-list>
|
||||
<el-form-item class="edit-form-button">
|
||||
<el-button :icon="Back" plain type="success" @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Right" plain type="warning" @click="next">{{ $t('common.next') }}</el-button>
|
||||
<el-button :icon="Back" plain @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Right" plain type="primary" @click="next">{{ $t('common.next') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-card>
|
||||
<el-card v-if="reactiveData.active === 3" shadow="hover">
|
||||
<el-divider content-position="left">{{ $t('profile.edit.eventConfig') }}</el-divider>
|
||||
<event-list :embedded="'edit'" :profile-id="reactiveData.id"></event-list>
|
||||
<el-form-item class="edit-form-button">
|
||||
<el-button :icon="Back" plain type="success" @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Right" plain type="warning" @click="next">{{ $t('common.next') }}</el-button>
|
||||
<el-button :icon="Back" plain @click="pre">{{ $t('common.previous') }}</el-button>
|
||||
<el-button :icon="Right" plain type="primary" @click="next">{{ $t('common.next') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-card>
|
||||
<el-card v-if="reactiveData.active === 4" shadow="hover">
|
||||
|
||||
@@ -189,11 +189,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-table {
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.agentic-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -174,10 +174,3 @@
|
||||
|
||||
load();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-table {
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -65,10 +65,10 @@
|
||||
{{ reactiveData.data.remark || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.createTime')">
|
||||
{{ reactiveData.data.createTime ? timestamp(reactiveData.data.createTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.createTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.operationTime')">
|
||||
{{ reactiveData.data.operateTime ? timestamp(reactiveData.data.operateTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.operateTime) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</detail-card>
|
||||
@@ -88,7 +88,7 @@
|
||||
import DefaultTag from '@/components/tag/DefaultTag.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
import type { AgenticModelConfig } from '@/config/types';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { timestampLabel } from '@/utils/dateUtil';
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
@@ -116,8 +116,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
|
||||
.agentic-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -82,7 +82,3 @@
|
||||
load();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
</style>
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
</el-form>
|
||||
<div class="things-dialog-footer">
|
||||
<el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="onReset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button plain @click="onReset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button :loading="submitting" type="primary" @click="onSubmit">
|
||||
{{ $t('common.confirm') }}
|
||||
</el-button>
|
||||
@@ -165,8 +165,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
|
||||
.agentic-form-flags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
</el-form>
|
||||
<div class="things-dialog-footer">
|
||||
<el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="onReset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button plain @click="onReset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button :loading="submitting" type="primary" @click="onSubmit">
|
||||
{{ $t('common.confirm') }}
|
||||
</el-button>
|
||||
@@ -152,7 +152,3 @@
|
||||
|
||||
defineExpose({ show, showEdit });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -146,7 +146,7 @@
|
||||
<template #footer>
|
||||
<div class="things-dialog-footer">
|
||||
<el-button @click="formVisible = false">{{ t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="resetForm">{{ t('common.reset') }}</el-button>
|
||||
<el-button plain @click="resetForm">{{ t('common.reset') }}</el-button>
|
||||
<el-button :loading="state.saving" type="primary" @click="submit">{{ t('common.confirm') }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -194,8 +194,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
|
||||
.alarm-notify {
|
||||
min-width: 0;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
<el-tab-pane v-for="prop in activeConfig.extProps" :key="prop" :label="extLabel(prop)" :name="prop">
|
||||
<detail-card>
|
||||
<pre class="alarm-detail__json">{{ prettyJson(reactiveData.data[prop]) }}</pre>
|
||||
<pre class="alarm-detail__json">{{ prettyJson(reactiveData.data[prop], '{}') }}</pre>
|
||||
</detail-card>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
@@ -61,7 +61,8 @@
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import DetailCard from '@/components/card/detail/DetailCard.vue';
|
||||
import type { AlarmEntityRecord } from '@/config/types';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { timestampLabel } from '@/utils/dateUtil';
|
||||
import { prettyJson } from '@/utils/jsonUtil';
|
||||
|
||||
type AlarmEntity = 'rule' | 'notify' | 'message' | 'channel' | 'bind' | 'state' | 'history';
|
||||
type FieldKind = 'text' | 'tag' | 'time' | 'code';
|
||||
@@ -259,7 +260,7 @@
|
||||
|
||||
const formatDetail = (field: DetailField) => {
|
||||
const value = reactiveData.data[field.prop];
|
||||
if (field.kind === 'time' || field.prop.endsWith('Time')) return value ? timestamp(String(value)) : '-';
|
||||
if (field.kind === 'time' || field.prop.endsWith('Time')) return timestampLabel(value);
|
||||
if (field.kind === 'tag') return enumLabel(value);
|
||||
if (value == null || value === '') return '-';
|
||||
return String(value);
|
||||
@@ -279,18 +280,6 @@
|
||||
return map[prop] || prop;
|
||||
};
|
||||
|
||||
const prettyJson = (value: unknown) => {
|
||||
if (value == null || value === '') return '{}';
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
return JSON.stringify(JSON.parse(value), null, 2);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return JSON.stringify(value, null, 2);
|
||||
};
|
||||
|
||||
const load = () => {
|
||||
if (!reactiveData.id) return;
|
||||
activeConfig.value
|
||||
@@ -309,8 +298,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
|
||||
.alarm-detail__inline-code {
|
||||
padding: 2px 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
@@ -20,7 +20,8 @@ import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import type { AlarmEntityRecord, Order, PageQuery } from '@/config/types';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { timestampLabel } from '@/utils/dateUtil';
|
||||
import { prettyJson } from '@/utils/jsonUtil';
|
||||
import { failMessage, successMessage } from '@/utils/notificationUtil';
|
||||
import { cleanSearchParams, resetSearchForm } from '@/utils/searchParamUtil';
|
||||
|
||||
@@ -148,25 +149,13 @@ export const useAlarmEntityPage = (props: AlarmEntityPageProps) => {
|
||||
load();
|
||||
};
|
||||
|
||||
const prettyJson = (value: unknown) => {
|
||||
if (value == null || value === '') return '{}';
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
return JSON.stringify(JSON.parse(value), null, 2);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return JSON.stringify(value, null, 2);
|
||||
};
|
||||
|
||||
const assignForm = (value: Record<string, unknown>) => {
|
||||
Object.keys(formModel).forEach((key) => delete formModel[key]);
|
||||
Object.assign(formModel, value);
|
||||
activeConfig.value.fields
|
||||
.filter((field) => field.kind === 'json')
|
||||
.forEach((field) => {
|
||||
formModel[field.prop] = prettyJson(formModel[field.prop]);
|
||||
formModel[field.prop] = prettyJson(formModel[field.prop], '{}');
|
||||
});
|
||||
};
|
||||
|
||||
@@ -261,11 +250,6 @@ export const useAlarmEntityPage = (props: AlarmEntityPageProps) => {
|
||||
});
|
||||
};
|
||||
|
||||
const formatTime = (value: unknown) => {
|
||||
if (!value) return '-';
|
||||
return timestamp(String(value)) || '-';
|
||||
};
|
||||
|
||||
const enumLabel = (value: unknown) => {
|
||||
const text = String(value || '');
|
||||
const map: Record<string, string> = {
|
||||
@@ -306,7 +290,7 @@ export const useAlarmEntityPage = (props: AlarmEntityPageProps) => {
|
||||
|
||||
const formatCell = (row: AlarmEntityRecord, column: AlarmColumnConfig) => {
|
||||
const value = row[column.prop];
|
||||
if (column.kind === 'time') return formatTime(value);
|
||||
if (column.kind === 'time') return timestampLabel(value);
|
||||
if (column.kind === 'tag') return enumLabel(value);
|
||||
if (value == null || value === '') return '-';
|
||||
return String(value);
|
||||
|
||||
@@ -35,13 +35,7 @@
|
||||
<el-table-column :label="t('settings.api.apiType')" min-width="100" prop="apiTypeFlag" />
|
||||
<el-table-column :label="t('common.enable')" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="String(row.enableFlag) === 'ENABLE' || Number(row.enableFlag) === 0 ? 'success' : 'info'">
|
||||
{{
|
||||
String(row.enableFlag) === 'ENABLE' || Number(row.enableFlag) === 0
|
||||
? t('common.enable')
|
||||
: t('common.disable')
|
||||
}}
|
||||
</el-tag>
|
||||
<enable-tag :value="row.enableFlag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('common.remark')" min-width="140" prop="remark" show-overflow-tooltip />
|
||||
@@ -66,10 +60,3 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-table {
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -37,28 +37,16 @@
|
||||
{{ reactiveData.data.apiTypeFlag }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.enable')">
|
||||
<el-tag
|
||||
:type="
|
||||
String(reactiveData.data.enableFlag) === 'ENABLE' || Number(reactiveData.data.enableFlag) === 0
|
||||
? 'success'
|
||||
: 'info'
|
||||
"
|
||||
>
|
||||
{{
|
||||
String(reactiveData.data.enableFlag) === 'ENABLE' || Number(reactiveData.data.enableFlag) === 0
|
||||
? $t('common.enable')
|
||||
: $t('common.disable')
|
||||
}}
|
||||
</el-tag>
|
||||
<enable-tag :value="reactiveData.data.enableFlag" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.remark')" :span="2">
|
||||
{{ reactiveData.data.remark || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.createTime')">
|
||||
{{ reactiveData.data.createTime ? timestamp(reactiveData.data.createTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.createTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.operationTime')">
|
||||
{{ reactiveData.data.operateTime ? timestamp(reactiveData.data.operateTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.operateTime) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</detail-card>
|
||||
@@ -73,10 +61,11 @@
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import { getApiById } from '@/api/api';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { timestampLabel } from '@/utils/dateUtil';
|
||||
|
||||
import blankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import detailCard from '@/components/card/detail/DetailCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
@@ -101,7 +90,3 @@
|
||||
load();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
</style>
|
||||
|
||||
@@ -21,9 +21,10 @@ import { useRouter } from 'vue-router';
|
||||
import { listApi } from '@/api/api';
|
||||
import { timestampColumn } from '@/utils/dateUtil';
|
||||
|
||||
import type { Order } from '@/config/types';
|
||||
import type { ApiRecord, Order } from '@/config/types';
|
||||
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
import apiTool from './tool/ApiTool.vue';
|
||||
|
||||
// APIs are auto-registered by each service on startup — editing them from
|
||||
@@ -33,6 +34,7 @@ export default defineComponent({
|
||||
name: 'SettingsApi',
|
||||
components: {
|
||||
BlankCard,
|
||||
EnableTag,
|
||||
apiTool,
|
||||
},
|
||||
setup() {
|
||||
@@ -41,8 +43,8 @@ export default defineComponent({
|
||||
|
||||
const reactiveData = reactive({
|
||||
loading: false,
|
||||
listData: [] as any[],
|
||||
query: {} as Record<string, any>,
|
||||
listData: [] as ApiRecord[],
|
||||
query: {} as Record<string, unknown>,
|
||||
order: false,
|
||||
page: {
|
||||
total: 0,
|
||||
@@ -55,7 +57,7 @@ export default defineComponent({
|
||||
const load = () => {
|
||||
reactiveData.loading = true;
|
||||
listApi({ page: reactiveData.page, ...reactiveData.query })
|
||||
.then((res: any) => {
|
||||
.then((res) => {
|
||||
const data = res.data || {};
|
||||
reactiveData.listData = data.records || [];
|
||||
reactiveData.page.total = data.total || 0;
|
||||
@@ -68,7 +70,7 @@ export default defineComponent({
|
||||
});
|
||||
};
|
||||
|
||||
const search = (params: any) => {
|
||||
const search = (params: Record<string, unknown>) => {
|
||||
reactiveData.query = params || {};
|
||||
reactiveData.page.current = 1;
|
||||
load();
|
||||
@@ -88,7 +90,7 @@ export default defineComponent({
|
||||
load();
|
||||
};
|
||||
|
||||
const openDetail = (row: any) => {
|
||||
const openDetail = (row: ApiRecord) => {
|
||||
router.push({ name: 'settingsApiDetail', query: { id: String(row.id) } }).catch(() => {
|
||||
// handled globally
|
||||
});
|
||||
|
||||
@@ -26,26 +26,61 @@
|
||||
@current-change="currentChange"
|
||||
>
|
||||
<template #filters>
|
||||
<el-form-item label="Device ID" prop="deviceId">
|
||||
<el-input v-model="formData.deviceId" class="edit-form-default" clearable placeholder="Device ID" />
|
||||
<el-form-item :label="$t('command.history.deviceId')" prop="deviceId">
|
||||
<el-input
|
||||
v-model="formData.deviceId"
|
||||
:placeholder="$t('command.history.deviceId')"
|
||||
class="edit-form-default"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Command Code" prop="commandCode">
|
||||
<el-input v-model="formData.commandCode" class="edit-form-default" clearable placeholder="Command Code" />
|
||||
<el-form-item :label="$t('command.history.commandCode')" prop="commandCode">
|
||||
<el-input
|
||||
v-model="formData.commandCode"
|
||||
:placeholder="$t('command.history.commandCode')"
|
||||
class="edit-form-default"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Status" prop="status">
|
||||
<el-input v-model="formData.status" class="edit-form-default" clearable placeholder="Status" />
|
||||
<el-form-item :label="$t('command.history.status')" prop="status">
|
||||
<el-input
|
||||
v-model="formData.status"
|
||||
:placeholder="$t('command.history.status')"
|
||||
class="edit-form-default"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</tool-card>
|
||||
|
||||
<blank-card>
|
||||
<el-table v-loading="reactiveData.loading" :data="reactiveData.listData" class="settings-table" stripe>
|
||||
<el-table-column label="Record ID" min-width="180" prop="recordId" show-overflow-tooltip />
|
||||
<el-table-column label="Device ID" min-width="160" prop="deviceId" show-overflow-tooltip />
|
||||
<el-table-column label="Command Code" min-width="140" prop="commandCode" />
|
||||
<el-table-column label="Status" prop="status" width="100" />
|
||||
<el-table-column label="Error" min-width="180" prop="errorMessage" show-overflow-tooltip />
|
||||
<el-table-column :formatter="timestampColumn" label="Occur Time" prop="occurTime" width="165" />
|
||||
<el-table-column
|
||||
:label="$t('command.history.recordId')"
|
||||
min-width="180"
|
||||
prop="recordId"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('command.history.deviceId')"
|
||||
min-width="160"
|
||||
prop="deviceId"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column :label="$t('command.history.commandCode')" min-width="140" prop="commandCode" />
|
||||
<el-table-column :label="$t('command.history.status')" prop="status" width="100" />
|
||||
<el-table-column
|
||||
:label="$t('command.history.error')"
|
||||
min-width="180"
|
||||
prop="errorMessage"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
:formatter="timestampColumn"
|
||||
:label="$t('command.history.occurTime')"
|
||||
prop="occurTime"
|
||||
width="165"
|
||||
/>
|
||||
<el-table-column :formatter="timestampColumn" :label="$t('common.createTime')" prop="createTime" width="165" />
|
||||
<el-table-column :label="$t('common.operation')" fixed="right" width="100">
|
||||
<template #default="{ row }">
|
||||
@@ -58,44 +93,60 @@
|
||||
</el-table>
|
||||
</blank-card>
|
||||
|
||||
<el-dialog v-model="detailVisible" :append-to-body="true" draggable title="Record Detail" width="700px">
|
||||
<el-dialog
|
||||
v-model="detailVisible"
|
||||
:append-to-body="true"
|
||||
:title="$t('command.history.detailTitle')"
|
||||
draggable
|
||||
width="700px"
|
||||
>
|
||||
<el-descriptions v-if="detailRow" :column="2" border>
|
||||
<el-descriptions-item :span="2" label="Record ID">{{ detailRow.recordId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Device ID">{{ detailRow.deviceId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Command ID">{{ detailRow.commandId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Command Code">{{ detailRow.commandCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Status">{{ detailRow.status }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Error Code">{{ detailRow.errorCode || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Error Message">{{ detailRow.errorMessage || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Source">{{ detailRow.source || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Source User ID">{{ detailRow.sourceUserId || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item :span="2" label="Param Values">
|
||||
<el-descriptions-item :label="$t('command.history.recordId')" :span="2">
|
||||
{{ detailRow.recordId }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.deviceId')">{{ detailRow.deviceId }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.commandId')">{{ detailRow.commandId }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.commandCode')">
|
||||
{{ detailRow.commandCode }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.status')">{{ detailRow.status }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.errorCode')">
|
||||
{{ detailRow.errorCode || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.errorMessage')">
|
||||
{{ detailRow.errorMessage || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.source')">{{ detailRow.source || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.sourceUserId')">
|
||||
{{ detailRow.sourceUserId || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.paramValues')" :span="2">
|
||||
<pre class="json-preview">{{ formatJson(detailRow.paramValues) }}</pre>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="2" label="Result Values">
|
||||
<el-descriptions-item :label="$t('command.history.resultValues')" :span="2">
|
||||
<pre class="json-preview">{{ formatJson(detailRow.resultValues) }}</pre>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="2" label="Config Snapshot">
|
||||
<el-descriptions-item :label="$t('command.history.configSnapshot')" :span="2">
|
||||
<pre class="json-preview">{{ formatJson(detailRow.configSnapshot) }}</pre>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :formatter="timestampColumn" label="Occur Time">{{
|
||||
detailRow.occurTime || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item :formatter="timestampColumn" label="Send Time">{{
|
||||
detailRow.sendTime || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item :formatter="timestampColumn" label="Finish Time">{{
|
||||
detailRow.finishTime || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item :formatter="timestampColumn" label="Expire Time">{{
|
||||
detailRow.expireTime || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item :formatter="timestampColumn" label="Create Time">{{
|
||||
detailRow.createTime || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item :formatter="timestampColumn" label="Operate Time">{{
|
||||
detailRow.operateTime || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.occurTime')">
|
||||
{{ timestampLabel(detailRow.occurTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.sendTime')">
|
||||
{{ timestampLabel(detailRow.sendTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.finishTime')">
|
||||
{{ timestampLabel(detailRow.finishTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.history.expireTime')">
|
||||
{{ timestampLabel(detailRow.expireTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.createTime')">
|
||||
{{ timestampLabel(detailRow.createTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.operationTime')">
|
||||
{{ timestampLabel(detailRow.operateTime) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-dialog>
|
||||
</div>
|
||||
@@ -104,7 +155,8 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import { getCommandHistoryById, listCommandHistory } from '@/api/command';
|
||||
import { timestampColumn } from '@/utils/dateUtil';
|
||||
import { timestampColumn, timestampLabel } from '@/utils/dateUtil';
|
||||
import { prettyJson } from '@/utils/jsonUtil';
|
||||
import type { CommandHistory, Order } from '@/config/types';
|
||||
import ToolCard from '@/components/card/tool/ToolCard.vue';
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
@@ -117,23 +169,11 @@
|
||||
page: { total: 0, size: 12, current: 1, orders: [] as Order[] },
|
||||
});
|
||||
|
||||
const formData = reactive<Record<string, any>>({});
|
||||
const formData = reactive<Record<string, string>>({});
|
||||
const detailVisible = ref(false);
|
||||
const detailRow = ref<CommandHistory | null>(null);
|
||||
|
||||
const formatJson = (value: unknown) => {
|
||||
if (!value) {
|
||||
return '-';
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
return JSON.stringify(JSON.parse(value), null, 2);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return JSON.stringify(value, null, 2);
|
||||
};
|
||||
const formatJson = (value: unknown) => prettyJson(value);
|
||||
|
||||
const load = () => {
|
||||
reactiveData.loading = true;
|
||||
@@ -148,7 +188,7 @@
|
||||
});
|
||||
};
|
||||
|
||||
const onSearch = (data: Record<string, any>) => {
|
||||
const onSearch = (data: Record<string, string>) => {
|
||||
reactiveData.query = cleanSearchParams(data);
|
||||
reactiveData.page.current = 1;
|
||||
load();
|
||||
@@ -186,24 +226,3 @@
|
||||
|
||||
load();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-table {
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.json-preview {
|
||||
max-height: 220px;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
overflow: auto;
|
||||
border-radius: 4px;
|
||||
background: var(--el-fill-color-light);
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -57,46 +57,40 @@
|
||||
|
||||
<command-edit-form ref="editRef" @add-thing="onAdd" @update-thing="onUpdate" />
|
||||
|
||||
<el-drawer v-model="reactiveData.detailVisible" title="Command Detail" size="520px">
|
||||
<el-drawer v-model="reactiveData.detailVisible" :title="$t('command.detail.title')" size="520px">
|
||||
<el-descriptions v-if="reactiveData.detailRecord" :column="1" border>
|
||||
<el-descriptions-item :label="$t('common.name')">{{
|
||||
reactiveData.detailRecord.commandName || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="Code">{{ reactiveData.detailRecord.commandCode || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Command Type">{{
|
||||
<el-descriptions-item :label="$t('command.detail.code')">
|
||||
{{ reactiveData.detailRecord.commandCode || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.detail.commandType')">{{
|
||||
reactiveData.detailRecord.commandTypeFlag || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="Call Type">{{
|
||||
<el-descriptions-item :label="$t('command.detail.callType')">{{
|
||||
reactiveData.detailRecord.callTypeFlag || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="Timeout (ms)">{{ reactiveData.detailRecord.timeout ?? '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.detail.timeout')">{{
|
||||
commandTimeoutLabel(reactiveData.detailRecord.timeout)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.enableFlag')">
|
||||
<el-tag
|
||||
:type="
|
||||
String(reactiveData.detailRecord.enableFlag) === 'ENABLE' ||
|
||||
Number(reactiveData.detailRecord.enableFlag) === 0
|
||||
? 'success'
|
||||
: 'info'
|
||||
"
|
||||
>
|
||||
{{
|
||||
String(reactiveData.detailRecord.enableFlag) === 'ENABLE' ||
|
||||
Number(reactiveData.detailRecord.enableFlag) === 0
|
||||
? $t('common.enable')
|
||||
: $t('common.disable')
|
||||
}}
|
||||
</el-tag>
|
||||
<enable-tag :value="reactiveData.detailRecord.enableFlag" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.remark')">{{
|
||||
reactiveData.detailRecord.remark || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="Profile ID">{{ reactiveData.detailRecord.profileId || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Tenant ID">{{ reactiveData.detailRecord.tenantId || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Create Time">{{
|
||||
formatTime(reactiveData.detailRecord.createTime)
|
||||
<el-descriptions-item :label="$t('command.detail.profileId')">
|
||||
{{ reactiveData.detailRecord.profileId || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('command.detail.tenantId')">
|
||||
{{ reactiveData.detailRecord.tenantId || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.createTime')">{{
|
||||
timestampLabel(reactiveData.detailRecord.createTime)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="Operate Time">{{
|
||||
formatTime(reactiveData.detailRecord.operateTime)
|
||||
<el-descriptions-item :label="$t('common.operationTime')">{{
|
||||
timestampLabel(reactiveData.detailRecord.operateTime)
|
||||
}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-empty v-else :description="$t('common.description')" />
|
||||
@@ -106,13 +100,24 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import { addCommand, deleteCommand, listCommand, updateCommand } from '@/api/command';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { successMessage } from '@/utils/notificationUtil';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import {
|
||||
addCommand,
|
||||
addCommandParam,
|
||||
deleteCommand,
|
||||
deleteCommandParam,
|
||||
listCommand,
|
||||
updateCommand,
|
||||
updateCommandParam,
|
||||
} from '@/api/command';
|
||||
import { timestampLabel } from '@/utils/dateUtil';
|
||||
import { failMessage, successMessage } from '@/utils/notificationUtil';
|
||||
import { commandTimeoutLabel } from '@/utils/thingModelFormatUtil';
|
||||
import { isNull } from '@/utils/validationUtil';
|
||||
import type { CommandForm, CommandRecord, Order } from '@/config/types';
|
||||
import type { CommandForm, CommandParamRecord, CommandRecord, Order } from '@/config/types';
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import SkeletonCard from '@/components/card/skeleton/SkeletonCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
import CommandCard from './card/CommandCard.vue';
|
||||
import CommandTool from './tool/CommandTool.vue';
|
||||
import CommandEditForm from './edit/CommandEditForm.vue';
|
||||
@@ -133,6 +138,7 @@
|
||||
}>();
|
||||
|
||||
const editRef = ref<InstanceType<typeof CommandEditForm>>();
|
||||
const { t } = useI18n();
|
||||
const canManage = computed(() => props.embedded === '' || props.embedded === 'edit');
|
||||
const hasData = computed(() => !reactiveData.loading && reactiveData.listData.length < 1);
|
||||
|
||||
@@ -162,8 +168,6 @@
|
||||
return isNull(profileId) ? { ...form } : { ...form, profileId };
|
||||
};
|
||||
|
||||
const formatTime = (value: unknown) => (isNull(value) ? '-' : timestamp(String(value)));
|
||||
|
||||
const load = () => {
|
||||
reactiveData.loading = true;
|
||||
const query = withFixedQuery(reactiveData.query);
|
||||
@@ -205,20 +209,69 @@
|
||||
};
|
||||
const openEdit = (row: CommandRecord) => editRef.value?.showEdit(row);
|
||||
|
||||
const onAdd = (form: CommandForm, done: () => void) => {
|
||||
addCommand(withFixedProfile(form)).then(() => {
|
||||
successMessage();
|
||||
load();
|
||||
done();
|
||||
type DoneCallback = (close?: boolean) => void;
|
||||
|
||||
const isValidCreatedId = (id: string) => /^\d+$/.test(id);
|
||||
|
||||
const syncCommandParams = (
|
||||
commandId: string,
|
||||
params: CommandParamRecord[],
|
||||
originalParams: CommandParamRecord[] = []
|
||||
) => {
|
||||
const currentIds = new Set(params.map((item) => String(item.id || '')).filter(Boolean));
|
||||
const deleteTasks = originalParams
|
||||
.filter((item) => item.id && !currentIds.has(String(item.id)))
|
||||
.map((item) => deleteCommandParam(String(item.id)));
|
||||
|
||||
const saveTasks = params.map((item) => {
|
||||
const payload = { ...item, commandId };
|
||||
return item.id ? updateCommandParam(payload) : addCommandParam({ ...payload, id: undefined });
|
||||
});
|
||||
|
||||
return Promise.all(deleteTasks).then(() => Promise.all(saveTasks));
|
||||
};
|
||||
|
||||
const onUpdate = (form: CommandForm, done: () => void) => {
|
||||
updateCommand(withFixedProfile(form)).then(() => {
|
||||
successMessage();
|
||||
load();
|
||||
done();
|
||||
});
|
||||
const onAdd = (form: CommandForm, params: CommandParamRecord[], done: DoneCallback) => {
|
||||
addCommand(withFixedProfile(form))
|
||||
.then((res) => {
|
||||
const commandId = String(res.data || '');
|
||||
if (!isValidCreatedId(commandId)) {
|
||||
failMessage(t('command.errors.idNotReturned'));
|
||||
return Promise.reject(new Error(t('command.errors.idNotReturned')));
|
||||
}
|
||||
return syncCommandParams(commandId, params).then(() => {
|
||||
successMessage();
|
||||
load();
|
||||
done();
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
done(false);
|
||||
});
|
||||
};
|
||||
|
||||
const onUpdate = (
|
||||
form: CommandForm,
|
||||
params: CommandParamRecord[],
|
||||
originalParams: CommandParamRecord[],
|
||||
done: DoneCallback
|
||||
) => {
|
||||
updateCommand(withFixedProfile(form))
|
||||
.then(() => {
|
||||
const commandId = String(form.id || '');
|
||||
if (!isValidCreatedId(commandId)) {
|
||||
failMessage(t('command.errors.idMissing'));
|
||||
return Promise.reject(new Error(t('command.errors.idMissing')));
|
||||
}
|
||||
return syncCommandParams(commandId, params, originalParams).then(() => {
|
||||
successMessage();
|
||||
load();
|
||||
done();
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
done(false);
|
||||
});
|
||||
};
|
||||
|
||||
const disableThing = (id: string, profileId: string, done: () => void) => {
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<span>
|
||||
<el-icon><Location /></el-icon> {{ $t('command.card.timeout') }}:
|
||||
</span>
|
||||
{{ data.timeout ?? '-' }}
|
||||
{{ commandTimeoutLabel(data.timeout) }}
|
||||
</li>
|
||||
<li class="nowrap-item">
|
||||
<span>
|
||||
@@ -102,7 +102,7 @@
|
||||
import { copy } from '@/utils/commonUtil';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { successMessage } from '@/utils/notificationUtil';
|
||||
import { callTypeLabel, commandTypeLabel, isEnabledFlag } from '@/utils/thingModelFormatUtil';
|
||||
import { callTypeLabel, commandTimeoutLabel, commandTypeLabel, isEnabledFlag } from '@/utils/thingModelFormatUtil';
|
||||
import ThingsCardHeader from '@/components/card/header/ThingsCardHeader.vue';
|
||||
import ThingsCardActions from '@/components/card/actions/ThingsCardActions.vue';
|
||||
import type { CommandRecord } from '@/config/types';
|
||||
@@ -127,8 +127,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
|
||||
.things-body-content-item-column-2 {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:show-close="false"
|
||||
:title="reactiveData.mode === 'add' ? $t('common.add') + ' Command' : $t('common.edit') + ' Command'"
|
||||
:title="reactiveData.mode === 'add' ? $t('command.form.addTitle') : $t('command.form.editTitle')"
|
||||
class="things-dialog"
|
||||
draggable
|
||||
@closed="reset"
|
||||
@@ -30,21 +30,21 @@
|
||||
<el-form-item :label="$t('common.name')" prop="commandName">
|
||||
<el-input v-model="reactiveData.form.commandName" :placeholder="$t('common.name')" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="Code" prop="commandCode">
|
||||
<el-input v-model="reactiveData.form.commandCode" clearable placeholder="Code" />
|
||||
<el-form-item :label="$t('command.form.code')" prop="commandCode">
|
||||
<el-input v-model="reactiveData.form.commandCode" :placeholder="$t('command.form.code')" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="Command Type" prop="commandTypeFlag">
|
||||
<el-form-item :label="$t('command.form.commandType')" prop="commandTypeFlag">
|
||||
<el-select v-model="reactiveData.form.commandTypeFlag" clearable>
|
||||
<el-option v-for="opt in COMMAND_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="Call Type" prop="callTypeFlag">
|
||||
<el-form-item :label="$t('command.form.callType')" prop="callTypeFlag">
|
||||
<el-select v-model="reactiveData.form.callTypeFlag" clearable>
|
||||
<el-option v-for="opt in CALL_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="Timeout (ms)" prop="timeout">
|
||||
<el-input-number v-model="reactiveData.form.timeout" :min="0" :step="1000" />
|
||||
<el-form-item :label="$t('command.form.timeout')" prop="timeout">
|
||||
<el-input-number v-model="reactiveData.form.timeout" :min="1" :precision="0" :step="1" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('common.enableFlag')" prop="enableFlag">
|
||||
<enable-flag-segmented v-model="reactiveData.form.enableFlag" />
|
||||
@@ -53,9 +53,70 @@
|
||||
<el-input v-model="reactiveData.form.remark" clearable maxlength="300" show-word-limit type="textarea" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div v-loading="reactiveData.paramLoading" class="param-editor">
|
||||
<div class="param-editor__toolbar">
|
||||
<span>{{ $t('command.form.params') }}</span>
|
||||
<el-button :icon="Plus" size="small" type="success" @click="addParamRow">
|
||||
{{ $t('common.add') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table :data="reactiveData.params" border max-height="260" size="small">
|
||||
<el-table-column :label="$t('common.name')" min-width="150">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.paramName" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('command.form.code')" min-width="150">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.paramCode" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('command.form.direction')" min-width="130">
|
||||
<template #default="{ row }">
|
||||
<el-select v-model="row.paramDirectionFlag">
|
||||
<el-option
|
||||
v-for="opt in PARAM_DIRECTION_OPTIONS"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('command.form.type')" min-width="130">
|
||||
<template #default="{ row }">
|
||||
<el-select v-model="row.paramTypeFlag">
|
||||
<el-option v-for="opt in POINT_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('command.form.required')" width="96">
|
||||
<template #default="{ row }">
|
||||
<el-checkbox v-model="row.requiredFlag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('command.form.defaultValue')" min-width="150">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.defaultValue" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('command.form.enabled')" width="104">
|
||||
<template #default="{ row }">
|
||||
<el-switch v-model="row.enableFlag" active-value="ENABLE" inactive-value="DISABLE" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" width="64">
|
||||
<template #default="{ $index }">
|
||||
<el-tooltip :content="$t('common.delete')" placement="top">
|
||||
<el-button :icon="Delete" link type="danger" @click="removeParamRow($index)" />
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="things-dialog-footer">
|
||||
<el-button @click="reactiveData.visible = false">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button :loading="reactiveData.submitting" type="primary" @click="submit">
|
||||
{{ $t('common.confirm') }}
|
||||
</el-button>
|
||||
@@ -66,16 +127,44 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { Delete, Plus } from '@element-plus/icons-vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { listCommandParamByCommandId } from '@/api/command';
|
||||
import EnableFlagSegmented from '@/components/segmented/EnableFlagSegmented.vue';
|
||||
import { CALL_TYPE_OPTIONS, COMMAND_TYPE_OPTIONS } from '@/config/constant/enums';
|
||||
import type { CommandRecord } from '@/config/types';
|
||||
import {
|
||||
CALL_TYPE_OPTIONS,
|
||||
COMMAND_TYPE_OPTIONS,
|
||||
PARAM_DIRECTION_OPTIONS,
|
||||
POINT_TYPE_OPTIONS,
|
||||
} from '@/config/constant/enums';
|
||||
import type { CommandForm, CommandParamRecord, CommandRecord } from '@/config/types';
|
||||
import { failMessage } from '@/utils/notificationUtil';
|
||||
import {
|
||||
callTypeValue,
|
||||
commandTypeValue,
|
||||
enableFlagValue,
|
||||
normalizeCommandTimeoutSeconds,
|
||||
paramDirectionValue,
|
||||
pointTypeValue,
|
||||
} from '@/utils/thingModelFormatUtil';
|
||||
|
||||
type FormMode = 'add' | 'edit';
|
||||
type DoneCallback = (close?: boolean) => void;
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const emit = defineEmits(['add-thing', 'update-thing']);
|
||||
type CommandParamDraft = CommandParamRecord & { _key: string };
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'add-thing', form: CommandForm, params: CommandParamRecord[], done: DoneCallback): void;
|
||||
(
|
||||
e: 'update-thing',
|
||||
form: CommandForm,
|
||||
params: CommandParamRecord[],
|
||||
originalParams: CommandParamRecord[],
|
||||
done: DoneCallback
|
||||
): void;
|
||||
}>();
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
@@ -86,7 +175,7 @@
|
||||
commandCode: '',
|
||||
commandTypeFlag: 'CUSTOM' as string,
|
||||
callTypeFlag: 'SYNC' as string,
|
||||
timeout: 30000,
|
||||
timeout: 30,
|
||||
enableFlag: 'ENABLE' as string,
|
||||
remark: '',
|
||||
});
|
||||
@@ -97,24 +186,95 @@
|
||||
submitting: false,
|
||||
form: createEmptyForm(),
|
||||
originalForm: createEmptyForm(),
|
||||
params: [] as CommandParamDraft[],
|
||||
originalParams: [] as CommandParamRecord[],
|
||||
paramLoading: false,
|
||||
});
|
||||
|
||||
const rules: FormRules = {
|
||||
commandName: [{ required: true, message: t('common.name'), trigger: 'blur' }],
|
||||
commandCode: [{ required: true, message: 'Code is required', trigger: 'blur' }],
|
||||
commandName: [{ required: true, message: t('command.form.nameRequired'), trigger: 'blur' }],
|
||||
commandCode: [{ required: true, message: t('command.form.codeRequired'), trigger: 'blur' }],
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
reactiveData.form = { ...reactiveData.originalForm };
|
||||
reactiveData.params = cloneParams(reactiveData.originalParams);
|
||||
reactiveData.submitting = false;
|
||||
formRef.value?.clearValidate();
|
||||
};
|
||||
|
||||
const rowKey = () => `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
||||
|
||||
const createEmptyParam = (): CommandParamDraft => ({
|
||||
_key: rowKey(),
|
||||
paramName: '',
|
||||
paramCode: '',
|
||||
paramDirectionFlag: 'INPUT',
|
||||
paramTypeFlag: 'STRING',
|
||||
requiredFlag: false,
|
||||
defaultValue: '',
|
||||
enableFlag: 'ENABLE',
|
||||
});
|
||||
|
||||
const cloneParams = (params: CommandParamRecord[] = []): CommandParamDraft[] =>
|
||||
params.map((item) => ({
|
||||
...item,
|
||||
_key: rowKey(),
|
||||
paramDirectionFlag: paramDirectionValue(item.paramDirectionFlag),
|
||||
paramTypeFlag: pointTypeValue(item.paramTypeFlag),
|
||||
requiredFlag: Boolean(item.requiredFlag),
|
||||
enableFlag: enableFlagValue(item.enableFlag),
|
||||
}));
|
||||
|
||||
const normalizeParams = (): CommandParamRecord[] =>
|
||||
reactiveData.params
|
||||
.filter((item) => String(item.paramName || item.paramCode || '').trim() !== '')
|
||||
.map((item) => {
|
||||
const param = { ...item } as CommandParamRecord;
|
||||
delete (param as { _key?: string })._key;
|
||||
return {
|
||||
...param,
|
||||
paramName: String(item.paramName || '').trim(),
|
||||
paramCode: String(item.paramCode || '').trim(),
|
||||
paramDirectionFlag: item.paramDirectionFlag || 'INPUT',
|
||||
paramTypeFlag: item.paramTypeFlag || 'STRING',
|
||||
requiredFlag: Boolean(item.requiredFlag),
|
||||
enableFlag: item.enableFlag || 'ENABLE',
|
||||
};
|
||||
});
|
||||
|
||||
const validateParams = (params: CommandParamRecord[]) => {
|
||||
const codes = new Set<string>();
|
||||
for (const item of params) {
|
||||
const code = String(item.paramCode || '').trim();
|
||||
if (!item.paramName || !code || !item.paramDirectionFlag || !item.paramTypeFlag) {
|
||||
failMessage(t('command.form.paramRequired'));
|
||||
return false;
|
||||
}
|
||||
if (codes.has(code)) {
|
||||
failMessage(t('command.form.paramCodeUnique'));
|
||||
return false;
|
||||
}
|
||||
codes.add(code);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const addParamRow = () => {
|
||||
reactiveData.params.push(createEmptyParam());
|
||||
};
|
||||
|
||||
const removeParamRow = (index: number) => {
|
||||
reactiveData.params.splice(index, 1);
|
||||
};
|
||||
|
||||
const show = (profileId = '') => {
|
||||
reactiveData.mode = 'add';
|
||||
const emptyForm = createEmptyForm(profileId);
|
||||
reactiveData.originalForm = { ...emptyForm };
|
||||
reactiveData.form = { ...emptyForm };
|
||||
reactiveData.originalParams = [];
|
||||
reactiveData.params = [];
|
||||
reactiveData.visible = true;
|
||||
};
|
||||
|
||||
@@ -125,35 +285,55 @@
|
||||
...emptyForm,
|
||||
...row,
|
||||
profileId: String(row.profileId ?? emptyForm.profileId),
|
||||
commandTypeFlag: String(row.commandTypeFlag ?? emptyForm.commandTypeFlag),
|
||||
callTypeFlag: String(row.callTypeFlag ?? emptyForm.callTypeFlag),
|
||||
enableFlag: String(row.enableFlag ?? emptyForm.enableFlag),
|
||||
commandTypeFlag: commandTypeValue(row.commandTypeFlag, emptyForm.commandTypeFlag),
|
||||
callTypeFlag: callTypeValue(row.callTypeFlag, emptyForm.callTypeFlag),
|
||||
timeout: normalizeCommandTimeoutSeconds(row.timeout) ?? emptyForm.timeout,
|
||||
enableFlag: enableFlagValue(row.enableFlag, emptyForm.enableFlag),
|
||||
};
|
||||
reactiveData.originalForm = { ...initial };
|
||||
reactiveData.form = { ...initial };
|
||||
reactiveData.originalParams = [];
|
||||
reactiveData.params = [];
|
||||
reactiveData.visible = true;
|
||||
if (row.id) {
|
||||
reactiveData.paramLoading = true;
|
||||
listCommandParamByCommandId(String(row.id))
|
||||
.then((res) => {
|
||||
reactiveData.originalParams = res.data || [];
|
||||
reactiveData.params = cloneParams(reactiveData.originalParams);
|
||||
})
|
||||
.finally(() => {
|
||||
reactiveData.paramLoading = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const done = () => {
|
||||
const done: DoneCallback = (close = true) => {
|
||||
reactiveData.submitting = false;
|
||||
reactiveData.visible = false;
|
||||
if (close) {
|
||||
reactiveData.visible = false;
|
||||
}
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
const valid = await formRef.value?.validate().catch(() => false);
|
||||
if (!valid) return;
|
||||
reactiveData.submitting = true;
|
||||
const payload = { ...reactiveData.form };
|
||||
const payload = {
|
||||
...reactiveData.form,
|
||||
timeout: normalizeCommandTimeoutSeconds(reactiveData.form.timeout) ?? 30,
|
||||
};
|
||||
const params = normalizeParams();
|
||||
if (!validateParams(params)) {
|
||||
reactiveData.submitting = false;
|
||||
return;
|
||||
}
|
||||
if (reactiveData.mode === 'add') {
|
||||
emit('add-thing', payload, done);
|
||||
emit('add-thing', payload, params, done);
|
||||
} else {
|
||||
emit('update-thing', payload, done);
|
||||
emit('update-thing', payload, params, reactiveData.originalParams, done);
|
||||
}
|
||||
};
|
||||
|
||||
defineExpose({ show, showEdit });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -54,12 +54,12 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-if="pre || next" #buttons="{ search, reset }">
|
||||
<el-button v-if="pre" :icon="Back" plain type="success" @click="$emit('pre-handle')">
|
||||
<el-button v-if="pre" :icon="Back" plain @click="$emit('pre-handle')">
|
||||
{{ $t('common.previous') }}
|
||||
</el-button>
|
||||
<el-button :icon="Search" type="primary" @click="search">{{ $t('common.search') }}</el-button>
|
||||
<el-button :icon="RefreshLeft" @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button v-if="next" :icon="Check" plain type="warning" @click="$emit('next-handle')">
|
||||
<el-button v-if="next" :icon="Check" plain type="primary" @click="$emit('next-handle')">
|
||||
{{ $t('common.next') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
@@ -26,25 +26,40 @@
|
||||
@current-change="currentChange"
|
||||
>
|
||||
<template #filters>
|
||||
<el-form-item label="Device ID" prop="deviceId">
|
||||
<el-input v-model="formData.deviceId" class="edit-form-default" clearable placeholder="Device ID" />
|
||||
<el-form-item :label="$t('eventHistory.deviceId')" prop="deviceId">
|
||||
<el-input
|
||||
v-model="formData.deviceId"
|
||||
:placeholder="$t('eventHistory.deviceId')"
|
||||
class="edit-form-default"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Event Code" prop="eventCode">
|
||||
<el-input v-model="formData.eventCode" class="edit-form-default" clearable placeholder="Event Code" />
|
||||
<el-form-item :label="$t('eventHistory.eventCode')" prop="eventCode">
|
||||
<el-input
|
||||
v-model="formData.eventCode"
|
||||
:placeholder="$t('eventHistory.eventCode')"
|
||||
class="edit-form-default"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</tool-card>
|
||||
|
||||
<blank-card>
|
||||
<el-table v-loading="reactiveData.loading" :data="reactiveData.listData" class="settings-table" stripe>
|
||||
<el-table-column label="Record ID" min-width="180" prop="recordId" show-overflow-tooltip />
|
||||
<el-table-column label="Device ID" min-width="160" prop="deviceId" show-overflow-tooltip />
|
||||
<el-table-column label="Event Code" min-width="140" prop="eventCode" />
|
||||
<el-table-column label="Type" prop="eventTypeFlag" width="110" />
|
||||
<el-table-column label="Level" prop="eventLevelFlag" width="100" />
|
||||
<el-table-column label="Ack" prop="acknowledgeFlag" width="90" />
|
||||
<el-table-column label="Message" min-width="200" prop="message" show-overflow-tooltip />
|
||||
<el-table-column :formatter="timestampColumn" label="Occur Time" prop="occurTime" width="165" />
|
||||
<el-table-column :label="$t('eventHistory.recordId')" min-width="180" prop="recordId" show-overflow-tooltip />
|
||||
<el-table-column :label="$t('eventHistory.deviceId')" min-width="160" prop="deviceId" show-overflow-tooltip />
|
||||
<el-table-column :label="$t('eventHistory.eventCode')" min-width="140" prop="eventCode" />
|
||||
<el-table-column :label="$t('eventHistory.type')" prop="eventTypeFlag" width="110" />
|
||||
<el-table-column :label="$t('eventHistory.level')" prop="eventLevelFlag" width="100" />
|
||||
<el-table-column :label="$t('eventHistory.ack')" prop="acknowledgeFlag" width="90" />
|
||||
<el-table-column :label="$t('eventHistory.message')" min-width="200" prop="message" show-overflow-tooltip />
|
||||
<el-table-column
|
||||
:formatter="timestampColumn"
|
||||
:label="$t('eventHistory.occurTime')"
|
||||
prop="occurTime"
|
||||
width="165"
|
||||
/>
|
||||
<el-table-column :formatter="timestampColumn" :label="$t('common.createTime')" prop="createTime" width="165" />
|
||||
<el-table-column :label="$t('common.operation')" fixed="right" width="100">
|
||||
<template #default="{ row }">
|
||||
@@ -57,37 +72,49 @@
|
||||
</el-table>
|
||||
</blank-card>
|
||||
|
||||
<el-dialog v-model="detailVisible" :append-to-body="true" draggable title="Event History Detail" width="700px">
|
||||
<el-dialog
|
||||
v-model="detailVisible"
|
||||
:append-to-body="true"
|
||||
:title="$t('eventHistory.detailTitle')"
|
||||
draggable
|
||||
width="700px"
|
||||
>
|
||||
<el-descriptions v-if="detailRow" :column="2" border>
|
||||
<el-descriptions-item :span="2" label="Record ID">{{ detailRow.recordId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Device ID">{{ detailRow.deviceId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Event ID">{{ detailRow.eventId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Event Code">{{ detailRow.eventCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Type">{{ detailRow.eventTypeFlag }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Level">{{ detailRow.eventLevelFlag }}</el-descriptions-item>
|
||||
<el-descriptions-item :span="2" label="Message">{{ detailRow.message || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item :span="2" label="Param Values">
|
||||
<el-descriptions-item :label="$t('eventHistory.recordId')" :span="2">
|
||||
{{ detailRow.recordId }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventHistory.deviceId')">{{ detailRow.deviceId }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventHistory.eventId')">{{ detailRow.eventId }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventHistory.eventCode')">{{ detailRow.eventCode }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventHistory.type')">{{ detailRow.eventTypeFlag }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventHistory.level')">{{ detailRow.eventLevelFlag }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventHistory.message')" :span="2">
|
||||
{{ detailRow.message || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventHistory.paramValues')" :span="2">
|
||||
<pre class="json-preview">{{ formatJson(detailRow.paramValues) }}</pre>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="2" label="Config Snapshot">
|
||||
<el-descriptions-item :label="$t('eventHistory.configSnapshot')" :span="2">
|
||||
<pre class="json-preview">{{ formatJson(detailRow.configSnapshot) }}</pre>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :formatter="timestampColumn" label="Occur Time">{{
|
||||
detailRow.occurTime
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item :formatter="timestampColumn" label="Receive Time">{{
|
||||
detailRow.receiveTime
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="Acknowledge Flag">{{ detailRow.acknowledgeFlag }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Acknowledge User ID">{{
|
||||
detailRow.acknowledgeUserId || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item :formatter="timestampColumn" label="Acknowledge Time">{{
|
||||
detailRow.acknowledgeTime || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item :formatter="timestampColumn" label="Operate Time">{{
|
||||
detailRow.operateTime || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventHistory.occurTime')">
|
||||
{{ timestampLabel(detailRow.occurTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventHistory.receiveTime')">
|
||||
{{ timestampLabel(detailRow.receiveTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventHistory.acknowledgeFlag')">
|
||||
{{ detailRow.acknowledgeFlag }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventHistory.acknowledgeUserId')">
|
||||
{{ detailRow.acknowledgeUserId || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventHistory.acknowledgeTime')">
|
||||
{{ timestampLabel(detailRow.acknowledgeTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.operationTime')">
|
||||
{{ timestampLabel(detailRow.operateTime) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-dialog>
|
||||
</div>
|
||||
@@ -96,7 +123,8 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import { getEventHistoryById, listEventHistory } from '@/api/event';
|
||||
import { timestampColumn } from '@/utils/dateUtil';
|
||||
import { timestampColumn, timestampLabel } from '@/utils/dateUtil';
|
||||
import { prettyJson } from '@/utils/jsonUtil';
|
||||
import type { EventHistory, Order } from '@/config/types';
|
||||
import ToolCard from '@/components/card/tool/ToolCard.vue';
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
@@ -109,23 +137,11 @@
|
||||
page: { total: 0, size: 12, current: 1, orders: [] as Order[] },
|
||||
});
|
||||
|
||||
const formData = reactive<Record<string, any>>({});
|
||||
const formData = reactive<Record<string, string>>({});
|
||||
const detailVisible = ref(false);
|
||||
const detailRow = ref<EventHistory | null>(null);
|
||||
|
||||
const formatJson = (value: unknown) => {
|
||||
if (!value) {
|
||||
return '-';
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
return JSON.stringify(JSON.parse(value), null, 2);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return JSON.stringify(value, null, 2);
|
||||
};
|
||||
const formatJson = (value: unknown) => prettyJson(value);
|
||||
|
||||
const load = () => {
|
||||
reactiveData.loading = true;
|
||||
@@ -140,7 +156,7 @@
|
||||
});
|
||||
};
|
||||
|
||||
const onSearch = (data: Record<string, any>) => {
|
||||
const onSearch = (data: Record<string, string>) => {
|
||||
reactiveData.query = cleanSearchParams(data);
|
||||
reactiveData.page.current = 1;
|
||||
load();
|
||||
@@ -178,24 +194,3 @@
|
||||
|
||||
load();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-table {
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.json-preview {
|
||||
max-height: 220px;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
overflow: auto;
|
||||
border-radius: 4px;
|
||||
background: var(--el-fill-color-light);
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -447,11 +447,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-table {
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.settings-table__sub {
|
||||
margin-left: 6px;
|
||||
color: #909399;
|
||||
|
||||
@@ -57,45 +57,37 @@
|
||||
|
||||
<event-edit-form ref="editRef" @add-thing="onAdd" @update-thing="onUpdate" />
|
||||
|
||||
<el-drawer v-model="reactiveData.detailVisible" title="Event Detail" size="520px">
|
||||
<el-drawer v-model="reactiveData.detailVisible" :title="$t('eventDefinition.detail.title')" size="520px">
|
||||
<el-descriptions v-if="reactiveData.detailRecord" :column="1" border>
|
||||
<el-descriptions-item :label="$t('common.name')">{{
|
||||
reactiveData.detailRecord.eventName || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="Code">{{ reactiveData.detailRecord.eventCode || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Event Type">{{
|
||||
<el-descriptions-item :label="$t('eventDefinition.detail.code')">
|
||||
{{ reactiveData.detailRecord.eventCode || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventDefinition.detail.eventType')">{{
|
||||
reactiveData.detailRecord.eventTypeFlag || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="Event Level">{{
|
||||
<el-descriptions-item :label="$t('eventDefinition.detail.eventLevel')">{{
|
||||
reactiveData.detailRecord.eventLevelFlag || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.enableFlag')">
|
||||
<el-tag
|
||||
:type="
|
||||
String(reactiveData.detailRecord.enableFlag) === 'ENABLE' ||
|
||||
Number(reactiveData.detailRecord.enableFlag) === 0
|
||||
? 'success'
|
||||
: 'info'
|
||||
"
|
||||
>
|
||||
{{
|
||||
String(reactiveData.detailRecord.enableFlag) === 'ENABLE' ||
|
||||
Number(reactiveData.detailRecord.enableFlag) === 0
|
||||
? $t('common.enable')
|
||||
: $t('common.disable')
|
||||
}}
|
||||
</el-tag>
|
||||
<enable-tag :value="reactiveData.detailRecord.enableFlag" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.remark')">{{
|
||||
reactiveData.detailRecord.remark || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="Profile ID">{{ reactiveData.detailRecord.profileId || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Tenant ID">{{ reactiveData.detailRecord.tenantId || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="Create Time">{{
|
||||
formatTime(reactiveData.detailRecord.createTime)
|
||||
<el-descriptions-item :label="$t('eventDefinition.detail.profileId')">
|
||||
{{ reactiveData.detailRecord.profileId || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('eventDefinition.detail.tenantId')">
|
||||
{{ reactiveData.detailRecord.tenantId || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.createTime')">{{
|
||||
timestampLabel(reactiveData.detailRecord.createTime)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="Operate Time">{{
|
||||
formatTime(reactiveData.detailRecord.operateTime)
|
||||
<el-descriptions-item :label="$t('common.operationTime')">{{
|
||||
timestampLabel(reactiveData.detailRecord.operateTime)
|
||||
}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-empty v-else :description="$t('common.description')" />
|
||||
@@ -105,13 +97,23 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import { addEvent, deleteEvent, listEvent, updateEvent } from '@/api/event';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { successMessage } from '@/utils/notificationUtil';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import {
|
||||
addEvent,
|
||||
addEventParam,
|
||||
deleteEvent,
|
||||
deleteEventParam,
|
||||
listEvent,
|
||||
updateEvent,
|
||||
updateEventParam,
|
||||
} from '@/api/event';
|
||||
import { timestampLabel } from '@/utils/dateUtil';
|
||||
import { failMessage, successMessage } from '@/utils/notificationUtil';
|
||||
import { isNull } from '@/utils/validationUtil';
|
||||
import type { EventForm, EventRecord, Order } from '@/config/types';
|
||||
import type { EventForm, EventParamRecord, EventRecord, Order } from '@/config/types';
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import SkeletonCard from '@/components/card/skeleton/SkeletonCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
import EventCard from './card/EventCard.vue';
|
||||
import EventTool from './tool/EventTool.vue';
|
||||
import EventEditForm from './edit/EventEditForm.vue';
|
||||
@@ -132,6 +134,7 @@
|
||||
}>();
|
||||
|
||||
const editRef = ref<InstanceType<typeof EventEditForm>>();
|
||||
const { t } = useI18n();
|
||||
const canManage = computed(() => props.embedded === '' || props.embedded === 'edit');
|
||||
const hasData = computed(() => !reactiveData.loading && reactiveData.listData.length < 1);
|
||||
|
||||
@@ -161,8 +164,6 @@
|
||||
return isNull(profileId) ? { ...form } : { ...form, profileId };
|
||||
};
|
||||
|
||||
const formatTime = (value: unknown) => (isNull(value) ? '-' : timestamp(String(value)));
|
||||
|
||||
const load = () => {
|
||||
reactiveData.loading = true;
|
||||
const query = withFixedQuery(reactiveData.query);
|
||||
@@ -204,20 +205,65 @@
|
||||
};
|
||||
const openEdit = (row: EventRecord) => editRef.value?.showEdit(row);
|
||||
|
||||
const onAdd = (form: EventForm, done: () => void) => {
|
||||
addEvent(withFixedProfile(form)).then(() => {
|
||||
successMessage();
|
||||
load();
|
||||
done();
|
||||
type DoneCallback = (close?: boolean) => void;
|
||||
|
||||
const isValidCreatedId = (id: string) => /^\d+$/.test(id);
|
||||
|
||||
const syncEventParams = (eventId: string, params: EventParamRecord[], originalParams: EventParamRecord[] = []) => {
|
||||
const currentIds = new Set(params.map((item) => String(item.id || '')).filter(Boolean));
|
||||
const deleteTasks = originalParams
|
||||
.filter((item) => item.id && !currentIds.has(String(item.id)))
|
||||
.map((item) => deleteEventParam(String(item.id)));
|
||||
|
||||
const saveTasks = params.map((item) => {
|
||||
const payload = { ...item, eventId };
|
||||
return item.id ? updateEventParam(payload) : addEventParam({ ...payload, id: undefined });
|
||||
});
|
||||
|
||||
return Promise.all(deleteTasks).then(() => Promise.all(saveTasks));
|
||||
};
|
||||
|
||||
const onUpdate = (form: EventForm, done: () => void) => {
|
||||
updateEvent(withFixedProfile(form)).then(() => {
|
||||
successMessage();
|
||||
load();
|
||||
done();
|
||||
});
|
||||
const onAdd = (form: EventForm, params: EventParamRecord[], done: DoneCallback) => {
|
||||
addEvent(withFixedProfile(form))
|
||||
.then((res) => {
|
||||
const eventId = String(res.data || '');
|
||||
if (!isValidCreatedId(eventId)) {
|
||||
failMessage(t('eventDefinition.errors.idNotReturned'));
|
||||
return Promise.reject(new Error(t('eventDefinition.errors.idNotReturned')));
|
||||
}
|
||||
return syncEventParams(eventId, params).then(() => {
|
||||
successMessage();
|
||||
load();
|
||||
done();
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
done(false);
|
||||
});
|
||||
};
|
||||
|
||||
const onUpdate = (
|
||||
form: EventForm,
|
||||
params: EventParamRecord[],
|
||||
originalParams: EventParamRecord[],
|
||||
done: DoneCallback
|
||||
) => {
|
||||
updateEvent(withFixedProfile(form))
|
||||
.then(() => {
|
||||
const eventId = String(form.id || '');
|
||||
if (!isValidCreatedId(eventId)) {
|
||||
failMessage(t('eventDefinition.errors.idMissing'));
|
||||
return Promise.reject(new Error(t('eventDefinition.errors.idMissing')));
|
||||
}
|
||||
return syncEventParams(eventId, params, originalParams).then(() => {
|
||||
successMessage();
|
||||
load();
|
||||
done();
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
done(false);
|
||||
});
|
||||
};
|
||||
|
||||
const disableThing = (id: string, profileId: string, done: () => void) => {
|
||||
|
||||
@@ -127,8 +127,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
|
||||
.things-body-content-item-column-2 {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:show-close="false"
|
||||
:title="reactiveData.mode === 'add' ? $t('common.add') + ' Event' : $t('common.edit') + ' Event'"
|
||||
:title="reactiveData.mode === 'add' ? $t('eventDefinition.form.addTitle') : $t('eventDefinition.form.editTitle')"
|
||||
class="things-dialog"
|
||||
draggable
|
||||
@closed="reset"
|
||||
@@ -30,15 +30,15 @@
|
||||
<el-form-item :label="$t('common.name')" prop="eventName">
|
||||
<el-input v-model="reactiveData.form.eventName" :placeholder="$t('common.name')" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="Code" prop="eventCode">
|
||||
<el-input v-model="reactiveData.form.eventCode" clearable placeholder="Code" />
|
||||
<el-form-item :label="$t('eventDefinition.form.code')" prop="eventCode">
|
||||
<el-input v-model="reactiveData.form.eventCode" :placeholder="$t('eventDefinition.form.code')" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="Event Type" prop="eventTypeFlag">
|
||||
<el-form-item :label="$t('eventDefinition.form.eventType')" prop="eventTypeFlag">
|
||||
<el-select v-model="reactiveData.form.eventTypeFlag" clearable>
|
||||
<el-option v-for="opt in EVENT_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="Event Level" prop="eventLevelFlag">
|
||||
<el-form-item :label="$t('eventDefinition.form.eventLevel')" prop="eventLevelFlag">
|
||||
<el-select v-model="reactiveData.form.eventLevelFlag" clearable>
|
||||
<el-option v-for="opt in EVENT_LEVEL_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
@@ -50,9 +50,48 @@
|
||||
<el-input v-model="reactiveData.form.remark" clearable maxlength="300" show-word-limit type="textarea" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div v-loading="reactiveData.paramLoading" class="param-editor">
|
||||
<div class="param-editor__toolbar">
|
||||
<span>{{ $t('eventDefinition.form.params') }}</span>
|
||||
<el-button :icon="Plus" size="small" type="success" @click="addParamRow">
|
||||
{{ $t('common.add') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table :data="reactiveData.params" border max-height="260" size="small">
|
||||
<el-table-column :label="$t('common.name')" min-width="170">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.paramName" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('eventDefinition.form.code')" min-width="170">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.paramCode" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('eventDefinition.form.type')" min-width="140">
|
||||
<template #default="{ row }">
|
||||
<el-select v-model="row.paramTypeFlag">
|
||||
<el-option v-for="opt in POINT_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('eventDefinition.form.enabled')" width="104">
|
||||
<template #default="{ row }">
|
||||
<el-switch v-model="row.enableFlag" active-value="ENABLE" inactive-value="DISABLE" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" width="64">
|
||||
<template #default="{ $index }">
|
||||
<el-tooltip :content="$t('common.delete')" placement="top">
|
||||
<el-button :icon="Delete" link type="danger" @click="removeParamRow($index)" />
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="things-dialog-footer">
|
||||
<el-button @click="reactiveData.visible = false">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button :loading="reactiveData.submitting" type="primary" @click="submit">
|
||||
{{ $t('common.confirm') }}
|
||||
</el-button>
|
||||
@@ -63,16 +102,32 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { Delete, Plus } from '@element-plus/icons-vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { listEventParamByEventId } from '@/api/event';
|
||||
import EnableFlagSegmented from '@/components/segmented/EnableFlagSegmented.vue';
|
||||
import { EVENT_LEVEL_OPTIONS, EVENT_TYPE_OPTIONS } from '@/config/constant/enums';
|
||||
import type { EventRecord } from '@/config/types';
|
||||
import { EVENT_LEVEL_OPTIONS, EVENT_TYPE_OPTIONS, POINT_TYPE_OPTIONS } from '@/config/constant/enums';
|
||||
import type { EventForm, EventParamRecord, EventRecord } from '@/config/types';
|
||||
import { failMessage } from '@/utils/notificationUtil';
|
||||
import { enableFlagValue, eventLevelValue, eventTypeValue, pointTypeValue } from '@/utils/thingModelFormatUtil';
|
||||
|
||||
type FormMode = 'add' | 'edit';
|
||||
type DoneCallback = (close?: boolean) => void;
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const emit = defineEmits(['add-thing', 'update-thing']);
|
||||
type EventParamDraft = EventParamRecord & { _key: string };
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'add-thing', form: EventForm, params: EventParamRecord[], done: DoneCallback): void;
|
||||
(
|
||||
e: 'update-thing',
|
||||
form: EventForm,
|
||||
params: EventParamRecord[],
|
||||
originalParams: EventParamRecord[],
|
||||
done: DoneCallback
|
||||
): void;
|
||||
}>();
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
@@ -93,24 +148,88 @@
|
||||
submitting: false,
|
||||
form: createEmptyForm(),
|
||||
originalForm: createEmptyForm(),
|
||||
params: [] as EventParamDraft[],
|
||||
originalParams: [] as EventParamRecord[],
|
||||
paramLoading: false,
|
||||
});
|
||||
|
||||
const rules: FormRules = {
|
||||
eventName: [{ required: true, message: t('common.name'), trigger: 'blur' }],
|
||||
eventCode: [{ required: true, message: 'Code is required', trigger: 'blur' }],
|
||||
eventName: [{ required: true, message: t('eventDefinition.form.nameRequired'), trigger: 'blur' }],
|
||||
eventCode: [{ required: true, message: t('eventDefinition.form.codeRequired'), trigger: 'blur' }],
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
reactiveData.form = { ...reactiveData.originalForm };
|
||||
reactiveData.params = cloneParams(reactiveData.originalParams);
|
||||
reactiveData.submitting = false;
|
||||
formRef.value?.clearValidate();
|
||||
};
|
||||
|
||||
const rowKey = () => `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
||||
|
||||
const createEmptyParam = (): EventParamDraft => ({
|
||||
_key: rowKey(),
|
||||
paramName: '',
|
||||
paramCode: '',
|
||||
paramTypeFlag: 'STRING',
|
||||
enableFlag: 'ENABLE',
|
||||
});
|
||||
|
||||
const cloneParams = (params: EventParamRecord[] = []): EventParamDraft[] =>
|
||||
params.map((item) => ({
|
||||
...item,
|
||||
_key: rowKey(),
|
||||
paramTypeFlag: pointTypeValue(item.paramTypeFlag),
|
||||
enableFlag: enableFlagValue(item.enableFlag),
|
||||
}));
|
||||
|
||||
const normalizeParams = (): EventParamRecord[] =>
|
||||
reactiveData.params
|
||||
.filter((item) => String(item.paramName || item.paramCode || '').trim() !== '')
|
||||
.map((item) => {
|
||||
const param = { ...item } as EventParamRecord;
|
||||
delete (param as { _key?: string })._key;
|
||||
return {
|
||||
...param,
|
||||
paramName: String(item.paramName || '').trim(),
|
||||
paramCode: String(item.paramCode || '').trim(),
|
||||
paramTypeFlag: item.paramTypeFlag || 'STRING',
|
||||
enableFlag: item.enableFlag || 'ENABLE',
|
||||
};
|
||||
});
|
||||
|
||||
const validateParams = (params: EventParamRecord[]) => {
|
||||
const codes = new Set<string>();
|
||||
for (const item of params) {
|
||||
const code = String(item.paramCode || '').trim();
|
||||
if (!item.paramName || !code || !item.paramTypeFlag) {
|
||||
failMessage(t('eventDefinition.form.paramRequired'));
|
||||
return false;
|
||||
}
|
||||
if (codes.has(code)) {
|
||||
failMessage(t('eventDefinition.form.paramCodeUnique'));
|
||||
return false;
|
||||
}
|
||||
codes.add(code);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const addParamRow = () => {
|
||||
reactiveData.params.push(createEmptyParam());
|
||||
};
|
||||
|
||||
const removeParamRow = (index: number) => {
|
||||
reactiveData.params.splice(index, 1);
|
||||
};
|
||||
|
||||
const show = (profileId = '') => {
|
||||
reactiveData.mode = 'add';
|
||||
const emptyForm = createEmptyForm(profileId);
|
||||
reactiveData.originalForm = { ...emptyForm };
|
||||
reactiveData.form = { ...emptyForm };
|
||||
reactiveData.originalParams = [];
|
||||
reactiveData.params = [];
|
||||
reactiveData.visible = true;
|
||||
};
|
||||
|
||||
@@ -121,18 +240,33 @@
|
||||
...emptyForm,
|
||||
...row,
|
||||
profileId: String(row.profileId ?? emptyForm.profileId),
|
||||
eventTypeFlag: String(row.eventTypeFlag ?? emptyForm.eventTypeFlag),
|
||||
eventLevelFlag: String(row.eventLevelFlag ?? emptyForm.eventLevelFlag),
|
||||
enableFlag: String(row.enableFlag ?? emptyForm.enableFlag),
|
||||
eventTypeFlag: eventTypeValue(row.eventTypeFlag, emptyForm.eventTypeFlag),
|
||||
eventLevelFlag: eventLevelValue(row.eventLevelFlag, emptyForm.eventLevelFlag),
|
||||
enableFlag: enableFlagValue(row.enableFlag, emptyForm.enableFlag),
|
||||
};
|
||||
reactiveData.originalForm = { ...initial };
|
||||
reactiveData.form = { ...initial };
|
||||
reactiveData.originalParams = [];
|
||||
reactiveData.params = [];
|
||||
reactiveData.visible = true;
|
||||
if (row.id) {
|
||||
reactiveData.paramLoading = true;
|
||||
listEventParamByEventId(String(row.id))
|
||||
.then((res) => {
|
||||
reactiveData.originalParams = res.data || [];
|
||||
reactiveData.params = cloneParams(reactiveData.originalParams);
|
||||
})
|
||||
.finally(() => {
|
||||
reactiveData.paramLoading = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const done = () => {
|
||||
const done: DoneCallback = (close = true) => {
|
||||
reactiveData.submitting = false;
|
||||
reactiveData.visible = false;
|
||||
if (close) {
|
||||
reactiveData.visible = false;
|
||||
}
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
@@ -140,16 +274,17 @@
|
||||
if (!valid) return;
|
||||
reactiveData.submitting = true;
|
||||
const payload = { ...reactiveData.form };
|
||||
const params = normalizeParams();
|
||||
if (!validateParams(params)) {
|
||||
reactiveData.submitting = false;
|
||||
return;
|
||||
}
|
||||
if (reactiveData.mode === 'add') {
|
||||
emit('add-thing', payload, done);
|
||||
emit('add-thing', payload, params, done);
|
||||
} else {
|
||||
emit('update-thing', payload, done);
|
||||
emit('update-thing', payload, params, reactiveData.originalParams, done);
|
||||
}
|
||||
};
|
||||
|
||||
defineExpose({ show, showEdit });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -54,12 +54,12 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-if="pre || next" #buttons="{ search, reset }">
|
||||
<el-button v-if="pre" :icon="Back" plain type="success" @click="$emit('pre-handle')">
|
||||
<el-button v-if="pre" :icon="Back" plain @click="$emit('pre-handle')">
|
||||
{{ $t('common.previous') }}
|
||||
</el-button>
|
||||
<el-button :icon="Search" type="primary" @click="search">{{ $t('common.search') }}</el-button>
|
||||
<el-button :icon="RefreshLeft" @click="reset">{{ $t('common.reset') }}</el-button>
|
||||
<el-button v-if="next" :icon="Check" plain type="warning" @click="$emit('next-handle')">
|
||||
<el-button v-if="next" :icon="Check" plain type="primary" @click="$emit('next-handle')">
|
||||
{{ $t('common.next') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
@@ -44,13 +44,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('common.enable')" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="String(row.enableFlag) === 'ENABLE' || Number(row.enableFlag) === 0 ? 'success' : 'info'">
|
||||
{{
|
||||
String(row.enableFlag) === 'ENABLE' || Number(row.enableFlag) === 0
|
||||
? t('common.enable')
|
||||
: t('common.disable')
|
||||
}}
|
||||
</el-tag>
|
||||
<enable-tag :value="row.enableFlag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('common.remark')" min-width="180" prop="remark" show-overflow-tooltip />
|
||||
@@ -82,10 +76,3 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-table {
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -40,9 +40,7 @@
|
||||
{{ reactiveData.data.groupIndex ?? '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.enable')">
|
||||
<el-tag :type="enableTagType(reactiveData.data.enableFlag)">
|
||||
{{ enableLabel(reactiveData.data.enableFlag) }}
|
||||
</el-tag>
|
||||
<enable-tag :value="reactiveData.data.enableFlag" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.remark')" :span="2">
|
||||
{{ reactiveData.data.remark || '-' }}
|
||||
@@ -51,13 +49,13 @@
|
||||
{{ reactiveData.data.creatorName || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.createTime')">
|
||||
{{ reactiveData.data.createTime ? timestamp(reactiveData.data.createTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.createTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.operatorName')">
|
||||
{{ reactiveData.data.operatorName || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.operationTime')">
|
||||
{{ reactiveData.data.operateTime ? timestamp(reactiveData.data.operateTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.operateTime) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</detail-card>
|
||||
@@ -75,7 +73,8 @@
|
||||
import { getGroupById, listGroup } from '@/api/group';
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import DetailCard from '@/components/card/detail/DetailCard.vue';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
import { timestampLabel } from '@/utils/dateUtil';
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
@@ -93,14 +92,6 @@
|
||||
return reactiveData.parentMap[String(id)] || String(id);
|
||||
});
|
||||
|
||||
const enableTagType = (value: unknown) => {
|
||||
return String(value) === 'ENABLE' || Number(value) === 0 ? 'success' : 'info';
|
||||
};
|
||||
|
||||
const enableLabel = (value: unknown) => {
|
||||
return String(value) === 'ENABLE' || Number(value) === 0 ? t('common.enable') : t('common.disable');
|
||||
};
|
||||
|
||||
const loadParents = () => {
|
||||
listGroup({ page: { current: 1, size: 5000 } })
|
||||
.then((res: any) => {
|
||||
@@ -130,7 +121,3 @@
|
||||
load();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
</style>
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
</el-form>
|
||||
<div class="things-dialog-footer">
|
||||
<el-button @click="reactiveData.visible = false">{{ t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ t('common.reset') }}</el-button>
|
||||
<el-button :loading="reactiveData.submitting" type="primary" @click="submit">
|
||||
{{ t('common.confirm') }}
|
||||
</el-button>
|
||||
@@ -78,7 +78,3 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -26,6 +26,7 @@ import type { Order } from '@/config/types';
|
||||
import type { GroupForm, GroupRecord } from '@/config/types/manager';
|
||||
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
import groupTool from './tool/GroupTool.vue';
|
||||
import groupEditForm from './edit/GroupEditForm.vue';
|
||||
|
||||
@@ -33,6 +34,7 @@ export default defineComponent({
|
||||
name: 'SettingsGroup',
|
||||
components: {
|
||||
BlankCard,
|
||||
EnableTag,
|
||||
groupTool,
|
||||
groupEditForm,
|
||||
},
|
||||
|
||||
@@ -47,13 +47,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('common.enable')" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="String(row.enableFlag) === 'ENABLE' || Number(row.enableFlag) === 0 ? 'success' : 'info'">
|
||||
{{
|
||||
String(row.enableFlag) === 'ENABLE' || Number(row.enableFlag) === 0
|
||||
? t('common.enable')
|
||||
: t('common.disable')
|
||||
}}
|
||||
</el-tag>
|
||||
<enable-tag :value="row.enableFlag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('common.remark')" min-width="180" prop="remark" show-overflow-tooltip />
|
||||
@@ -87,11 +81,6 @@
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-table {
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.label-color {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -40,9 +40,7 @@
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.enable')">
|
||||
<el-tag :type="enableTagType(reactiveData.data.enableFlag)">
|
||||
{{ enableLabel(reactiveData.data.enableFlag) }}
|
||||
</el-tag>
|
||||
<enable-tag :value="reactiveData.data.enableFlag" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.remark')" :span="2">
|
||||
{{ reactiveData.data.remark || '-' }}
|
||||
@@ -51,13 +49,13 @@
|
||||
{{ reactiveData.data.creatorName || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.createTime')">
|
||||
{{ reactiveData.data.createTime ? timestamp(reactiveData.data.createTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.createTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.operatorName')">
|
||||
{{ reactiveData.data.operatorName || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.operationTime')">
|
||||
{{ reactiveData.data.operateTime ? timestamp(reactiveData.data.operateTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.operateTime) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</detail-card>
|
||||
@@ -69,16 +67,15 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, reactive } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import { getLabelById } from '@/api/label';
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import DetailCard from '@/components/card/detail/DetailCard.vue';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
import { timestampLabel } from '@/utils/dateUtil';
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
|
||||
const reactiveData = reactive({
|
||||
id: route.query.id as string,
|
||||
@@ -86,14 +83,6 @@
|
||||
data: {} as Record<string, any>,
|
||||
});
|
||||
|
||||
const enableTagType = (value: unknown) => {
|
||||
return String(value) === 'ENABLE' || Number(value) === 0 ? 'success' : 'info';
|
||||
};
|
||||
|
||||
const enableLabel = (value: unknown) => {
|
||||
return String(value) === 'ENABLE' || Number(value) === 0 ? t('common.enable') : t('common.disable');
|
||||
};
|
||||
|
||||
const load = () => {
|
||||
if (!reactiveData.id) return;
|
||||
getLabelById(reactiveData.id)
|
||||
@@ -111,8 +100,6 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
|
||||
.label-color {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
</el-form>
|
||||
<div class="things-dialog-footer">
|
||||
<el-button @click="reactiveData.visible = false">{{ t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ t('common.reset') }}</el-button>
|
||||
<el-button :loading="reactiveData.submitting" type="primary" @click="submit">
|
||||
{{ t('common.confirm') }}
|
||||
</el-button>
|
||||
@@ -67,7 +67,3 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -26,6 +26,7 @@ import type { Order } from '@/config/types';
|
||||
import type { LabelForm, LabelRecord } from '@/config/types/manager';
|
||||
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
import labelTool from './tool/LabelTool.vue';
|
||||
import labelEditForm from './edit/LabelEditForm.vue';
|
||||
|
||||
@@ -33,6 +34,7 @@ export default defineComponent({
|
||||
name: 'SettingsLabel',
|
||||
components: {
|
||||
BlankCard,
|
||||
EnableTag,
|
||||
labelTool,
|
||||
labelEditForm,
|
||||
},
|
||||
|
||||
@@ -51,13 +51,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('common.enable')" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="String(row.enableFlag) === 'ENABLE' || Number(row.enableFlag) === 0 ? 'success' : 'info'">
|
||||
{{
|
||||
String(row.enableFlag) === 'ENABLE' || Number(row.enableFlag) === 0
|
||||
? t('common.enable')
|
||||
: t('common.disable')
|
||||
}}
|
||||
</el-tag>
|
||||
<enable-tag :value="row.enableFlag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :formatter="timestampColumn" :label="t('common.createTime')" prop="createTime" width="165" />
|
||||
@@ -90,11 +84,6 @@
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-table {
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.menu-icon-cell {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -46,28 +46,16 @@
|
||||
{{ reactiveData.data.menuExt?.content?.url || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.enable')">
|
||||
<el-tag
|
||||
:type="
|
||||
String(reactiveData.data.enableFlag) === 'ENABLE' || Number(reactiveData.data.enableFlag) === 0
|
||||
? 'success'
|
||||
: 'info'
|
||||
"
|
||||
>
|
||||
{{
|
||||
String(reactiveData.data.enableFlag) === 'ENABLE' || Number(reactiveData.data.enableFlag) === 0
|
||||
? $t('common.enable')
|
||||
: $t('common.disable')
|
||||
}}
|
||||
</el-tag>
|
||||
<enable-tag :value="reactiveData.data.enableFlag" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.remark')" :span="2">
|
||||
{{ reactiveData.data.remark || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.createTime')">
|
||||
{{ reactiveData.data.createTime ? timestamp(reactiveData.data.createTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.createTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.operationTime')">
|
||||
{{ reactiveData.data.operateTime ? timestamp(reactiveData.data.operateTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.operateTime) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</detail-card>
|
||||
@@ -83,10 +71,11 @@
|
||||
|
||||
import { getMenuById } from '@/api/menu';
|
||||
import { useMenuStore } from '@/store';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { timestampLabel } from '@/utils/dateUtil';
|
||||
|
||||
import blankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import detailCard from '@/components/card/detail/DetailCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const menuStore = useMenuStore();
|
||||
@@ -125,7 +114,3 @@
|
||||
load();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
</style>
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
</el-form>
|
||||
<div class="things-dialog-footer">
|
||||
<el-button @click="reactiveData.visible = false">{{ t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ t('common.reset') }}</el-button>
|
||||
<el-button :loading="reactiveData.submitting" type="primary" @click="submit">
|
||||
{{ t('common.confirm') }}
|
||||
</el-button>
|
||||
@@ -114,8 +114,6 @@
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
|
||||
.icon-option {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -25,6 +25,7 @@ import { timestampColumn } from '@/utils/dateUtil';
|
||||
import { successMessage } from '@/utils/notificationUtil';
|
||||
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
import menuTool from './tool/MenuTool.vue';
|
||||
import menuEditForm from './edit/MenuEditForm.vue';
|
||||
|
||||
@@ -32,6 +33,7 @@ export default defineComponent({
|
||||
name: 'SettingsMenu',
|
||||
components: {
|
||||
BlankCard,
|
||||
EnableTag,
|
||||
menuTool,
|
||||
menuEditForm,
|
||||
},
|
||||
|
||||
@@ -57,13 +57,7 @@
|
||||
<el-table-column :label="t('common.remark')" min-width="140" prop="remark" show-overflow-tooltip />
|
||||
<el-table-column :label="t('common.enable')" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="String(row.enableFlag) === 'ENABLE' || Number(row.enableFlag) === 0 ? 'success' : 'info'">
|
||||
{{
|
||||
String(row.enableFlag) === 'ENABLE' || Number(row.enableFlag) === 0
|
||||
? t('common.enable')
|
||||
: t('common.disable')
|
||||
}}
|
||||
</el-tag>
|
||||
<enable-tag :value="row.enableFlag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :formatter="timestampColumn" :label="t('common.createTime')" prop="createTime" width="165" />
|
||||
@@ -97,10 +91,3 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-table {
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -40,28 +40,16 @@
|
||||
{{ reactiveData.data.entityId || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.enable')">
|
||||
<el-tag
|
||||
:type="
|
||||
String(reactiveData.data.enableFlag) === 'ENABLE' || Number(reactiveData.data.enableFlag) === 0
|
||||
? 'success'
|
||||
: 'info'
|
||||
"
|
||||
>
|
||||
{{
|
||||
String(reactiveData.data.enableFlag) === 'ENABLE' || Number(reactiveData.data.enableFlag) === 0
|
||||
? $t('common.enable')
|
||||
: $t('common.disable')
|
||||
}}
|
||||
</el-tag>
|
||||
<enable-tag :value="reactiveData.data.enableFlag" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.remark')" :span="2">
|
||||
{{ reactiveData.data.remark || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.createTime')">
|
||||
{{ reactiveData.data.createTime ? timestamp(reactiveData.data.createTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.createTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.operationTime')">
|
||||
{{ reactiveData.data.operateTime ? timestamp(reactiveData.data.operateTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.operateTime) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</detail-card>
|
||||
@@ -73,9 +61,7 @@
|
||||
<el-table-column :label="$t('settings.role.roleCode')" min-width="180" prop="roleCode" />
|
||||
<el-table-column :label="$t('common.enable')" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="Number(row.enableFlag) === 0 ? 'success' : 'info'">
|
||||
{{ Number(row.enableFlag) === 0 ? $t('common.enable') : $t('common.disable') }}
|
||||
</el-tag>
|
||||
<enable-tag :value="row.enableFlag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common.remark')" min-width="220" prop="remark" show-overflow-tooltip />
|
||||
@@ -121,10 +107,11 @@
|
||||
|
||||
import { getResourceById, listResourceTree } from '@/api/resource';
|
||||
import { getRoleListByResourceId } from '@/api/roleResourceBind';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { timestampLabel } from '@/utils/dateUtil';
|
||||
|
||||
import blankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import detailCard from '@/components/card/detail/DetailCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@@ -213,7 +200,3 @@
|
||||
if (reactiveData.active === 'children') loadChildren();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
</style>
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
</el-form>
|
||||
<div class="things-dialog-footer">
|
||||
<el-button @click="reactiveData.visible = false">{{ t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ t('common.reset') }}</el-button>
|
||||
<el-button :loading="reactiveData.submitting" type="primary" @click="submit">
|
||||
{{ t('common.confirm') }}
|
||||
</el-button>
|
||||
@@ -89,7 +89,3 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -28,14 +28,29 @@ import { useMenuStore } from '@/store';
|
||||
import { timestampColumn } from '@/utils/dateUtil';
|
||||
import { successMessage } from '@/utils/notificationUtil';
|
||||
|
||||
import type {
|
||||
ApiRecord,
|
||||
DeviceRecord,
|
||||
DriverRecord,
|
||||
Order,
|
||||
PointRecord,
|
||||
ProfileRecord,
|
||||
ResourceForm,
|
||||
ResourceRecord,
|
||||
} from '@/config/types';
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
import resourceTool from './tool/ResourceTool.vue';
|
||||
import resourceEditForm from './edit/ResourceEditForm.vue';
|
||||
|
||||
type LinkableResourceType = 'DRIVER' | 'DEVICE' | 'POINT' | 'PROFILE' | 'API' | 'MENU';
|
||||
type EntityRecord = DriverRecord | DeviceRecord | PointRecord | ProfileRecord | ApiRecord;
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SettingsResource',
|
||||
components: {
|
||||
BlankCard,
|
||||
EnableTag,
|
||||
resourceTool,
|
||||
resourceEditForm,
|
||||
},
|
||||
@@ -48,32 +63,32 @@ export default defineComponent({
|
||||
|
||||
const reactiveData = reactive({
|
||||
loading: false,
|
||||
listData: [] as any[],
|
||||
query: {} as Record<string, any>,
|
||||
listData: [] as ResourceRecord[],
|
||||
query: {} as Record<string, unknown>,
|
||||
page: {
|
||||
total: 0,
|
||||
size: 12,
|
||||
current: 1,
|
||||
orders: [] as any[],
|
||||
orders: [] as Order[],
|
||||
},
|
||||
});
|
||||
|
||||
const entityNameMap = reactive<Record<string, string>>({});
|
||||
|
||||
const isGroupingNode = (row: any): boolean => {
|
||||
const isGroupingNode = (row: ResourceRecord): boolean => {
|
||||
// Virtual grouping nodes registered by ResourceRegistrySync carry entity_id=0.
|
||||
return !row.entityId || String(row.entityId) === '0';
|
||||
};
|
||||
|
||||
const formatEntityId = (row: any) => {
|
||||
const formatEntityId = (row: ResourceRecord) => {
|
||||
if (isGroupingNode(row)) return '—';
|
||||
const id = String(row.entityId);
|
||||
return entityNameMap[id] || id;
|
||||
};
|
||||
|
||||
const LINKABLE_TYPES = ['DRIVER', 'DEVICE', 'POINT', 'PROFILE', 'API', 'MENU'];
|
||||
const LINKABLE_TYPES: LinkableResourceType[] = ['DRIVER', 'DEVICE', 'POINT', 'PROFILE', 'API', 'MENU'];
|
||||
|
||||
const ENTITY_ROUTE_MAP: Record<string, string> = {
|
||||
const ENTITY_ROUTE_MAP: Record<LinkableResourceType, string> = {
|
||||
DRIVER: 'driverDetail',
|
||||
DEVICE: 'deviceDetail',
|
||||
POINT: 'pointDetail',
|
||||
@@ -82,27 +97,34 @@ export default defineComponent({
|
||||
MENU: 'settingsMenuDetail',
|
||||
};
|
||||
|
||||
const isEntityLinkable = (row: any) => {
|
||||
if (isGroupingNode(row)) return false;
|
||||
return LINKABLE_TYPES.includes(row.resourceTypeFlag);
|
||||
const resourceType = (row: ResourceRecord): LinkableResourceType | undefined => {
|
||||
const type = String(row.resourceTypeFlag || '') as LinkableResourceType;
|
||||
return LINKABLE_TYPES.includes(type) ? type : undefined;
|
||||
};
|
||||
|
||||
const goEntityDetail = (row: any) => {
|
||||
const routeName = ENTITY_ROUTE_MAP[row.resourceTypeFlag];
|
||||
const isEntityLinkable = (row: ResourceRecord) => {
|
||||
if (isGroupingNode(row)) return false;
|
||||
return Boolean(resourceType(row));
|
||||
};
|
||||
|
||||
const goEntityDetail = (row: ResourceRecord) => {
|
||||
const type = resourceType(row);
|
||||
if (!type) return;
|
||||
const routeName = ENTITY_ROUTE_MAP[type];
|
||||
if (!routeName) return;
|
||||
router.push({ name: routeName, query: { id: String(row.entityId) } }).catch(() => {
|
||||
// handled globally
|
||||
});
|
||||
};
|
||||
|
||||
const openDetail = (row: any) => {
|
||||
const openDetail = (row: ResourceRecord) => {
|
||||
router.push({ name: 'settingsResourceDetail', query: { id: String(row.id) } }).catch(() => {
|
||||
// handled globally
|
||||
});
|
||||
};
|
||||
|
||||
// Flatten tree rows into a list for post-load entity-name resolution.
|
||||
const flatten = (nodes: any[], acc: any[] = []): any[] => {
|
||||
const flatten = (nodes: ResourceRecord[], acc: ResourceRecord[] = []): ResourceRecord[] => {
|
||||
for (const n of nodes || []) {
|
||||
acc.push(n);
|
||||
if (n.children && n.children.length > 0) {
|
||||
@@ -112,7 +134,7 @@ export default defineComponent({
|
||||
return acc;
|
||||
};
|
||||
|
||||
const resolveEntityNames = (records: any[]) => {
|
||||
const resolveEntityNames = (records: ResourceRecord[]) => {
|
||||
const driverIds: string[] = [];
|
||||
const deviceIds: string[] = [];
|
||||
const pointIds: string[] = [];
|
||||
@@ -144,11 +166,12 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
const fill = (ids: string[], res: any, nameKey: string) => {
|
||||
const fill = (ids: string[], res: R<Record<string, EntityRecord>>, nameKey: keyof EntityRecord) => {
|
||||
const data = res.data || {};
|
||||
ids.forEach((id) => {
|
||||
const item = data[id];
|
||||
if (item) entityNameMap[id] = item[nameKey] || id;
|
||||
const name = item?.[nameKey];
|
||||
if (name) entityNameMap[id] = String(name);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -183,8 +206,8 @@ export default defineComponent({
|
||||
if (apiIds.length)
|
||||
promises.push(
|
||||
listApi({ page: { size: 1000, current: 1 } })
|
||||
.then((r: any) => {
|
||||
const records = (r.data?.records as any[]) || [];
|
||||
.then((r) => {
|
||||
const records = r.data?.records || [];
|
||||
const byId = new Map(records.map((a) => [String(a.id), a.apiName]));
|
||||
apiIds.forEach((id) => {
|
||||
const name = byId.get(id);
|
||||
@@ -211,7 +234,7 @@ export default defineComponent({
|
||||
// names — fetchTree is idempotent and skips the network if already
|
||||
// loaded (Layout mounts it on startup, so this is usually a no-op).
|
||||
await menuStore.fetchTree();
|
||||
const res: any = await listResourceTree(reactiveData.query);
|
||||
const res = await listResourceTree(reactiveData.query);
|
||||
const tree = res.data || [];
|
||||
reactiveData.listData = tree;
|
||||
reactiveData.page.total = tree.length;
|
||||
@@ -223,7 +246,7 @@ export default defineComponent({
|
||||
}
|
||||
};
|
||||
|
||||
const search = (params: any) => {
|
||||
const search = (params: Record<string, unknown>) => {
|
||||
reactiveData.query = params || {};
|
||||
load();
|
||||
};
|
||||
@@ -241,9 +264,9 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
const openAdd = () => editRef.value?.show();
|
||||
const openEdit = (row: any) => editRef.value?.showEdit(row);
|
||||
const openEdit = (row: ResourceRecord) => editRef.value?.showEdit(row);
|
||||
|
||||
const onAdd = (form: any, done: () => void) => {
|
||||
const onAdd = (form: ResourceForm, done: () => void) => {
|
||||
addResource(form)
|
||||
.then(() => {
|
||||
successMessage();
|
||||
@@ -255,7 +278,7 @@ export default defineComponent({
|
||||
});
|
||||
};
|
||||
|
||||
const onUpdate = (form: any, done: () => void) => {
|
||||
const onUpdate = (form: ResourceForm, done: () => void) => {
|
||||
updateResource(form)
|
||||
.then(() => {
|
||||
successMessage();
|
||||
|
||||
@@ -33,13 +33,7 @@
|
||||
<el-table-column :label="t('settings.role.roleCode')" min-width="160" prop="roleCode" />
|
||||
<el-table-column :label="t('common.enable')" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="String(row.enableFlag) === 'ENABLE' || Number(row.enableFlag) === 0 ? 'success' : 'info'">
|
||||
{{
|
||||
String(row.enableFlag) === 'ENABLE' || Number(row.enableFlag) === 0
|
||||
? t('common.enable')
|
||||
: t('common.disable')
|
||||
}}
|
||||
</el-tag>
|
||||
<enable-tag :value="row.enableFlag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('common.remark')" min-width="200" prop="remark" show-overflow-tooltip />
|
||||
@@ -75,10 +69,3 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-table {
|
||||
margin-top: 1px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -31,28 +31,16 @@
|
||||
{{ reactiveData.data.parentRoleId || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.enable')">
|
||||
<el-tag
|
||||
:type="
|
||||
String(reactiveData.data.enableFlag) === 'ENABLE' || Number(reactiveData.data.enableFlag) === 0
|
||||
? 'success'
|
||||
: 'info'
|
||||
"
|
||||
>
|
||||
{{
|
||||
String(reactiveData.data.enableFlag) === 'ENABLE' || Number(reactiveData.data.enableFlag) === 0
|
||||
? $t('common.enable')
|
||||
: $t('common.disable')
|
||||
}}
|
||||
</el-tag>
|
||||
<enable-tag :value="reactiveData.data.enableFlag" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.remark')" :span="2">
|
||||
{{ reactiveData.data.remark || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.createTime')">
|
||||
{{ reactiveData.data.createTime ? timestamp(reactiveData.data.createTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.createTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.operationTime')">
|
||||
{{ reactiveData.data.operateTime ? timestamp(reactiveData.data.operateTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.operateTime) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</detail-card>
|
||||
@@ -66,9 +54,7 @@
|
||||
<el-table-column :label="$t('settings.user.email')" min-width="180" prop="email" show-overflow-tooltip />
|
||||
<el-table-column :label="$t('common.enable')" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="Number(row.enableFlag) === 0 ? 'success' : 'info'">
|
||||
{{ Number(row.enableFlag) === 0 ? $t('common.enable') : $t('common.disable') }}
|
||||
</el-tag>
|
||||
<enable-tag :value="row.enableFlag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty>
|
||||
@@ -102,10 +88,11 @@
|
||||
import { getRoleById } from '@/api/role';
|
||||
import { getResourceListByRoleId } from '@/api/roleResourceBind';
|
||||
import { getUserListByRoleId } from '@/api/roleUserBind';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { timestampLabel } from '@/utils/dateUtil';
|
||||
|
||||
import blankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import detailCard from '@/components/card/detail/DetailCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@@ -178,7 +165,3 @@
|
||||
if (reactiveData.active === 'resource') loadResources();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
</style>
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</el-form>
|
||||
<div class="things-dialog-footer">
|
||||
<el-button @click="reactiveData.visible = false">{{ t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ t('common.reset') }}</el-button>
|
||||
<el-button :loading="reactiveData.submitting" type="primary" @click="submit">
|
||||
{{ t('common.confirm') }}
|
||||
</el-button>
|
||||
@@ -70,7 +70,3 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -27,6 +27,7 @@ import type { Order } from '@/config/types';
|
||||
import type { RoleForm, RoleRecord } from '@/config/types/auth';
|
||||
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
import roleTool from './tool/RoleTool.vue';
|
||||
import roleEditForm from './edit/RoleEditForm.vue';
|
||||
import roleAssignResources from './assign/RoleAssignResources.vue';
|
||||
@@ -35,6 +36,7 @@ export default defineComponent({
|
||||
name: 'SettingsRole',
|
||||
components: {
|
||||
BlankCard,
|
||||
EnableTag,
|
||||
roleTool,
|
||||
roleEditForm,
|
||||
roleAssignResources,
|
||||
|
||||
@@ -35,9 +35,7 @@
|
||||
<el-table-column :label="t('settings.user.email')" min-width="180" prop="email" show-overflow-tooltip />
|
||||
<el-table-column :label="t('common.enable')" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="Number(row.enableFlag) === 0 ? 'success' : 'info'">
|
||||
{{ Number(row.enableFlag) === 0 ? t('common.enable') : t('common.disable') }}
|
||||
</el-tag>
|
||||
<enable-tag :value="row.enableFlag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :formatter="timestampColumn" :label="t('common.createTime')" prop="createTime" width="165" />
|
||||
@@ -72,9 +70,3 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-table {
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -34,18 +34,16 @@
|
||||
{{ reactiveData.data.email || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.enable')">
|
||||
<el-tag :type="Number(reactiveData.data.enableFlag) === 0 ? 'success' : 'info'">
|
||||
{{ Number(reactiveData.data.enableFlag) === 0 ? $t('common.enable') : $t('common.disable') }}
|
||||
</el-tag>
|
||||
<enable-tag :value="reactiveData.data.enableFlag" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.remark')">
|
||||
{{ reactiveData.data.remark || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.createTime')">
|
||||
{{ reactiveData.data.createTime ? timestamp(reactiveData.data.createTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.createTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('common.operationTime')">
|
||||
{{ reactiveData.data.operateTime ? timestamp(reactiveData.data.operateTime) : '-' }}
|
||||
{{ timestampLabel(reactiveData.data.operateTime) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</detail-card>
|
||||
@@ -57,9 +55,7 @@
|
||||
<el-table-column :label="$t('settings.role.roleCode')" min-width="180" prop="roleCode" />
|
||||
<el-table-column :label="$t('common.enable')" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="Number(row.enableFlag) === 0 ? 'success' : 'info'">
|
||||
{{ Number(row.enableFlag) === 0 ? $t('common.enable') : $t('common.disable') }}
|
||||
</el-tag>
|
||||
<enable-tag :value="row.enableFlag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common.remark')" min-width="220" prop="remark" show-overflow-tooltip />
|
||||
@@ -94,10 +90,11 @@
|
||||
import { getResourceListByUserId } from '@/api/roleResourceBind';
|
||||
import { getRoleListByUserId } from '@/api/roleUserBind';
|
||||
import { getUserById } from '@/api/user';
|
||||
import { timestamp } from '@/utils/dateUtil';
|
||||
import { timestampLabel } from '@/utils/dateUtil';
|
||||
|
||||
import blankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import detailCard from '@/components/card/detail/DetailCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@@ -170,7 +167,3 @@
|
||||
if (reactiveData.active === 'resource') loadResources();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-card.scss';
|
||||
</style>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
</el-form>
|
||||
<div class="things-dialog-footer">
|
||||
<el-button @click="reactiveData.visible = false">{{ t('common.cancel') }}</el-button>
|
||||
<el-button plain type="success" @click="reset">{{ t('common.reset') }}</el-button>
|
||||
<el-button plain @click="reset">{{ t('common.reset') }}</el-button>
|
||||
<el-button :loading="reactiveData.submitting" type="primary" @click="submit">
|
||||
{{ t('common.confirm') }}
|
||||
</el-button>
|
||||
@@ -63,7 +63,3 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" src="./index.ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use '@/styles/things-dialog.scss';
|
||||
</style>
|
||||
|
||||
@@ -30,11 +30,13 @@ import userTool from './tool/UserTool.vue';
|
||||
import userEditForm from './edit/UserEditForm.vue';
|
||||
import userAssignRoles from './assign/UserAssignRoles.vue';
|
||||
import BlankCard from '@/components/card/blank/BlankCard.vue';
|
||||
import EnableTag from '@/components/tag/EnableTag.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SettingsUser',
|
||||
components: {
|
||||
BlankCard,
|
||||
EnableTag,
|
||||
userTool,
|
||||
userEditForm,
|
||||
userAssignRoles,
|
||||
|
||||
Reference in New Issue
Block a user