Dataset.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <template>
  2. <div class="dataset-component">
  3. <div class="form-item mt-8">
  4. <label>数据模型名称</label>
  5. <t-input v-model="modelValue.name" placeholder="名称" />
  6. </div>
  7. <div class="form-item mt-8">
  8. <label>数据方式</label>
  9. <t-radio-group v-model="modelValue.mode">
  10. <t-radio value="api">HTTP请求</t-radio>
  11. <t-radio value="">自定义</t-radio>
  12. </t-radio-group>
  13. </div>
  14. <div v-if="modelValue.mode === 'api'" class="form-item mt-8">
  15. <label>URL地址</label>
  16. <t-input v-model="modelValue.url" @blur="getDatas" @enter="getDatas" />
  17. </div>
  18. <template v-else>
  19. <div class="form-item mt-8">
  20. <label>从Excel导入</label>
  21. <div class="flex middle w-full">
  22. <t-button
  23. class="shrink-0"
  24. style="width: 90px; height: 30px"
  25. @click="importDataset"
  26. >
  27. 导入Excel
  28. </t-button>
  29. <a
  30. :href="cdn ? cdn + '/v/data.xlsx' : '/data.xlsx'"
  31. download
  32. class="ml-12 mt-4 nowrap"
  33. >
  34. 下载Excel示例
  35. </a>
  36. <span class="flex-grow"></span>
  37. <a class="ml-12 mt-4 nowrap" @click="showAddData()"> + 添加数据 </a>
  38. </div>
  39. </div>
  40. </template>
  41. <t-table
  42. class="mt-16"
  43. row-key="id"
  44. :data="modelValue.data"
  45. :columns="datasetColumns"
  46. size="small"
  47. >
  48. <template #type="{ row }">
  49. {{ row.type || 'string' }}
  50. </template>
  51. <template v-if="!modelValue.mode" #actions="{ row, rowIndex }">
  52. <t-icon name="edit" class="hover" @click="showAddData(row, rowIndex)" />
  53. <t-icon
  54. name="delete"
  55. class="ml-12 hover"
  56. @click="modelValue.data.splice(rowIndex, 1)"
  57. />
  58. </template>
  59. </t-table>
  60. <t-dialog
  61. v-if="addDataDialog.show"
  62. :visible="true"
  63. class="data-dialog"
  64. :header="addDataDialog.header"
  65. @close="addDataDialog.show = false"
  66. @confirm="onOkAddData"
  67. >
  68. <div class="form-item mt-16">
  69. <label>设备</label>
  70. <t-input v-model="addDataDialog.data.device" placeholder="设备名称" />
  71. </div>
  72. <div class="form-item mt-16">
  73. <label>数据点名称</label>
  74. <t-input
  75. v-model="addDataDialog.data.label"
  76. placeholder="数据点简短描述"
  77. />
  78. </div>
  79. <div class="form-item mt-16">
  80. <label>数据点ID</label>
  81. <t-input v-model="addDataDialog.data.id" placeholder="数据点ID" />
  82. </div>
  83. <div class="form-item mt-16">
  84. <label>类型</label>
  85. <t-select
  86. class="w-full"
  87. :options="typeOptions"
  88. v-model="addDataDialog.data.type"
  89. placeholder="字符串"
  90. @change="addDataDialog.data.value = null"
  91. />
  92. </div>
  93. <div class="form-item mt-16">
  94. <label>值范围</label>
  95. <div class="w-full">
  96. <t-input v-model="addDataDialog.data.mock" placeholder="值范围" />
  97. <h6 class="desc mt-8">值范围说明</h6>
  98. <ul class="desc ml-16">
  99. <li>
  100. <label class="inline" style="width: 80px">固定值:</label>
  101. 直接填写,例如:10
  102. </li>
  103. <li>
  104. <label class="inline" style="width: 80px">随机值:</label>
  105. {值1,值2,...}。例如:{1,2,3,4,5}
  106. </li>
  107. <li>
  108. <label class="inline" style="width: 80px">范围数字:</label>
  109. 最小值-最大值。例如:0-1.0 或 0-100
  110. </li>
  111. <li>
  112. <label class="inline" style="width: 80px">随机字符串:</label>
  113. [长度]。例如:[8]
  114. </li>
  115. </ul>
  116. </div>
  117. </div>
  118. </t-dialog>
  119. </div>
  120. </template>
  121. <script lang="ts" setup>
  122. import { onBeforeMount, reactive, ref } from 'vue';
  123. import axios from 'axios';
  124. import { MessagePlugin } from 'tdesign-vue-next';
  125. import { importExcel } from '@/services/excel';
  126. import { typeOptions } from '@/services/common';
  127. import { cdn } from '@/services/api';
  128. const { modelValue } = defineProps<{
  129. modelValue: any;
  130. }>();
  131. const emit = defineEmits(['update:modelValue', 'change']);
  132. const datasetColumns = ref([
  133. {
  134. colKey: 'device',
  135. title: '设备',
  136. ellipsis: true,
  137. },
  138. {
  139. colKey: 'label',
  140. title: '数据点名称',
  141. ellipsis: true,
  142. },
  143. {
  144. colKey: 'id',
  145. title: '数据点ID',
  146. ellipsis: true,
  147. },
  148. {
  149. colKey: 'type',
  150. title: '类型',
  151. ellipsis: true,
  152. },
  153. {
  154. colKey: 'mock',
  155. title: '值范围',
  156. ellipsis: true,
  157. },
  158. {
  159. colKey: 'actions',
  160. title: '操作',
  161. width: 100,
  162. },
  163. ]);
  164. const addDataDialog = reactive<any>({});
  165. onBeforeMount(() => {
  166. if (!modelValue.data) {
  167. modelValue.data = [];
  168. }
  169. getDatas();
  170. });
  171. const getDatas = async () => {
  172. if (!modelValue.url) {
  173. return;
  174. }
  175. const ret = await axios.get(modelValue.url);
  176. if (ret) {
  177. modelValue.data = ret;
  178. }
  179. };
  180. const importDataset = async () => {
  181. let columns: any = [
  182. {
  183. header: '设备',
  184. key: 'device',
  185. },
  186. {
  187. header: '数据点名称',
  188. key: 'label',
  189. },
  190. {
  191. header: '数据点ID',
  192. key: 'id',
  193. },
  194. {
  195. header: '类型',
  196. key: 'type',
  197. },
  198. {
  199. header: '值范围',
  200. key: 'mock',
  201. },
  202. ];
  203. const data: any = await importExcel(columns);
  204. modelValue.data = data;
  205. emit('update:modelValue', modelValue);
  206. emit('change', modelValue);
  207. };
  208. const showAddData = (row?: any, index?: number) => {
  209. if (row) {
  210. addDataDialog.header = '编辑数据';
  211. addDataDialog.data = JSON.parse(JSON.stringify(row));
  212. addDataDialog.index = index;
  213. } else {
  214. addDataDialog.header = '添加数据';
  215. addDataDialog.data = { type: 'string' };
  216. }
  217. addDataDialog.show = true;
  218. };
  219. const onOkAddData = () => {
  220. if (!addDataDialog.data.label) {
  221. MessagePlugin.error('请填写名称');
  222. return;
  223. }
  224. if (!addDataDialog.data.id) {
  225. MessagePlugin.error('请填写数据ID');
  226. return;
  227. }
  228. if (addDataDialog.header === '添加数据') {
  229. modelValue.data.push(addDataDialog.data);
  230. } else {
  231. modelValue.data[addDataDialog.index] = addDataDialog.data;
  232. }
  233. addDataDialog.show = false;
  234. };
  235. </script>
  236. <style lang="postcss" scoped>
  237. .dataset-component {
  238. padding-right: 16px;
  239. }
  240. </style>