Showing
16 changed files
with
919 additions
and
20 deletions
| 1 | +<template> | |
| 2 | + <div class="table-content"> | |
| 3 | + <table align="center" style="width: 100%" cellspacing="0"> | |
| 4 | + <thead> | |
| 5 | + <tr> | |
| 6 | + <th></th> | |
| 7 | + <th>Key</th> | |
| 8 | + <th>Value</th> | |
| 9 | + <th>操作</th> | |
| 10 | + </tr> | |
| 11 | + </thead> | |
| 12 | + <tbody> | |
| 13 | + <tr v-for="(item, index) in tableArray.content" :key="index"> | |
| 14 | + <td> | |
| 15 | + {{ index + 1 }} | |
| 16 | + </td> | |
| 17 | + <td> | |
| 18 | + <Select | |
| 19 | + v-model:value="item.key" | |
| 20 | + placeholder="请选择" | |
| 21 | + notFoundContent="请选择" | |
| 22 | + style="width: 14rem" | |
| 23 | + :options="selectOptions" | |
| 24 | + @change="handleChange" | |
| 25 | + allowClear | |
| 26 | + /> | |
| 27 | + </td> | |
| 28 | + <td> | |
| 29 | + <a-input | |
| 30 | + :disabled="item.editDisabled" | |
| 31 | + placeholder="请输入" | |
| 32 | + v-model:value="item.value" | |
| 33 | + style="width: 14rem" | |
| 34 | + /> | |
| 35 | + </td> | |
| 36 | + <td> | |
| 37 | + <div> | |
| 38 | + <Button type="dashed" @click="add(item, index)"> | |
| 39 | + <template #icon><PlusOutlined /></template | |
| 40 | + ></Button> | |
| 41 | + <Button type="dashed" style="margin-left: 5px" @click="remove(item, index)"> | |
| 42 | + <template #icon> <MinusOutlined /></template> | |
| 43 | + </Button> | |
| 44 | + </div> | |
| 45 | + </td> | |
| 46 | + </tr> | |
| 47 | + </tbody> | |
| 48 | + </table> | |
| 49 | + </div> | |
| 50 | +</template> | |
| 51 | +<script lang="ts" setup name="editCellTable"> | |
| 52 | + import { reactive, ref, onMounted } from 'vue'; | |
| 53 | + import { Select, Button } from 'ant-design-vue'; | |
| 54 | + import { findDictItemByCode } from '/@/api/system/dict'; | |
| 55 | + import { PlusOutlined, MinusOutlined } from '@ant-design/icons-vue'; | |
| 56 | + import { buildUUID } from '/@/utils/uuid'; | |
| 57 | + | |
| 58 | + const props = defineProps({ | |
| 59 | + method: { | |
| 60 | + type: String, | |
| 61 | + }, | |
| 62 | + }); | |
| 63 | + | |
| 64 | + onMounted(async () => { | |
| 65 | + const res = await findDictItemByCode({ dictCode: 'dataview_builtin_params' }); | |
| 66 | + selectOptions.value = res.map((m) => ({ label: m.itemText, value: m.itemValue })); | |
| 67 | + selectOptions.value.push({ | |
| 68 | + label: '自定义', | |
| 69 | + value: 'scope', | |
| 70 | + }); | |
| 71 | + if (props.method === '2') | |
| 72 | + selectOptions.value = selectOptions.value.filter((f) => f.value !== 'scope'); | |
| 73 | + }); | |
| 74 | + | |
| 75 | + const selectOptions = ref<{ label: string; value: string; disabled?: boolean }[]>([]); | |
| 76 | + | |
| 77 | + type defaultItem = { | |
| 78 | + id: string; | |
| 79 | + key: null | string; | |
| 80 | + value: string; | |
| 81 | + editDisabled: boolean; | |
| 82 | + }; | |
| 83 | + | |
| 84 | + const tableArray = reactive<{ | |
| 85 | + content: defaultItem[]; | |
| 86 | + }>({ | |
| 87 | + content: [ | |
| 88 | + { | |
| 89 | + id: buildUUID(), | |
| 90 | + key: null, | |
| 91 | + value: '', | |
| 92 | + editDisabled: false, | |
| 93 | + }, | |
| 94 | + ], | |
| 95 | + }); | |
| 96 | + | |
| 97 | + // 新增 | |
| 98 | + const add = (_, index: number) => { | |
| 99 | + tableArray.content.splice(index + 1, 0, { | |
| 100 | + id: buildUUID(), | |
| 101 | + key: null, | |
| 102 | + value: '', | |
| 103 | + editDisabled: false, | |
| 104 | + }); | |
| 105 | + }; | |
| 106 | + | |
| 107 | + // 减少 | |
| 108 | + const remove = (item, index: number) => { | |
| 109 | + if (tableArray.content.length !== 1) { | |
| 110 | + selectOptions.value.forEach((ele) => { | |
| 111 | + if (ele.value == item.key) { | |
| 112 | + ele.disabled = false; | |
| 113 | + } | |
| 114 | + }); | |
| 115 | + tableArray.content.splice(index, 1); | |
| 116 | + } | |
| 117 | + }; | |
| 118 | + | |
| 119 | + //Select互斥 | |
| 120 | + const handleChange = () => { | |
| 121 | + selectOptions.value.forEach((ele) => { | |
| 122 | + ele.disabled = false; | |
| 123 | + tableArray.content.forEach((element) => { | |
| 124 | + if (element.key === 'scope') { | |
| 125 | + element.editDisabled = false; | |
| 126 | + } else { | |
| 127 | + element.editDisabled = true; | |
| 128 | + } | |
| 129 | + if (element.key === ele.value && element.key !== 'scope') { | |
| 130 | + ele.disabled = true; | |
| 131 | + } | |
| 132 | + }); | |
| 133 | + }); | |
| 134 | + }; | |
| 135 | + | |
| 136 | + //获取数据 | |
| 137 | + const getValue = () => { | |
| 138 | + const params = {}; | |
| 139 | + tableArray.content?.map((item: any) => { | |
| 140 | + if (item?.key !== 'scope') params[item?.key] = item.value; | |
| 141 | + params[`${(item?.key + item?.id).slice(0, 10)}`] = item.value; | |
| 142 | + }); | |
| 143 | + return params; | |
| 144 | + }; | |
| 145 | + | |
| 146 | + //设置数据 | |
| 147 | + const setValue = (data) => (tableArray.content = data); | |
| 148 | + | |
| 149 | + defineExpose({ | |
| 150 | + getValue, | |
| 151 | + setValue, | |
| 152 | + }); | |
| 153 | +</script> | |
| 154 | + | |
| 155 | +<style scoped lang="less"> | |
| 156 | + @table-color: #e5e7eb; | |
| 157 | + | |
| 158 | + .table-border-color { | |
| 159 | + border: 1px solid #e5e7eb; | |
| 160 | + text-align: center; | |
| 161 | + } | |
| 162 | + | |
| 163 | + .table-content { | |
| 164 | + margin-top: 20px; | |
| 165 | + margin-right: 20px; | |
| 166 | + | |
| 167 | + table { | |
| 168 | + &:extend(.table-border-color); | |
| 169 | + } | |
| 170 | + | |
| 171 | + table td { | |
| 172 | + padding: 5px; | |
| 173 | + white-space: nowrap; | |
| 174 | + &:extend(.table-border-color); | |
| 175 | + } | |
| 176 | + | |
| 177 | + table th { | |
| 178 | + padding: 5px; | |
| 179 | + &:extend(.table-border-color); | |
| 180 | + } | |
| 181 | + } | |
| 182 | +</style> | ... | ... |
| 1 | +<template> | |
| 2 | + <div> | |
| 3 | + <a-radio-group v-model:value="getRequestBody.content.radioValue" @change="handleChange"> | |
| 4 | + <a-radio v-for="item in RequestBodyTypeEnum" :key="item" :value="item">{{ item }}</a-radio> | |
| 5 | + </a-radio-group> | |
| 6 | + <div class="mt-3"> | |
| 7 | + <a-textarea | |
| 8 | + v-if="getRequestBody.content.radioValue === 'none'" | |
| 9 | + disabled | |
| 10 | + placeholder="该接口没有 Body 体" | |
| 11 | + :rows="2" | |
| 12 | + /> | |
| 13 | + <EditCellTable | |
| 14 | + v-if=" | |
| 15 | + getRequestBody.content.radioValue === 'form-data' || | |
| 16 | + getRequestBody.content.radioValue === 'x-www-form-urlencoded' | |
| 17 | + " | |
| 18 | + /> | |
| 19 | + <a-textarea | |
| 20 | + v-model:value="getRequestBody.content.json" | |
| 21 | + v-if="getRequestBody.content.radioValue === 'json'" | |
| 22 | + placeholder="请输入json" | |
| 23 | + :rows="6" | |
| 24 | + /> | |
| 25 | + <a-textarea | |
| 26 | + v-model:value="getRequestBody.content.xml" | |
| 27 | + v-if="getRequestBody.content.radioValue === 'xml'" | |
| 28 | + placeholder="请输入xml" | |
| 29 | + :rows="6" | |
| 30 | + /> | |
| 31 | + </div> | |
| 32 | + </div> | |
| 33 | +</template> | |
| 34 | +<script lang="ts" setup name="body"> | |
| 35 | + import { reactive } from 'vue'; | |
| 36 | + import { RequestBodyTypeEnum } from '../../enum/index'; | |
| 37 | + import { EditCellTable } from '../EditCellTable/index'; | |
| 38 | + | |
| 39 | + defineProps({ | |
| 40 | + method: { | |
| 41 | + type: String, | |
| 42 | + }, | |
| 43 | + }); | |
| 44 | + | |
| 45 | + const getRequestBody = reactive({ | |
| 46 | + content: { json: '', xml: '', radioValue: 'none' }, | |
| 47 | + }); | |
| 48 | + | |
| 49 | + const handleChange = ({ target }) => { | |
| 50 | + const { value } = target; | |
| 51 | + getRequestBody.content.radioValue = value; | |
| 52 | + }; | |
| 53 | + | |
| 54 | + //获取数据 | |
| 55 | + const getValue = () => { | |
| 56 | + return getRequestBody.content; | |
| 57 | + }; | |
| 58 | + | |
| 59 | + //设置数据 | |
| 60 | + const setValue = (data) => { | |
| 61 | + getRequestBody.content = data; | |
| 62 | + }; | |
| 63 | + defineExpose({ | |
| 64 | + getValue, | |
| 65 | + setValue, | |
| 66 | + }); | |
| 67 | +</script> | ... | ... |
| 1 | +<template> | |
| 2 | + <div> | |
| 3 | + <div> | |
| 4 | + <Tabs type="card" v-model:activeKey="activeKey"> | |
| 5 | + <TabPane forceRender v-for="item in RequestParamsTypeEnum" :key="item" :tab="item" /> | |
| 6 | + </Tabs> | |
| 7 | + </div> | |
| 8 | + <div> | |
| 9 | + <div v-if="activeKey === RequestParamsTypeEnum.PARAMS"> | |
| 10 | + <EditCellTable ref="editCellTableRef" :method="method" /> | |
| 11 | + <TestRequest :method="method" /> | |
| 12 | + </div> | |
| 13 | + <div v-if="activeKey === RequestParamsTypeEnum.BODY"> | |
| 14 | + <Body :method="method" /> | |
| 15 | + <TestRequest :method="method" /> | |
| 16 | + </div> | |
| 17 | + <div v-if="activeKey === RequestParamsTypeEnum.HEADER"> | |
| 18 | + <EditCellTable ref="editCellTableRef" :method="method" /> | |
| 19 | + <TestRequest :method="method" /> | |
| 20 | + </div> | |
| 21 | + </div> | |
| 22 | + </div> | |
| 23 | +</template> | |
| 24 | +<script lang="ts" setup name="simpleRequest"> | |
| 25 | + import { ref } from 'vue'; | |
| 26 | + import { Tabs, TabPane } from 'ant-design-vue'; | |
| 27 | + import { RequestParamsTypeEnum } from '../../enum'; | |
| 28 | + import { EditCellTable } from '../EditCellTable'; | |
| 29 | + import Body from './body.vue'; | |
| 30 | + import { TestRequest } from '../TestRequest/index'; | |
| 31 | + | |
| 32 | + const props = defineProps({ | |
| 33 | + method: { | |
| 34 | + type: String, | |
| 35 | + }, | |
| 36 | + }); | |
| 37 | + | |
| 38 | + if (props.method === '2') { | |
| 39 | + Reflect.deleteProperty(RequestParamsTypeEnum, 'BODY'); | |
| 40 | + Reflect.deleteProperty(RequestParamsTypeEnum, 'HEADER'); | |
| 41 | + } else { | |
| 42 | + Reflect.set(RequestParamsTypeEnum, 'BODY', 'Body'); | |
| 43 | + Reflect.set(RequestParamsTypeEnum, 'HEADER', 'Header'); | |
| 44 | + } | |
| 45 | + | |
| 46 | + const activeKey = ref('Params'); | |
| 47 | + | |
| 48 | + const editCellTableRef = ref<InstanceType<typeof EditCellTable>>(); | |
| 49 | + | |
| 50 | + //获取数据 | |
| 51 | + const getValue = () => { | |
| 52 | + return editCellTableRef?.value?.getValue(); | |
| 53 | + }; | |
| 54 | + | |
| 55 | + //设置数据 | |
| 56 | + const setValue = (data) => { | |
| 57 | + editCellTableRef?.value?.setValue(data); | |
| 58 | + }; | |
| 59 | + | |
| 60 | + defineExpose({ | |
| 61 | + getValue, | |
| 62 | + setValue, | |
| 63 | + }); | |
| 64 | +</script> | ... | ... |
| 1 | +<template> | |
| 2 | + <div class="table-content"> | |
| 3 | + <table align="center" style="width: 100%" cellspacing="0"> | |
| 4 | + <thead> | |
| 5 | + <tr> | |
| 6 | + <th></th> | |
| 7 | + <th>Key</th> | |
| 8 | + <th>Value</th> | |
| 9 | + <th>操作</th> | |
| 10 | + </tr> | |
| 11 | + </thead> | |
| 12 | + <tbody> | |
| 13 | + <tr v-for="(item, index) in tableArray.content" :key="index"> | |
| 14 | + <td> | |
| 15 | + {{ index + 1 }} | |
| 16 | + </td> | |
| 17 | + <td> | |
| 18 | + <Select | |
| 19 | + v-model:value="item.key" | |
| 20 | + placeholder="请选择" | |
| 21 | + notFoundContent="请选择" | |
| 22 | + style="width: 14rem" | |
| 23 | + :options="selectOptions" | |
| 24 | + @change="handleChange(item)" | |
| 25 | + allowClear | |
| 26 | + /> | |
| 27 | + </td> | |
| 28 | + <td> | |
| 29 | + <a-input | |
| 30 | + v-if="item.key === 'scope'" | |
| 31 | + placeholder="请输入" | |
| 32 | + v-model:value="item.value" | |
| 33 | + style="width: 14rem" | |
| 34 | + /> | |
| 35 | + <a-tree-select | |
| 36 | + v-else-if="item.key === 'organizationId'" | |
| 37 | + v-model:value="item.value" | |
| 38 | + show-search | |
| 39 | + style="width: 14rem" | |
| 40 | + :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" | |
| 41 | + placeholder="请选择组织" | |
| 42 | + allow-clear | |
| 43 | + tree-default-expand-all | |
| 44 | + :tree-data="treeData" | |
| 45 | + @change="handleOrgnationChange(item)" | |
| 46 | + /> | |
| 47 | + <Select | |
| 48 | + v-else-if="item.key === 'entityId'" | |
| 49 | + v-model:value="item.value" | |
| 50 | + placeholder="请选择" | |
| 51 | + notFoundContent="请选择" | |
| 52 | + style="width: 14rem" | |
| 53 | + :options="entityOptions" | |
| 54 | + allowClear | |
| 55 | + /> | |
| 56 | + <Select | |
| 57 | + v-else-if="item.key === 'keys'" | |
| 58 | + v-model:value="item.value" | |
| 59 | + placeholder="请选择" | |
| 60 | + notFoundContent="请选择" | |
| 61 | + style="width: 14rem" | |
| 62 | + :options="attributeOptions" | |
| 63 | + allowClear | |
| 64 | + /> | |
| 65 | + <Select | |
| 66 | + v-else | |
| 67 | + v-model:value="item.value" | |
| 68 | + placeholder="请选择" | |
| 69 | + notFoundContent="请选择" | |
| 70 | + style="width: 14rem" | |
| 71 | + :options="valueOptions" | |
| 72 | + allowClear | |
| 73 | + @change="handleValueChange(item)" | |
| 74 | + /> | |
| 75 | + </td> | |
| 76 | + <td> | |
| 77 | + <div> | |
| 78 | + <Button type="dashed" @click="add(index)"> | |
| 79 | + <template #icon><PlusOutlined /></template | |
| 80 | + ></Button> | |
| 81 | + <Button type="dashed" style="margin-left: 5px" @click="remove(item, index)"> | |
| 82 | + <template #icon> <MinusOutlined /></template> | |
| 83 | + </Button> | |
| 84 | + </div> | |
| 85 | + </td> | |
| 86 | + </tr> | |
| 87 | + </tbody> | |
| 88 | + </table> | |
| 89 | + </div> | |
| 90 | +</template> | |
| 91 | +<script lang="ts" setup name="editCellTable"> | |
| 92 | + import { reactive, ref, onMounted } from 'vue'; | |
| 93 | + import { Select, Button } from 'ant-design-vue'; | |
| 94 | + import { findDictItemByCode } from '/@/api/system/dict'; | |
| 95 | + import { PlusOutlined, MinusOutlined } from '@ant-design/icons-vue'; | |
| 96 | + import { getAllDeviceByOrg } from '/@/api/dataBoard'; | |
| 97 | + import { getDeviceAttributes } from '/@/api/dataBoard'; | |
| 98 | + import { useApi } from '../../hooks/useApi'; | |
| 99 | + import { buildUUID } from '/@/utils/uuid'; | |
| 100 | + | |
| 101 | + const props = defineProps({ | |
| 102 | + method: { | |
| 103 | + type: String, | |
| 104 | + }, | |
| 105 | + }); | |
| 106 | + | |
| 107 | + onMounted(async () => { | |
| 108 | + const res = await findDictItemByCode({ dictCode: 'dataview_builtin_params' }); | |
| 109 | + selectOptions.value = res.map((m) => ({ label: m.itemText, value: m.itemValue })); | |
| 110 | + selectOptions.value.push({ | |
| 111 | + label: '自定义', | |
| 112 | + value: 'scope', | |
| 113 | + }); | |
| 114 | + if (props.method === '2') | |
| 115 | + selectOptions.value = selectOptions.value.filter((f) => f.value !== 'scope'); | |
| 116 | + }); | |
| 117 | + | |
| 118 | + const selectOptions = ref<{ label: string; value: string; disabled?: boolean }[]>([]); | |
| 119 | + | |
| 120 | + const valueOptions = ref<{ label: string; value: string; disabled?: boolean }[]>([]); | |
| 121 | + | |
| 122 | + const entityOptions = ref<{ label: string; value: string; disabled?: boolean }[]>([]); | |
| 123 | + | |
| 124 | + const attributeOptions = ref<{ label: string; value: string; disabled?: boolean }[]>([]); | |
| 125 | + | |
| 126 | + const treeData = ref([]); | |
| 127 | + | |
| 128 | + type defaultItem = { | |
| 129 | + id: string; | |
| 130 | + key: null | string; | |
| 131 | + value: null | string; | |
| 132 | + editDisabled: boolean; | |
| 133 | + }; | |
| 134 | + | |
| 135 | + const tableArray = reactive<{ | |
| 136 | + content: defaultItem[]; | |
| 137 | + }>({ | |
| 138 | + content: [ | |
| 139 | + { | |
| 140 | + id: buildUUID(), | |
| 141 | + key: null, | |
| 142 | + value: null, | |
| 143 | + editDisabled: false, | |
| 144 | + }, | |
| 145 | + ], | |
| 146 | + }); | |
| 147 | + | |
| 148 | + // 新增 | |
| 149 | + const add = (index: number) => { | |
| 150 | + tableArray.content.splice(index + 1, 0, { | |
| 151 | + id: buildUUID(), | |
| 152 | + key: null, | |
| 153 | + value: null, | |
| 154 | + editDisabled: false, | |
| 155 | + }); | |
| 156 | + }; | |
| 157 | + | |
| 158 | + // 减少 | |
| 159 | + const remove = (item, index: number) => { | |
| 160 | + if (item.key === 'organizationId') { | |
| 161 | + entityOptions.value.length = 0; | |
| 162 | + tableArray.content.forEach((f) => { | |
| 163 | + if (f.key === 'entityId') { | |
| 164 | + f.value = null; | |
| 165 | + } | |
| 166 | + }); | |
| 167 | + } | |
| 168 | + if (item.key === 'deviceProfileId') { | |
| 169 | + attributeOptions.value.length = 0; | |
| 170 | + tableArray.content.forEach((f) => { | |
| 171 | + if (f.key === 'keys') { | |
| 172 | + f.value = null; | |
| 173 | + } | |
| 174 | + }); | |
| 175 | + } | |
| 176 | + if (tableArray.content.length !== 1) { | |
| 177 | + selectOptions.value.forEach((ele) => { | |
| 178 | + if (ele.value == item.key) { | |
| 179 | + ele.disabled = false; | |
| 180 | + } | |
| 181 | + }); | |
| 182 | + tableArray.content.splice(index, 1); | |
| 183 | + } | |
| 184 | + }; | |
| 185 | + | |
| 186 | + //Select互斥 | |
| 187 | + const handleChange = async (e) => { | |
| 188 | + selectOptions.value.forEach((ele) => { | |
| 189 | + ele.disabled = false; | |
| 190 | + tableArray.content.forEach((element) => { | |
| 191 | + if (element.key === e.key && element.key !== 'scope') { | |
| 192 | + element.value = null; | |
| 193 | + } | |
| 194 | + if (element.key === ele.value && element.key !== 'scope') { | |
| 195 | + ele.disabled = true; | |
| 196 | + } | |
| 197 | + }); | |
| 198 | + }); | |
| 199 | + //获取对应项 | |
| 200 | + if (e.key === 'deviceProfileId') { | |
| 201 | + const { options } = await useApi(e.key); | |
| 202 | + valueOptions.value = options; | |
| 203 | + } else if (e.key === 'organizationId') { | |
| 204 | + const { options } = await useApi(e.key); | |
| 205 | + treeData.value = options as any; | |
| 206 | + } else if (e.key === 'entityId') { | |
| 207 | + const getOrganizationIds = tableArray.content | |
| 208 | + .map((f) => { | |
| 209 | + if (f.key === 'organizationId') { | |
| 210 | + return f.value; | |
| 211 | + } | |
| 212 | + }) | |
| 213 | + .filter(Boolean); | |
| 214 | + if (getOrganizationIds.length === 0) return; | |
| 215 | + getEntityOptions(getOrganizationIds?.at(-1)); | |
| 216 | + } else if (e.key === 'keys') { | |
| 217 | + const getIds = tableArray.content | |
| 218 | + .map((f) => { | |
| 219 | + if (f.key === 'deviceProfileId') { | |
| 220 | + return f.value; | |
| 221 | + } | |
| 222 | + }) | |
| 223 | + .filter(Boolean); | |
| 224 | + if (getIds.length === 0) return; | |
| 225 | + getAttributeOptions({ deviceProfileId: getIds?.at(-1) }); | |
| 226 | + } else if (e.key === 'date') { | |
| 227 | + valueOptions.value = []; | |
| 228 | + } | |
| 229 | + }; | |
| 230 | + | |
| 231 | + const handleOrgnationChange = async (e) => { | |
| 232 | + tableArray.content.forEach((f) => { | |
| 233 | + if (f.key === 'entityId') { | |
| 234 | + f.value = null; | |
| 235 | + } | |
| 236 | + }); | |
| 237 | + getEntityOptions(e.value); | |
| 238 | + }; | |
| 239 | + | |
| 240 | + const getEntityOptions = async (organizationId: string, deviceProfileId?: string) => { | |
| 241 | + const res = await getAllDeviceByOrg(organizationId, deviceProfileId); | |
| 242 | + entityOptions.value = res.map((item) => ({ | |
| 243 | + label: item.name, | |
| 244 | + value: item.tbDeviceId, | |
| 245 | + })); | |
| 246 | + }; | |
| 247 | + | |
| 248 | + const getAttributeOptions = async (params) => { | |
| 249 | + const res = await getDeviceAttributes(params); | |
| 250 | + if (Object.keys(res).length === 0) return (attributeOptions.value.length = 0); | |
| 251 | + attributeOptions.value = res?.map((item) => ({ label: item.name, value: item.identifier })); | |
| 252 | + }; | |
| 253 | + | |
| 254 | + const handleValueChange = (e) => { | |
| 255 | + if (e.key === 'deviceProfileId') { | |
| 256 | + tableArray.content.forEach((f) => { | |
| 257 | + if (f.key === 'keys') { | |
| 258 | + f.value = null; | |
| 259 | + } | |
| 260 | + }); | |
| 261 | + getAttributeOptions({ deviceProfileId: e.value }); | |
| 262 | + } | |
| 263 | + }; | |
| 264 | + | |
| 265 | + //获取数据 | |
| 266 | + const getValue = () => { | |
| 267 | + const params = {}; | |
| 268 | + tableArray.content?.map((item: any) => { | |
| 269 | + if (item?.key !== 'scope') params[item?.key] = item.value; | |
| 270 | + params[`${(item?.key + item?.id).slice(0, 10)}`] = item.value; | |
| 271 | + }); | |
| 272 | + return params; | |
| 273 | + }; | |
| 274 | + defineExpose({ | |
| 275 | + getValue, | |
| 276 | + }); | |
| 277 | +</script> | |
| 278 | + | |
| 279 | +<style scoped lang="less"> | |
| 280 | + @table-color: #e5e7eb; | |
| 281 | + | |
| 282 | + .table-border-color { | |
| 283 | + border: 1px solid #e5e7eb; | |
| 284 | + text-align: center; | |
| 285 | + } | |
| 286 | + | |
| 287 | + .table-content { | |
| 288 | + table { | |
| 289 | + &:extend(.table-border-color); | |
| 290 | + } | |
| 291 | + | |
| 292 | + table td { | |
| 293 | + padding: 5px; | |
| 294 | + white-space: nowrap; | |
| 295 | + &:extend(.table-border-color); | |
| 296 | + } | |
| 297 | + | |
| 298 | + table th { | |
| 299 | + padding: 5px; | |
| 300 | + &:extend(.table-border-color); | |
| 301 | + } | |
| 302 | + } | |
| 303 | +</style> | ... | ... |
| 1 | +<template> | |
| 2 | + <div class="mt-8"> | |
| 3 | + <div> | |
| 4 | + <Button @click="showTestEditCell = true" type="primary"> 测试一下 </Button> | |
| 5 | + </div> | |
| 6 | + <div v-if="showTestEditCell" class="mt-8"> | |
| 7 | + <a-row type="flex" justify="center"> | |
| 8 | + <a-col :span="3"> 参数设置 </a-col> | |
| 9 | + <a-col :span="21"> | |
| 10 | + <TestEditCellTable ref="testEditCellTableRef" :method="method" /> | |
| 11 | + </a-col> | |
| 12 | + </a-row> | |
| 13 | + </div> | |
| 14 | + </div> | |
| 15 | + <div v-if="showTestEditCell" class="mt-8"> | |
| 16 | + <div> | |
| 17 | + <Button @click="handleExcute" type="primary"> 执行 </Button> | |
| 18 | + </div> | |
| 19 | + <div class="mt-8"> | |
| 20 | + <a-row type="flex" justify="center"> | |
| 21 | + <a-col :span="3"> 测试结果 </a-col> | |
| 22 | + <a-col :span="21"> | |
| 23 | + <a-textarea v-model:value="testResult" placeholder="测试结果为:" :rows="6" /> | |
| 24 | + </a-col> | |
| 25 | + </a-row> | |
| 26 | + </div> | |
| 27 | + </div> | |
| 28 | +</template> | |
| 29 | +<script lang="ts" setup name="testSql"> | |
| 30 | + import { ref } from 'vue'; | |
| 31 | + import { Button } from 'ant-design-vue'; | |
| 32 | + import { TestEditCellTable } from '../TestEditCellTable/index'; | |
| 33 | + | |
| 34 | + defineProps({ | |
| 35 | + method: { | |
| 36 | + type: String, | |
| 37 | + }, | |
| 38 | + }); | |
| 39 | + | |
| 40 | + const showTestEditCell = ref(false); | |
| 41 | + | |
| 42 | + const testEditCellTableRef = ref<InstanceType<typeof TestEditCellTable>>(); | |
| 43 | + | |
| 44 | + const testResult = ref(''); | |
| 45 | + | |
| 46 | + const handleExcute = async () => { | |
| 47 | + const params = testEditCellTableRef.value?.getValue(); | |
| 48 | + testResult.value = JSON.stringify(params); | |
| 49 | + }; | |
| 50 | +</script> | |
| 51 | + | |
| 52 | +<style scoped lang="less"></style> | ... | ... |
| 1 | +<template> | |
| 2 | + <div class="mt-8"> | |
| 3 | + <div> | |
| 4 | + <Button @click="handleExcute" type="primary"> 测试一下 </Button> | |
| 5 | + </div> | |
| 6 | + </div> | |
| 7 | + <div class="mt-8"> | |
| 8 | + <div class="mt-8"> | |
| 9 | + <a-row type="flex" justify="center"> | |
| 10 | + <a-col :span="3"> 测试结果 </a-col> | |
| 11 | + <a-col :span="21"> | |
| 12 | + <a-textarea v-model:value="testResult" placeholder="测试结果为:" :rows="6" /> | |
| 13 | + </a-col> | |
| 14 | + </a-row> | |
| 15 | + </div> | |
| 16 | + </div> | |
| 17 | +</template> | |
| 18 | +<script lang="ts" setup name="testRequest"> | |
| 19 | + import { ref } from 'vue'; | |
| 20 | + import { Button } from 'ant-design-vue'; | |
| 21 | + | |
| 22 | + defineProps({ | |
| 23 | + method: { | |
| 24 | + type: String, | |
| 25 | + }, | |
| 26 | + }); | |
| 27 | + | |
| 28 | + const testResult = ref(''); | |
| 29 | + | |
| 30 | + const handleExcute = () => { | |
| 31 | + testResult.value = '测试结果为:1234'; | |
| 32 | + }; | |
| 33 | +</script> | |
| 34 | + | |
| 35 | +<style scoped lang="less"></style> | ... | ... |
| ... | ... | @@ -7,13 +7,16 @@ import { findDictItemByCode } from '/@/api/system/dict'; |
| 7 | 7 | export const columns: BasicColumn[] = [ |
| 8 | 8 | { |
| 9 | 9 | title: '接口名称', |
| 10 | - dataIndex: 'name', | |
| 10 | + dataIndex: 'interfaceName', | |
| 11 | 11 | width: 80, |
| 12 | 12 | }, |
| 13 | 13 | { |
| 14 | 14 | title: '请求方式', |
| 15 | - dataIndex: 'method', | |
| 15 | + dataIndex: 'requestContentType', | |
| 16 | 16 | width: 120, |
| 17 | + format(text) { | |
| 18 | + return text === '0' ? '普通请求' : text === '1' ? 'SQL请求' : 'websocket请求'; | |
| 19 | + }, | |
| 17 | 20 | }, |
| 18 | 21 | { |
| 19 | 22 | title: '接口内容', |
| ... | ... | @@ -36,24 +39,29 @@ export const columns: BasicColumn[] = [ |
| 36 | 39 | //模拟数据 |
| 37 | 40 | export const list = [ |
| 38 | 41 | { |
| 39 | - name: '传感器趋势图', | |
| 40 | - method: 'get', | |
| 42 | + interfaceName: '传感器趋势图', | |
| 43 | + requestContentType: '0', | |
| 41 | 44 | content: '/api/sensor', |
| 42 | 45 | status: 0, |
| 43 | 46 | }, |
| 44 | 47 | { |
| 45 | - name: '报警器趋势图', | |
| 46 | - method: 'get', | |
| 47 | - content: '/api/alarm', | |
| 48 | + interfaceName: '2co趋势图', | |
| 49 | + requestContentType: '2', | |
| 50 | + content: '/api/2co', | |
| 51 | + status: 1, | |
| 52 | + }, | |
| 53 | + { | |
| 54 | + interfaceName: 'temp趋势图', | |
| 55 | + requestContentType: '1', | |
| 56 | + content: '/api/temp', | |
| 48 | 57 | status: 1, |
| 49 | 58 | }, |
| 50 | 59 | ]; |
| 51 | 60 | |
| 52 | 61 | //表单配置 |
| 53 | -// 新增编辑配置 | |
| 54 | 62 | export const schemas: FormSchema[] = [ |
| 55 | 63 | { |
| 56 | - field: 'name', | |
| 64 | + field: 'interfaceName', | |
| 57 | 65 | label: '接口名称', |
| 58 | 66 | colProps: { span: 24 }, |
| 59 | 67 | required: true, |
| ... | ... | @@ -64,30 +72,120 @@ export const schemas: FormSchema[] = [ |
| 64 | 72 | }, |
| 65 | 73 | }, |
| 66 | 74 | { |
| 67 | - field: 'address', | |
| 68 | - label: '接口地址', | |
| 75 | + field: 'requestContentType', | |
| 76 | + label: '请求方式', | |
| 77 | + component: 'ApiSelect', | |
| 78 | + required: true, | |
| 79 | + colProps: { span: 24 }, | |
| 80 | + defaultValue: '0', | |
| 81 | + componentProps: ({ formActionType }) => { | |
| 82 | + const { setFieldsValue, updateSchema } = formActionType; | |
| 83 | + return { | |
| 84 | + api: findDictItemByCode, | |
| 85 | + params: { | |
| 86 | + dictCode: 'dataview_select_methods', | |
| 87 | + }, | |
| 88 | + placeholder: '请选择请求方式', | |
| 89 | + labelField: 'itemText', | |
| 90 | + valueField: 'itemValue', | |
| 91 | + getPopupContainer: () => document.body, | |
| 92 | + async onChange(e) { | |
| 93 | + setFieldsValue({ requestHttpType: e === '1' ? 'POST' : 'GET' }); | |
| 94 | + const res = await findDictItemByCode({ | |
| 95 | + dictCode: e === '1' ? 'dataview_select_sql_request' : 'dataview_select_request', | |
| 96 | + }); | |
| 97 | + const options = res.map((m) => ({ label: m.itemText, value: m.itemValue })); | |
| 98 | + updateSchema({ | |
| 99 | + field: 'requestHttpType', | |
| 100 | + componentProps: { | |
| 101 | + options, | |
| 102 | + }, | |
| 103 | + }); | |
| 104 | + }, | |
| 105 | + }; | |
| 106 | + }, | |
| 107 | + }, | |
| 108 | + { | |
| 109 | + field: 'requestOriginUrl', | |
| 110 | + label: '源地址', | |
| 69 | 111 | colProps: { span: 24 }, |
| 70 | 112 | required: true, |
| 71 | 113 | component: 'Input', |
| 72 | 114 | componentProps: { |
| 73 | 115 | maxLength: 64, |
| 74 | - placeholder: '请输入接口地址', | |
| 116 | + placeholder: '请输入源地址', | |
| 75 | 117 | }, |
| 76 | 118 | }, |
| 77 | 119 | { |
| 78 | - field: 'method', | |
| 79 | - label: '选择方式', | |
| 120 | + field: 'requestHttpType', | |
| 121 | + label: '请求类型', | |
| 80 | 122 | component: 'ApiSelect', |
| 81 | 123 | required: true, |
| 82 | - colProps: { span: 24 }, | |
| 124 | + colProps: { span: 6 }, | |
| 125 | + defaultValue: 'GET', | |
| 83 | 126 | componentProps: { |
| 84 | - placeholder: '请选择选择方式', | |
| 127 | + placeholder: '请选择请求类型', | |
| 85 | 128 | api: findDictItemByCode, |
| 86 | 129 | params: { |
| 87 | - dictCode: 'dataview_select_methods', | |
| 130 | + dictCode: 'dataview_select_request', | |
| 88 | 131 | }, |
| 89 | 132 | labelField: 'itemText', |
| 90 | 133 | valueField: 'itemValue', |
| 91 | 134 | }, |
| 135 | + ifShow: ({ values }) => | |
| 136 | + values['requestContentType'] === '0' || values['requestContentType'] === '1', | |
| 137 | + }, | |
| 138 | + { | |
| 139 | + field: 'requestUrl', | |
| 140 | + label: '', | |
| 141 | + component: 'Input', | |
| 142 | + required: true, | |
| 143 | + colProps: { span: 18 }, | |
| 144 | + componentProps: { | |
| 145 | + maxLength: 64, | |
| 146 | + placeholder: '请输入接口地址', | |
| 147 | + }, | |
| 148 | + ifShow: ({ values }) => | |
| 149 | + values['requestContentType'] === '0' || values['requestContentType'] === '1', | |
| 150 | + }, | |
| 151 | + { | |
| 152 | + field: 'sqlKey', | |
| 153 | + label: '键名', | |
| 154 | + colProps: { span: 12 }, | |
| 155 | + component: 'Input', | |
| 156 | + defaultValue: 'sql', | |
| 157 | + componentProps: { | |
| 158 | + disabled: true, | |
| 159 | + }, | |
| 160 | + ifShow: ({ values }) => values['requestContentType'] === '1', | |
| 161 | + }, | |
| 162 | + { | |
| 163 | + field: 'sqlValue', | |
| 164 | + label: '键值', | |
| 165 | + colProps: { span: 24 }, | |
| 166 | + component: 'InputTextArea', | |
| 167 | + defaultValue: 'select * from where', | |
| 168 | + componentProps: { | |
| 169 | + maxLength: 255, | |
| 170 | + placeholder: '请输入键值', | |
| 171 | + rows: 6, | |
| 172 | + }, | |
| 173 | + ifShow: ({ values }) => values['requestContentType'] === '1', | |
| 174 | + }, | |
| 175 | + { | |
| 176 | + field: 'slot', | |
| 177 | + label: '参数设置', | |
| 178 | + component: 'Input', | |
| 179 | + slot: 'selectMethods', | |
| 180 | + colProps: { span: 24 }, | |
| 181 | + ifShow: ({ values }) => values['requestContentType'] !== '1', | |
| 182 | + }, | |
| 183 | + { | |
| 184 | + field: 'testSlot', | |
| 185 | + label: '测试', | |
| 186 | + component: 'Input', | |
| 187 | + slot: 'testSql', | |
| 188 | + colProps: { span: 24 }, | |
| 189 | + ifShow: ({ values }) => values['requestContentType'] === '1', | |
| 92 | 190 | }, |
| 93 | 191 | ]; | ... | ... |
src/views/dataview/publicApi/enum/index.ts
0 → 100644
| 1 | +/** | |
| 2 | + * @description: 请求参数类型 | |
| 3 | + */ | |
| 4 | +export enum RequestParamsTypeEnum { | |
| 5 | + PARAMS = 'Params', | |
| 6 | + BODY = 'Body', | |
| 7 | + HEADER = 'Header', | |
| 8 | +} | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * @description: 请求体类型 | |
| 12 | + */ | |
| 13 | +export enum RequestBodyTypeEnum { | |
| 14 | + NONE = 'none', | |
| 15 | + FORMDATA = 'form-data', | |
| 16 | + XWWW = 'x-www-form-urlencoded', | |
| 17 | + JSON = 'json', | |
| 18 | + XML = 'xml', | |
| 19 | +} | ... | ... |
| ... | ... | @@ -4,17 +4,41 @@ |
| 4 | 4 | showFooter |
| 5 | 5 | v-bind="$attrs" |
| 6 | 6 | @register="registerDrawer" |
| 7 | - width="50%" | |
| 7 | + width="45%" | |
| 8 | 8 | @ok="handleOnSubmit" |
| 9 | 9 | > |
| 10 | - <BasicForm @register="registerForm" /> | |
| 10 | + <BasicForm @register="registerForm"> | |
| 11 | + <template #selectMethods="{ model }"> | |
| 12 | + <SimpleRequest | |
| 13 | + ref="simpleRequestRef" | |
| 14 | + v-if="model['requestContentType'] === '0'" | |
| 15 | + :method="model['requestContentType']" | |
| 16 | + /> | |
| 17 | + <SimpleRequest | |
| 18 | + ref="simpleRequestRef" | |
| 19 | + v-if="model['requestContentType'] === '2'" | |
| 20 | + :method="model['requestContentType']" | |
| 21 | + /> | |
| 22 | + </template> | |
| 23 | + <template #testSql="{ model }"> | |
| 24 | + <TestSql | |
| 25 | + v-if="model['requestContentType'] === '1'" | |
| 26 | + :method="model['requestContentType']" | |
| 27 | + /> | |
| 28 | + </template> | |
| 29 | + </BasicForm> | |
| 11 | 30 | </BasicDrawer> |
| 12 | 31 | </div> |
| 13 | 32 | </template> |
| 14 | 33 | <script lang="ts" setup name="publicApi"> |
| 34 | + import { ref } from 'vue'; | |
| 15 | 35 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
| 16 | 36 | import { BasicForm, useForm } from '/@/components/Form'; |
| 17 | 37 | import { schemas } from './config'; |
| 38 | + import { SimpleRequest } from './components/SimpleRequest'; | |
| 39 | + import { TestSql } from './components/TestSql/index'; | |
| 40 | + | |
| 41 | + const simpleRequestRef = ref<InstanceType<typeof SimpleRequest>>(); | |
| 18 | 42 | |
| 19 | 43 | const [registerForm, { resetFields, validate, setFieldsValue }] = useForm({ |
| 20 | 44 | labelWidth: 120, |
| ... | ... | @@ -32,6 +56,13 @@ |
| 32 | 56 | const handleOnSubmit = async () => { |
| 33 | 57 | const values = await validate(); |
| 34 | 58 | if (!values) return; |
| 35 | - console.log('Get values', values); | |
| 59 | + const params = simpleRequestRef?.value?.getValue(); | |
| 60 | + const data = { | |
| 61 | + ...values, | |
| 62 | + requestParams: { | |
| 63 | + params, | |
| 64 | + }, | |
| 65 | + }; | |
| 66 | + console.log('Get form values', data); | |
| 36 | 67 | }; |
| 37 | 68 | </script> | ... | ... |
src/views/dataview/publicApi/hooks/useApi.ts
0 → 100644
| 1 | +import { ref } from 'vue'; | |
| 2 | +import { deviceProfile } from '/@/api/device/deviceManager'; | |
| 3 | +import { getOrganizationList } from '/@/api/system/system'; | |
| 4 | +// import { copyTransFun } from '/@/utils/fnUtils'; | |
| 5 | +// import { getAllDeviceByOrg } from '/@/api/dataBoard'; | |
| 6 | +// import { getDeviceAttributes } from '/@/api/dataBoard'; | |
| 7 | +import { copyTransFun } from '/@/utils/fnUtils'; | |
| 8 | + | |
| 9 | +export const useApi = async (key) => { | |
| 10 | + const options = ref<{ label: string; value: string; disabled?: boolean }[]>([]); | |
| 11 | + switch (key) { | |
| 12 | + case 'deviceProfileId': | |
| 13 | + const res = await deviceProfile(); | |
| 14 | + options.value = res?.map((m) => ({ label: m.name, value: m.id })); | |
| 15 | + break; | |
| 16 | + case 'organizationId': | |
| 17 | + const data = await getOrganizationList(); | |
| 18 | + copyTransFun(data as never as any); | |
| 19 | + options.value = data as any; | |
| 20 | + } | |
| 21 | + | |
| 22 | + return { options: options.value }; | |
| 23 | +}; | ... | ... |
| ... | ... | @@ -8,6 +8,16 @@ |
| 8 | 8 | <TableAction |
| 9 | 9 | :actions="[ |
| 10 | 10 | { |
| 11 | + label: '发布', | |
| 12 | + icon: 'clarity:note-edit-line', | |
| 13 | + onClick: handleCreateOrEdit.bind(null, record), | |
| 14 | + }, | |
| 15 | + { | |
| 16 | + label: '取消发布', | |
| 17 | + icon: 'clarity:note-edit-line', | |
| 18 | + onClick: handleCreateOrEdit.bind(null, record), | |
| 19 | + }, | |
| 20 | + { | |
| 11 | 21 | label: '修改', |
| 12 | 22 | icon: 'clarity:note-edit-line', |
| 13 | 23 | onClick: handleCreateOrEdit.bind(null, record), | ... | ... |