screens.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. <template>
  2. <div>
  3. <div class="gva-search-box">
  4. <el-form
  5. ref="searchForm"
  6. :inline="true"
  7. :model="searchInfo"
  8. >
  9. <el-form-item label="项目名称:">
  10. <el-select
  11. v-model="searchInfo.projectId"
  12. filterable
  13. collapse-tags
  14. placeholder="选择项目"
  15. clearable
  16. @change="getTableData()"
  17. >
  18. <el-option
  19. v-for="item in projects"
  20. :key="item.ID"
  21. :label="item.projectName"
  22. :value="item.ID"
  23. />
  24. </el-select>
  25. </el-form-item>
  26. <el-form-item label="设备SN:">
  27. <el-input
  28. v-model="searchInfo.sn"
  29. placeholder="搜索sn"
  30. />
  31. </el-form-item>
  32. <el-form-item>
  33. <el-button
  34. type="primary"
  35. icon="search"
  36. @click="getTableData"
  37. >查询</el-button>
  38. <el-button
  39. icon="refresh"
  40. @click="onReset"
  41. >重置</el-button>
  42. </el-form-item>
  43. </el-form>
  44. </div>
  45. <div class="gva-table-box">
  46. <div class="gva-btn-list">
  47. <el-button
  48. type="primary"
  49. icon="plus"
  50. @click="add()"
  51. >添加显示屏</el-button>
  52. </div>
  53. <el-table
  54. :data="tableData"
  55. style="width: 100%; margin-bottom: 20px"
  56. row-key="id"
  57. border
  58. :table-layout="'fixed'"
  59. :row-class-name="tableRowClassName"
  60. >
  61. <el-table-column
  62. prop="ID"
  63. label="编号"
  64. :width="100"
  65. />
  66. <el-table-column
  67. label="名称"
  68. :width="200"
  69. prop="screensName"
  70. />
  71. <el-table-column
  72. label="sn"
  73. :width="220"
  74. prop="sn"
  75. />
  76. <el-table-column
  77. label="ip地址"
  78. :width="200"
  79. prop="ipAddress"
  80. />
  81. <el-table-column
  82. label="所属项目"
  83. :width="180"
  84. prop="Project.projectName"
  85. />
  86. <el-table-column
  87. prop="Remark"
  88. label="备注"
  89. />
  90. <el-table-column
  91. prop="status"
  92. label="在线状态"
  93. :width="100"
  94. >
  95. <template #default="scope">
  96. <div
  97. class="onlinebox"
  98. :style="{'background': scope.row.status===0 ? 'red':'green' }"
  99. />
  100. <span :style="{ color: scope.row.status === 0 ? 'red' : 'green' }">{{ scope.row.status === 0 ? '离线' : '在线' }}</span>
  101. </template>
  102. </el-table-column>
  103. <el-table-column
  104. align="left"
  105. fixed="right"
  106. label="操作"
  107. :width="300"
  108. >
  109. <template #default="scope">
  110. <el-button
  111. type="primary"
  112. link
  113. @click="openSet(scope.row)"
  114. >操作</el-button>
  115. <el-button
  116. type="primary"
  117. link
  118. icon="edit"
  119. @click="editScreens(scope.row)"
  120. >编辑</el-button>
  121. <el-button
  122. type="primary"
  123. link
  124. icon="delete"
  125. @click="deleteScreens(scope.row)"
  126. >删除</el-button>
  127. </template>
  128. </el-table-column>
  129. </el-table>
  130. <div class="gva-pagination">
  131. <el-pagination
  132. :current-page="page"
  133. :page-size="pageSize"
  134. :page-sizes="[10, 30, 50, 100]"
  135. :total="total"
  136. layout="total, sizes, prev, pager, next, jumper"
  137. @current-change="handleCurrentChange"
  138. @size-change="handleSizeChange"
  139. />
  140. </div>
  141. <el-dialog
  142. v-model="addScreensDialog"
  143. title="LED屏"
  144. width="600"
  145. >
  146. <el-form
  147. ref="screensForm"
  148. :rules="rules"
  149. :model="screensInfo"
  150. label-width="100px"
  151. style="padding: 15px"
  152. >
  153. <el-row>
  154. <el-col :span="24">
  155. <el-form-item
  156. label="LED名称:"
  157. :inline="false"
  158. prop="screensName"
  159. >
  160. <el-input v-model="screensInfo.screensName" />
  161. </el-form-item>
  162. <el-form-item
  163. label="设备Sn:"
  164. :inline="false"
  165. prop="sn"
  166. >
  167. <el-input v-model="screensInfo.sn" />
  168. </el-form-item>
  169. <el-form-item
  170. label="所属项目:"
  171. prop="projectId"
  172. >
  173. <el-select
  174. v-model="screensInfo.projectId"
  175. filterable
  176. collapse-tags
  177. placeholder="选择项目"
  178. >
  179. <el-option
  180. v-for="item in projects"
  181. :key="item.ID"
  182. :label="item.projectName"
  183. :value="item.ID"
  184. />
  185. </el-select>
  186. </el-form-item>
  187. <el-form-item
  188. label="ip地址:"
  189. :inline="false"
  190. >
  191. <el-input v-model="screensInfo.ipAddress" />
  192. </el-form-item>
  193. <el-form-item
  194. label="备注:"
  195. :inline="false"
  196. >
  197. <el-input
  198. v-model="screensInfo.Remark"
  199. type="textarea"
  200. />
  201. </el-form-item>
  202. </el-col>
  203. </el-row>
  204. </el-form>
  205. <template #footer>
  206. <div class="dialog-footer">
  207. <el-button @click="closeAddScreensDialog">取消</el-button>
  208. <el-button
  209. type="primary"
  210. @click="enterAddScreensDialog"
  211. >
  212. 确定
  213. </el-button>
  214. </div>
  215. </template>
  216. </el-dialog>
  217. <el-dialog
  218. v-model="showSettingDialog"
  219. :title="`操作,设备序号=`+deviceSn"
  220. width="1000"
  221. >
  222. <el-tabs v-model="activeName">
  223. <el-tab-pane
  224. label="节目"
  225. name="first"
  226. >
  227. <el-form
  228. :model="programData"
  229. label-width="auto"
  230. >
  231. <el-form-item label="内容编号">
  232. <el-select
  233. v-model="programData.num"
  234. placeholder="请选择"
  235. style="width: 240px"
  236. >
  237. <el-option
  238. v-for="item in contentNumberOptions"
  239. :key="item.value"
  240. :label="item.label"
  241. :value="item.value"
  242. />
  243. </el-select>
  244. </el-form-item>
  245. <el-form-item label="显示方式">
  246. <el-select
  247. v-model="programData.effect"
  248. placeholder="请选择"
  249. style="width: 240px"
  250. >
  251. <el-option
  252. v-for="item in displayModeOptions"
  253. :key="item.value"
  254. :label="item.label"
  255. :value="item.value"
  256. />
  257. </el-select>
  258. </el-form-item>
  259. <el-form-item label="移动速度">
  260. <el-input
  261. v-model="programData.speed"
  262. placeholder="默认推荐 3"
  263. style="width: 240px;"
  264. />
  265. </el-form-item>
  266. <el-form-item label="节目停留时间">
  267. <el-input
  268. v-model="programData.stay"
  269. placeholder="默认推荐 5"
  270. style="width: 240px;"
  271. />
  272. </el-form-item>
  273. <el-form-item label="预留">
  274. <el-input
  275. v-model="programData.total"
  276. placeholder="默认推荐 100"
  277. style="width: 240px;"
  278. />
  279. </el-form-item>
  280. <el-form-item label="节目颜色">
  281. <el-select
  282. v-model="programData.color"
  283. placeholder="请选择"
  284. style="width: 240px"
  285. >
  286. <el-option
  287. v-for="item in colorOptions"
  288. :key="item.value"
  289. :label="item.label"
  290. :value="item.value"
  291. />
  292. </el-select>
  293. </el-form-item>
  294. <el-form-item label="节目内容">
  295. <el-input
  296. v-model="programData.content"
  297. placeholder="默认推荐 [32M]注意弯道"
  298. style="width: 240px;"
  299. />
  300. </el-form-item>
  301. <el-form-item>
  302. <el-button
  303. type="success"
  304. @click="storageProgram"
  305. >存储</el-button>
  306. <el-button type="primary">发送</el-button>
  307. </el-form-item>
  308. </el-form>
  309. </el-tab-pane>
  310. <el-tab-pane
  311. label="声音"
  312. name="second"
  313. >
  314. <el-form
  315. :model="soundPeriodData"
  316. label-width="auto"
  317. >
  318. <el-alert
  319. v-if="isWarning"
  320. title="当前值未保存"
  321. type="warning"
  322. />
  323. <el-form-item label="星期">
  324. <el-select
  325. v-model="soundPeriodData.time"
  326. placeholder="请选择"
  327. style="width: 240px"
  328. >
  329. <el-option
  330. v-for="item in timeOptions"
  331. :key="item.value"
  332. :label="item.label"
  333. :value="item.value"
  334. />
  335. </el-select>
  336. </el-form-item>
  337. <div
  338. v-for="(period, key) in formDataPeriods"
  339. :key="key"
  340. >
  341. <el-form-item :label="key">
  342. <el-row :gutter="10">
  343. <el-col :span="8">
  344. <span>小时:</span>
  345. <el-input-number
  346. v-model.number="period[0]"
  347. :min="0"
  348. :max="23"
  349. label="小时"
  350. />
  351. </el-col>
  352. <el-col :span="8">
  353. <span>分钟:</span>
  354. <el-input-number
  355. v-model.number="period[1]"
  356. :min="0"
  357. :max="59"
  358. label="分钟"
  359. />
  360. </el-col>
  361. <el-col :span="8">
  362. <span>音量:</span>
  363. <el-input-number
  364. v-model.number="period[2]"
  365. :min="0"
  366. :max="10"
  367. label="音量"
  368. />
  369. </el-col>
  370. </el-row>
  371. </el-form-item>
  372. </div>
  373. <el-form-item>
  374. <el-button
  375. type="success"
  376. @click="storageSoundPeriod"
  377. >存储</el-button>
  378. <el-button type="primary">发送</el-button>
  379. </el-form-item>
  380. </el-form>
  381. </el-tab-pane>
  382. </el-tabs>
  383. <template #footer>
  384. <div class="dialog-footer">
  385. <el-button @click="showSettingDialog = false">取消</el-button>
  386. <el-button
  387. type="primary"
  388. @click="showSettingDialog = false"
  389. >
  390. 确定
  391. </el-button>
  392. </div>
  393. </template>
  394. </el-dialog>
  395. </div>
  396. </div>
  397. </template>
  398. <script setup>
  399. import { addScreens, delScreens, getProjectList, getScreensList, updateScreens } from '@/api/screens'
  400. import { ref, onMounted } from 'vue'
  401. import { ElMessage, ElMessageBox } from 'element-plus'
  402. import { createProgram, updateProgram } from '@/api/program'
  403. import {createSoundPeriod, updateSoundPeriod} from "@/api/soundPeriod";
  404. const page = ref(1)
  405. const total = ref(0)
  406. const pageSize = ref(10)
  407. const tableData = ref([])
  408. const screensInfo = ref({})
  409. const searchInfo = ref({})
  410. const screensForm = ref(null)
  411. const dialogFlag = ref('add')
  412. const isFlag = ref('')
  413. const addScreensDialog = ref(false)
  414. const rules = ref({
  415. screensName: [
  416. { required: true, message: '请输入名称', trigger: 'blur' },
  417. // { min: 5, message: '最低5位字符', trigger: 'blur' }
  418. ],
  419. projectId: [
  420. { required: true, message: '请选择归属项目', trigger: 'blur' },
  421. // { min: 5, message: '最低5位字符', trigger: 'blur' }
  422. ],
  423. sn: [
  424. { required: true, message: '请输入设备sn', trigger: 'blur' },
  425. // { min: 5, message: '最低5位字符', trigger: 'blur' }
  426. ]
  427. })
  428. // eslint-disable-next-line no-unused-vars
  429. const getNowDay = () => {
  430. const timestamp = Date.now() // 获取当前时间戳,单位是毫秒
  431. screensInfo.value.startTime = new Date(timestamp)
  432. }
  433. const tableRowClassName = ({ row, rowIndex }) => {
  434. if ((rowIndex + 1) % 2 === 0) {
  435. return 'success-row'
  436. }
  437. return ''
  438. }
  439. const getTableData = async() => {
  440. const table = await getScreensList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
  441. if (table.code === 0) {
  442. tableData.value = table.data.list
  443. total.value = table.data.total
  444. page.value = table.data.page
  445. pageSize.value = table.data.pageSize
  446. }
  447. }
  448. const onReset = () => {
  449. searchInfo.value = {}
  450. getTableData()
  451. }
  452. const projects = ref([])
  453. onMounted(async() => {
  454. getTableData()
  455. const res = await getProjectList()
  456. projects.value = res.data
  457. })
  458. const handleSizeChange = (val) => {
  459. pageSize.value = val
  460. getTableData()
  461. }
  462. const handleCurrentChange = (val) => {
  463. page.value = val
  464. getTableData()
  465. }
  466. const add = () => {
  467. screensInfo.value = {}
  468. dialogFlag.value = 'add'
  469. getNowDay()
  470. addScreensDialog.value = true
  471. }
  472. const closeAddScreensDialog = () => {
  473. screensForm.value.resetFields()
  474. addScreensDialog.value = false
  475. isFlag.value = ''
  476. }
  477. const enterAddScreensDialog = async() => {
  478. screensForm.value.validate(async valid => {
  479. if (valid) {
  480. const req = {
  481. ...screensInfo.value
  482. }
  483. if (dialogFlag.value === 'add') {
  484. const res = await addScreens(req)
  485. if (res.code === 0) {
  486. ElMessage({ type: 'success', message: '创建成功' })
  487. await getTableData()
  488. closeAddScreensDialog()
  489. }
  490. }
  491. if (dialogFlag.value === 'edit') {
  492. const res = await updateScreens(req)
  493. if (res.code === 0) {
  494. ElMessage({ type: 'success', message: '编辑成功' })
  495. await getTableData()
  496. closeAddScreensDialog()
  497. }
  498. }
  499. }
  500. })
  501. }
  502. const editScreens = (row) => {
  503. dialogFlag.value = 'edit'
  504. screensInfo.value = JSON.parse(JSON.stringify(row))
  505. addScreensDialog.value = true
  506. }
  507. const deleteScreens = (obj) => {
  508. ElMessageBox.confirm('您确定要删除吗?', '提示', {
  509. confirmButtonText: '确定',
  510. cancelButtonText: '取消',
  511. type: 'warning',
  512. })
  513. .then(async() => {
  514. const res = await delScreens({ ID: obj.ID })
  515. if (res.code === 0) {
  516. ElMessage({
  517. type: 'success',
  518. message: '删除成功!',
  519. })
  520. getTableData()
  521. }
  522. })
  523. .catch(() => {
  524. ElMessage({
  525. type: 'info',
  526. message: '已取消删除',
  527. })
  528. })
  529. }
  530. const showSettingDialog = ref(false)
  531. const openSet = (val) => {
  532. showSettingDialog.value = true
  533. deviceSn.value = val.sn
  534. programData.value = val.Program
  535. if (val.soundPeriodId === 0) {
  536. isWarning.value = true
  537. soundPeriodData.value = soundPeriodForm.value
  538. } else {
  539. isWarning.value = false
  540. soundPeriodData.value = val.SoundPeriod
  541. }
  542. formDataPeriods.value = {
  543. period0: soundPeriodData.value.period0,
  544. period1: soundPeriodData.value.period1,
  545. period2: soundPeriodData.value.period2,
  546. period3: soundPeriodData.value.period3,
  547. period4: soundPeriodData.value.period4,
  548. period5: soundPeriodData.value.period5,
  549. period6: soundPeriodData.value.period6,
  550. period7: soundPeriodData.value.period7,
  551. }
  552. }
  553. const isWarning = ref(false)
  554. // 切换
  555. const activeName = ref('first')
  556. const deviceSn = ref()
  557. // 节目program
  558. const programData = ref({
  559. mum: undefined,
  560. effect: undefined,
  561. speed: '',
  562. stay: '',
  563. total: '',
  564. color: '',
  565. content: '',
  566. })
  567. // 节目选择参数
  568. const contentNumberOptions = [
  569. {
  570. value: '0',
  571. label: '待机',
  572. },
  573. {
  574. value: '1',
  575. label: '正常速度',
  576. },
  577. {
  578. value: '2',
  579. label: '超速',
  580. },
  581. {
  582. value: '3',
  583. label: '对向',
  584. },
  585. {
  586. value: '4',
  587. label: '双向',
  588. },
  589. {
  590. value: '5',
  591. label: '无车',
  592. },
  593. {
  594. value: '6',
  595. label: '快速显示配置',
  596. },
  597. {
  598. value: '7',
  599. label: '无信号',
  600. },
  601. ]
  602. const displayModeOptions = [
  603. {
  604. value: '10',
  605. label: '闪烁显示',
  606. },
  607. {
  608. value: '11',
  609. label: '立即打出',
  610. }
  611. ]
  612. const colorOptions = [
  613. {
  614. value: '0',
  615. label: '红',
  616. },
  617. {
  618. value: '1',
  619. label: '绿',
  620. },
  621. {
  622. value: '2',
  623. label: '蓝',
  624. },
  625. {
  626. value: '3',
  627. label: '黄',
  628. },
  629. ]
  630. // 存储
  631. const storageProgram = async() => {
  632. if (programData.value.ID === 0) {
  633. console.log('create')
  634. await createProgram({
  635. deviceSn: deviceSn.value,
  636. program: programData.value,
  637. }).then(res => {
  638. if (res.code === 0) {
  639. ElMessage.success('存储成功')
  640. }
  641. getTableData()
  642. })
  643. } else {
  644. console.log('update')
  645. await updateProgram({
  646. deviceSn: deviceSn.value,
  647. program: programData.value,
  648. }).then(res => {
  649. if (res.code === 0) {
  650. ElMessage.success('存储成功')
  651. }
  652. getTableData()
  653. })
  654. }
  655. }
  656. // 声音调节soundPeriod
  657. const soundPeriodData = ref({
  658. ID: 0,
  659. time: '0',
  660. period0: [],
  661. period1: [],
  662. period2: [],
  663. period3: [],
  664. period4: [],
  665. period5: [],
  666. period6: [],
  667. period7: [],
  668. })
  669. const timeOptions = [
  670. {
  671. label: '整周',
  672. value: '0',
  673. },
  674. {
  675. label: '星期一',
  676. value: '1',
  677. },
  678. {
  679. label: '星期二',
  680. value: '2',
  681. },
  682. {
  683. label: '星期三',
  684. value: '3',
  685. },
  686. {
  687. label: '星期四',
  688. value: '4',
  689. },
  690. {
  691. label: '星期五',
  692. value: '5',
  693. },
  694. {
  695. label: '星期六',
  696. value: '6',
  697. },
  698. {
  699. label: '星期七',
  700. value: '7',
  701. },
  702. ]
  703. // 初始化表单数据
  704. const soundPeriodForm = ref({
  705. ID: 0,
  706. time: '1',
  707. period0: [0, 0, 0],
  708. period1: [7, 0, 4],
  709. period2: [8, 30, 8],
  710. period3: [12, 0, 6],
  711. period4: [13, 30, 8],
  712. period5: [19, 0, 0],
  713. period6: [22, 0, 0],
  714. period7: [23, 59, 5],
  715. })
  716. const formDataPeriods = ref({
  717. period0: soundPeriodData.value.period0,
  718. period1: soundPeriodData.value.period1,
  719. period2: soundPeriodData.value.period2,
  720. period3: soundPeriodData.value.period3,
  721. period4: soundPeriodData.value.period4,
  722. period5: soundPeriodData.value.period5,
  723. period6: soundPeriodData.value.period6,
  724. period7: soundPeriodData.value.period7,
  725. })
  726. // 存储
  727. const storageSoundPeriod = async() => {
  728. console.log(soundPeriodData.value)
  729. if (soundPeriodData.value.ID === 0) {
  730. console.log('create')
  731. await createSoundPeriod({
  732. deviceSn: deviceSn.value,
  733. soundPeriod: soundPeriodData.value,
  734. }).then(res => {
  735. if (res.code === 0) {
  736. ElMessage.success('存储成功')
  737. }
  738. getTableData()
  739. })
  740. } else {
  741. console.log('update')
  742. await updateSoundPeriod({
  743. deviceSn: deviceSn.value,
  744. soundPeriod: soundPeriodData.value,
  745. }).then(res => {
  746. if (res.code === 0) {
  747. ElMessage.success('存储成功')
  748. }
  749. getTableData()
  750. })
  751. }
  752. }
  753. </script>
  754. <style>
  755. .el-table .success-row {
  756. background: #f3fdef;
  757. }
  758. .onlinebox{
  759. width: 10px; height: 10px;border-radius: 50%; display: inline-block; margin-right: 4px; position: relative; top: 1px;
  760. }
  761. .el-dialog__header{
  762. border-bottom: 1px solid #e8eaec;
  763. }
  764. .el-dialog__footer {
  765. border-top: 1px solid #e8eaec;
  766. }
  767. </style>