| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587 |
- <template>
- <div class="trigger-config">
- <el-form :model="form" label-width="90px" size="small">
- <el-form-item label="触发器名称">
- <el-input v-model="form.triggerName" placeholder="请输入触发器名称" />
- </el-form-item>
- <el-form-item label="触发类型">
- <el-select v-model="form.triggerType" style="width: 100%" @change="handleTypeChange">
- <el-option label="事件触发" value="EVENT">
- <i class="el-icon-lightning" style="color: #f56c6c; margin-right: 8px"></i> 事件触发
- </el-option>
- <el-option label="属性变化" value="ATTR">
- <i class="el-icon-data-line" style="color: #e6a23c; margin-right: 8px"></i> 属性变化
- </el-option>
- <el-option label="定时触发" value="TIME">
- <i class="el-icon-time" style="color: #409eff; margin-right: 8px"></i> 定时触发
- </el-option>
- <el-option label="条件触发" value="CONDITION">
- <i class="el-icon-set-up" style="color: #67c23a; margin-right: 8px"></i> 条件触发
- </el-option>
- </el-select>
- </el-form-item>
- <!-- 事件触发配置 -->
- <template v-if="form.triggerType === 'EVENT'">
- <el-divider content-position="left">事件源配置</el-divider>
- <el-form-item label="对象类型">
- <el-radio-group v-model="form.sourceObjType" @change="handleObjTypeChange">
- <el-radio :label="2">设备</el-radio>
- <el-radio :label="3">系统</el-radio>
- </el-radio-group>
- </el-form-item>
- <!-- 设备选择 -->
- <el-form-item label="选择设备" v-if="form.sourceObjType === 2">
- <el-select
- v-model="form.sourceObjCode"
- filterable
- placeholder="搜索选择设备"
- style="width: 100%"
- @change="handleObjChange"
- >
- <el-option
- v-for="device in deviceList"
- :key="device.deviceCode"
- :label="device.deviceName"
- :value="device.deviceCode"
- >
- <span>{{ device.deviceName }}</span>
- <span style="color: #909399; font-size: 12px; margin-left: 8px">{{ device.deviceCode }}</span>
- </el-option>
- </el-select>
- </el-form-item>
- <!-- 系统选择 -->
- <el-form-item label="选择系统" v-else-if="form.sourceObjType === 3">
- <el-select
- v-model="form.sourceObjCode"
- filterable
- placeholder="搜索选择系统"
- style="width: 100%"
- @change="handleObjChange"
- >
- <el-option
- v-for="system in systemList"
- :key="system.systemCode"
- :label="system.systemName"
- :value="system.systemCode"
- >
- <span>{{ system.systemName }}</span>
- <span style="color: #909399; font-size: 12px; margin-left: 8px">{{ system.systemCode }}</span>
- </el-option>
- </el-select>
- </el-form-item>
- <el-form-item label="模型代码">
- <el-input v-model="form.sourceModelCode" placeholder="自动关联" disabled />
- </el-form-item>
- <!-- 事件选择 - 从物模型加载 -->
- <el-form-item label="监听事件">
- <el-select
- v-model="form.eventKey"
- filterable
- placeholder="请选择事件"
- style="width: 100%"
- :loading="loadingModel"
- :disabled="!form.sourceObjCode"
- >
- <el-option
- v-for="event in eventList"
- :key="event.eventKey"
- :label="event.eventName"
- :value="event.eventKey"
- >
- <div style="display: flex; justify-content: space-between; align-items: center;">
- <span>
- <i class="el-icon-bell" style="color: #f56c6c; margin-right: 4px"></i>
- {{ event.eventName }}
- </span>
- <el-tag size="mini" type="info">{{ event.eventKey }}</el-tag>
- </div>
- </el-option>
- </el-select>
- <div class="form-tip" v-if="selectedEvent">
- {{ selectedEvent.eventDesc || '暂无描述' }}
- </div>
- <div class="form-tip" v-else-if="!loadingModel && eventList.length === 0 && form.sourceObjCode">
- ⚠️ 该对象暂无事件定义
- </div>
- </el-form-item>
- </template>
- <!-- 属性变化配置 -->
- <template v-if="form.triggerType === 'ATTR'">
- <el-divider content-position="left">属性监控配置</el-divider>
- <el-form-item label="对象类型">
- <el-radio-group v-model="form.sourceObjType" @change="handleObjTypeChange">
- <el-radio :label="2">设备</el-radio>
- <el-radio :label="3">系统</el-radio>
- </el-radio-group>
- </el-form-item>
- <!-- 设备选择 -->
- <el-form-item label="选择设备" v-if="form.sourceObjType === 2">
- <el-select
- v-model="form.sourceObjCode"
- filterable
- placeholder="搜索选择设备"
- style="width: 100%"
- @change="handleObjChange"
- >
- <el-option
- v-for="device in deviceList"
- :key="device.deviceCode"
- :label="device.deviceName"
- :value="device.deviceCode"
- />
- </el-select>
- </el-form-item>
- <!-- 系统选择 -->
- <el-form-item label="选择系统" v-else-if="form.sourceObjType === 3">
- <el-select
- v-model="form.sourceObjCode"
- filterable
- placeholder="搜索选择系统"
- style="width: 100%"
- @change="handleObjChange"
- >
- <el-option
- v-for="system in systemList"
- :key="system.systemCode"
- :label="system.systemName"
- :value="system.systemCode"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="模型代码">
- <el-input v-model="form.sourceModelCode" placeholder="自动关联" disabled />
- </el-form-item>
- <!-- 属性选择 - 从物模型加载 -->
- <el-form-item label="监控属性">
- <el-select
- v-model="form.attrKey"
- filterable
- placeholder="请选择属性"
- style="width: 100%"
- :loading="loadingModel"
- :disabled="!form.sourceObjCode"
- @change="handleAttrChange"
- >
- <el-option-group
- v-for="group in attrGroups"
- :key="group.name"
- :label="group.label"
- >
- <el-option
- v-for="attr in group.attrs"
- :key="attr.attrKey"
- :label="attr.attrName"
- :value="attr.attrKey"
- >
- <div style="display: flex; justify-content: space-between; align-items: center;">
- <span>
- <i class="el-icon-document" style="color: #409eff; margin-right: 4px"></i>
- {{ attr.attrName }}
- </span>
- <div>
- <el-tag size="mini" type="info" style="margin-right: 4px">{{ attr.attrKey }}</el-tag>
- <el-tag size="mini" v-if="attr.attrUnit">{{ attr.attrUnit }}</el-tag>
- </div>
- </div>
- </el-option>
- </el-option-group>
- </el-select>
- <div class="form-tip" v-if="!loadingModel && attrList.length === 0 && form.sourceObjCode">
- ⚠️ 该对象暂无属性定义
- </div>
- </el-form-item>
- <!-- 属性类型提示 -->
- <el-form-item label="属性类型" v-if="selectedAttr">
- <el-tag :type="getAttrTypeTag(selectedAttr.attrValueType)">
- {{ getAttrTypeName(selectedAttr.attrValueType) }}
- </el-tag>
- <span style="margin-left: 8px; color: #909399; font-size: 12px">
- {{ selectedAttr.attrUnit || '无单位' }}
- </span>
- </el-form-item>
- <!-- 触发条件 -->
- <el-form-item label="触发条件" v-if="form.attrKey">
- <condition-builder
- v-model="form.conditionExpr"
- :attr-key="form.attrKey"
- :attr-info="selectedAttr"
- />
- </el-form-item>
- </template>
- <!-- 定时触发配置 -->
- <template v-if="form.triggerType === 'TIME'">
- <el-divider content-position="left">定时配置</el-divider>
- <el-form-item label="CRON表达式">
- <el-input v-model="cronExpression" placeholder="0 0 8 * * ?">
- <el-button slot="append" @click="showCronHelper">
- <i class="el-icon-question"></i>
- </el-button>
- </el-input>
- </el-form-item>
- <el-form-item label="快捷选择">
- <div class="cron-shortcuts">
- <el-tag
- v-for="shortcut in cronShortcuts"
- :key="shortcut.value"
- @click="setCron(shortcut.value)"
- class="cron-tag"
- >
- {{ shortcut.label }}
- </el-tag>
- </div>
- </el-form-item>
- </template>
- <!-- 条件触发配置 -->
- <template v-if="form.triggerType === 'CONDITION'">
- <el-divider content-position="left">条件配置</el-divider>
- <el-form-item label="条件表达式">
- <condition-builder
- v-model="form.conditionExpr"
- :variables="availableVariables"
- :device-list="deviceList"
- :show-attr-select="true"
- />
- </el-form-item>
- </template>
- <el-divider content-position="left">高级配置</el-divider>
- <el-form-item label="优先级">
- <el-slider v-model="form.priority" :min="0" :max="100" show-input />
- </el-form-item>
- <el-form-item label="是否启用">
- <el-switch v-model="form.enable" :active-value="1" :inactive-value="0" />
- </el-form-item>
- </el-form>
- </div>
- </template>
- <script>
- import { getModelByCode } from '@/api/basecfg/objModel';
- import { listSubsystemAll } from '@/api/adapter/subsystem';
- import ConditionBuilder from './ConditionBuilder.vue';
- export default {
- name: 'TriggerConfig',
- components: { ConditionBuilder },
- props: {
- trigger: {
- type: Object,
- default: () => ({})
- },
- deviceList: {
- type: Array,
- default: () => []
- }
- },
- data() {
- return {
- form: {
- triggerName: '',
- triggerType: 'EVENT',
- sourceObjType: 2,
- sourceObjCode: '',
- sourceModelCode: '',
- eventKey: '',
- attrKey: '',
- conditionExpr: '',
- priority: 50,
- enable: 1
- },
- systemList: [], // 系统列表
- eventList: [], // 物模型事件列表
- attrList: [], // 物模型属性列表
- loadingModel: false,
- cronExpression: '',
- cronShortcuts: [
- { label: '每天8点', value: '0 0 8 * * ?' },
- { label: '每天0点', value: '0 0 0 * * ?' },
- { label: '每小时', value: '0 0 * * * ?' },
- { label: '每30分钟', value: '0 */30 * * * ?' },
- { label: '工作日8点', value: '0 0 8 ? * MON-FRI' },
- { label: '每月1号', value: '0 0 0 1 * ?' }
- ],
- availableVariables: []
- };
- },
- computed: {
- // 选中的事件
- selectedEvent() {
- return this.eventList.find(e => e.eventKey === this.form.eventKey);
- },
- // 选中的属性
- selectedAttr() {
- return this.attrList.find(a => a.attrKey === this.form.attrKey);
- },
- // 属性分组
- attrGroups() {
- const groups = {};
- this.attrList.forEach(attr => {
- const groupName = attr.attrGroup || 'Default';
- if (!groups[groupName]) {
- groups[groupName] = [];
- }
- groups[groupName].push(attr);
- });
- return Object.entries(groups).map(([name, attrs]) => ({
- name,
- label: this.getGroupLabel(name),
- attrs
- }));
- }
- },
- watch: {
- trigger: {
- immediate: true,
- handler(val) {
- this.form = {
- triggerName: '',
- triggerType: 'EVENT',
- sourceObjType: 2,
- sourceObjCode: '',
- sourceModelCode: '',
- eventKey: '',
- attrKey: '',
- conditionExpr: '',
- priority: 50,
- enable: 1,
- ...val
- };
- // 如果已有对象代码,加载物模型
- if (val.sourceObjCode && val.sourceModelCode) {
- this.loadObjectModel(val.sourceModelCode);
- }
- }
- },
- form: {
- deep: true,
- handler(val) {
- this.$emit('change', val);
- }
- }
- },
- created() {
- this.loadSystems();
- },
- methods: {
- // 加载系统列表
- async loadSystems() {
- try {
- const response = await listSubsystemAll();
- this.systemList = response.data || [];
- } catch (error) {
- console.error('加载系统列表失败', error);
- this.systemList = [];
- }
- },
- // 触发类型改变
- handleTypeChange() {
- this.form.eventKey = null;
- this.form.attrKey = null;
- this.form.conditionExpr = null;
- this.eventList = [];
- this.attrList = [];
- },
- // 对象类型改变
- handleObjTypeChange() {
- this.form.sourceObjCode = null;
- this.form.sourceModelCode = null;
- this.form.eventKey = null;
- this.form.attrKey = null;
- this.eventList = [];
- this.attrList = [];
- },
- // 对象改变(设备或系统)
- async handleObjChange(objCode) {
- let modelCode = null;
- if (this.form.sourceObjType === 2) {
- // 设备 - 使用 deviceModel
- const device = this.deviceList.find(d => d.deviceCode === objCode);
- if (device) {
- modelCode = device.modelCode || device.deviceModel;
- }
- } else if (this.form.sourceObjType === 3) {
- // 系统
- const system = this.systemList.find(s => s.systemCode === objCode);
- if (system) {
- modelCode = system.modelCode;
- }
- }
- this.form.sourceModelCode = modelCode;
- if (modelCode) {
- await this.loadObjectModel(modelCode);
- } else {
- this.$message.warning('该对象未配置物模型');
- this.eventList = [];
- this.attrList = [];
- }
- },
- // 加载物模型(核心方法)
- async loadObjectModel(modelCode) {
- if (!modelCode) return;
- this.loadingModel = true;
- try {
- const response = await getModelByCode(modelCode);
- const modelData = response.data;
- if (!modelData) {
- throw new Error('物模型数据为空');
- }
- // 加载属性列表
- this.attrList = modelData.attrList || [];
- // 加载事件列表
- this.eventList = modelData.eventList || [];
- console.log('物模型加载成功:', {
- modelCode,
- attrCount: this.attrList.length,
- eventCount: this.eventList.length
- });
- } catch (error) {
- console.error('加载物模型失败', error);
- this.$message.error('加载物模型失败: ' + (error.message || '未知错误'));
- this.attrList = [];
- this.eventList = [];
- } finally {
- this.loadingModel = false;
- }
- },
- // 属性改变
- handleAttrChange(attrKey) {
- const attr = this.attrList.find(a => a.attrKey === attrKey);
- console.log('选中属性:', attr);
- },
- // 设置CRON表达式
- setCron(value) {
- this.cronExpression = value;
- this.form.conditionExpr = JSON.stringify({ cron: value });
- },
- // 显示CRON帮助
- showCronHelper() {
- this.$alert(`
- <div style="line-height: 1.8">
- <p><b>CRON表达式格式:</b>秒 分 时 日 月 周</p>
- <p><b>常用示例:</b></p>
- <p>• 0 0 8 * * ? - 每天8点执行</p>
- <p>• 0 0/30 * * * ? - 每30分钟执行</p>
- <p>• 0 0 9-18 * * ? - 每天9-18点整点执行</p>
- <p>• 0 0 8 ? * MON-FRI - 工作日8点执行</p>
- </div>
- `, 'CRON表达式帮助', {
- dangerouslyUseHTMLString: true
- });
- },
- // 辅助方法
- getGroupLabel(groupName) {
- const labelMap = {
- 'Base': '基础信息',
- 'State': '状态信息',
- 'Protocol': '协议信息',
- 'Measure': '测量数据',
- 'Control': '控制参数',
- 'Default': '其他'
- };
- return labelMap[groupName] || groupName;
- },
- getAttrTypeName(type) {
- const typeMap = {
- 'Value': '数值',
- 'String': '字符串',
- 'Enum': '枚举',
- 'Boolean': '布尔',
- 'WebPic': '图片',
- 'Object': '对象'
- };
- return typeMap[type] || type;
- },
- getAttrTypeTag(type) {
- const tagMap = {
- 'Value': '',
- 'String': 'info',
- 'Enum': 'warning',
- 'Boolean': 'success'
- };
- return tagMap[type] || '';
- }
- }
- };
- </script>
- <style lang="scss" scoped>
- .trigger-config {
- .cron-shortcuts {
- display: flex;
- flex-wrap: wrap;
- gap: 8px;
- .cron-tag {
- cursor: pointer;
- transition: all 0.2s;
- &:hover {
- background: #ecf5ff;
- color: #409eff;
- transform: scale(1.05);
- }
- }
- }
- .form-tip {
- font-size: 12px;
- color: #909399;
- margin-top: 4px;
- line-height: 1.5;
- }
- }
- </style>
|