index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. <template>
  2. <a-card :bordered="false" style="margin-bottom: 10px" class="mb-2">
  3. <a-form ref="searchFormRef" name="advanced_search" :model="searchFormState" class="ant-advanced-search-form">
  4. <a-row :gutter="24">
  5. <a-col :span="6">
  6. <a-form-item label="订单编号" name="orderNumber">
  7. <a-input v-model:value="searchFormState.orderNumber" placeholder="订单编号查询" />
  8. </a-form-item>
  9. </a-col>
  10. <a-col :span="6">
  11. <a-form-item label="订单名称" name="orderName">
  12. <a-input v-model:value="searchFormState.orderName" placeholder="订单名称查询" />
  13. </a-form-item>
  14. </a-col>
  15. <a-col :span="6">
  16. <a-form-item label="车牌号" name="licenseNumber">
  17. <a-input v-model:value="searchFormState.licenseNumber" placeholder="车牌号码查询" />
  18. </a-form-item>
  19. </a-col>
  20. <template v-if="advanced">
  21. <a-col :span="6">
  22. <a-form-item label="客户名称" name="customerName">
  23. <a-input v-model:value="searchFormState.customerName" placeholder="客户名称查询" />
  24. </a-form-item>
  25. </a-col>
  26. <a-col :span="6">
  27. <a-form-item label="货品名称" name="goodsName">
  28. <a-input v-model:value="searchFormState.goodsName" placeholder="货品名称查询" />
  29. </a-form-item>
  30. </a-col>
  31. <a-col :span="6">
  32. <a-form-item label="司机名称" name="driverName">
  33. <a-input v-model:value="searchFormState.driverName" placeholder="司机名称查询" />
  34. </a-form-item>
  35. </a-col>
  36. <a-col :span="6">
  37. <a-form-item label="司机电话" name="driverMobile">
  38. <a-input v-model:value="searchFormState.driverMobile" placeholder="司机电话查询" />
  39. </a-form-item>
  40. </a-col>
  41. <a-col :span="6">
  42. <a-form-item label="预约状态" name="status">
  43. <a-select v-model:value="searchFormState.status" placeholder="预约状态查询"
  44. :options="statusList"
  45. > </a-select>
  46. </a-form-item>
  47. </a-col>
  48. </template>
  49. <a-col :span="6">
  50. <a-button type="primary" @click="tableRef.refresh()">查询</a-button>
  51. <a-button style="margin: 0 8px" @click="reset">重置</a-button>
  52. <a @click="toggleAdvanced" style="margin-left: 8px">
  53. {{ advanced ? '收起' : '展开' }}
  54. <component :is="advanced ? 'up-outlined' : 'down-outlined'" />
  55. </a>
  56. </a-col>
  57. </a-row>
  58. </a-form>
  59. </a-card>
  60. <a-card :bordered="false">
  61. <s-table
  62. ref="tableRef"
  63. :columns="columns"
  64. :data="loadData"
  65. bordered
  66. :row-key="(record) => record.id"
  67. >
  68. <template #operator class="table-operator">
  69. <a-space>
  70. <a-button type="primary" @click="formRef.onOpen()" v-if="hasPerm('bizAppointmentRecordAdd')">
  71. <template #icon><plus-outlined /></template>
  72. 新增
  73. </a-button>
  74. <a-button @click="exportTotal" v-if="hasPerm('bizAppointmentExport')">
  75. <template #icon>
  76. <export-outlined/>
  77. </template>
  78. 导出
  79. </a-button>
  80. </a-space>
  81. </template>
  82. <template #bodyCell="{ column, record }">
  83. <template v-if="column.dataIndex === 'orderInfo'">
  84. <div class="time-list">
  85. <p>名称:{{ record.orderName }}</p>
  86. <p style="margin-bottom: 0">编号:{{ record.orderNumber }}</p>
  87. </div>
  88. </template>
  89. <template v-if="column.dataIndex === 'carInfo'">
  90. <div class="time-list">
  91. <p>车牌号:{{ record.licenseNumber }}</p>
  92. <p style="margin-bottom: 0">车轴数:{{ record.axleNumber + '轴' }}</p>
  93. </div>
  94. </template>
  95. <template v-if="column.dataIndex === 'timeInfo'">
  96. <span>{{record.beginTime + '~' + record.endTime}}</span>
  97. </template>
  98. <template v-if="column.dataIndex === 'customerInfo'">
  99. <span>{{record.customerName}}</span>
  100. </template>
  101. <template v-if="column.dataIndex === 'driverInfo'">
  102. <div class="time-list">
  103. <p>姓名:{{ record.driverName }}</p>
  104. <p style="margin-bottom: 0">电话:{{ record.driverMobile }}</p>
  105. </div>
  106. </template>
  107. <template v-if="column.dataIndex === 'goodsInfo'">
  108. <div class="time-list">
  109. <p>名称:{{ record.goodsName }}</p>
  110. <p style="margin-bottom: 0">规格:{{ record.goodsModel }}</p>
  111. </div>
  112. </template>
  113. <template v-if="column.dataIndex === 'axleNumber'">
  114. {{record.axleNumber+'轴'}}
  115. </template>
  116. <template v-if="column.dataIndex === 'status'">
  117. <a-tag
  118. :color="
  119. record.status === '1'
  120. ? 'volcano'
  121. : record.status === '2'
  122. ? 'red'
  123. : record.status === '3'
  124. ? 'processing'
  125. : record.status === '4'
  126. ? 'warning'
  127. : record.status === '5'
  128. ? 'magenta'
  129. : record.status === '6'
  130. ? 'orange'
  131. : record.status === '7'
  132. ? 'gold'
  133. : record.status === '8'
  134. ? 'lime'
  135. : record.status === '9'
  136. ? 'green'
  137. : record.status === '10'
  138. ? 'cyan'
  139. : record.status === '11'
  140. ? 'success'
  141. : record.status === '12'
  142. ? 'blue'
  143. : record.status === '13'
  144. ? 'geekblue'
  145. : 'error'
  146. "
  147. >
  148. {{ $TOOL.dictTypeData('appointment_status', record.status) }}
  149. </a-tag>
  150. </template>
  151. <template v-if="column.dataIndex === 'action'">
  152. <a @click="showModal(record)" v-if="record.status!='1'&& record.status!='2'">二维码</a>
  153. <a-divider type="vertical" v-if="record.status!='1'&& record.status!='2'"/>
  154. <a-space>
  155. <a-dropdown>
  156. <a class="ant-dropdown-link">
  157. 更多
  158. <DownOutlined />
  159. </a>
  160. <template #overlay>
  161. <a-menu>
  162. <a-menu-item>
  163. <a @click="detailRef.onOpen(record)">详情</a>
  164. </a-menu-item>
  165. <a-menu-item v-if="hasPerm('bizAppointmentAudit') && (record.status == '1')">
  166. <a style="color: #ffaa00" @click="reviewRef.showModal(record.id)">审核</a>
  167. </a-menu-item>
  168. <a-menu-item v-if="hasPerm('bizAppointmentRecordEdit') && (record.status == '1' || record.status == '2')">
  169. <a style="color:blue" @click="formRef.onOpen(record)" >编辑</a>
  170. </a-menu-item>
  171. <a-menu-item v-if="hasPerm('bizAppointmentRecordDelete') && (record.status == '1' || record.status == '2')">
  172. <a style="color:red" type="link" danger size="small" @click="deleteConfig(record)">删除</a>
  173. </a-menu-item>
  174. </a-menu>
  175. </template>
  176. </a-dropdown>
  177. </a-space>
  178. </template>
  179. </template>
  180. </s-table>
  181. </a-card>
  182. <Form ref="formRef" @successful="tableRef.refresh()" />
  183. <Review ref="reviewRef" @successful="tableRef.refresh(true)" />
  184. <Detail ref="detailRef" @successful="tableRef.refresh()" />
  185. <a-modal v-model:visible="open" title="二维码" width="600px" style="height: 700px">
  186. <div id="qrcode" style="text-align: center; margin: 15px 5px 15px 5px">
  187. <a-row>
  188. <a-col :span="13" id="colFlag">
  189. <div style="margin-top:10px;font-size:16px;">
  190. <p id="projectNameFlag">订单名称:{{nowRecord.orderName}}</p>
  191. <p id="projectCodeFlag">订单编码:{{ nowRecord.orderNumber }}</p>
  192. <p id="projectCodeFlag">客户名称:{{ nowRecord.customerName }}</p>
  193. <p id="projectCodeFlag">货品名称:{{ nowRecord.goodsName }}</p>
  194. <p id="projectCodeFlag">司机姓名:{{ nowRecord.driverName }}</p>
  195. <p id="projectCodeFlag">预约状态:{{ $TOOL.dictTypeData('appointment_status', nowRecord.status) }}</p>
  196. </div>
  197. </a-col>
  198. <a-col :span="11">
  199. <a-image width="250" height="100%" :src="qrCodeUrl.codeUrl"></a-image>
  200. </a-col>
  201. </a-row>
  202. </div>
  203. <template #footer>
  204. <a-button @click="closeQrCode">关闭</a-button>
  205. <a-button type="primary" @click="downloadFile">下载</a-button>
  206. </template>
  207. </a-modal>
  208. </template>
  209. <script setup name="bizappointmentrecord">
  210. import { cloneDeep } from 'lodash-es'
  211. import Form from './form.vue'
  212. import Detail from './detail.vue'
  213. import bizAppointmentRecordApi from '@/api/biz/bizAppointmentRecordApi'
  214. import {ExclamationCircleOutlined} from '@ant-design/icons-vue';
  215. import {Modal} from 'ant-design-vue';
  216. import {createVNode} from 'vue';
  217. import Review from './review.vue'
  218. import tool from '@/utils/tool'
  219. import QRCode from 'qrcode'
  220. import html2canvas from 'html2canvas'
  221. import downloadUtil from '@/utils/downloadUtil'
  222. const submitLoading = ref(false)
  223. const tableRef = ref()
  224. const formRef = ref()
  225. const reviewRef = ref()
  226. const detailRef = ref()
  227. const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
  228. const nowRecord = ref()
  229. //查询数据
  230. const searchFormState = ref({})
  231. const searchFormRef = ref()
  232. const statusList = tool.dictList('appointment_status')
  233. // 查询区域显示更多控制
  234. const advanced = ref(false)
  235. const toggleAdvanced = () => {
  236. advanced.value = !advanced.value
  237. }
  238. const columns = [
  239. {
  240. title: '订单信息',
  241. dataIndex: 'orderInfo',
  242. width:200
  243. },
  244. {
  245. title: '车牌号',
  246. dataIndex: 'licenseNumber',
  247. width:150,
  248. align: 'center'
  249. },
  250. {
  251. title: '提货开始时间',
  252. dataIndex: 'beginTime',
  253. align:'center',
  254. width:180
  255. },
  256. {
  257. title: '提货结束时间',
  258. dataIndex: 'endTime',
  259. align:'center',
  260. width:180
  261. },
  262. {
  263. title: '客户信息',
  264. dataIndex: 'customerInfo',
  265. align:'center',
  266. width:180
  267. },
  268. {
  269. title: '货品信息',
  270. dataIndex: 'goodsInfo',
  271. width:160
  272. },
  273. {
  274. title: '司机信息',
  275. dataIndex: 'driverInfo',
  276. width: 160
  277. },
  278. {
  279. title: '状态',
  280. dataIndex: 'status',
  281. align: 'center',
  282. width:150
  283. },
  284. ]
  285. // 操作栏通过权限判断是否显示
  286. columns.push({
  287. title: '操作',
  288. dataIndex: 'action',
  289. align: 'center',
  290. width: 150,
  291. })
  292. const selectedRowKeys = ref([])
  293. // 列表选择配置
  294. const options = {
  295. // columns数字类型字段加入 needTotal: true 可以勾选自动算账
  296. alert: {
  297. show: true,
  298. clear: () => {
  299. selectedRowKeys.value = ref([])
  300. }
  301. },
  302. rowSelection: {
  303. onChange: (selectedRowKey, selectedRows) => {
  304. selectedRowKeys.value = selectedRowKey
  305. }
  306. }
  307. }
  308. const loadData = (parameter) => {
  309. const searchFormParam = cloneDeep(searchFormState.value)
  310. return bizAppointmentRecordApi.bizAppointmentRecordPage(Object.assign(parameter, searchFormParam)).then((data) => {
  311. return data
  312. })
  313. }
  314. // 重置
  315. const reset = () => {
  316. searchFormRef.value.resetFields()
  317. tableRef.value.refresh(true)
  318. }
  319. // 删除
  320. const deleteBizAppointmentRecord = (record) => {
  321. let params = [
  322. {
  323. id: record.id
  324. }
  325. ]
  326. bizAppointmentRecordApi.bizAppointmentRecordDelete(params).then(() => {
  327. tableRef.value.refresh(true)
  328. })
  329. }
  330. // 删除
  331. const deleteConfig = (record) => {
  332. Modal.confirm({
  333. title: '确定删除该数据吗?',
  334. icon: createVNode(ExclamationCircleOutlined),
  335. content: '',
  336. onOk() {
  337. submitLoading.value = true
  338. let params = [
  339. {
  340. id: record.id
  341. }
  342. ]
  343. bizAppointmentRecordApi
  344. .bizAppointmentRecordDelete(params)
  345. .then(() => {
  346. tableRef.value.refresh(true)
  347. })
  348. .finally(() => {
  349. submitLoading.value = false
  350. })
  351. },
  352. onCancel() {}
  353. })
  354. }
  355. // 批量删除
  356. const deleteBatchBizAppointmentRecord = (params) => {
  357. bizAppointmentRecordApi.bizAppointmentRecordDelete(params).then(() => {
  358. tableRef.value.clearRefreshSelected()
  359. })
  360. }
  361. //二维码
  362. const open = ref(false);
  363. const qrCodeUrl = ref({})
  364. const showModal = (record) => {
  365. nowRecord.value = record
  366. open.value = true;
  367. getQrCode(record)
  368. };
  369. const getQrCode = (record) => {
  370. //QRCode.toDataURL("id:"+record.id+"saleCode:"+record.saleCode, {
  371. let param = {
  372. id:record.id,
  373. licenseNumber:record.licenseNumber
  374. }
  375. QRCode.toDataURL(JSON.stringify(param), {
  376. errorCorrectionLevel: 'H',
  377. margin: 1,
  378. height: 206,
  379. width: 206,
  380. type: '10',
  381. scal: 177,
  382. color: {
  383. dark: '#000' // 二维码背景颜色
  384. },
  385. rendererOpts: {
  386. quality: 0.9
  387. }
  388. })
  389. .then((url) => {
  390. qrCodeUrl.value.codeUrl = url
  391. })
  392. .catch((err) => {
  393. console.error(err)
  394. })
  395. }
  396. const closeQrCode = () => {
  397. open.value = false;
  398. }
  399. // 下载二维码
  400. const downloadFile = () => {
  401. const qrcodeDiv = document.getElementById('qrcode');
  402. html2canvas(qrcodeDiv, {
  403. logging: false,
  404. allowTaint: true,
  405. scale: window.devicePixelRatio,
  406. scrollY: 0,
  407. scrollX: 0,
  408. useCORS: true,
  409. backgroundColor: '#ffffff'
  410. })
  411. .then(function (canvas) {
  412. const a = window.document.createElement('a')
  413. a.href = canvas.toDataURL('image/png')
  414. a.download = '二维码'
  415. a.click()
  416. this.$message.success('正在进行下载保存')
  417. })
  418. .catch((err) => {
  419. console.log(err)
  420. })
  421. }
  422. //导出
  423. const exportTotal = () => {
  424. const searchFormParam = cloneDeep(searchFormState.value)
  425. bizAppointmentRecordApi.exportRecord(Object.assign(searchFormParam)).then((res)=>{
  426. downloadUtil.resultDownload(res)
  427. })
  428. }
  429. </script>
  430. <style lang="less" scoped>
  431. /** 表头居中 */
  432. :deep .ant-table-thead > tr > th {
  433. text-align: center;
  434. }
  435. .time-list {
  436. -webkit-text-size-adjust: none;
  437. font-size: 13px;
  438. display: flex;
  439. flex-direction: column;
  440. p {
  441. white-space: nowrap;
  442. span {
  443. display: inline-block;
  444. font-weight: 600;
  445. height: 16px;
  446. line-height: 16px;
  447. border-radius: 5px;
  448. text-align: center;
  449. margin-right: 2px;
  450. padding: 0 5px;
  451. }
  452. .blueTag {
  453. color: #1890ff;
  454. background: rgba(24, 144, 255, 0.1);
  455. }
  456. .orangeTag {
  457. color: #ff7c18;
  458. background: rgba(24, 144, 255, 0.1);
  459. }
  460. .greenTag {
  461. color: rgb(82, 196, 26);
  462. background: rgba(82, 196, 26, 0.1);
  463. }
  464. .purpleTag {
  465. color: rgb(77, 26, 196);
  466. background: rgba(82, 196, 26, 0.1);
  467. }
  468. .showNum {
  469. display: inline-block;
  470. height: 16px;
  471. line-height: 16px;
  472. width: 45px;
  473. border-radius: 5px;
  474. text-align: center;
  475. margin-right: 2px;
  476. text-align: right;
  477. }
  478. }
  479. }
  480. </style>