index.vue 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. <template>
  2. <div class="sy-content">
  3. <el-row>
  4. <el-col :span="12">
  5. <el-form ref="queryForm" :inline="true" size="small" :model="queryParams">
  6. <el-form-item label="" prop="queryVal">
  7. <el-input placeholder="请输入采集器名称/IP" prefix-icon="el-icon-search" v-model="queryParams.queryVal"/>
  8. </el-form-item>
  9. <el-form-item>
  10. <el-button type="primary" icon="el-icon-search" size="small" @click="handelSearch">搜索</el-button>
  11. <el-button type="info" icon="el-icon-refresh" size="small" @click="handelReset">重置</el-button>
  12. </el-form-item>
  13. </el-form>
  14. </el-col>
  15. <el-col :span="12">
  16. <el-row style="float:right">
  17. <el-button size="small" icon="el-icon-plus" type="primary" style="margin-bottom: 20px"
  18. @click="handelAdd">新增
  19. </el-button>
  20. <el-button size="small" icon="el-icon-download" type="primary" style="margin-bottom: 20px"
  21. @click="downloadApp">采集器下载
  22. </el-button>
  23. </el-row>
  24. </el-col>
  25. </el-row>
  26. <el-row>
  27. <el-col :span="24">
  28. <el-table ref="table" :loading="loading" :data="tableList" row-key="id" border stripe
  29. header-row-class-name="headBackground">
  30. <!-- <el-table-column label="序号" type="index" width="70" align="center" />-->
  31. <el-table-column key="clientName" label="采集器名称" prop="clientName" show-overflow-tooltip/>
  32. <el-table-column key="ipAddr" label="IP地址" prop="ipAddr" show-overflow-tooltip/>
  33. <el-table-column key="onLine" label="在线状态" prop="onLine" show-overflow-tooltip width="100">
  34. <template slot-scope="scope">
  35. <el-tag :type="scope.row.onLine === 1 ? 'success' : 'info'">{{
  36. scope.row.onLine === 1 ? "在线" : "离线"
  37. }}
  38. </el-tag>
  39. </template>
  40. </el-table-column>
  41. <el-table-column key="runStatus" label="运行状态" prop="runStatus" show-overflow-tooltip width="100">
  42. <template slot-scope="scope">
  43. <el-tag :type="scope.row.runStatus === 1 ? 'success' : 'danger'">{{
  44. scope.row.runStatus === 1 ? "运行" :
  45. "停止"
  46. }}
  47. </el-tag>
  48. </template>
  49. </el-table-column>
  50. <!-- <el-table-column key="createTime" label="创建时间" prop="createTime" show-overflow-tooltip />-->
  51. <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="500">
  52. <template slot-scope="scope">
  53. <el-button size="mini" type="text" icon="el-icon-tickets" @click="handelEdit(scope.row)">编辑
  54. </el-button>
  55. <el-button :disabled="scope.row.onLine !== 1"
  56. size="mini" type="text" icon="el-icon-tickets" @click="handelConfig(scope.row.id)">配置
  57. </el-button>
  58. <el-button :disabled="scope.row.onLine !== 1"
  59. size="mini" type="text" icon="el-icon-s-order"
  60. @click="handelLog(scope.row.id)">日志
  61. </el-button>
  62. <el-button :disabled="scope.row.onLine !== 1"
  63. size="mini" type="text" icon="el-icon-refresh" @click="refreshConfig(scope.row.id,true)">刷新配置
  64. </el-button>
  65. <el-button v-if="(!scope.row.runStatus || scope.row.runStatus === 0)" :disabled="scope.row.onLine !== 1"
  66. size="mini" type="text" icon="el-icon-video-play" :style="scope.row.onLine === 1?'color: #67c23a;':''"
  67. @click="handelStart(scope.row.id, scope.row.clientName)">启动
  68. </el-button>
  69. <el-button v-if="scope.row.runStatus === 1" :disabled="scope.row.onLine !== 1"
  70. size="mini" type="text"
  71. icon="el-icon-video-pause" style="color: #f56c6c;" @click="handelStop(scope.row.id, scope.row.clientName)">停止
  72. </el-button>
  73. <el-button size="mini" type="text" icon="el-icon-delete" style="color: #f56c6c;"
  74. @click="deleteCollector(scope.row)">删除
  75. </el-button>
  76. </template>
  77. </el-table-column>
  78. </el-table>
  79. <pagination v-show="total > 0" :total="total" :page.sync="queryParams.page" :limit.sync="queryParams.limit"
  80. align="right" @pagination="getCollectorList"/>
  81. </el-col>
  82. </el-row>
  83. <el-dialog title="新增采集器" :visible.sync="dialogAdd" width="800px" :close-on-click-modal="false">
  84. <el-form ref="addForm" :model="addForm" :rules="addRules" label-width="90px">
  85. <el-form-item label="采集器" prop="name">
  86. <el-input v-model="addForm.name" placeholder="请输入采集器名称"/>
  87. </el-form-item>
  88. <el-form-item label="IP地址" prop="ip">
  89. <el-input v-model="addForm.ip" placeholder="请输入IP地址"/>
  90. </el-form-item>
  91. </el-form>
  92. <span slot="footer" class="dialog-footer">
  93. <el-button type="primary" @click="handelAddSubmit" size="mini">确定</el-button>
  94. <el-button @click="handelAddCancel()" size="mini">取消</el-button>
  95. </span>
  96. </el-dialog>
  97. <el-dialog title="高级设置" :visible.sync="dialogSetting" width="800px" :close-on-click-modal="false">
  98. <el-form ref="configForm" :model="configForm" :rules="configRules" label-width="120px">
  99. <el-row :span="24">
  100. <el-col :span="11">
  101. <el-form-item label="间隔取整" prop="roundInterval">
  102. <el-radio-group v-model="configForm.roundInterval">
  103. <el-radio :label="0">否</el-radio>
  104. <el-radio :label="1">是</el-radio>
  105. </el-radio-group>
  106. </el-form-item>
  107. </el-col>
  108. <el-col :span="1">
  109. <el-tooltip class="item" effect="dark"
  110. content="将采集的间隔时间取整。比如,如果interval设置为10s,但我们在1分02秒启动了telegraf服务,那么采集的时间会取整到1分10秒,1分20秒,1分30秒"
  111. placement="top">
  112. <i class="el-icon-question" style="line-height: 36px;margin-left: 5px;"></i>
  113. </el-tooltip>
  114. </el-col>
  115. <el-col :span="11">
  116. <el-form-item label="刷新间隔" prop="flushInterval">
  117. <el-input placeholder="请输入刷新间隔" v-model="configForm.flushInterval">
  118. <template slot="append">秒</template>
  119. </el-input>
  120. </el-form-item>
  121. </el-col>
  122. <el-col :span="1">
  123. <el-tooltip class="item" effect="dark"
  124. content="所有output的输出间隔,这个参数不应该设的比interval(所有input组件的采集间隔)小"
  125. placement="top">
  126. <i class="el-icon-question" style="line-height: 36px;margin-left: 5px;"></i>
  127. </el-tooltip>
  128. </el-col>
  129. </el-row>
  130. <el-row :span="24">
  131. <el-col :span="11">
  132. <el-form-item label="发送量" prop="metricBatchSize">
  133. <el-input placeholder="请输入发送量" v-model="configForm.metricBatchSize">
  134. <template slot="append">条</template>
  135. </el-input>
  136. </el-form-item>
  137. </el-col>
  138. <el-col :span="1">
  139. <el-tooltip class="item" effect="dark"
  140. content="telegraf一批次从output组件向外发送数据的大小,网络不稳定时可以减小此参数。"
  141. placement="top">
  142. <i class="el-icon-question" style="line-height: 36px;margin-left: 5px;"></i>
  143. </el-tooltip>
  144. </el-col>
  145. <el-col :span="11">
  146. <el-form-item label="缓存量" prop="metricBufferLimit">
  147. <el-input placeholder="请输入发送量" v-model="configForm.metricBufferLimit">
  148. <template slot="append">条</template>
  149. </el-input>
  150. </el-form-item>
  151. </el-col>
  152. <el-col :span="1">
  153. <el-tooltip class="item" effect="dark"
  154. content="telegraf会为每个output插件创建一个缓冲区,来缓存指标数据,并在output成功将数据发送后,将成功发送的数据从缓冲区删除。所以,metriac_buffer_limit参数应该至少是metric_batch_size参数的两倍"
  155. placement="top">
  156. <i class="el-icon-question" style="line-height: 36px;margin-left: 5px;"></i>
  157. </el-tooltip>
  158. </el-col>
  159. </el-row>
  160. <el-row :span="24">
  161. <el-col :span="11">
  162. <el-form-item label="采集抖动" prop="collectionJitter">
  163. <el-input placeholder="请输入采集抖动" v-model="configForm.collectionJitter">
  164. <template slot="append">秒</template>
  165. </el-input>
  166. </el-form-item>
  167. </el-col>
  168. <el-col :span="1">
  169. <el-tooltip class="item" effect="dark"
  170. content="这个参数会在采集的时间点上加一个随机的抖动,这样可以避免很多插件同时查询一些消耗资源的指标,从而对被观测的系统产生不可忽视的影响。"
  171. placement="top">
  172. <i class="el-icon-question" style="line-height: 36px;margin-left: 5px;"></i>
  173. </el-tooltip>
  174. </el-col>
  175. <el-col :span="11">
  176. <el-form-item label="刷新抖动" prop="flushJitter">
  177. <el-input placeholder="请输入刷新抖动" v-model="configForm.flushJitter">
  178. <template slot="append">秒</template>
  179. </el-input>
  180. </el-form-item>
  181. </el-col>
  182. <el-col :span="1">
  183. <el-tooltip class="item" effect="dark"
  184. content="对output的输出时间加上一个随机的抖动,这主要是为了避免大量的Telegraf实例在同样的时间同时执行写入操作,出现较大的写入峰值。比如,flush_jitter设为5s,flush_interval设为10s意味着会在10~15秒的时候进行一次输出。"
  185. placement="top">
  186. <i class="el-icon-question" style="line-height: 36px;margin-left: 5px;"></i>
  187. </el-tooltip>
  188. </el-col>
  189. </el-row>
  190. </el-form>
  191. <span slot="footer" class="dialog-footer">
  192. <el-button type="primary" @click="handelSettingSubmit()" size="mini">确定</el-button>
  193. <el-button @click="handelSettingCancel()" size="mini">取消</el-button>
  194. </span>
  195. </el-dialog>
  196. <el-dialog title="采集配置" :visible.sync="dialogConfig" width="800px" :close-on-click-modal="false" :before-close="handelConfigCancel">
  197. <el-row :span="24">
  198. <el-button size="mini" icon="el-icon-plus" type="primary" style="margin-bottom: 20px"
  199. @click="itemAddBtn">新增
  200. </el-button>
  201. <el-button size="mini" icon="el-icon-setting" type="primary" style="margin-bottom: 20px"
  202. @click="itemSettingBtn">高级设置
  203. </el-button>
  204. </el-row>
  205. <el-row :span="24">
  206. <el-table :data="itemTableData" height="250" border style="width: 100%">
  207. <el-table-column label="序号" type="index" width="70" align="left"/>
  208. <el-table-column key="group_name" label="数据组" align="left" prop="group_name" show-overflow-tooltip>
  209. </el-table-column>
  210. <el-table-column key="userName" label="创建用户" align="left" prop="userName" show-overflow-tooltip>
  211. </el-table-column>
  212. <el-table-column key="interval" label="采集间隔" align="left" prop="interval" show-overflow-tooltip/>
  213. <el-table-column key="unit" label="单位" align="left" prop="unit" show-overflow-tooltip/>
  214. <el-table-column label="操作" align="left" width="250" class-name="small-padding fixed-width">
  215. <template slot-scope="scope">
  216. <el-button v-show="scope.row.isupdate==1" size="mini" type="text" icon="el-icon-edit"
  217. @click="editItem(scope.row)">修改
  218. </el-button>
  219. <el-button v-show="scope.row.isupdate==1" size="mini" type="text" icon="el-icon-delete"
  220. @click="delItem(scope.row)">删除
  221. </el-button>
  222. </template>
  223. </el-table-column>
  224. </el-table>
  225. </el-row>
  226. <span slot="footer" class="dialog-footer">
  227. <el-button v-if="false" type="primary" @click="handelConfigSubmit()" size="mini">确定</el-button>
  228. <el-button @click="handelConfigCancel()" size="mini">关闭</el-button>
  229. </span>
  230. </el-dialog>
  231. <el-dialog title="日志" :visible.sync="dialogLog" width="800px" :close-on-click-modal="false">
  232. <div style="height: 600px;overflow-y: auto;">
  233. <el-collapse v-model="activeName" accordion>
  234. <el-collapse-item v-for="item in LogList" :title="item.path + '(' + item.itemGroupName + ')'" :name="item.index">
  235. <div v-for="txt in item.log">{{ txt }}</div>
  236. </el-collapse-item>
  237. </el-collapse>
  238. </div>
  239. </el-dialog>
  240. <el-dialog title="数据组配置" :visible.sync="groupDialog" width="500px" :close-on-click-modal="false">
  241. <el-form ref="itemForm" :model="itemForm" :rules="itemRules" label-width="120px">
  242. <el-form-item label="采集数据组" prop="itemGroupId">
  243. <el-select v-model="itemForm.itemGroupId" placeholder="请选择数据组" style="width: 100%;" @change="itemGroupChange">
  244. <el-option v-for="group in itemGroupList" :key="group.id" :label="group.groupName" :value="group.id">
  245. </el-option>
  246. </el-select>
  247. </el-form-item>
  248. <el-form-item label="采集间隔" prop="interval">
  249. <el-input placeholder="请输入采集间隔" v-model="itemForm.interval">
  250. <template slot="append">
  251. <div class="unit-my">
  252. <el-select v-model="itemForm.unit" style="width: 80px">
  253. <el-option label="毫秒" value="ms"/>
  254. <el-option label="秒" value="s" :disabled="isSubscribe"/>
  255. <el-option label="分" value="m" :disabled="isSubscribe"/>
  256. <el-option label="时" value="h" :disabled="isSubscribe"/>
  257. <el-option label="天" value="d" :disabled="isSubscribe"/>
  258. </el-select>
  259. </div>
  260. </template>
  261. </el-input>
  262. </el-form-item>
  263. </el-form>
  264. <span slot="footer" class="dialog-footer">
  265. <el-button type="primary" @click="itemFormSub" size="mini">确定</el-button>
  266. <el-button @click="itemFormClose()" size="mini">取消</el-button>
  267. </span>
  268. </el-dialog>
  269. </div>
  270. </template>
  271. <script>
  272. import {showLoading} from "@/utils/cqcy";
  273. import {
  274. getClientStatus,
  275. getCollectorInfo,
  276. getCollectorInfoPage, getErrorFile,
  277. getLogFile,
  278. refreshConfig,
  279. saveCollector,
  280. saveConfigInfo,
  281. startClient,
  282. stopClient,
  283. deleteCollectorApi
  284. } from "@/api/collector";
  285. import {
  286. getAllItemGroup
  287. } from '@/api/source/itemGroup';
  288. export default {
  289. name: "index",
  290. data() {
  291. return {
  292. isSubscribe: false,
  293. dialogSetting: false,
  294. activeName: '0',
  295. loading: true,
  296. groupDialog: false,
  297. queryParams: {
  298. page: 1,
  299. limit: 10,
  300. queryVal: ''
  301. },
  302. tableList: [],
  303. total: 0,
  304. dialogAdd: false,
  305. addForm: {
  306. id: null,
  307. name: '',
  308. ip: ''
  309. },
  310. addRules: {
  311. name: [{
  312. required: true,
  313. message: '采集器名称不能为空',
  314. trigger: 'blur'
  315. }],
  316. ip: [{
  317. required: true,
  318. message: 'IP地址格式错误',
  319. pattern: '^((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}$',
  320. trigger: 'blur'
  321. }],
  322. },
  323. itemGroupList: [],
  324. dialogConfig: false,
  325. configForm: {
  326. id: 0,
  327. // 默认数据收集间隔
  328. interval: '1',
  329. // 是否在整点收集数据0、否1、是
  330. roundInterval: 1,
  331. // telegraf一批次从output组件向外发送数据的大小
  332. metricBatchSize: '1000',
  333. // 缓存指标数据,并在output成功将数据发送后,将成功发送的数据从缓冲区删除。metriac_buffer_limit参数应该至少是metric_batch_size参数的两倍
  334. metricBufferLimit: '10000',
  335. // 在采集的时间点上加一个随机的抖动,这样可以避免很多插件同时查询一些消耗资源的指标
  336. collectionJitter: '0',
  337. // output的输出间隔,这个参数不应该设的比interval
  338. flushInterval: '10',
  339. // output的输出时间加上一个随机的抖动,这主要是为了避免大量的Telegraf实例在同样的时间同时执行写入操作
  340. flushJitter: '0',
  341. // 收集的指标四舍五入为指定的精度
  342. precision: '',
  343. // 主机名
  344. hostname: '',
  345. // 不要在 Telegraf 代理中设置host标记0、否1、是
  346. omitHostname: 1,
  347. // 采集失败重试间隔
  348. restartDelay: '10',
  349. itemGroupId: ''
  350. },
  351. configRules: {
  352. interval: [{
  353. required: true,
  354. message: '收集间隔格式错误',
  355. pattern: '^([1-9][0-9]*)$',
  356. trigger: 'blur'
  357. }],
  358. roundInterval: [{
  359. required: true,
  360. message: '间隔取整不能为空',
  361. trigger: 'blur'
  362. }],
  363. metricBatchSize: [{
  364. required: true,
  365. message: '发送量格式错误',
  366. pattern: '^(0|[1-9][0-9]*)$',
  367. trigger: 'blur'
  368. }],
  369. metricBufferLimit: [{
  370. required: true,
  371. message: '缓存量隔格式错误',
  372. pattern: '^(0|[1-9][0-9]*)$',
  373. trigger: 'blur'
  374. }],
  375. collectionJitter: [{
  376. required: true,
  377. message: '采集抖动格式错误',
  378. pattern: '^(0|[1-9][0-9]*)$',
  379. trigger: 'blur'
  380. }],
  381. flushJitter: [{
  382. required: true,
  383. message: '输出抖动格式错误',
  384. pattern: '^(0|[1-9][0-9]*)$',
  385. trigger: 'blur'
  386. }],
  387. flushInterval: [{
  388. required: true,
  389. message: '输出间隔格式错误',
  390. pattern: '^([1-9][0-9]*)$',
  391. trigger: 'blur'
  392. }],
  393. restartDelay: [{
  394. required: true,
  395. message: '采集重试格式错误',
  396. pattern: '^([1-9][0-9]*)$',
  397. trigger: 'blur'
  398. }],
  399. omitHostname: [{
  400. required: true,
  401. message: '忽略主机名不能为空',
  402. trigger: 'blur'
  403. }],
  404. itemGroupId: [{
  405. required: true,
  406. message: '请选择要采集的数据组',
  407. trigger: 'blur'
  408. }],
  409. },
  410. dialogLog: false,
  411. LogList: [],
  412. statusTask: null,
  413. itemForm: {
  414. itemGroupId: '',
  415. interval: '10',
  416. unit: 's'
  417. },
  418. itemRules: {
  419. itemGroupId: [{
  420. required: true,
  421. message: '请选择要采集的数据组',
  422. trigger: 'blur'
  423. }],
  424. interval: [{
  425. required: true,
  426. //message: '采集间隔格式错误',
  427. //pattern: '^([1-9][0-9]*)$',
  428. trigger: 'blur',
  429. validator: (rule, value, callback) => {
  430. if(!/^([1-9][0-9]*)$/.test(value)){
  431. callback("采集间隔格式错误")
  432. return
  433. } else if (this.isSubscribe && parseInt(value) < 10) {
  434. callback("OPC UA 订阅模式采集间隔最低只支持10毫秒")
  435. return
  436. }
  437. callback()
  438. },
  439. }],
  440. },
  441. itemTableData: [],
  442. isItemEdit: false
  443. }
  444. },
  445. created() {
  446. this.getCollectorList();
  447. this.statusTask = setInterval(() => {
  448. this.getClientStatusByList();
  449. this.getClientErrorList();
  450. }, 15000)
  451. },
  452. beforeDestroy() {
  453. if (this.statusTask) {
  454. clearInterval(this.statusTask)
  455. this.statusTask = null
  456. }
  457. },
  458. methods: {
  459. itemGroupChange(e) {
  460. const data = this.itemGroupList.filter(item => item.id == e)[0]
  461. this.isSubscribe = data.subscribe == 1
  462. if (data.subscribe == 1) {
  463. this.itemForm.unit = 'ms'
  464. this.itemForm.interval = data.uaInterval
  465. }
  466. },
  467. /** 搜索 */
  468. handelSearch(event) {
  469. this.$resetBtn(event)
  470. this.queryParams.page = 1
  471. this.getCollectorList()
  472. },
  473. /** 重置按钮操作 */
  474. handelReset(event) {
  475. this.$refs['queryForm'].resetFields()
  476. this.handelSearch(event)
  477. },
  478. getCollectorList() {
  479. getCollectorInfoPage(this.queryParams).then((json) => {
  480. this.tableList = json.data.list || [];
  481. this.total = json.data.count || 0;
  482. this.getClientStatusByList();
  483. })
  484. },
  485. getClientStatusByList() {
  486. const data = this.tableList;
  487. if (data && data.length) {
  488. for (let i = 0; i < data.length; i++) {
  489. getClientStatus(data[i].ipAddr).then((json) => {
  490. const client = json.data;
  491. this.tableList[i].onLine = client.onLine;
  492. this.tableList[i].runStatus = client.runStatus;
  493. }).catch(e => {
  494. console.error(e)
  495. })
  496. }
  497. }
  498. },
  499. getClientErrorList() {
  500. const data = this.tableList;
  501. if (data && data.length) {
  502. // for (let i = 0; i < data.length; i++) {
  503. // if (data[i].onLine === 1 && data[i].runStatus === 1) {
  504. // getErrorFile(data[i].ipAddr).then((json) => {
  505. // const client = json.data;
  506. // if (client.logStatus === 1) {
  507. // this.$message.error(`监测到${data[i].clientName}【${data[i].ipAddr}】近15分钟内有错误日志产生,请检查配置或联系维护人员`);
  508. // }
  509. // })
  510. // }
  511. //
  512. // }
  513. }
  514. },
  515. handelAdd() {
  516. this.dialogAdd = true
  517. },
  518. handelAddCancel() {
  519. this.dialogAdd = false
  520. if (this.$refs['addForm']) {
  521. this.$refs['addForm'].resetFields()
  522. }
  523. this.addForm = {
  524. id: null,
  525. name: '',
  526. ip: ''
  527. }
  528. },
  529. handelAddSubmit() {
  530. this.$refs['addForm'].validate((valid) => {
  531. if (valid) {
  532. saveCollector(this.addForm).then((json) => {
  533. if (json.code != 200) {
  534. this.$message({
  535. message: json.msg,
  536. type: 'warning'
  537. })
  538. return;
  539. }
  540. this.$message({
  541. message: (this.addForm.id ? '编辑' : '新增') + '成功',
  542. type: 'success'
  543. })
  544. this.handelAddCancel()
  545. this.getCollectorList()
  546. })
  547. }
  548. })
  549. },
  550. handelConfig(id) {
  551. this.getAllItemGroup();
  552. getCollectorInfo(id).then((json) => {
  553. const data = json.data || {};
  554. this.configForm = {
  555. id,
  556. interval: (data.interval || 1).toString(),
  557. roundInterval: data.roundInterval || 1,
  558. metricBatchSize: (data.metricBatchSize || 1000).toString(),
  559. metricBufferLimit: (data.metricBufferLimit || 10000).toString(),
  560. collectionJitter: (data.collectionJitter || 0).toString(),
  561. flushInterval: (data.flushInterval || 10).toString(),
  562. flushJitter: (data.flushJitter || 0).toString(),
  563. precision: data.precision || '',
  564. hostname: data.hostname || '',
  565. omitHostname: data.omitHostname || 1,
  566. restartDelay: (data.restartDelay || 10).toString(),
  567. // itemGroupId: JSON.parse(data.itemGroupIds || '[]')
  568. }
  569. if (data.itemJson) {
  570. const itemData = JSON.parse(data.itemJson || '[]')
  571. this.itemTableData = itemData.map(item => {
  572. return {
  573. group_name: item.group_name,
  574. isupdate: item.isupdate,
  575. userName: item.userName,
  576. itemGroupId: item.itemGroupId,
  577. interval: item.itemInterval,
  578. unit: item.itemUnit
  579. }
  580. })
  581. }
  582. this.dialogConfig = true
  583. });
  584. },
  585. refreshConfig(id, showLoad) {
  586. let loading = null
  587. if(showLoad)loading = showLoading(this, '加载中,请稍候···')
  588. refreshConfig(id).then((json) => {
  589. if(showLoad){
  590. loading.close()
  591. this.$message({
  592. message: json.msg,
  593. type: 'success'
  594. })
  595. }
  596. this.getClientStatusByList()
  597. }).catch(() => {
  598. if(showLoad)loading.close()
  599. })
  600. },
  601. getAllItemGroup() {
  602. let params = {
  603. page: 1,
  604. limit: 9999
  605. }
  606. getAllItemGroup(params).then((res) => {
  607. this.itemGroupList = res.data.itemGroupList
  608. })
  609. },
  610. handelConfigCancel() {
  611. if (this.$refs['configForm']) {
  612. this.$refs['configForm'].resetFields()
  613. }
  614. this.dialogConfig = false
  615. this.itemTableData = []
  616. //let data = this.configForm
  617. //this.refreshConfig(data.id)
  618. },
  619. handelConfigSubmit() {
  620. this.saveConfigInfo((data) => {
  621. this.refreshConfig(data.id, true)
  622. this.handelConfigCancel()
  623. })
  624. },
  625. saveConfigInfo(callback) {
  626. if (this.itemTableData.length === 0) {
  627. this.$message({
  628. message: '请配置需要采集的数据组',
  629. type: 'warning'
  630. })
  631. return;
  632. }
  633. const loading = showLoading(this, '加载中,请稍候···')
  634. let data = this.configForm;
  635. data.itemJson = JSON.stringify(this.itemTableData)
  636. saveConfigInfo(data).then((json) => {
  637. loading.close()
  638. if (json.code != 200) {
  639. this.$message({
  640. message: json.msg,
  641. type: 'warning'
  642. })
  643. return;
  644. }
  645. this.$message({
  646. message: '配置成功',
  647. type: 'success'
  648. })
  649. if (callback) callback(data)
  650. }).catch(() => {
  651. loading.close()
  652. this.handelConfig(data.id)
  653. })
  654. },
  655. handelStart(id, clientName) {
  656. const loading = showLoading(this, '加载中,请稍候···')
  657. startClient({
  658. id: id,
  659. clientName: clientName
  660. }).then((json) => {
  661. loading.close()
  662. this.$message({
  663. message: json.msg,
  664. type: 'success'
  665. })
  666. this.getClientStatusByList()
  667. }).catch(() => {
  668. loading.close()
  669. })
  670. },
  671. handelStop(id, clientName) {
  672. const loading = showLoading(this, '加载中,请稍候···')
  673. stopClient({
  674. id: id,
  675. clientName: clientName
  676. }).then((json) => {
  677. loading.close()
  678. this.$message({
  679. message: json.msg,
  680. type: 'success'
  681. })
  682. this.getClientStatusByList()
  683. }).catch(() => {
  684. loading.close()
  685. })
  686. },
  687. handelLog(id) {
  688. const loading = showLoading(this, '加载中,请稍候···')
  689. getLogFile(id).then((json) => {
  690. loading.close()
  691. getCollectorInfo(id).then((json2) => {
  692. if (json2.data?.itemJson) {
  693. const itemData = JSON.parse(json2.data.itemJson || '[]')
  694. let obj = {}
  695. itemData.forEach(item => {
  696. obj[item.itemGroupId] = item.group_name
  697. })
  698. this.LogList = json.data.map(item => {
  699. let id = item.path.substring(item.path.lastIndexOf('_') + 1)
  700. id = id.substring(0, id.indexOf('.'))
  701. item.itemGroupName = obj[id]
  702. return item
  703. })
  704. }
  705. this.dialogLog = true
  706. })
  707. }).catch(() => {
  708. loading.close()
  709. })
  710. },
  711. itemAddBtn() {
  712. this.groupDialog = true
  713. this.isItemEdit = false
  714. this.itemForm = {
  715. itemGroupId: '',
  716. interval: '10',
  717. unit: 's'
  718. }
  719. },
  720. itemFormSub() {
  721. this.$refs['itemForm'].validate((valid) => {
  722. if (!valid) return;
  723. let data = this.itemForm
  724. if (this.isItemEdit) {
  725. if (data.oldItemGroupId !== data.itemGroupId) {
  726. const arr = this.itemTableData.filter(item => {
  727. return data.itemGroupId === item.itemGroupId
  728. })
  729. if (arr.length) {
  730. this.$message({
  731. message: '当前数据组已配置',
  732. type: 'warning'
  733. })
  734. return
  735. }
  736. }
  737. this.itemTableData = this.itemTableData.map(item => {
  738. if (item.itemGroupId === data.oldItemGroupId) {
  739. return data
  740. }
  741. return item
  742. })
  743. } else {
  744. const arr = this.itemTableData.filter(item => {
  745. return data.itemGroupId === item.itemGroupId
  746. })
  747. if (arr.length) {
  748. this.$message({
  749. message: '当前数据组已配置',
  750. type: 'warning'
  751. })
  752. return
  753. }
  754. this.itemTableData.push(data)
  755. }
  756. this.saveConfigInfo((data) => {
  757. this.itemFormClose()
  758. this.handelConfig(data.id)
  759. })
  760. })
  761. },
  762. itemFormClose() {
  763. this.groupDialog = false
  764. this.itemForm = {
  765. itemGroupId: '',
  766. interval: '10',
  767. unit: 's'
  768. }
  769. this.isItemEdit = false
  770. },
  771. editItem(row) {
  772. const arr = this.itemTableData.filter(item => {
  773. return row.itemGroupId === item.itemGroupId
  774. })
  775. this.itemForm = {
  776. oldItemGroupId: arr[0].itemGroupId,
  777. itemGroupId: arr[0].itemGroupId,
  778. interval: arr[0].interval,
  779. unit: arr[0].unit
  780. }
  781. this.groupDialog = true
  782. this.isItemEdit = true
  783. },
  784. delItem(row) {
  785. this.itemTableData = this.itemTableData.filter(item => {
  786. return row.itemGroupId !== item.itemGroupId
  787. })
  788. this.saveConfigInfo((data) => {
  789. this.handelConfig(data.id)
  790. })
  791. },
  792. deleteCollector(row) {
  793. if (row.runStatus === 1 && scope.row.onLine === 1) {
  794. this.$message({
  795. message: '采集器已启动,请先停止采集器再删除',
  796. type: 'warning'
  797. })
  798. return
  799. }
  800. this.$confirm('是否删除该采集器?', '提示', {
  801. confirmButtonText: '确定',
  802. cancelButtonText: '取消',
  803. type: 'warning'
  804. }).then(() => {
  805. deleteCollectorApi(row.id).then(json => {
  806. this.$message({
  807. type: json.code === 200 ? 'success' : 'warning',
  808. message: json.code === 200 ? '删除成功!' : json.msg
  809. });
  810. this.getCollectorList()
  811. })
  812. }).catch(() => {
  813. });
  814. },
  815. downloadApp() {
  816. window.open(process.env.VUE_APP_BASE_API + '/cy-collector.7z')
  817. },
  818. itemSettingBtn() {
  819. this.dialogSetting = true
  820. },
  821. handelSettingSubmit() {
  822. this.$refs['configForm'].validate((valid) => {
  823. if (valid) {
  824. this.saveConfigInfo((data) => {
  825. this.dialogSetting = false
  826. this.handelConfig(data.id)
  827. })
  828. }
  829. })
  830. },
  831. handelSettingCancel() {
  832. this.dialogSetting = false
  833. },
  834. handelEdit(row) {
  835. this.dialogAdd = true
  836. this.addForm = {
  837. id: row.id,
  838. ip: row.ipAddr,
  839. name: row.clientName
  840. }
  841. }
  842. }
  843. }
  844. </script>
  845. <style rel="stylesheet/scss" lang="scss" scoped>
  846. .unit-my {
  847. input {
  848. width: 80px;
  849. }
  850. }
  851. .fixed-width .el-button--mini {
  852. padding: 7px 0px;
  853. }
  854. </style>