station.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. <template>
  2. <div class="hc-layout-box">
  3. <HcNewCard>
  4. <template #header>
  5. <HcTooltip keys="gauge-station-add">
  6. <el-button hc-btn type="primary" @click="AddRowClick">
  7. <HcIcon name="add-box" />
  8. <span>新增</span>
  9. </el-button>
  10. </HcTooltip>
  11. <HcTooltip keys="gauge-station-import">
  12. <el-button hc-btn @click="importModalClick">
  13. <HcIcon name="upload-cloud" />
  14. <span>导入</span>
  15. </el-button>
  16. </HcTooltip>
  17. <HcTooltip keys="gauge-station-export">
  18. <el-button :loading="downloadLoading" hc-btn @click="exportModalClick">
  19. <HcIcon name="download" />
  20. <span>导出</span>
  21. </el-button>
  22. </HcTooltip>
  23. <div class="w-60 ml-6">
  24. <el-input v-model="searchForm.name" clearable placeholder="请输入测站点或关键字进行搜索" @keyup="keyUpEvent" />
  25. </div>
  26. <div class="ml-2">
  27. <el-button type="primary" @click="searchClick">
  28. <HcIcon name="search-2" />
  29. <span>搜索</span>
  30. </el-button>
  31. </div>
  32. </template>
  33. <template #extra>
  34. <HcNewSwitch :datas="tabsTypeData" size="default" :keys="tabsTypeKey" @change="tabsTypeChange" />
  35. </template>
  36. <HcTable v-if="tabsTypeKey === '0'" :column="levelTableColumn" :datas="levelTable" :loading="tableLoading" is-new :index-style="{ width: 60 }">
  37. <template #action="{ row }">
  38. <HcTooltip keys="gauge-station-edit">
  39. <el-button size="small" text type="primary" @click="handleLevelEdit(row)">编辑</el-button>
  40. </HcTooltip>
  41. <HcTooltip keys="gauge-station-del">
  42. <el-button v-del-com:[handleLevelDelete]="row" size="small" text type="danger">删除</el-button>
  43. </HcTooltip>
  44. </template>
  45. </HcTable>
  46. <HcTable v-if="tabsTypeKey === '1'" :column="traverseTableColumn" :datas="traverseTable" :loading="tableLoading" is-new :index-style="{ width: 60 }">
  47. <template #action="{ row }">
  48. <HcTooltip keys="gauge-station-edit">
  49. <el-button size="small" text type="primary" @click="handleTraverseEdit(row)">编辑</el-button>
  50. </HcTooltip>
  51. <HcTooltip keys="gauge-station-del">
  52. <el-button v-del-com:[handleTraverseDelete]="row" size="small" text type="danger">删除</el-button>
  53. </HcTooltip>
  54. </template>
  55. </HcTable>
  56. <template #action>
  57. <HcPages :pages="searchForm" @change="pageChange" />
  58. </template>
  59. </HcNewCard>
  60. <!-- 新增/编辑 弹框 -->
  61. <hc-new-dialog v-model="showRowModal" :title="`${formRowValue?.id ? '编辑' : '新增'}${tabsTypeKey === '1' ? '导线点' : '水准点'}`" widths="47rem">
  62. <el-form ref="formRowRef" :model="formRowValue" :rules="rulesRow" label-width="auto" size="large">
  63. <el-form-item label="点名称" prop="name">
  64. <el-input v-model="formRowValue.name" placeholder="请输入点名称" />
  65. </el-form-item>
  66. <el-form-item v-if="tabsTypeKey === '1'" label="X坐标(m)" prop="x">
  67. <el-input v-model="formRowValue.x" placeholder="请输入X坐标(m)" />
  68. </el-form-item>
  69. <el-form-item v-if="tabsTypeKey === '1'" label="Y坐标(m)" prop="y">
  70. <el-input v-model="formRowValue.y" placeholder="请输入Y坐标(m)" />
  71. </el-form-item>
  72. <el-form-item label="高程(m)" prop="h">
  73. <el-input v-model="formRowValue.h" placeholder="请输入高程(m)" />
  74. </el-form-item>
  75. <el-form-item label="等级">
  76. <el-select v-model="formRowValue.level" block>
  77. <el-option v-for="(item, index) in personData" :key="index" :label="item.label" :value="item.value" placeholder="请选择等级" />
  78. </el-select>
  79. </el-form-item>
  80. <el-form-item label="里程" prop="milestone">
  81. <el-input v-model="formRowValue.milestone" placeholder="请输入对应的设计里程" />
  82. </el-form-item>
  83. <el-form-item label="备注">
  84. <el-input v-model="formRowValue.remark" :autosize="{ minRows: 3, maxRows: 5 }" placeholder="请输入文字说明" type="textarea" />
  85. </el-form-item>
  86. </el-form>
  87. <template #footer>
  88. <div class="dialog-footer">
  89. <el-button size="large" @click="showRowModal = false">取消</el-button>
  90. <el-button :loading="saveFormLoading" hc-btn type="primary" @click="saveFormClick">提交</el-button>
  91. </div>
  92. </template>
  93. </hc-new-dialog>
  94. <!-- 导入 弹框 -->
  95. <hc-new-dialog v-model="showImportModal" :title="`导入${tabsTypeKey === '1' ? '导线点' : '水准点'}`" widths="47rem">
  96. <div class="hc-import-modal-box">
  97. <div class="tip-box">
  98. <span>请先下载导入模板(</span>
  99. <a
  100. v-if="tabsTypeKey === '1'"
  101. class="text-link"
  102. href="https://bladex-chongqing-info.oss-cn-hangzhou.aliyuncs.com//upload/20230821/d9ac14618c04b91b03c5746a24867e54.xlsx"
  103. target="_blank"
  104. >导线点导入模板</a>
  105. <a
  106. v-if="tabsTypeKey === '0'"
  107. class="text-link"
  108. href="https://bladex-chongqing-info.oss-cn-hangzhou.aliyuncs.com//upload/20230821/cdc62c130027dafa575dfb478cedba61.xlsx"
  109. target="_blank"
  110. >水准点导入模板</a>
  111. <span> ),按模板样式编辑测站点后,再点击"选择文件"按钮选择编辑好的文件,并点击底部的"确认导入"按钮即可导入成功!</span>
  112. </div>
  113. <div class="upload-box">
  114. <el-upload
  115. ref="uploadRef" v-model:file-list="fileList" :accept="accept" :action="action"
  116. :auto-upload="false" :data="addition" :headers="getHeader()" :limit="1"
  117. :on-error="handleUploadError" :on-exceed="handleUploadExceed"
  118. :on-progress="handleUploadProgress" :on-success="handleUploadFinish"
  119. >
  120. <template #trigger>
  121. <el-button :loading="importLoading" type="primary">选择文件</el-button>
  122. </template>
  123. </el-upload>
  124. </div>
  125. <div class="text-orange">导入模板格式示例:</div>
  126. <div v-if="tabsTypeKey === '1'" class="demo-img-box">
  127. <img alt="" src="../../assets/view/152221@2x.png">
  128. </div>
  129. <div v-if="tabsTypeKey === '0'" class="demo-img-box">
  130. <img alt="" src="../../assets/view/152211@2x.png">
  131. </div>
  132. </div>
  133. <template #footer>
  134. <div class="dialog-footer">
  135. <el-button size="large" @click="showImportModal = false">取消</el-button>
  136. <el-button
  137. :disabled="fileList.length <= 0" :loading="importLoading" hc-btn type="primary"
  138. @click="handleImportClick"
  139. >
  140. 确认导入
  141. </el-button>
  142. </div>
  143. </template>
  144. </hc-new-dialog>
  145. </div>
  146. </template>
  147. <script setup>
  148. import { onMounted, ref } from 'vue'
  149. import { useRoute, useRouter } from 'vue-router'
  150. import { useAppStore } from '~src/store'
  151. import stationApi from '~api/gauge/station'
  152. import { getHeader } from 'hc-vue3-ui'
  153. import { genFileId } from 'element-plus'
  154. import { downloadBlob, formValidate, getArrValue } from 'js-fast-way'
  155. //初始变量
  156. const router = useRouter()
  157. const useRoutes = useRoute()
  158. const useAppState = useAppStore()
  159. //路由参数
  160. const routerQuery = useRoutes?.query
  161. const typeName = routerQuery?.type || '0'
  162. //全局变量
  163. const projectId = ref(useAppState.getProjectId)
  164. const contractId = ref(useAppState.getContractId)
  165. //类型tab数据和相关处理
  166. const tabsTypeKey = ref(typeName)
  167. const tabsTypeData = ref([
  168. { key: '0', name: '水准点' },
  169. { key: '1', name: '导线点' },
  170. ])
  171. const tabsTypeChange = (item) => {
  172. tabsTypeKey.value = item?.key
  173. searchForm.value.type = item?.key
  174. searchForm.value.current = 1
  175. getTableData()
  176. //路由跳转
  177. router.push({
  178. path: useRoutes.path,
  179. query: {
  180. type: item?.key,
  181. },
  182. })
  183. }
  184. //渲染完成
  185. onMounted(() => {
  186. searchForm.value.type = typeName
  187. getTableData()
  188. })
  189. //搜索表单
  190. const searchForm = ref({
  191. projectId: projectId.value, contractId: contractId.value, name: null, type: '0',
  192. current: 1, size: 20, total: 0,
  193. })
  194. //回车搜索
  195. const keyUpEvent = (e) => {
  196. if (e.key === 'Enter') {
  197. searchForm.value.current = 1
  198. getTableData()
  199. }
  200. }
  201. //重新搜索数据
  202. const searchClick = () => {
  203. searchForm.value.current = 1
  204. getTableData()
  205. }
  206. //分页被点击
  207. const pageChange = ({ current, size }) => {
  208. searchForm.value.current = current
  209. searchForm.value.size = size
  210. getTableData()
  211. }
  212. //导线点
  213. const traverseTableColumn = ref([
  214. { key: 'name', name: '测站点名称' },
  215. { key: 'x', name: 'X坐标(m)' },
  216. { key: 'y', name: 'Y坐标(m)' },
  217. { key: 'h', name: '高程(m)' },
  218. { key: 'level', name: '等级' },
  219. { key: 'milestone', name: '里程' },
  220. { key: 'remark', name: '备注' },
  221. { key: 'action', name: '操作', width: '130' },
  222. ])
  223. const traverseTable = ref([])
  224. //水准点
  225. const levelTableColumn = ref([
  226. { key: 'name', name: '测站点名称' },
  227. { key: 'h', name: '高程(m)' },
  228. { key: 'level', name: '等级' },
  229. { key: 'milestone', name: '里程' },
  230. { key: 'remark', name: '备注' },
  231. { key: 'action', name: '操作', width: '130' },
  232. ])
  233. const levelTable = ref([])
  234. //获取数据
  235. const tableLoading = ref(false)
  236. const getTableData = async () => {
  237. tableLoading.value = true
  238. const { error, code, data } = await stationApi.queryListData({
  239. projectId: projectId.value,
  240. contractId: contractId.value,
  241. ...searchForm.value,
  242. })
  243. //处理数据
  244. tableLoading.value = false
  245. if (!error && code === 200) {
  246. let records = getArrValue(data['records'])
  247. if (tabsTypeKey.value === '0') {
  248. levelTable.value = records
  249. } else if (tabsTypeKey.value === '1') {
  250. traverseTable.value = records
  251. }
  252. searchForm.value.total = data.total || 0
  253. } else {
  254. levelTable.value = []
  255. traverseTable.value = []
  256. searchForm.value.total = 0
  257. }
  258. }
  259. //等级
  260. const personData = ref([
  261. { label: '一级', value: '一级' }, { label: '二级', value: '二级' },
  262. { label: '三级', value: '三级' }, { label: '四级', value: '四级' },
  263. ])
  264. //新增 / 编辑 配置
  265. const showRowModal = ref(false)
  266. const formRowRef = ref(null)
  267. const formRowValue = ref({ name: '', x: '', y: '', h: '', level: null, remark: null })
  268. const rulesRow = {
  269. name: {
  270. required: true,
  271. trigger: 'blur',
  272. message: '请输入测站点名称',
  273. },
  274. x: {
  275. required: true,
  276. trigger: 'blur',
  277. message: '请输入X坐标(m)',
  278. },
  279. y: {
  280. required: true,
  281. trigger: 'blur',
  282. message: '请输入Y坐标(m)',
  283. },
  284. h: {
  285. required: true,
  286. trigger: 'blur',
  287. message: '请输入高程(m)',
  288. },
  289. }
  290. //新增
  291. const AddRowClick = () => {
  292. const type = tabsTypeKey.value
  293. const obj = {
  294. projectId: projectId.value,
  295. contractId: contractId.value,
  296. type: tabsTypeKey.value,
  297. name: '', h: '', level: null, remark: null,
  298. }
  299. if (type === '0') {
  300. formRowValue.value = obj
  301. } else if (type === '1') {
  302. formRowValue.value = { ...obj, x: '', y: '' }
  303. }
  304. saveFormLoading.value = false
  305. showRowModal.value = true
  306. }
  307. //新增/编辑 保存
  308. const saveFormLoading = ref(false)
  309. const saveFormClick = async () => {
  310. const validate = await formValidate(formRowRef.value)
  311. if (validate) {
  312. const form = formRowValue.value
  313. if (form.id) {
  314. saveFormLoading.value = true
  315. const { error, code, msg } = await stationApi.updateSave(form, false)
  316. //判断状态
  317. saveFormLoading.value = false
  318. if (!error && code === 200) {
  319. showRowModal.value = false
  320. window?.$message?.success('保存成功')
  321. getTableData()
  322. } else {
  323. window?.$message?.error(msg || '操作失败')
  324. }
  325. } else {
  326. saveFormLoading.value = true
  327. const { error, code, msg } = await stationApi.addSave(form, false)
  328. //判断状态
  329. saveFormLoading.value = false
  330. if (!error && code === 200) {
  331. showRowModal.value = false
  332. window?.$message?.success('新增成功')
  333. getTableData()
  334. } else {
  335. window?.$message?.error(msg || '操作失败')
  336. }
  337. }
  338. }
  339. }
  340. //导入配置
  341. const showImportModal = ref(false)
  342. const importLoading = ref(false)
  343. //上传配置
  344. const uploadRef = ref(null)
  345. const addition = ref({})
  346. const fileList = ref([])
  347. const action = '/api/blade-business/dap/import'
  348. const accept = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel'
  349. //导入
  350. const importModalClick = () => {
  351. addition.value = {
  352. projectId: projectId.value,
  353. contractId: contractId.value,
  354. type: tabsTypeKey.value,
  355. }
  356. importLoading.value = false
  357. showImportModal.value = true
  358. }
  359. //上传一个文件时,重置
  360. const handleUploadExceed = (files) => {
  361. uploadRef.value?.clearFiles()
  362. const file = files[0]
  363. file.uid = genFileId()
  364. uploadRef.value?.handleStart(file)
  365. }
  366. //确认导入
  367. const handleImportClick = () => {
  368. uploadRef.value?.submit()
  369. }
  370. //上传中
  371. const handleUploadProgress = () => {
  372. importLoading.value = true
  373. }
  374. //上传完成
  375. const handleUploadFinish = () => {
  376. importLoading.value = false
  377. showImportModal.value = false
  378. window?.$message?.success('导入成功')
  379. uploadRef.value?.clearFiles()
  380. getTableData()
  381. }
  382. //上传失败
  383. const handleUploadError = () => {
  384. importLoading.value = false
  385. window?.$message?.error('导入失败')
  386. }
  387. //导出
  388. const exportModalClick = () => {
  389. window?.$messageBox?.alert('将导出当前所有数据?', '导出数据', {
  390. showCancelButton: true,
  391. confirmButtonText: '确定导出',
  392. cancelButtonText: '取消',
  393. callback: (action) => {
  394. if (action === 'confirm') {
  395. getExportExcel()
  396. }
  397. },
  398. })
  399. }
  400. //确定导出
  401. const downloadLoading = ref(false)
  402. const getExportExcel = async () => {
  403. //批量下载
  404. downloadLoading.value = true
  405. const { error, disposition, res } = await stationApi.getExportExcel({
  406. projectId: projectId.value,
  407. contractId: contractId.value,
  408. type: tabsTypeKey.value,
  409. search: searchForm.value['name'] || '',
  410. })
  411. //处理数据
  412. downloadLoading.value = false
  413. if (!error) {
  414. if (disposition) {
  415. downloadBlob(res, disposition)
  416. } else {
  417. window.$message?.error('数据异常')
  418. }
  419. }
  420. }
  421. //水准点
  422. const handleLevelEdit = (row) => {
  423. formRowValue.value = {
  424. ...row,
  425. projectId: projectId.value,
  426. contractId: contractId.value,
  427. type: tabsTypeKey.value,
  428. }
  429. saveFormLoading.value = false
  430. showRowModal.value = true
  431. }
  432. const handleLevelDelete = async ({ item }, resolve) => {
  433. await delData(item.id)
  434. resolve()
  435. }
  436. //导线点
  437. const handleTraverseEdit = (row) => {
  438. formRowValue.value = {
  439. ...row,
  440. projectId: projectId.value,
  441. contractId: contractId.value,
  442. type: tabsTypeKey.value,
  443. }
  444. saveFormLoading.value = false
  445. showRowModal.value = true
  446. }
  447. const handleTraverseDelete = async ({ item }, resolve) => {
  448. await delData(item.id)
  449. resolve()
  450. }
  451. //删除请求
  452. const delData = async (id) => {
  453. const { error, code } = await stationApi.delData({ ids: id }, false)
  454. //判断状态
  455. if (!error && code === 200) {
  456. window?.$message?.success('删除成功')
  457. getTableData()
  458. } else {
  459. window?.$message?.error('删除失败')
  460. }
  461. }
  462. </script>
  463. <style lang="scss" scoped>
  464. @import '../../styles/gauge/station.scss';
  465. </style>