|
@@ -1,7 +1,7 @@
|
|
|
<template>
|
|
|
<div class="props">
|
|
|
<t-collapse
|
|
|
- :defaultValue="['1', '2', '3', '7']"
|
|
|
+ :defaultValue="['1', '2', '3','4', '7']"
|
|
|
expandIconPlacement="right"
|
|
|
:borderless="true"
|
|
|
>
|
|
@@ -173,14 +173,18 @@
|
|
|
</div>
|
|
|
</t-space>
|
|
|
</t-collapse-panel> -->
|
|
|
-
|
|
|
- <t-collapse-panel value="3" :header="$t('数据')">
|
|
|
- <div class="form-item" v-if="props.pen.name==='tablePlus'">
|
|
|
- <label class="label">{{$t('数据源')}}</label>
|
|
|
- <t-select v-model="dataSource" @change="getDataSource" :placeholder="$t('请选择')">
|
|
|
- <t-option key="api" value="api" :label="$t('API接口')"></t-option>
|
|
|
- <t-option key="csv" value="csv" :label="$t('CSV文件')"></t-option>
|
|
|
- <t-option key="excel" value="excel" :label="$t('从Excel导入')"></t-option>
|
|
|
+ <t-collapse-panel value="4" header="设置" v-if="props.pen.name==='tablePlus'">
|
|
|
+ <div class="form-item py-8">
|
|
|
+ <label class="label">数据源</label>
|
|
|
+ <t-select
|
|
|
+ v-model="dataSource"
|
|
|
+ placeholder="请选择"
|
|
|
+ @change="getDataSource"
|
|
|
+ >
|
|
|
+ <t-option key="api" value="api" label="API接口"/>
|
|
|
+ <t-option key="csv" value="csv" label="CSV文件"/>
|
|
|
+ <t-option key="excel" value="excel" label="从Excel导入"/>
|
|
|
+ <t-option key="sql" value="sql" label="SQL数据库"/>
|
|
|
</t-select>
|
|
|
</div>
|
|
|
<div class="t-space-item" v-if="props.pen.name==='tablePlus'">
|
|
@@ -197,14 +201,61 @@
|
|
|
</t-tooltip>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <div class="form-item py-8" v-if="props.pen.dbid">
|
|
|
+ <label>自动保存
|
|
|
+ <t-tooltip content="编辑表格后会自动保存到sql数据库" placement="top">
|
|
|
+ <HelpCircleIcon style="font-size: 12px" class="ml-2"/>
|
|
|
+ </t-tooltip>
|
|
|
+ </label>
|
|
|
+ <t-switch size="small" style="margin:8px 8px" v-model="props.pen.autoSave" />
|
|
|
</div>
|
|
|
+ <div class="form-item py-8">
|
|
|
+ <label>可编辑
|
|
|
+ <t-tooltip content="表格可以在运行时被编辑" placement="top">
|
|
|
+ <HelpCircleIcon style="font-size: 12px" class="ml-2"/>
|
|
|
+ </t-tooltip>
|
|
|
+ </label>
|
|
|
+ <t-switch size="small" style="margin:8px 8px" v-model="props.pen.input" />
|
|
|
+ </div>
|
|
|
+ <div class="form-item py-8" v-if="props.pen.columns?.length">
|
|
|
+ <label>不可编辑列</label>
|
|
|
+ <t-select
|
|
|
+ @change="changeColumns"
|
|
|
+ v-model="props.pen.notEdit"
|
|
|
+ :options="props.pen.columns.map(item=>{return {key:item.colKey,value:item.text}})"
|
|
|
+ multiple
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </t-collapse-panel>
|
|
|
+ <t-collapse-panel value="3" header="数据">
|
|
|
<div class="t-space-item">
|
|
|
<div class="form-item py-12">
|
|
|
<label style="width: 76px">{{$t('关联设备')}}</label>
|
|
|
<t-input class="w-full" v-model="props.pen.deviceId" @change="changeValue('deviceId')" :placeholder="$t('设备ID')"></t-input>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="real-times" v-if="props.pen.realTimes && props.pen.realTimes.length||pen.children?.length">
|
|
|
+ <template v-if="props.pen.name==='tablePlus'">
|
|
|
+ <div class="t-space-item">
|
|
|
+ <div v-if="cell.row!==undefined" class="flex between form-item py-12">
|
|
|
+ <div v-if="cell.col!==undefined" style="line-height: 30px">
|
|
|
+ 选中单元格 (第{{ cell.row }}行,第{{ cell.col}}列)
|
|
|
+ </div>
|
|
|
+ <div v-else style="line-height: 30px">
|
|
|
+ 选中行 (第{{ cell.row }}行)
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <t-tooltip content="快捷绑定" placement="top">
|
|
|
+ <link-icon style="width: 13px;margin-right: 26px"class="hover ml-4" @click="onQuickBind()"/>
|
|
|
+ </t-tooltip>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <div
|
|
|
+ class="real-times"
|
|
|
+ v-if="props.pen.realTimes && props.pen.realTimes.length||pen.children?.length"
|
|
|
+ >
|
|
|
<div class="grid head">
|
|
|
<div class="title">{{$t('数据名')}}</div>
|
|
|
<div class="title">{{$t('值')}}</div>
|
|
@@ -273,11 +324,19 @@
|
|
|
</t-badge>
|
|
|
</t-tooltip> -->
|
|
|
<t-dropdown
|
|
|
- :options="triggerOptions"
|
|
|
@click="addTrigger(item, $event, i)"
|
|
|
:minColumnWidth="120"
|
|
|
>
|
|
|
<ViewListIcon class="hover"/>
|
|
|
+ <template #dropdown>
|
|
|
+ <t-dropdown-menu >
|
|
|
+ <t-dropdown-item v-for="(option) in triggerOptions" :value="option.value">
|
|
|
+ {{ option.content }}
|
|
|
+ <t-divider v-if="option.divider"></t-divider>
|
|
|
+ <check-icon class="ml-16" v-show="option.value === 'mock' && item.enableMock" />
|
|
|
+ </t-dropdown-item>
|
|
|
+ </t-dropdown-menu>
|
|
|
+ </template>
|
|
|
</t-dropdown>
|
|
|
</div>
|
|
|
<!-- <div class="actions">
|
|
@@ -319,7 +378,7 @@
|
|
|
</div>
|
|
|
<div v-if="props.pen.children?.length" class="c-titile">
|
|
|
<t-tooltip :content="$t('ctrl+shift+点击,可选中子图元')">
|
|
|
- {{$t('子图元')}}
|
|
|
+ {{$t('图元结构')}}
|
|
|
</t-tooltip>
|
|
|
</div>
|
|
|
<template v-for="(cPen) in childrenPens">
|
|
@@ -474,47 +533,53 @@
|
|
|
:top="70"
|
|
|
:width="700"
|
|
|
>
|
|
|
- <t-tabs :defaultValue="1">
|
|
|
- <t-tab-panel :value="1" :destroy-on-hide="false" style="height: 420px" :label="$t('绑定变量')">
|
|
|
- <div class="form-item mt-12">
|
|
|
- <label>{{$t('当前绑定')}}:</label>
|
|
|
- <div class="label" v-if="dataBindDialog.data.bind?.id">
|
|
|
- <t-tooltip :content="dataBindDialog.data.bind?.id">
|
|
|
- <t-tag class="mr-8 mb-8" closable @close="onRemoveBind()">
|
|
|
- {{ dataBindDialog.data.bind?.label }}
|
|
|
- </t-tag>
|
|
|
- </t-tooltip>
|
|
|
- </div>
|
|
|
- <div class="label gray" v-else>{{$t('无')}}</div>
|
|
|
- </div>
|
|
|
+ <div class="form-item" style="height: 32px;">
|
|
|
+ <label>当前绑定:</label>
|
|
|
+ <div class="label" v-if="dataBindDialog.data.bind?.id">
|
|
|
+ <t-tooltip :content="dataBindDialog.data.bind?.id">
|
|
|
+ <t-tag class="mr-8 mb-8" closable @close="onRemoveBind()">
|
|
|
+ {{ dataBindDialog.data.bind?.label }}
|
|
|
+ </t-tag>
|
|
|
+ </t-tooltip>
|
|
|
+ </div>
|
|
|
+ <div class="label gray" v-else>无</div>
|
|
|
+ </div>
|
|
|
+ <div class="input-search mb-8 mt-8" style="padding:0px;">
|
|
|
+ <div class="btn" style="left:10px">
|
|
|
+ <img style="margin-top: 7px" src="/img/icon_search_gray.svg" />
|
|
|
+ </div>
|
|
|
+ <t-input
|
|
|
+ style="height: 32px;"
|
|
|
+ v-model="bindSearch"
|
|
|
+ @change="onSearchBind"
|
|
|
+ @enter="onSearchBind"
|
|
|
+ placeholder="搜索绑定变量"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <t-tree
|
|
|
+ style="height:420px;overflow:auto; scrollbar-width: thin;"
|
|
|
+ v-model="dataBindDialog.selectedIds"
|
|
|
+ :activeMultiple="false"
|
|
|
+ :data="bindTreeData"
|
|
|
+ :expand-level="1"
|
|
|
+ :checkable="true"
|
|
|
+ :checkStrictly="false"
|
|
|
+ allow-fold-node-on-filter
|
|
|
+ :filter="bindFilter"
|
|
|
+ @change="doBind"
|
|
|
+ />
|
|
|
+
|
|
|
+ <!--
|
|
|
<div class="form-item flex middle mt-8">
|
|
|
- <!-- <t-input
|
|
|
- v-if="dataBindDialog.url"
|
|
|
- v-model="dataBindDialog.device"
|
|
|
- placeholder="设备"
|
|
|
- style="width: 200px"
|
|
|
- />
|
|
|
- <t-select
|
|
|
- v-else
|
|
|
- class="mr-16"
|
|
|
- style="width: 200px"
|
|
|
- v-model="dataBindDialog.device"
|
|
|
- clearable
|
|
|
- placeholder="设备"
|
|
|
- @change="getDataset"
|
|
|
+ <t-input
|
|
|
+ style="width:250px;"
|
|
|
+ placeholder="搜索"
|
|
|
+ v-model="dataBindDialog.input"
|
|
|
+ @change="onSearchDataset"
|
|
|
+ @enter="onSearchDataset"
|
|
|
>
|
|
|
- <t-option
|
|
|
- v-for="(item, i) in dataBindDialog.devices"
|
|
|
- :key="item"
|
|
|
- :value="item"
|
|
|
- :label="item"
|
|
|
- />
|
|
|
- </t-select> -->
|
|
|
-
|
|
|
- <t-input style="width:250px;" v-model="dataBindDialog.input" @change="onSearchDataset" @enter="onSearchDataset" :placeholder="$t('搜索')">
|
|
|
<template #suffixIcon>
|
|
|
<search-icon class="hover" @click="onSearchDataset"/>
|
|
|
- <!-- <t-icon name="search" class="hover" @click="onSearchDataset" /> -->
|
|
|
</template>
|
|
|
</t-input>
|
|
|
</div>
|
|
@@ -534,43 +599,59 @@
|
|
|
:max-height="270"
|
|
|
>
|
|
|
</t-table>
|
|
|
- </t-tab-panel>
|
|
|
- <t-tab-panel :value="2" :destroy-on-hide="false" style="height: 420px" :label="$t('本地调试')">
|
|
|
- <div class="form-item mt-20">
|
|
|
- <label>{{$t('模拟值')}}:</label>
|
|
|
- <t-input v-model="dataBindDialog.data.mock"></t-input>
|
|
|
- </div>
|
|
|
- <div class="form-item mt-20">
|
|
|
- <label>{{$t('类型')}}:</label>
|
|
|
- <t-select class="w-full" :options="typeOptions" v-model="dataBindDialog.data.type" :placeholder="$t('字符串')"></t-select>
|
|
|
- </div>
|
|
|
- <div class="form-item mt-12">
|
|
|
- <label>{{$t('开启')}}:</label>
|
|
|
- <t-switch class="mt-8" size="small" v-model="dataBindDialog.data.enableMock"></t-switch>
|
|
|
- </div>
|
|
|
- <h6 class="desc mt-20">{{$t('模拟值说明')}}</h6>
|
|
|
- <ul class="desc mt-4">
|
|
|
- <li class="mt-4">
|
|
|
- <label class="inline" style="width: 80px">{{$t('固定值')}}:</label>
|
|
|
- {{$t('直接填写')}},{{$t('例如')}}:10
|
|
|
- </li>
|
|
|
- <li class="mt-4">
|
|
|
- <label class="inline" style="width: 80px">{{$t('随机值')}}:</label>
|
|
|
- {{$t('值')}}1,{{$t('值')}}2,...。{{$t('例如')}}:1,2,3,4,5
|
|
|
- </li>
|
|
|
- <li class="mt-4">
|
|
|
- <label class="inline" style="width: 80px">{{$t('范围数字')}}:</label>
|
|
|
- {{$t('最小值')}}-{{$t('最大值')}}。{{$t('例如')}}:0-1.0 {{$t('或')}} 0-100
|
|
|
- </li>
|
|
|
- <li class="mt-4">
|
|
|
- <label class="inline" style="width: 80px">{{$t('随机字符串')}}:</label>
|
|
|
- [{{$t('长度')}}]。{{$t('例如')}}:[8]
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
- </t-tab-panel>
|
|
|
- </t-tabs>
|
|
|
+ -->
|
|
|
+ </t-dialog>
|
|
|
+ <t-dialog
|
|
|
+ v-if="dataMockDialog.show"
|
|
|
+ :visible="true"
|
|
|
+ class="data-link-dialog"
|
|
|
+ header="本地调试"
|
|
|
+ @close="dataMockDialog.show = false;"
|
|
|
+ @confirm="dataMockDialog.show = false;"
|
|
|
+ :top="70"
|
|
|
+ :width="700"
|
|
|
+ >
|
|
|
+ <div class="form-item mt-20">
|
|
|
+ <label>模拟值:</label>
|
|
|
+ <t-input v-model="dataMockDialog.data.mock" />
|
|
|
+ </div>
|
|
|
+ <div class="form-item mt-20">
|
|
|
+ <label>类型:</label>
|
|
|
+ <t-select
|
|
|
+ class="w-full"
|
|
|
+ :options="typeOptions"
|
|
|
+ v-model="dataMockDialog.data.type"
|
|
|
+ placeholder="字符串"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="form-item mt-12">
|
|
|
+ <label>开启:</label>
|
|
|
+ <t-switch
|
|
|
+ class="mt-8"
|
|
|
+ size="small"
|
|
|
+ v-model="dataMockDialog.data.enableMock"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <h6 class="desc mt-20" style="font-size: 13px;">模拟值说明</h6>
|
|
|
+ <ul class="desc mt-4" style="list-style-type: none;">
|
|
|
+ <li class="mt-4">
|
|
|
+ <label class="inline" style="width: 80px">固定值:</label>
|
|
|
+ 直接填写,例如:10
|
|
|
+ </li>
|
|
|
+ <li class="mt-4">
|
|
|
+ <label class="inline" style="width: 80px">随机值:</label>
|
|
|
+ 值1,值2,...。例如:1,2,3,4,5
|
|
|
+ </li>
|
|
|
+ <li class="mt-4">
|
|
|
+ <label class="inline" style="width: 80px">范围数字:</label>
|
|
|
+ 最小值-最大值。例如:0-1.0 或 0-100
|
|
|
+ </li>
|
|
|
+ <li class="mt-4">
|
|
|
+ <label class="inline" style="width: 80px">随机字符串:</label>
|
|
|
+ [长度]。例如:[8]
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
</t-dialog>
|
|
|
-
|
|
|
<t-dialog
|
|
|
v-if="triggersDialog.show"
|
|
|
:visible="true"
|
|
@@ -778,6 +859,51 @@
|
|
|
<CodeEditor :json="true" :language="'json'" v-model="apiDialog.body" class="mt-4" style="height: 50px"></CodeEditor>
|
|
|
</div>
|
|
|
</t-dialog>
|
|
|
+ <t-dialog
|
|
|
+ v-if="sqlDialog.show"
|
|
|
+ :visible="true"
|
|
|
+ class="data-link-dialog"
|
|
|
+ header="绑定sql数据源"
|
|
|
+ @close="sqlDialog.show = false;"
|
|
|
+ @confirm="sqlConnect"
|
|
|
+ :top="70"
|
|
|
+ :width="700"
|
|
|
+ >
|
|
|
+ <div class="form-item py-12">
|
|
|
+ <label style="width: 76px">SQL数据源</label>
|
|
|
+ <t-select v-model="sqlDialog.dbid" placeholder="请选择数据源" >
|
|
|
+ <t-option v-for="sql in sqlList " @click="sqlChange(sql)" :key="sql.id" :value="sql.id" :label="sql.name+'('+sql.dbType+')'" />
|
|
|
+ </t-select>
|
|
|
+ </div>
|
|
|
+ <div class="form-item mt-8">
|
|
|
+ <label>sql语句</label>
|
|
|
+ <CodeEditor
|
|
|
+ :json="false"
|
|
|
+ :language="'sql'"
|
|
|
+ v-model="sqlDialog.sql"
|
|
|
+ class="mt-4"
|
|
|
+ style="height: 100px"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="form-item mt-8">
|
|
|
+ <label>第几页</label>
|
|
|
+ <t-input-number
|
|
|
+ v-model="sqlDialog.current"
|
|
|
+ theme="normal"
|
|
|
+ :min="1"
|
|
|
+ placeholder="默认1"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="form-item mt-8">
|
|
|
+ <label>每页数量</label>
|
|
|
+ <t-input-number
|
|
|
+ v-model="sqlDialog.pageSize"
|
|
|
+ theme="normal"
|
|
|
+ placeholder="20"
|
|
|
+ :min="1"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </t-dialog>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
@@ -805,10 +931,11 @@ import Actions from './Actions.vue';
|
|
|
import { useSelection } from '@/services/selections';
|
|
|
import { defaultGradientColor, defaultPureColor } from '@/services/defaults';
|
|
|
import { getLe5le3d, getLe5leV, getLe5le2d } from '@/services/api';
|
|
|
-import { EllipsisIcon, MoreIcon, LinkIcon, RelativityIcon, AddRectangleIcon, SearchIcon ,DeleteIcon, ArrowRightIcon, CloseIcon, ChevronLeftDoubleIcon, AddIcon, ViewListIcon } from 'tdesign-icons-vue-next';
|
|
|
+import { EllipsisIcon, MoreIcon, LinkIcon, RelativityIcon, AddRectangleIcon, SearchIcon ,DeleteIcon, ArrowRightIcon, CloseIcon, ChevronLeftDoubleIcon, AddIcon, ViewListIcon, CheckIcon, HelpCircleIcon } from 'tdesign-icons-vue-next';
|
|
|
import { s8 } from '@/services/random';
|
|
|
import { importExcel } from '@/services/excel';
|
|
|
import { importCSV } from '@/services/file';
|
|
|
+import { getDevices, getDeviceProperties,getSqlSourceList, doSqlCode } from '@/services/iot';
|
|
|
|
|
|
const route = useRoute();
|
|
|
const router = useRouter();
|
|
@@ -913,6 +1040,11 @@ const dataBindDialog = reactive<any>({
|
|
|
data: undefined,
|
|
|
});
|
|
|
|
|
|
+const dataMockDialog = reactive<any>({
|
|
|
+ show: false,
|
|
|
+ data: undefined,
|
|
|
+});
|
|
|
+
|
|
|
const ojbectDialog = reactive<any>({
|
|
|
show: false,
|
|
|
data: undefined,
|
|
@@ -1161,9 +1293,84 @@ const onBind = (item: any) => {
|
|
|
dataBindDialog.selectedIds.push(item.bind.id);
|
|
|
}
|
|
|
dataBindDialog.show = true;
|
|
|
- getDataset();
|
|
|
+ // getDataset();
|
|
|
+ // getIotTree();
|
|
|
+ // getSqlTree();
|
|
|
+ getBindTreeData();
|
|
|
+};
|
|
|
+
|
|
|
+const bindTreeData = ref<any>([]);
|
|
|
+
|
|
|
+const getBindTreeData = ()=>{
|
|
|
+ let data = [];
|
|
|
+ const iotTree = meta2d.store.data.iot?.tree || [];
|
|
|
+ if(iotTree.length){
|
|
|
+ iotTree.forEach((item:any)=>{
|
|
|
+ item.checkable = false;
|
|
|
+ });
|
|
|
+ data.push({
|
|
|
+ label: '物联网平台',
|
|
|
+ value: 'iot',
|
|
|
+ checkable: false,
|
|
|
+ children: iotTree,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ const sqlTree = meta2d.store.data.sqls || [];
|
|
|
+ if(sqlTree.length){
|
|
|
+ data.push({
|
|
|
+ label: 'sql数据源',
|
|
|
+ value: 'sql',
|
|
|
+ checkable: false,
|
|
|
+ children: sqlTree,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ const networks = meta2d.store.data.networks || [];
|
|
|
+ if(networks.length){
|
|
|
+ networks.forEach((item:any)=>{
|
|
|
+ item.checkable = false;
|
|
|
+ });
|
|
|
+ data.push({
|
|
|
+ label: 'MQTT',
|
|
|
+ value: 'network',
|
|
|
+ checkable: false,
|
|
|
+ children: meta2d.store.data.networks.filter((item)=>item.protocol==='mqtt'),
|
|
|
+ });
|
|
|
+ data.push({
|
|
|
+ label: 'Websocket',
|
|
|
+ value: 'network',
|
|
|
+ checkable: false,
|
|
|
+ children: meta2d.store.data.networks.filter((item)=>item.protocol==='websocket'),
|
|
|
+ });
|
|
|
+ data.push({
|
|
|
+ label: 'HTTP',
|
|
|
+ value: 'network',
|
|
|
+ checkable: false,
|
|
|
+ children: meta2d.store.data.networks.filter((item)=>item.protocol==='http'),
|
|
|
+ });
|
|
|
+ }
|
|
|
+ bindTreeData.value = data;
|
|
|
+}
|
|
|
+
|
|
|
+const bindSearch = ref('');
|
|
|
+const bindFilter = ref(null);
|
|
|
+const onSearchBind = () => {
|
|
|
+ bindFilter.value = bindSearch.value ? (node) => { return node.data.label?.indexOf(bindSearch.value) >= 0|| node.data.value?.indexOf(bindSearch.value) >= 0 }: null;
|
|
|
};
|
|
|
|
|
|
+const bindValue = ref('');
|
|
|
+
|
|
|
+const doBind = (value:any,context:any)=>{
|
|
|
+ // bindValue.value = [context.node.value];
|
|
|
+ dataBindDialog.selectedIds = [context.node.value];
|
|
|
+ dataBindDialog.data.bind = {
|
|
|
+ id: context.node.value,
|
|
|
+ label: context.node.data._label|| context.node.data.label,
|
|
|
+ class: context.node.data.class,
|
|
|
+ token: context.node.data.token,
|
|
|
+ }
|
|
|
+ meta2d.initBinds();
|
|
|
+}
|
|
|
+
|
|
|
const onSearchDataset = () => {
|
|
|
debounce(getDataset, 300);
|
|
|
};
|
|
@@ -1171,6 +1378,7 @@ const onSearchDataset = () => {
|
|
|
const getDataset = async () => {
|
|
|
// @ts-ignore
|
|
|
const data: Meta2dBackData = meta2d.data();
|
|
|
+ dataBindDialog.sqls = data.sqls;
|
|
|
if (!data.dataset) {
|
|
|
return;
|
|
|
}
|
|
@@ -1690,6 +1898,10 @@ const triggerOptions = computed(() => {
|
|
|
content: $t('条件动画'),
|
|
|
divider: true
|
|
|
},
|
|
|
+ {
|
|
|
+ value: 'mock',
|
|
|
+ content: '本地调试',
|
|
|
+ },
|
|
|
{
|
|
|
value: 'edit',
|
|
|
content: $t('编辑'),
|
|
@@ -1886,8 +2098,12 @@ const addTrigger = (item:any, e:any, i:any) => {
|
|
|
],
|
|
|
});
|
|
|
break;
|
|
|
+ case 'mock':
|
|
|
+ dataMockDialog.data = item;
|
|
|
+ dataMockDialog.show = true;
|
|
|
+ break;
|
|
|
}
|
|
|
- if(!['edit', 'delete'].includes(e.value)){
|
|
|
+ if(!['edit', 'delete','mock'].includes(e.value)){
|
|
|
emit('tabchange',props.pen.triggers.length-1);
|
|
|
}
|
|
|
}
|
|
@@ -1973,8 +2189,104 @@ const getDataSource = async (e) => {
|
|
|
}
|
|
|
} else if (e === 'api') {
|
|
|
apiDialog.show = true;
|
|
|
+ } else if (e === 'sql') {
|
|
|
+ // getSqlTree();
|
|
|
+ // sqlDialog.show = true;
|
|
|
+ // props.pen.sql = true;
|
|
|
+ sqlDialog.value.dbid = props.pen.dbid;
|
|
|
+ sqlDialog.value.sql = props.pen.sql||'-- eg:SELECT * FROM "directory"';
|
|
|
+ sqlDialog.value.show = true;
|
|
|
+ sqlDialog.value.current = props.pen.pagination?.current;
|
|
|
+ sqlDialog.value.pageSize = props.pen.pagination?.pageSize;
|
|
|
+ sqlList.value = await getSqlSourceList();
|
|
|
}
|
|
|
}
|
|
|
+const sqlDialog = ref({
|
|
|
+ show: false,
|
|
|
+ dbid: '',
|
|
|
+ sql:'',
|
|
|
+ method: 'list',
|
|
|
+ pageSize: 10,
|
|
|
+ current: 1,
|
|
|
+});
|
|
|
+const sqlList = ref([]);
|
|
|
+const sqlChange = (sql)=>{
|
|
|
+ props.pen.sql = sql;
|
|
|
+}
|
|
|
+const sqlConnect =async ()=>{
|
|
|
+ // console.log('value',sqlDialog.value);
|
|
|
+ // if(sqlDialog.value.method === 'exec'){
|
|
|
+ // let data:any = await doSqlCode({method:'exec',dbid:sqlDialog.value.dbid,sql: sqlDialog.value.sql});
|
|
|
+ // console.log("data",data);
|
|
|
+ // }else if(sqlDialog.value.method === 'list'){
|
|
|
+ props.pen.sql = sqlDialog.value.sql;
|
|
|
+ props.pen.dbid = sqlDialog.value.dbid;
|
|
|
+ let sql = sqlDialog.value.sql+' LIMIT '+(sqlDialog.value.pageSize||20)+(sqlDialog.value.current>1?(' OFFSET '+(sqlDialog.value.current-1)*sqlDialog.value.pageSize):'');
|
|
|
+ // }
|
|
|
+ let data:any =await doSqlCode({method:'list',dbid:props.pen.dbid,sql});
|
|
|
+ if(data.error){
|
|
|
+ MessagePlugin.error(data.detail);
|
|
|
+ }else{
|
|
|
+ if(data.length){
|
|
|
+ let columns = [];
|
|
|
+ let colWidth = 0;
|
|
|
+ for(let key in data[0]){
|
|
|
+ if(key === 'id'||key === '_id'){
|
|
|
+ columns.unshift({
|
|
|
+ colKey: key,
|
|
|
+ text: key,
|
|
|
+ });
|
|
|
+ }else{
|
|
|
+ columns.push({
|
|
|
+ colKey: key,
|
|
|
+ text: key,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ let len = data[0][key].length*10
|
|
|
+ if(len>colWidth){
|
|
|
+ colWidth = len;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(colWidth>200){
|
|
|
+ colWidth = 200;
|
|
|
+ }
|
|
|
+ let _data = [];
|
|
|
+ data.forEach((item)=>{
|
|
|
+ // _data.push(Object.values(item))
|
|
|
+ let itemData = [];
|
|
|
+ columns.forEach((col)=>{
|
|
|
+ itemData.push(item[col.colKey]);
|
|
|
+ });
|
|
|
+ _data.push(itemData);
|
|
|
+ });
|
|
|
+ meta2d.setValue({
|
|
|
+ id:props.pen.id,
|
|
|
+ data: _data,
|
|
|
+ columns,
|
|
|
+ styles:[],
|
|
|
+ mergeCells:[],
|
|
|
+ colWidth,
|
|
|
+ sqlList:[],
|
|
|
+ whiteSpace:"nowrap",
|
|
|
+ ellipsis:true
|
|
|
+ });
|
|
|
+ MessagePlugin.success("导入成功");
|
|
|
+ sqlDialog.value.show = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const changeColumns = (e)=>{
|
|
|
+ props.pen.columns.forEach((item)=>{
|
|
|
+ if(e.includes(item.colKey)){
|
|
|
+ item.edited = false;
|
|
|
+ }else{
|
|
|
+ delete item.edited;
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
|
|
|
const apiDialog = reactive<any>({
|
|
|
show: false,
|