detail.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. <template>
  2. <div class="system-dic-container">
  3. <div class="content">
  4. <div class="cont_box">
  5. <div class="title">产品:{{ detail.name }}</div>
  6. <div class="pro-status"><span :class="developer_status == 1 ? 'on' : 'off'"></span>{{ developer_status == 1
  7. ? '已发布' : '未发布' }}</div>
  8. <div class="pro-option" @click="CkOption" v-auth="'startOrStop'"> {{ developer_status == 1 ? '停用' : '启用' }}
  9. </div>
  10. </div>
  11. </div>
  12. <div class="content-box">
  13. <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
  14. <el-tab-pane label="产品信息" name="1">
  15. <div class="pro-box">
  16. <div class="protitle">产品信息</div>
  17. <el-button type="" :icon="Edit" class="buttonedit" v-auth="'edit'"
  18. @click="onOpenEditDic(detail)">编辑</el-button>
  19. </div>
  20. <div class="ant-descriptions-view">
  21. <table>
  22. <tbody>
  23. <tr class="ant-descriptions-row">
  24. <th class="ant-descriptions-item-label ant-descriptions-item-colon">产品标识</th>
  25. <td class="ant-descriptions-item-content" colspan="1">{{ detail.key }}</td>
  26. <th class="ant-descriptions-item-label ant-descriptions-item-colon">所属品类</th>
  27. <td class="ant-descriptions-item-content" colspan="1">{{ detail.categoryName }}</td>
  28. <!-- <th class="ant-descriptions-item-label ant-descriptions-item-colon">所属组织</th>
  29. <td class="ant-descriptions-item-content" colspan="1">{{ detail.deptName }}</td> -->
  30. <th class="ant-descriptions-item-label ant-descriptions-item-colon">设备类型</th>
  31. <td class="ant-descriptions-item-content" colspan="1">{{ detail.deviceType }}</td>
  32. </tr>
  33. <tr class="ant-descriptions-row">
  34. <th class="ant-descriptions-item-label ant-descriptions-item-colon">消息协议</th>
  35. <td class="ant-descriptions-item-content" colspan="1">{{ detail.messageProtocol }}</td>
  36. <th class="ant-descriptions-item-label ant-descriptions-item-colon">接入方式</th>
  37. <td class="ant-descriptions-item-content" colspan="1">{{ detail.transportProtocol }}
  38. </td>
  39. </tr>
  40. <tr class="ant-descriptions-row">
  41. <th class="ant-descriptions-item-label ant-descriptions-item-colon">描述</th>
  42. <td class="ant-descriptions-item-content" colspan="5">{{ detail.desc }}</td>
  43. </tr>
  44. </tbody>
  45. </table>
  46. </div>
  47. </el-tab-pane>
  48. <el-tab-pane label="物模型" name="2">
  49. <div class="wu-box">
  50. <el-tabs type="border-card" v-model="activetab" @tab-click="wuhandleClick">
  51. <el-tab-pane label="属性定义" name="attr">
  52. <div class="wu-title">
  53. <div class="title">属性定义</div>
  54. <div><el-button type="primary" v-auth="'edit'" @click="onOpenEditAttr()">添加</el-button>
  55. </div>
  56. </div>
  57. <el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'attr'">
  58. <el-table-column label="属性标识" align="center" prop="key" />
  59. <el-table-column label="属性名称" prop="name" :show-overflow-tooltip="true" />
  60. <el-table-column prop="valueType" label="数据类型" width="100" align="center">
  61. <template #default="scope">
  62. <span>{{ scope.row.valueType.type }}</span>
  63. </template>
  64. </el-table-column>
  65. <el-table-column prop="decimals" label="精度" width="60" align="center">
  66. <template #default="scope">
  67. <span>{{ scope.row.valueType.decimals }}</span>
  68. </template>
  69. </el-table-column>
  70. <el-table-column prop="unit" label="单位" width="60" align="center">
  71. <template #default="scope">
  72. <span>{{ scope.row.valueType.unit }}</span>
  73. </template>
  74. </el-table-column>
  75. <el-table-column prop="accessMode" label="是否只读" width="120" align="center">
  76. <template #default="scope">
  77. <el-tag type="info" size="small" v-if="scope.row.accessMode">只读</el-tag>
  78. <el-tag type="success" size="small" v-else>读写</el-tag>
  79. </template>
  80. </el-table-column>
  81. <el-table-column label="说明" prop="desc" :show-overflow-tooltip="true" />
  82. <el-table-column label="操作" width="300" align="center" fixed="right">
  83. <template #default="scope">
  84. <el-button size="small" text type="warning" v-auth="'edit'"
  85. @click="onEditAttr(scope.row)">修改</el-button>
  86. <el-button size="small" text type="danger" v-auth="'del'"
  87. @click="onRowDel(scope.row.key, 'attr')">删除</el-button>
  88. </template>
  89. </el-table-column>
  90. </el-table>
  91. </el-tab-pane>
  92. <el-tab-pane label="功能定义" name="fun">
  93. <div class="wu-title">
  94. <div class="title">功能定义</div>
  95. <div><el-button type="primary" v-auth="'add'" @click="onOpenEditFun()">添加</el-button>
  96. </div>
  97. </div>
  98. <el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'fun'">
  99. <el-table-column label="功能标识" align="center" prop="key" />
  100. <el-table-column label="名称" prop="name" :show-overflow-tooltip="true" />
  101. <el-table-column label="描述" prop="desc" :show-overflow-tooltip="true" />
  102. <el-table-column label="操作" width="300" align="center" fixed="right">
  103. <template #default="scope">
  104. <el-button size="small" text type="warning" v-auth="'edit'"
  105. @click="onEditFun(scope.row)">修改</el-button>
  106. <el-button size="small" text type="danger" v-auth="'del'"
  107. @click="onRowDel(scope.row.key, 'fun')">删除</el-button>
  108. </template>
  109. </el-table-column>
  110. </el-table>
  111. </el-tab-pane>
  112. <el-tab-pane label="事件定义" name="event">
  113. <div class="wu-title">
  114. <div class="title">事件定义</div>
  115. <div><el-button type="primary" v-auth="'add'" @click="onOpenEditEvent()">添加</el-button>
  116. </div>
  117. </div>
  118. <el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'event'">
  119. <el-table-column label="事件标识" align="center" prop="key" />
  120. <el-table-column label="名称" prop="name" :show-overflow-tooltip="true" />
  121. <el-table-column prop="level" label="事件级别" width="120" align="center">
  122. <template #default="scope">
  123. <el-tag type="primary" size="small" v-if="scope.row.level == 0">普通</el-tag>
  124. <el-tag type="warning" size="small" v-if="scope.row.level == 1">警告</el-tag>
  125. <el-tag type="danger" size="small" v-if="scope.row.level == 2">紧急</el-tag>
  126. </template>
  127. </el-table-column>
  128. <el-table-column label="描述" prop="desc" :show-overflow-tooltip="true" />
  129. <el-table-column label="操作" width="300" align="center" fixed="right">
  130. <template #default="scope">
  131. <el-button size="small" text type="warning" v-auth="'edit'"
  132. @click="onEditEvent(scope.row)">修改</el-button>
  133. <el-button size="small" text type="danger" v-auth="'del'"
  134. @click="onRowDel(scope.row.key, 'event')">删除</el-button>
  135. </template>
  136. </el-table-column>
  137. </el-table>
  138. </el-tab-pane>
  139. <el-tab-pane label="标签定义" name="tab">
  140. <div class="wu-title">
  141. <div class="title">标签定义</div>
  142. <div><el-button type="primary" v-auth="'add'" @click="onOpenEditTab()">添加</el-button>
  143. </div>
  144. </div>
  145. <el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'tab'">
  146. <el-table-column label="属性标识" align="center" prop="key" />
  147. <el-table-column label="属性名称" prop="name" :show-overflow-tooltip="true" />
  148. <el-table-column prop="valueType" label="数据类型" width="120" align="center">
  149. <template #default="scope">
  150. <span>{{ scope.row.valueType.type }}</span>
  151. </template>
  152. </el-table-column>
  153. <el-table-column prop="accessMode" label="是否只读" width="120" align="center">
  154. <template #default="scope">
  155. <el-tag type="info" size="small" v-if="scope.row.accessMode">只读</el-tag>
  156. <el-tag type="success" size="small" v-else>读写</el-tag>
  157. </template>
  158. </el-table-column>
  159. <el-table-column label="描述" prop="desc" :show-overflow-tooltip="true" />
  160. <el-table-column label="操作" width="300" align="center" fixed="right">
  161. <template #default="scope">
  162. <el-button size="small" text type="warning" v-auth="'edit'"
  163. @click="onEditTag(scope.row)">修改</el-button>
  164. <el-button size="small" text type="danger" v-auth="'del'"
  165. @click="onRowDel(scope.row.key, 'tab')">删除</el-button>
  166. </template>
  167. </el-table-column>
  168. </el-table>
  169. </el-tab-pane>
  170. </el-tabs>
  171. <div class="import">
  172. <div class="row_bet">
  173. <el-upload accept="json" :show-file-list="false" :limit="1" :data="{ key: detail.key }"
  174. :headers="headers" :action="uploadUrl" :on-success="updateImg">
  175. <el-button>
  176. <el-icon> <ele-Upload /> </el-icon>
  177. 导入物模型
  178. </el-button>
  179. </el-upload>
  180. <el-button size="default" type="default" class="ml10" @click="onRowExport()">
  181. <el-icon>
  182. <ele-Download />
  183. </el-icon>
  184. 导出物模型
  185. </el-button>
  186. </div>
  187. </div>
  188. <pagination v-show="tableData.total > 0" :total="tableData.total"
  189. v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize"
  190. @pagination="getList()" />
  191. </div>
  192. </el-tab-pane>
  193. <el-tab-pane label="设备接入" name="3">
  194. <deviceIn></deviceIn>
  195. </el-tab-pane>
  196. <el-tab-pane label="数据解析" name="4" lazy>
  197. <dataParse v-if="activeName === '4'" :script="detail.scriptInfo" @updateScript="updateScript">
  198. </dataParse>
  199. </el-tab-pane>
  200. </el-tabs>
  201. </div>
  202. <EditDic ref="editDicRef" @typeList="typeList" />
  203. <EditAttr ref="editAttrRef" @typeList="getproperty" />
  204. <EditFun ref="editFunRef" @typeList="getfunction" />
  205. <EditEvent ref="editEventRef" @typeList="getevent" />
  206. <EditTab ref="editTabRef" @typeList="gettab" />
  207. </div>
  208. </template>
  209. <script lang="ts">
  210. import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
  211. import { Delete, Edit, Search, Share, Upload } from '@element-plus/icons-vue';
  212. import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
  213. import downloadFile from '/@/utils/download';
  214. import getOrigin from '/@/utils/origin';
  215. import EditDic from './component/editPro.vue';
  216. import deviceIn from './component/deviceIn.vue';
  217. import dataParse from './component/dataParse.vue';
  218. import EditAttr from './component/editAttr.vue';
  219. import EditFun from './component/editFun.vue';
  220. import EditEvent from './component/editEvent.vue';
  221. import EditTab from './component/editTab.vue';
  222. import { useRoute } from 'vue-router';
  223. import api from '/@/api/device';
  224. interface TableDataState {
  225. ids: number[];
  226. detail: any;
  227. tableData: {
  228. data: [];
  229. total: number;
  230. loading: boolean;
  231. param: {
  232. pageNum: number;
  233. pageSize: number;
  234. name: string;
  235. deviceType: string;
  236. status: string;
  237. dateRange: string[];
  238. };
  239. };
  240. }
  241. export default defineComponent({
  242. name: 'deviceEditPro',
  243. components: { EditDic, EditAttr, EditFun, EditEvent, EditTab, deviceIn, dataParse },
  244. setup(prop, context) {
  245. const uploadUrl: string = getOrigin(import.meta.env.VITE_API_URL + "/product/tsl/import");
  246. const headers = {
  247. Authorization: 'Bearer ' + localStorage.token,
  248. };
  249. const route = useRoute();
  250. const editDicRef = ref();
  251. const editAttrRef = ref();
  252. const editFunRef = ref();
  253. const editEventRef = ref();
  254. const editTabRef = ref();
  255. const state = reactive<TableDataState>({
  256. isShowDialog: false,
  257. activeName: '1', // 分类数据
  258. activetab: 'attr', // 分类数据
  259. detail: {},
  260. developer_status: 0,
  261. tableData: {
  262. data: [],
  263. total: 0,
  264. loading: false,
  265. param: {
  266. pageNum: 1,
  267. productId: route.params && route.params.id,
  268. pageSize: 10,
  269. status: '',
  270. dateRange: [],
  271. },
  272. },
  273. });
  274. onMounted(() => {
  275. const ids = route.params && route.params.id;
  276. api.product.detail(ids).then((res: any) => {
  277. state.detail = res.data;
  278. state.developer_status = res.data.status
  279. });
  280. //第一次加载
  281. api.model.property(state.tableData.param).then((res: any) => {
  282. state.tableData.data = res.Data;
  283. state.tableData.total = res.Total;
  284. });
  285. });
  286. //编辑属性
  287. const onEditAttr = (row: TableDataRow) => {
  288. editAttrRef.value.openDialog(row, route.params.id);
  289. };
  290. //编辑功能
  291. const onEditFun = (row: TableDataRow) => {
  292. editFunRef.value.openDialog(row, route.params.id);
  293. }
  294. //编辑事件
  295. const onEditEvent = (row: TableDataRow) => {
  296. editEventRef.value.openDialog(row, route.params.id);
  297. }
  298. //编辑标签
  299. const onEditTag = (row: TableDataRow) => {
  300. editTabRef.value.openDialog(row, route.params.id);
  301. }
  302. //打开添加属性弹窗
  303. const onOpenEditAttr = () => {
  304. editAttrRef.value.openDialog({ product_id: route.params.id, id: 0, accessMode: 1 });
  305. };
  306. //打开添加功能弹窗
  307. const onOpenEditFun = () => {
  308. editFunRef.value.openDialog({ product_id: route.params.id, id: 0 });
  309. };
  310. //打开添加事件弹窗
  311. const onOpenEditEvent = () => {
  312. editEventRef.value.openDialog({ product_id: route.params.id, id: 0, level: 0 });
  313. };
  314. //打开添加事件弹窗
  315. const onOpenEditTab = () => {
  316. editTabRef.value.openDialog({ product_id: route.params.id, id: 0, accessMode: 1 });
  317. };
  318. // 打开修改产品弹窗
  319. const onOpenEditDic = (row: TableDataRow) => {
  320. editDicRef.value.openDialog(row);
  321. };
  322. // 删除产品
  323. const onRowDel = (key, type) => {
  324. let msg = `此操作将永久删除该数据吗?,是否继续?`;
  325. if (key.length === 0) {
  326. ElMessage.error('请选择要删除的数据。');
  327. return;
  328. }
  329. ElMessageBox.confirm(msg, '提示', {
  330. confirmButtonText: '确认',
  331. cancelButtonText: '取消',
  332. type: 'warning',
  333. })
  334. .then(() => {
  335. if (type == 'attr') {
  336. api.model.propertydel(route.params.id, key).then(() => {
  337. ElMessage.success('删除成功');
  338. getproperty();
  339. });
  340. }
  341. if (type == 'fun') {
  342. api.model.functiondel(route.params.id, key).then(() => {
  343. ElMessage.success('删除成功');
  344. getfunction();
  345. });
  346. }
  347. if (type == 'event') {
  348. api.model.eventdel(route.params.id, key).then(() => {
  349. ElMessage.success('删除成功');
  350. getevent();
  351. });
  352. }
  353. if (type == 'tab') {
  354. api.model.tagdel(route.params.id, key).then(() => {
  355. ElMessage.success('删除成功');
  356. tagdel();
  357. });
  358. }
  359. })
  360. .catch(() => { });
  361. };
  362. //根据不同类型获取列表
  363. const getList = () => {
  364. switch (state.activetab) {
  365. case 'attr':
  366. getproperty();
  367. break;
  368. case 'fun':
  369. getfunction();
  370. break;
  371. case 'event':
  372. getevent();
  373. break;
  374. case 'tab':
  375. gettab();
  376. break;
  377. }
  378. };
  379. const getproperty = () => {
  380. api.model.property(state.tableData.param).then((res: any) => {
  381. state.tableData.data = res.Data;
  382. state.tableData.total = res.Total;
  383. });
  384. };
  385. const getfunction = () => {
  386. api.model.function(state.tableData.param).then((res: any) => {
  387. state.tableData.data = res.Data;
  388. state.tableData.total = res.Total;
  389. });
  390. };
  391. const getevent = () => {
  392. api.model.event(state.tableData.param).then((res: any) => {
  393. state.tableData.data = res.Data;
  394. state.tableData.total = res.Total;
  395. });
  396. };
  397. const gettab = () => {
  398. api.model.tag(state.tableData.param).then((res: any) => {
  399. state.tableData.data = res.Data;
  400. state.tableData.total = res.Total;
  401. });
  402. };
  403. const wuhandleClick = (tab: TabsPaneContext) => {
  404. state.activetab = tab.props.name;
  405. switch (tab.props.name) {
  406. case 'attr':
  407. getproperty();
  408. break;
  409. case 'fun':
  410. getfunction();
  411. break;
  412. case 'event':
  413. getevent();
  414. break;
  415. case 'tab':
  416. gettab();
  417. break;
  418. }
  419. };
  420. const handleClick = (tab: TabsPaneContext, event: Event) => {
  421. };
  422. const updateScript = (scriptInfo: string) => {
  423. state.detail.scriptInfo = scriptInfo
  424. };
  425. const CkOption = () => {
  426. if (state.developer_status == 1) {
  427. api.product.undeploy({ id: route.params.id }).then((res: any) => {
  428. ElMessage.success('操作成功');
  429. state.developer_status = 0;
  430. });
  431. } else {
  432. api.product.deploy({ id: route.params.id }).then((res: any) => {
  433. ElMessage.success('操作成功');
  434. state.developer_status = 1;
  435. });
  436. }
  437. }
  438. // 导出
  439. const onRowExport = () => {
  440. api.product.export({ key: state.detail.key }).then((res: any) => downloadFile(res, "TSL-" + state.detail.key + "-" + getCurrentTime() + ".json"))
  441. };
  442. const getCurrentTime = () => {
  443. const date = new Date();
  444. const year = date.getFullYear().toString();
  445. const month = (date.getMonth() + 1).toString().padStart(2, '0');
  446. const day = date.getDate().toString().padStart(2, '0');
  447. const hours = date.getHours().toString().padStart(2, '0');
  448. const minutes = date.getMinutes().toString().padStart(2, '0');
  449. return year + month + day + hours + minutes;
  450. }
  451. const updateImg = (res: any) => {
  452. if (res.code === 0) {
  453. getList("attr");
  454. ElMessage.success('物模型导入成功');
  455. } else {
  456. ElMessage.error(res.message);
  457. }
  458. };
  459. return {
  460. updateImg,
  461. headers,
  462. uploadUrl,
  463. getCurrentTime,
  464. onRowExport,
  465. Edit,
  466. updateScript,
  467. editDicRef,
  468. editAttrRef,
  469. editFunRef,
  470. editEventRef,
  471. editTabRef,
  472. CkOption,
  473. onRowDel,
  474. onEditFun,
  475. onEditEvent,
  476. onEditTag,
  477. onEditAttr,
  478. getList,
  479. getproperty,
  480. getfunction,
  481. getevent,
  482. gettab,
  483. wuhandleClick,
  484. onOpenEditTab,
  485. onOpenEditEvent,
  486. onOpenEditAttr,
  487. onOpenEditFun,
  488. onOpenEditDic,
  489. handleClick,
  490. ...toRefs(state),
  491. };
  492. },
  493. });
  494. </script>
  495. <style scoped>
  496. .import {
  497. position: absolute;
  498. top: 26px;
  499. right: 35px;
  500. }
  501. .import .row_bet {
  502. display: flex;
  503. flex-direction: row;
  504. align-items: center;
  505. padding-right: 5px;
  506. flex: 1;
  507. }
  508. .content {
  509. background: #fff;
  510. width: 100%;
  511. padding: 20px;
  512. }
  513. .content-box {
  514. background: #fff;
  515. width: 100%;
  516. padding: 20px;
  517. margin-top: 20px;
  518. }
  519. .cont_box {
  520. display: flex;
  521. }
  522. .cont_box .title {
  523. font-size: 24px;
  524. }
  525. .cont_box .pro-status {
  526. line-height: 40px;
  527. margin-left: 30px;
  528. }
  529. .cont_box .pro-status .on {
  530. background: #52c41a;
  531. }
  532. .cont_box .pro-status .off {
  533. background: #c41a1a;
  534. }
  535. .cont_box .pro-status span {
  536. position: relative;
  537. top: -1px;
  538. display: inline-block;
  539. width: 6px;
  540. height: 6px;
  541. vertical-align: middle;
  542. border-radius: 50%;
  543. margin-right: 5px;
  544. }
  545. .cont_box .pro-option {
  546. line-height: 40px;
  547. margin-left: 10px;
  548. color: #1890ff;
  549. cursor: pointer;
  550. }
  551. .content-box .pro-box {
  552. display: flex;
  553. padding: 10px;
  554. }
  555. .content-box .pro-box .protitle {
  556. font-size: 18px;
  557. font-weight: bold;
  558. line-height: 35px;
  559. }
  560. .content-box .pro-box .buttonedit {
  561. border: 0px;
  562. color: #1890ff;
  563. }
  564. table {
  565. border-collapse: collapse;
  566. text-indent: initial;
  567. border-spacing: 2px;
  568. }
  569. tbody {
  570. box-sizing: border-box;
  571. display: table-row-group;
  572. vertical-align: middle;
  573. border-color: inherit;
  574. }
  575. tr {
  576. display: table-row;
  577. vertical-align: inherit;
  578. border-color: inherit;
  579. }
  580. .ant-descriptions-view {
  581. width: 100%;
  582. overflow: hidden;
  583. border-radius: 4px;
  584. }
  585. .ant-descriptions-view {
  586. border: 1px solid #e8e8e8;
  587. }
  588. .ant-descriptions-view table {
  589. width: 100%;
  590. table-layout: fixed;
  591. }
  592. .ant-descriptions-view>table {
  593. table-layout: auto;
  594. }
  595. .ant-descriptions-row {
  596. border-bottom: 1px solid #e8e8e8;
  597. }
  598. .ant-descriptions-item-label {
  599. color: rgba(0, 0, 0, 0.85);
  600. font-weight: 400;
  601. font-size: 14px;
  602. line-height: 1.5;
  603. }
  604. .ant-descriptions-item-label {
  605. padding: 16px 24px;
  606. border-right: 1px solid #e8e8e8;
  607. }
  608. .ant-descriptions-item-label {
  609. background-color: #fafafa;
  610. }
  611. .ant-descriptions-item-content {
  612. padding: 16px 24px;
  613. border-right: 1px solid #e8e8e8;
  614. display: table-cell;
  615. color: rgba(0, 0, 0, 0.65);
  616. font-size: 14px;
  617. line-height: 1.5;
  618. }
  619. .wu-box {
  620. border: #e8e8e8 solid 1px;
  621. padding: 20px;
  622. width: 100%;
  623. }
  624. .wu-box .wu-title {
  625. display: flex;
  626. flex-direction: row;
  627. justify-content: space-between;
  628. padding: 20px;
  629. border-bottom: #e8e8e8 1px solid;
  630. }
  631. .wu-box .wu-title .title {
  632. font-size: 18px;
  633. }</style>