You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

667 lines
22 KiB

3 months ago
2 months ago
2 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
2 months ago
3 months ago
  1. <script setup>
  2. // 这是退款明细页面
  3. import { computed, onMounted, ref } from 'vue'
  4. import { ElMessage } from 'element-plus'
  5. import moment from 'moment'
  6. import API from '@/util/http.js'
  7. import request from '@/util/http.js'
  8. import { reverseMarketMapping } from "@/utils/marketMap.js";
  9. import dayjs from "dayjs";
  10. const showEmployeeData = ref(true)
  11. const defaultTime = [
  12. new Date(2000, 1, 1, 0, 0, 0),
  13. new Date(2000, 2, 1, 23, 59, 59),
  14. ]
  15. //无法选择的时间
  16. const disabledDate = (time) => {
  17. const limitDate = new Date(2025, 0, 1);
  18. return time.getTime() < limitDate.getTime();
  19. }
  20. const format3 = (num) => {
  21. // 每三位添加逗号
  22. return num.toLocaleString('en-US')
  23. }
  24. // 精网号去空格
  25. const trimJwCode = () => {
  26. if (refundUser.value.jwcode) {
  27. // 去除所有空格,并尝试转换为整数
  28. const trimmed = refundUser.value.jwcode.toString().replace(/\s/g, '');
  29. const numeric = Number(trimmed);
  30. // 如果转换为数字成功,保存为数字,否则提示错误
  31. if (!isNaN(numeric)) {
  32. refundUser.value.jwcode = numeric;
  33. } else {
  34. ElMessage.error("精网号格式不正确,请输入数字");
  35. }
  36. }
  37. }
  38. // 变量
  39. //这是获取用户信息的接口
  40. // 标记当前激活的时间范围按钮
  41. const activeTimeRange = ref('')
  42. // 日期选择器变化时清除按钮激活状态
  43. const handleDatePickerChange = () => {
  44. activeTimeRange.value = ''
  45. }
  46. const adminData = ref({})
  47. const getAdminData = async function () {
  48. try {
  49. const result = await API({ url: '/admin/userinfo', data: {} })
  50. adminData.value = result
  51. console.log('请求成功', result)
  52. console.log('用户信息', adminData.value)
  53. } catch (error) {
  54. console.log('请求失败', error)
  55. }
  56. }
  57. // 充值明细表格
  58. const tableData = ref([])
  59. // 搜索======================================
  60. // 搜索detail
  61. const refundUser = ref({
  62. market: ""
  63. })
  64. // 搜索对象
  65. const getObj = ref({
  66. pageNum: 1,
  67. pageSize: 50
  68. })
  69. //分页总条目
  70. const total = ref(100)
  71. // 搜索对象时间
  72. const getTime = ref([])
  73. // 搜索地区列表
  74. const market = ref([])
  75. // 定义响应式变量存储金币合计数
  76. const permanentGolds = ref(0)
  77. const freeGolds = ref(0)
  78. const taskGolds = ref(0)
  79. // 计算总金币数
  80. const sumGolds = computed(() => permanentGolds.value + freeGolds.value + taskGolds.value)
  81. // 退款类型
  82. const refundType = ref([])
  83. //时间格式化
  84. const formatTime = (val) => val ? moment(val).format('YYYY-MM-DD HH:mm:ss') : ''
  85. // 获取退款类型
  86. const getRefundTypes = async function () {
  87. try {
  88. // 发送请求获取退款类型
  89. const result = await API({
  90. url: '/refund/refundType', //这里应该写上一个退款类型的接口
  91. data: {}
  92. })
  93. console.log('退款类型请求成功', result)
  94. // 检查返回的数据是否为数组
  95. if (Array.isArray(result.data)) {
  96. // 将字符串数组转换为 { value, label } 格式
  97. refundType.value = result.data.map(item => ({ value: item, label: item }));
  98. } else {
  99. console.error('退款类型数据格式错误', result)
  100. ElMessage.error('退款类型数据格式错误,请联系管理员')
  101. }
  102. console.log('退款类型', refundType.value)
  103. } catch (error) {
  104. console.log('退款类型请求失败', error)
  105. }
  106. }
  107. // 搜索==============================================================
  108. // 搜索方法
  109. const getSelectBy = async function (val) {
  110. try {
  111. // 搜索参数页码赋值
  112. if (typeof val === 'number') {
  113. getObj.value.pageNum = val
  114. }
  115. // 搜索参数时间赋值
  116. if (getTime.value != null) {
  117. if (getTime.value.startTime != '' && getTime.value.endTime != '') {
  118. refundUser.value.startTime = formatTime(getTime.value[0])
  119. refundUser.value.endTime = formatTime(getTime.value[1])
  120. }
  121. } else {
  122. refundUser.value.startTime = ''
  123. refundUser.value.endTime = ''
  124. }
  125. // 添加排序字段和排序方式到请求参数
  126. refundUser.value.sortField = sortField.value
  127. refundUser.value.sortOrder = sortOrder.value
  128. console.log('搜索参数', getObj.value)
  129. // 发送POST请求
  130. if (refundUser.value.market === '9' || refundUser.value.market === '9999') {
  131. refundUser.value.market = '';
  132. }
  133. if (refundUser.value.jwcode) {
  134. // 纯数字
  135. const numberRegex = /^\d{1,9}$/;
  136. // 检查是否不是数字
  137. if (!numberRegex.test(refundUser.value.jwcode)) {
  138. ElMessage.error('请检查精网号格式')
  139. // 上面提示过了
  140. return
  141. }
  142. }
  143. const result = await API({
  144. url: '/refund/selectBy',
  145. data: {
  146. ...getObj.value,
  147. refundUser: { ...refundUser.value, flag: showEmployeeData.value ? 0 : 1 }
  148. }
  149. })
  150. // 复制一份 refundUser.value 并移除排序字段和排序方式
  151. const detailWithoutSort = { ...refundUser.value,
  152. flag: showEmployeeData.value ? 0 : 1
  153. }
  154. delete detailWithoutSort.sortField
  155. delete detailWithoutSort.sortOrder
  156. const resultTotalGold = await API({
  157. url: '/refund/statsGold',
  158. data: {
  159. ...detailWithoutSort
  160. }
  161. })
  162. // 将响应结果存储到响应式数据中
  163. console.log('resultTotalGold请求成功', resultTotalGold)
  164. // 检查响应的 code 是否为 200 且 data 存在
  165. if (resultTotalGold.code === 200 && resultTotalGold.data) {
  166. const data = resultTotalGold.data
  167. console.log('获取到的金币数据:', data)
  168. permanentGolds.value = (Number(data.permanentGolds) || 0)
  169. freeGolds.value = (Number(data.freeGolds) || 0)
  170. taskGolds.value = (Number(data.taskGolds) || 0)
  171. }
  172. // 存储表格数据
  173. tableData.value = result.data.list
  174. tableData.value = tableData.value.map(item => ({
  175. ...item,
  176. sumGold: (Number(item.sumGold) || 0) ,
  177. permanentGold: (Number(item.permanentGold) || 0) ,
  178. freeGold: (Number(item.freeGold) || 0) ,
  179. taskGold: (Number(item.taskGold) || 0)
  180. }))
  181. console.log('tableData', tableData.value)
  182. // 存储分页总数
  183. total.value = result.data.total
  184. console.log('total', total.value)
  185. // 调用分类的方法
  186. handleClick()
  187. } catch (error) {
  188. console.log('请求失败', error)
  189. // 在这里可以处理错误逻辑,比如显示错误提示等
  190. }
  191. }
  192. // 搜索
  193. const search = function () {
  194. trimJwCode()
  195. getObj.value.pageNum = 1
  196. getSelectBy()
  197. }
  198. // 重置
  199. const reset = function () {
  200. refundUser.value = { market: "" }
  201. sortField.value = ''
  202. sortOrder.value = ''
  203. getTime.value = {}
  204. activeTimeRange.value = '' // 清除激活状态
  205. selectedMarketPath.value = []
  206. getSelectBy()
  207. }
  208. // 今天
  209. const getToday = function () {
  210. const today = dayjs()
  211. const startTime = today.startOf('day').format('YYYY-MM-DD HH:mm:ss')
  212. const endTime = today.endOf('day').format('YYYY-MM-DD HH:mm:ss')
  213. getTime.value = [startTime, endTime]
  214. console.log('getTime', getTime.value)
  215. activeTimeRange.value = 'today' // 标记当前激活状态
  216. getSelectBy()
  217. }
  218. // 昨天
  219. const getYesterday = function () {
  220. const today = dayjs()
  221. const startTime = today.subtract(1, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss')
  222. const endTime = today.subtract(1, 'day').endOf('day').format('YYYY-MM-DD HH:mm:ss')
  223. getTime.value = [startTime, endTime]
  224. console.log('getTime', getTime.value)
  225. activeTimeRange.value = 'yesterday' // 标记当前激活状态
  226. getSelectBy()
  227. }
  228. // 近7天
  229. const get7Days = function () {
  230. const today = dayjs()
  231. const startTime = today.subtract(6, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss')
  232. const endTime = today.endOf('day').format('YYYY-MM-DD HH:mm:ss')
  233. getTime.value = [startTime, endTime]
  234. console.log('getTime', getTime.value)
  235. activeTimeRange.value = '7days' // 标记当前激活状态
  236. getSelectBy()
  237. }
  238. //点击标签页
  239. // 设置tab.props.name默认为all
  240. const tabName = ref('all')
  241. const handleClick = function (tab, event) {
  242. if (tab.props.name === 'all') {
  243. adminAll()
  244. } else if (tab.props.name === 'wait') {
  245. adminWait()
  246. } else if (tab.props.name === 'pass') {
  247. adminPass()
  248. } else if (tab.props.name === 'reject') {
  249. adminReject()
  250. }
  251. }
  252. const delObj = ref({})
  253. const del = function (row) {
  254. delObj.value.detailId = row.detailId
  255. console.log('delObj', delObj.value)
  256. }
  257. // 删除按钮的气泡弹出框确认按钮
  258. const delConfirm = async function () {
  259. try {
  260. console.log('delObj', delObj.value)
  261. // 发送POST请求
  262. const result = await API({
  263. url: '/refund/softDelete?detailId=' + delObj.value.detailId,
  264. data: {}
  265. })
  266. // 将响应结果存储到响应式数据中
  267. console.log('请求成功', result)
  268. // 刷新表格数据
  269. getSelectBy()
  270. } catch (error) {
  271. console.log('请求失败', error)
  272. // 在这里可以处理错误逻辑,比如显示错误提示等
  273. }
  274. }
  275. // 查询商品的接口
  276. const goods = ref([])
  277. const getGoods = async function () {
  278. try {
  279. // 发送POST请求
  280. const result = await request({
  281. url: '/general/goods',
  282. data: {}
  283. })
  284. // 将响应结果存储到响应式数据中
  285. console.log('请求成功product', result)
  286. if (Array.isArray(result.data)) {
  287. // 过滤掉空字符串和 null 值
  288. const validGoods = result.data.filter(item => item && item.trim() !== '');
  289. // 直接使用后端返回的字符串作为 value 和 label
  290. goods.value = validGoods.map(item => ({
  291. value: item,
  292. label: item
  293. }));
  294. }
  295. } catch (error) {
  296. console.log('请求失败', error)
  297. // 在这里可以处理错误逻辑,比如显示错误提示等
  298. }
  299. }
  300. // 挂载
  301. onMounted(async function () {
  302. await getAdminData()
  303. await getSelectBy()
  304. await getMarket()
  305. await getRefundTypes()
  306. await getGoods()
  307. })
  308. // 新增排序字段和排序方式
  309. const sortField = ref('')
  310. const sortOrder = ref('')
  311. // 处理排序事件
  312. const handleSortChange = (column) => {
  313. console.log('排序字段:', column.prop)
  314. console.log('排序方式:', column.order)
  315. if (column.prop === 'permanentGold') {
  316. sortField.value = 'permanentGold'
  317. } else if (column.prop === 'taskGold') {
  318. sortField.value = 'taskGold'
  319. } else if (column.prop === 'freeGold') {
  320. sortField.value = 'freeGold'
  321. } else if (column.prop === 'createTime') {
  322. sortField.value = 'createTime'
  323. } else if (column.prop === 'auditTime') {
  324. sortField.value = 'auditTime'
  325. } else if (column.prop === 'sumGold') {
  326. sortField.value = 'sumGold'
  327. }
  328. sortOrder.value = column.order === 'ascending' ? 'ASC' : 'DESC'
  329. getSelectBy()
  330. }
  331. const handlePageSizeChange = function (val) {
  332. getObj.value.pageSize = val
  333. getSelectBy()
  334. }
  335. const handleCurrentChange = function (val) {
  336. getObj.value.pageNum = val
  337. getSelectBy()
  338. }
  339. const exportExcel = async function () {
  340. const params = {
  341. refundUser: {
  342. jwcode: refundUser.value.jwcode || '',
  343. refundModel: refundUser.value.refundModel || '',
  344. market: refundUser.value.market || "",
  345. startTime: refundUser.value.startTime || '',
  346. endTime: refundUser.value.endTime || '',
  347. goodsName: refundUser.value.goodsName || '',
  348. flag: showEmployeeData.value ? 0 : 1
  349. },
  350. page: getObj.pageNum,
  351. size: total.value
  352. }
  353. try {
  354. const res = await API({ url: '/export/exportRefund', data: params })
  355. if (res.code === 200) {
  356. ElMessage.success('导出成功')
  357. } else {
  358. ElMessage.error(res.message || '导出失败,请稍后重试')
  359. }
  360. } catch (error) {
  361. console.log('请求失败', error)
  362. ElMessage.error('导出失败,请稍后重试')
  363. }
  364. }
  365. const exportListVisible = ref(false)
  366. // 打开导出列表弹窗
  367. const openExportList = () => {
  368. getExportList()
  369. exportListVisible.value = true
  370. }
  371. // 导出列表数据
  372. const exportList = ref([])
  373. // 导出列表加载状态
  374. const exportListLoading = ref(false)
  375. // 获取导出列表
  376. const getExportList = async () => {
  377. exportListLoading.value = true
  378. try {
  379. const result = await API({ url: '/export/export' })
  380. if (result.code === 200) {
  381. const filteredData = result.data.filter(item => {
  382. return item.type === 3; //3表示金币退款列表
  383. });
  384. exportList.value = filteredData
  385. } else {
  386. ElMessage.error(result.msg || '获取导出列表失败')
  387. }
  388. } catch (error) {
  389. console.error('获取导出列表出错:', error)
  390. ElMessage.error('获取导出列表失败,请稍后重试')
  391. } finally {
  392. exportListLoading.value = false
  393. }
  394. }
  395. // 下载导出文件
  396. const downloadExportFile = (item) => {
  397. if (item.state === 2) {
  398. const link = document.createElement('a')
  399. link.href = item.url
  400. link.download = item.fileName
  401. link.click()
  402. } else {
  403. ElMessage.warning('文件还在导出中,请稍后再试')
  404. }
  405. }
  406. //根据状态返回对应的标签类型
  407. const getTagType = (state) => {
  408. switch (state) {
  409. case 0:
  410. return 'info';
  411. case 1:
  412. return 'primary';
  413. case 2:
  414. return 'success';
  415. case 3:
  416. return 'danger';
  417. default:
  418. return 'info';
  419. }
  420. }
  421. //根据状态返回对应的标签文案
  422. const getTagText = (state) => {
  423. switch (state) {
  424. case 0:
  425. return '待执行';
  426. case 1:
  427. return '执行中';
  428. case 2:
  429. return '执行完成';
  430. case 3:
  431. return '执行出错';
  432. default:
  433. return '未知状态';
  434. }
  435. }
  436. // 存储地区选择变化
  437. const selectedMarketPath = ref("")
  438. const handleMarketChange = (value) => {
  439. if (value && value.length > 0) {
  440. const lastValue = value[value.length - 1]
  441. refundUser.value.market = reverseMarketMapping[lastValue]
  442. } else {
  443. refundUser.value.market = ''
  444. }
  445. }
  446. // 获取地区,修改为级联下拉框
  447. const getMarket = async function () {
  448. try {
  449. // 发送POST请求
  450. const result = await API({
  451. url: '/market/selectMarket',
  452. });
  453. // 将响应结果存储到响应式数据中
  454. console.log('请求成功', result)
  455. // 递归转换树形结构为级联选择器需要的格式(跳过第一级节点)
  456. const transformTree = (nodes) => {
  457. // 直接处理第一级节点的子节点
  458. const allChildren = nodes.flatMap(node => node.children || []);
  459. return allChildren.map(child => {
  460. const grandchildren = child.children && child.children.length
  461. ? transformTree([child]) // 递归处理子节点
  462. : null;
  463. return {
  464. value: child.name,
  465. label: child.name,
  466. children: grandchildren
  467. };
  468. });
  469. };
  470. // 存储地区信息
  471. market.value = transformTree(result.data)
  472. console.log('转换后的地区树==============', market.value)
  473. } catch (error) {
  474. console.log('请求失败', error)
  475. }
  476. }
  477. </script>
  478. <template>
  479. <el-card style="margin-bottom: 20px;margin-top:10px">
  480. <el-row style="margin-bottom: 10px">
  481. <el-col :span="5">
  482. <div class="head-card-element">
  483. <el-text>精网号</el-text>
  484. <el-input v-model="refundUser.jwcode" placeholder="请输入精网号" style="width: 150px" clearable />
  485. </div>
  486. </el-col>
  487. <el-col :span="5">
  488. <div class="head-card-element">
  489. <el-text>商品名称</el-text>
  490. <el-select v-model="refundUser.goodsName" placeholder="请选择商品名称" style="width: 180px" clearable>
  491. <el-option v-for="item in goods" :key="item.value" :label="item.label" :value="item.value" />
  492. </el-select>
  493. </div>
  494. </el-col>
  495. <el-col :span="5">
  496. <el-text size="large">所属地区</el-text>
  497. <el-cascader v-model="selectedMarketPath" :options="market" placeholder="请选择所属地区" clearable
  498. style="width:180px" @change="handleMarketChange" />
  499. </el-col>
  500. <el-col :span="5">
  501. <div class="head-card-element">
  502. <el-text>退款类型</el-text>
  503. <el-select v-model="refundUser.refundType" placeholder="请选择退款类型" style="width: 180px" clearable>
  504. <!-- todo 这需要改-->
  505. <el-option v-for="item in refundType" :key="item.value" :label="item.label" :value="item.value" />
  506. </el-select>
  507. </div>
  508. </el-col>
  509. <el-col :span="3">
  510. <div class="head-card-element">
  511. <el-checkbox v-model="showEmployeeData" @change="search()">员工数据</el-checkbox>
  512. </div>
  513. </el-col>
  514. </el-row>
  515. <el-row>
  516. <el-col :span="24">
  517. <div class="head-card-element">
  518. <el-text>退款时间</el-text>
  519. <el-date-picker v-model="getTime" type="datetimerange" range-separator="" start-placeholder="起始时间"
  520. end-placeholder="结束时间" style="width: 400px" @change="handleDatePickerChange"
  521. :default-time="defaultTime" :disabled-date="disabledDate"/>
  522. <el-button @click="getToday()" style="margin-left: 10px"
  523. :type="activeTimeRange === 'today' ? 'primary' : ''">
  524. </el-button>
  525. <el-button @click="getYesterday()" style="margin-left: 10px"
  526. :type="activeTimeRange === 'yesterday' ? 'primary' : ''">
  527. </el-button>
  528. <el-button @click="get7Days()" style="margin-left: 10px"
  529. :type="activeTimeRange === '7days' ? 'primary' : ''"> 近7天
  530. </el-button>
  531. <el-button type="success" @click="reset()">重置</el-button>
  532. <el-button type="primary" @click="search()">查询</el-button>
  533. <el-button type="primary" @click="exportExcel">导出Excel</el-button>
  534. <el-button type="primary" @click="openExportList">查看导出列表</el-button>
  535. </div>
  536. </el-col>
  537. </el-row>
  538. </el-card>
  539. <el-card>
  540. <div>
  541. 退款金币总数{{ format3(Math.abs(sumGolds).toFixed(2)) }}&nbsp;&nbsp;&nbsp;&nbsp;
  542. 永久金币{{ format3(Math.abs(permanentGolds).toFixed(2)) }}&nbsp;&nbsp;&nbsp;&nbsp;
  543. 免费金币{{ format3(Math.abs(freeGolds).toFixed(2)) }}&nbsp;&nbsp;&nbsp;&nbsp;
  544. 任务金币{{ format3(Math.abs(taskGolds).toFixed(2)) }}
  545. </div>
  546. <!-- 设置表格容器的高度和滚动样式 -->
  547. <div style="height: 520px; overflow-y: auto;margin-top:10px">
  548. <el-table :data="tableData" style="width: 100%" @sort-change="handleSortChange" height="520px">
  549. <el-table-column type="index" label="序号" width="80px" fixed="left">
  550. <template #default="scope">
  551. <span>{{
  552. scope.$index + 1 + (getObj.pageNum - 1) * getObj.pageSize
  553. }}</span>
  554. </template>
  555. </el-table-column>
  556. <el-table-column prop="name" label="姓名" fixed="left" width="130px" show-overflow-tooltip />
  557. <el-table-column prop="jwcode" label="精网号" fixed="left" width="110px" />
  558. <el-table-column prop="market" label="所属地区" width="110px" />
  559. <el-table-column prop="goodsName" label="商品名称" width="110px" show-overflow-tooltip />
  560. <el-table-column prop="refundType" label="退款类型" width="100px" />
  561. <el-table-column prop="sumGold" label="金额总数" width="110px" sortable="custom" />
  562. <el-table-column prop="refundModel" label="退款方式" width="110px">
  563. <template #default="scope">
  564. {{ scope.row.refundModel === 0 ? '全部退款' : scope.row.refundModel === 1 ? '部分退款' : '' }}
  565. </template>
  566. </el-table-column>
  567. <el-table-column prop="permanentGold" label="永久金币" width="110px" sortable="custom" />
  568. <el-table-column prop="freeGold" sortable="custom" label="免费金币" width="110px" />
  569. <el-table-column prop="taskGold" sortable="custom" label="任务金币" width="110px" />
  570. <el-table-column prop="remark" label="退款原因" width="160px" show-overflow-tooltip />
  571. <el-table-column prop="adminName" label="提交人" width="100px" />
  572. <el-table-column prop="createTime" sortable="custom" label="提交时间" width="180px">
  573. <template #default="scope">
  574. {{ moment(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
  575. </template>
  576. </el-table-column>
  577. </el-table>
  578. </div>
  579. <!-- 分页 -->
  580. <div class="pagination" style="margin-top: 20px;display: flex;">
  581. <el-pagination background :page-size="getObj.pageSize" :page-sizes="[5, 10, 20, 50, 100]"
  582. layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handlePageSizeChange"
  583. @current-change="handleCurrentChange" @jump="checkPageNumber"></el-pagination>
  584. </div>
  585. </el-card>
  586. <!-- 导出弹窗 -->
  587. <el-dialog v-model="exportListVisible" title="导出列表" width="80%">
  588. <el-table :data="exportList" style="width: 100% ;height: 60vh;" :loading="exportListLoading">
  589. <el-table-column prop="fileName" label="文件名" />
  590. <el-table-column prop="state" label="状态">
  591. <template #default="scope">
  592. <el-tag :type="getTagType(scope.row.state)" :effect="scope.row.state === 3 ? 'light' : 'plain'">
  593. {{ getTagText(scope.row.state) }}
  594. </el-tag>
  595. </template>
  596. </el-table-column>
  597. <el-table-column prop="createTime" label="创建时间">
  598. <template #default="scope">
  599. {{ moment(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
  600. </template>
  601. </el-table-column>
  602. <el-table-column label="操作">
  603. <template #default="scope">
  604. <el-button type="primary" size="small" @click="downloadExportFile(scope.row)"
  605. :disabled="scope.row.state !== 2">
  606. 下载
  607. </el-button>
  608. </template>
  609. </el-table-column>
  610. </el-table>
  611. <template #footer>
  612. <div class="dialog-footer">
  613. <el-button text @click="exportListVisible = false">关闭</el-button>
  614. </div>
  615. </template>
  616. </el-dialog>
  617. </template>
  618. <style scoped>
  619. .head-card-element {
  620. margin-right: 20px;
  621. }
  622. </style>