edit.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. <template>
  2. <div class="system-edit-dic-container">
  3. <el-dialog :title="(ruleForm.sourceId !== 0 ? '修改' : '添加') + '数据源'" v-model="isShowDialog" width="769px">
  4. <el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="110px" v-if="isShowDialog">
  5. <el-form-item label="数据源标识" prop="key">
  6. <el-input v-model="ruleForm.key" placeholder="请输入数据源名称" :disabled="ruleForm.sourceId" />
  7. </el-form-item>
  8. <el-form-item label="数据源名称" prop="name">
  9. <el-input v-model="ruleForm.name" placeholder="请输入数据源名称" />
  10. </el-form-item>
  11. <el-form-item label="描述" prop="desc">
  12. <el-input v-model="ruleForm.desc" type="textarea" placeholder="请输入内容"></el-input>
  13. </el-form-item>
  14. <el-form-item label="数据来源" prop="from">
  15. <el-radio-group v-model="ruleForm.from">
  16. <el-radio :label="1">api导入</el-radio>
  17. <el-radio :label="4">设备</el-radio>
  18. <el-radio :label="2">数据库</el-radio>
  19. </el-radio-group>
  20. </el-form-item>
  21. <el-divider content-position="left">数据源配置</el-divider>
  22. <div v-if="ruleForm.from == 1" >
  23. <el-form-item label="请求方法" prop="method">
  24. <el-select v-model="config.method" placeholder="请选择请求方法" >
  25. <el-option v-for="item in methodData" :key="item.value" :label="item.label" :value="item.value" />
  26. </el-select>
  27. </el-form-item>
  28. <el-form-item label="请求地址" prop="url">
  29. <el-input v-model="config.url" placeholder="请输入请求地址" />
  30. </el-form-item>
  31. <el-form-item label="定时请求" prop="cronExpression">
  32. <div style="display:flex">
  33. <el-input v-model="config.cronExpression" placeholder="请输入cron表达式" />
  34. <el-button type="success" @click="showCron('config')" style=" margin-left: 5px;">设置</el-button>
  35. </div>
  36. </el-form-item>
  37. <div class="box-content">
  38. <div>
  39. <div v-for="(item, index) in requestParams" :key="index" style="padding: 10px; border: 1px solid #eee; margin-bottom: 10px; position: relative">
  40. <div class="conicon" style="width: 100%; text-align: right; position: absolute; right: -8px; top: -8px; color: red">
  41. <el-icon @click="delParams(index)">
  42. <CircleClose />
  43. </el-icon>
  44. </div>
  45. <div style="display: flex">
  46. <el-divider content-position="left">请求参数</el-divider>
  47. </div>
  48. <div class="content-f" v-for="(aaa, bbb) in item" :key="bbb">
  49. <el-select v-model="aaa.type" placeholder="参数类型" style="width: 320px">
  50. <el-option v-for="item in paramData" :key="item.value" :label="item.label" :value="item.value" />
  51. </el-select>
  52. <el-input v-model="aaa.name" placeholder="请输入参数标题" style="width: 320px" />
  53. <el-input v-model="aaa.key" placeholder="请输入参标识" style="width: 320px" />
  54. <el-input v-model="aaa.value" placeholder="请输入参数值" style="width: 320px" />
  55. <div class="conicon">
  56. <el-icon @click="delParamss(index, bbb)">
  57. <Delete />
  58. </el-icon>
  59. </div>
  60. </div>
  61. <el-button type="primary" class="addbutton" @click="addParams(index)">增加</el-button>
  62. <div style=""></div>
  63. </div>
  64. </div>
  65. </div>
  66. <el-button type="success" class="addbutton" @click="addParamss">增加分组</el-button>
  67. </div>
  68. <div v-if="ruleForm.from == 4">
  69. <el-form-item label="选择设备" prop="deviceKey">
  70. <el-select v-model="devconfig.deviceKey" filterable placeholder="请选择设备" @change="setNode">
  71. <el-option v-for="item in sourceData" :key="item.id" :label="item.key" :value="item.id">
  72. <span style="float: left">{{ item.name }}</span>
  73. <span style="float: right; font-size: 13px">{{ item.key }}</span>
  74. </el-option>
  75. </el-select>
  76. </el-form-item>
  77. </div>
  78. <div v-if="ruleForm.from == 2">
  79. <el-form-item label="数据来源" prop="type">
  80. <el-radio-group v-model="tabconfig.type">
  81. <el-radio label="mysql">mysql</el-radio>
  82. <el-radio label="mssql">mssql</el-radio>
  83. </el-radio-group>
  84. </el-form-item>
  85. <div class="inline">
  86. <el-form-item label="主机地址" prop="host">
  87. <el-input v-model="tabconfig.host" placeholder="请输入主机地址" />
  88. </el-form-item>
  89. <el-form-item label="端口号" prop="port">
  90. <el-input v-model="tabconfig.port" placeholder="请输入端口号" />
  91. </el-form-item>
  92. </div>
  93. <div class="inline">
  94. <el-form-item label="用户名" prop="user">
  95. <el-input v-model="tabconfig.user" placeholder="请输入用户名" />
  96. </el-form-item>
  97. <el-form-item label="密码" prop="passwd">
  98. <el-input v-model="tabconfig.passwd" placeholder="请输入密码" />
  99. </el-form-item>
  100. </div>
  101. <el-form-item label="数据库名称" prop="dbName">
  102. <el-input v-model="tabconfig.dbName" placeholder="请输入数据库名称" />
  103. </el-form-item>
  104. <el-form-item label="执行方式" prop="queryType">
  105. <el-radio-group v-model="tabconfig.queryType">
  106. <el-radio label="tableName">数据表</el-radio>
  107. <el-radio label="sql">Sql</el-radio>
  108. </el-radio-group>
  109. </el-form-item>
  110. <el-form-item label="" prop="tableName">
  111. <el-input v-model="tabconfig.tableName" type="textarea" :placeholder="tabconfig.queryType == 'sql' ? '请输入sql语句' : '请输入表名称'" />
  112. </el-form-item>
  113. <el-form-item label="主键字段" prop="pk">
  114. <el-input v-model="tabconfig.pk" placeholder="请输入主键字段" />
  115. </el-form-item>
  116. <el-form-item label="每次获取数量" prop="num">
  117. <el-input v-model="tabconfig.num" placeholder="请输入每次获取数量" />
  118. </el-form-item>
  119. <el-form-item label="任务表达式" prop="tabcronExpression">
  120. <div style="display:flex" >
  121. <el-input v-model="tabconfig.cronExpression" placeholder="请输入cron任务表达式" />
  122. <el-button type="success" @click="showCron('tabconfig')" style=" margin-left: 5px;">设置</el-button>
  123. </div>
  124. </el-form-item>
  125. </div>
  126. </el-form>
  127. <template #footer>
  128. <span class="dialog-footer">
  129. <el-button @click="onTest" type="warning" size="default" v-if="ruleForm.sourceId > 0">测试</el-button>
  130. <el-button @click="onCancel" size="default">取 消</el-button>
  131. <el-button type="primary" @click="onSubmit" size="default">{{ ruleForm.sourceId !== 0 ? '修 改' : '添 加' }}</el-button>
  132. </span>
  133. </template>
  134. </el-dialog>
  135. <el-dialog v-model="dialogVisible" title="返回Json数据" width="30%">
  136. <JsonViewer :value="jsonData" boxed sort theme="jv-dark" @click="onKeyclick" />
  137. <template #footer>
  138. <span class="dialog-footer">
  139. <el-button @click="dialogVisible = false">关闭</el-button>
  140. </span>
  141. </template>
  142. </el-dialog>
  143. <el-dialog v-model="cronShow" title="选择Cron规则" width="60%">
  144. <vue3cron @handlelisten="handlelisten" :type="crontype" @close="cronclose"></vue3cron>
  145. </el-dialog>
  146. </div>
  147. </template>
  148. <script lang="ts">
  149. import { reactive, toRefs, defineComponent, ref, unref } from 'vue';
  150. import api from '/@/api/datahub';
  151. import 'vue3-json-viewer/dist/index.css';
  152. import vue3cron from '/@/components/vue3cron/vue3cron.vue';
  153. import { validateNoSpace } from '/@/utils/validator';
  154. import { ElMessage } from 'element-plus';
  155. import { Delete, CircleClose, } from '@element-plus/icons-vue';
  156. interface RuleFormState {
  157. sourceId: number;
  158. name: string;
  159. from: number;
  160. key: string;
  161. userName: string;
  162. password: string;
  163. desc: string;
  164. status: number;
  165. }
  166. interface DicState {
  167. isShowDialog: boolean;
  168. ruleForm: RuleFormState;
  169. rules: {};
  170. }
  171. const baseFrom = {
  172. sourceId: 0,
  173. name: '',
  174. from: 1,
  175. key: '',
  176. rule: [],
  177. config: {
  178. method: '',
  179. url: '',
  180. interval: '',
  181. intervalUnit: '',
  182. requestParams: [],
  183. },
  184. desc: '',
  185. }
  186. export default defineComponent({
  187. name: 'Edit',
  188. components: { Delete, CircleClose, vue3cron },
  189. setup(prop, { emit }) {
  190. const myRef = ref<HTMLElement | null>(null);
  191. const formRef = ref<HTMLElement | null>(null);
  192. const state = reactive<DicState>({
  193. isShowDialog: false,
  194. dialogVisible: false,
  195. cronShow: false,
  196. crontype: '',
  197. config: {},
  198. devconfig: {},
  199. tabconfig: {
  200. type:'mysql'
  201. },
  202. sourceData: [],
  203. sourceId: 0,
  204. jsonData: '',
  205. ruledata: [
  206. {
  207. expression: '',
  208. replace: '',
  209. //params: {},
  210. },
  211. ],
  212. rule: [
  213. {
  214. expression: '',
  215. replace: '',
  216. // params: {
  217. // name: '',
  218. // value: '',
  219. // },
  220. },
  221. ],
  222. requestParams: [
  223. [
  224. {
  225. type: '',
  226. key: '',
  227. name: '',
  228. value: '',
  229. },
  230. ],
  231. ],
  232. methodData: [
  233. {
  234. label: 'GET',
  235. value: 'get',
  236. },
  237. {
  238. label: 'POST',
  239. value: 'post',
  240. },
  241. // {
  242. // label: 'PUT',
  243. // value: 'put',
  244. // },
  245. ],
  246. unitData: [
  247. {
  248. label: '秒',
  249. value: 'second',
  250. },
  251. {
  252. label: '分',
  253. value: 'minute',
  254. },
  255. {
  256. label: '时',
  257. value: 'hour',
  258. },
  259. {
  260. label: '天',
  261. value: 'day',
  262. },
  263. ],
  264. paramData: [
  265. {
  266. lable: 'header',
  267. value: 'header',
  268. },
  269. {
  270. lable: 'body',
  271. value: 'body',
  272. },
  273. {
  274. lable: 'param',
  275. value: 'param',
  276. },
  277. ],
  278. ruleForm: JSON.parse(JSON.stringify(baseFrom)),
  279. rules: {
  280. key: [{ required: true, message: '数据源标识不能为空', trigger: 'blur' }],
  281. name: [ { required: true, message: '数据源名称不能为空', trigger: 'blur' },
  282. { max: 32, message: '数据源名称不能超过32个字符', trigger: 'blur' },
  283. { validator: validateNoSpace, message: '数据源名称不能包含空格', trigger: 'blur' }
  284. ],
  285. from: [{ required: true, message: '数据源类型不能为空', trigger: 'blur' }],
  286. method: [{ required: true, message: '请求方法不能为空', trigger: 'blur', when: (formItem:any) => formItem.from === 1 }],
  287. url: [{ required: true, message: '请求地址不能为空', trigger: 'blur', when: (formItem:any) => formItem.from === 1 }],
  288. cronExpression: [{ required: true, message: '定时请求不能为空', trigger: 'blur', when: (formItem:any) => formItem.from === 1 }],
  289. deviceKey: [{ required: true, message: '请选择设备', trigger: 'blur', when: (formItem:any) => formItem.from === 2 }],
  290. type: [{ required: true, message: '请选择数据来源', trigger: 'blur', when: (formItem:any) => formItem.from === 3 }],
  291. host: [{ required: true, message: '请输入主机地址', trigger: 'blur', when: (formItem:any) => formItem.from === 3 }],
  292. port: [{ required: true, message: '请输入端口号', trigger: 'blur', when: (formItem:any) => formItem.from === 3 }],
  293. user: [{ required: true, message: '请输入用户名', trigger: 'blur', when: (formItem:any) => formItem.from === 3 }],
  294. passwd: [{ required: true, message: '请输入密码', trigger: 'blur', when: (formItem:any) => formItem.from === 3 }],
  295. dbName: [{ required: true, message: '请输入数据库名称', trigger: 'blur', when: (formItem:any) => formItem.from === 3 }],
  296. queryType: [{ required: true, message: '请选择执行方式', trigger: 'blur', when: (formItem:any) => formItem.from === 3 }],
  297. tableName: [{ required: true, message: '该项不能为空', trigger: 'blur', when: (formItem:any) => formItem.from === 3 }],
  298. pk: [{ required: true, message: '请输入主键字段', trigger: 'blur', when: (formItem:any) => formItem.from === 3 }],
  299. num: [{ required: true, message: '请输入每次获取数量', trigger: 'blur', when: (formItem:any) => formItem.from === 3 }],
  300. tabcronExpression: [{ required: true, message: '请输入cron任务表达式', trigger: 'blur', when: (formItem:any) => formItem.from === 3 }],
  301. },
  302. });
  303. const delParams = (index) => {
  304. state.requestParams.splice(index, 1);
  305. };
  306. const delParamss = (index, bbb) => {
  307. state.requestParams[index].splice(bbb, 1);
  308. };
  309. const addParamss = () => {
  310. state.requestParams.push([
  311. {
  312. type: '',
  313. key: '',
  314. name: '',
  315. value: '',
  316. },
  317. ]);
  318. };
  319. const addParams = (index) => {
  320. state.requestParams[index].push({
  321. type: '',
  322. key: '',
  323. name: '',
  324. value: '',
  325. });
  326. };
  327. const delRule = (index) => {
  328. state.rule.splice(index, 1);
  329. };
  330. const addRule = () => {
  331. state.rule.push({
  332. expression: '',
  333. replace: '',
  334. // params: {
  335. // name: '',
  336. // value: '',
  337. // },
  338. });
  339. };
  340. // 打开弹窗
  341. const openDialog = (row: RuleFormState | null) => {
  342. resetForm();
  343. getDevData();
  344. if (row) {
  345. state.sourceId = row.sourceId;
  346. api.common.detail(row.sourceId).then((res: any) => {
  347. state.ruleForm = res.data;
  348. if (res.data.from == 1) {
  349. state.config = res.data.apiConfig;
  350. state.requestParams = res.data.apiConfig.requestParams;
  351. } else if (res.data.from == 4) {
  352. state.devconfig = res.data.deviceConfig;
  353. } else if (res.data.from == 2) {
  354. state.tabconfig = res.data.dbConfig;
  355. }
  356. res.data.sourceRule.forEach((item, index) => {
  357. state.rule[index].expression = item.expression;
  358. state.rule[index].replace = item.replace;
  359. // state.rule[index].params.name = Object.keys(item.params);
  360. // state.rule[index].params.value = item.params[Object.keys(item.params)];
  361. });
  362. });
  363. } else {
  364. state.requestParams = []
  365. }
  366. state.isShowDialog = true;
  367. };
  368. const onKeyclick = () => {
  369. // if (e.target.innerText && e.target.className == 'jv-key') {
  370. // let str = e.target.innerText;
  371. // str = str.substr(0, str.length - 1);
  372. // }
  373. };
  374. const resetForm = () => {
  375. state.devconfig = {};
  376. state.tabconfig = {
  377. type:'mysql'
  378. };
  379. state.config = { ...baseFrom.config };
  380. state.ruleForm = JSON.parse(JSON.stringify(baseFrom))
  381. };
  382. // 关闭弹窗
  383. const closeDialog = () => {
  384. resetForm()
  385. formRef.value && formRef.value.resetFields()
  386. state.isShowDialog = false;
  387. };
  388. // 取消
  389. const onCancel = () => {
  390. closeDialog();
  391. };
  392. const getDevData = () => {
  393. api.common.getdevList({}).then((res: any) => {
  394. state.sourceData = res.device;
  395. });
  396. };
  397. const setNode = (event) => {
  398. state.sourceData.forEach((item) => {
  399. if (item.id == event) {
  400. state.devconfig.productKey = item.product.key;
  401. state.devconfig.deviceKey = item.key;
  402. }
  403. });
  404. };
  405. const onTest = () => {
  406. if (state.ruleForm.from == 1) {
  407. api.common.api(state.sourceId).then((res: any) => {
  408. state.jsonData = JSON.parse(res.data);
  409. state.dialogVisible = true;
  410. });
  411. } else if (state.ruleForm.from == 4) {
  412. api.common.devapi(state.sourceId).then((res: any) => {
  413. state.jsonData = JSON.parse(res.data);
  414. state.dialogVisible = true;
  415. });
  416. }
  417. };
  418. // 新增
  419. const onSubmit = () => {
  420. const formWrap = unref(formRef) as any;
  421. if (!formWrap) return;
  422. formWrap.validate((valid: boolean) => {
  423. if (valid) {
  424. //修改rule数据
  425. // state.rule.forEach((item, index) => {
  426. // item.params[item.params.name] = item.params.value;
  427. // delete item.params.name;
  428. // delete item.params.value;
  429. // });
  430. state.ruleForm.rule = state.rule;
  431. if (state.ruleForm.from == 1) {
  432. state.config.requestParams = state.requestParams;
  433. state.ruleForm.config = state.config;
  434. } else if (state.ruleForm.from == 4) {
  435. state.ruleForm.config = state.devconfig;
  436. } else if (state.ruleForm.from == 2) {
  437. state.ruleForm.config = state.tabconfig;
  438. }
  439. if (state.ruleForm.sourceId !== 0) {
  440. //修改
  441. if (state.ruleForm.from == 1) {
  442. api.common.edit(state.ruleForm).then(() => {
  443. ElMessage.success('数据源类型修改成功');
  444. closeDialog(); // 关闭弹窗
  445. emit('typeList');
  446. });
  447. } else if (state.ruleForm.from == 4) {
  448. api.common.devedit(state.ruleForm).then(() => {
  449. ElMessage.success('数据源类型修改成功');
  450. closeDialog(); // 关闭弹窗
  451. emit('typeList');
  452. });
  453. } else if (state.ruleForm.from == 2) {
  454. api.common.dbedit(state.ruleForm).then(() => {
  455. ElMessage.success('数据源类型修改成功');
  456. closeDialog(); // 关闭弹窗
  457. emit('typeList');
  458. });
  459. }
  460. } else {
  461. //添加
  462. if (state.ruleForm.from == 1) {
  463. api.common.add(state.ruleForm).then(() => {
  464. ElMessage.success('数据源类型添加成功');
  465. closeDialog(); // 关闭弹窗
  466. emit('typeList');
  467. });
  468. } else if (state.ruleForm.from == 4) {
  469. api.common.devadd(state.ruleForm).then(() => {
  470. ElMessage.success('数据源类型添加成功');
  471. closeDialog(); // 关闭弹窗
  472. emit('typeList');
  473. });
  474. } else if (state.ruleForm.from == 2) {
  475. api.common.dbadd(state.ruleForm).then(() => {
  476. ElMessage.success('数据源类型添加成功');
  477. closeDialog(); // 关闭弹窗
  478. emit('typeList');
  479. });
  480. }
  481. }
  482. }
  483. });
  484. };
  485. const handlelisten = (e) => {
  486. if (e.type == 'config') {
  487. state.config.cronExpression = e.cron
  488. } else if (e.type == 'tabconfig') {
  489. state.tabconfig.cronExpression = e.cron
  490. }
  491. };
  492. const showCron = (type) => {
  493. state.crontype = type
  494. state.cronShow = true;
  495. };
  496. const cronclose = () => {
  497. state.cronShow = false;
  498. }
  499. return {
  500. cronclose,
  501. showCron,
  502. onTest,
  503. addRule,
  504. delRule,
  505. handlelisten,
  506. addParams,
  507. addParamss,
  508. delParamss,
  509. delParams,
  510. onKeyclick,
  511. openDialog,
  512. setNode,
  513. closeDialog,
  514. getDevData,
  515. onCancel,
  516. onSubmit,
  517. formRef,
  518. myRef,
  519. ...toRefs(state),
  520. };
  521. },
  522. });
  523. </script>
  524. <style>
  525. .inline {
  526. display: inline-flex;
  527. }
  528. .el-input__wrapper {
  529. width: 98%;
  530. }
  531. .box-content {
  532. border: 1px solid #e8e8e8;
  533. margin: 10px;
  534. padding: 10px;
  535. }
  536. .content-f {
  537. display: flex;
  538. margin-bottom: 10px;
  539. }
  540. .content-f .el-input__wrapper {
  541. margin-right: 5px;
  542. }
  543. .addbutton {
  544. width: 100%;
  545. margin-top: 10px;
  546. background: #fff;
  547. border: 1px solid #d1d1d1;
  548. color: #8d8b8b;
  549. }
  550. .conicon {
  551. width: 55px;
  552. height: 25px;
  553. font-size: 28px;
  554. line-height: 28px;
  555. cursor: pointer;
  556. }
  557. .jv-node {
  558. margin-left: 25px;
  559. }
  560. </style>