edit.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. <template>
  2. <div class="system-edit-dic-container">
  3. <el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '环路'" v-model="dialogVisible" width="950px">
  4. <el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="110px">
  5. <el-form-item label="环路名称" prop="name">
  6. <el-input v-model="ruleForm.name" placeholder="请输入环路名称" />
  7. </el-form-item>
  8. <el-form-item label="环路编号" prop="code">
  9. <el-input v-model="ruleForm.code" placeholder="请输入环路编号" />
  10. </el-form-item>
  11. <el-form-item label="所属换热站" prop="stationId">
  12. <el-tree-select
  13. v-model="ruleForm.stationId"
  14. :data="treeData"
  15. :props="{
  16. label: 'name',
  17. children: 'children'
  18. }"
  19. node-key="id"
  20. :clearable="true"
  21. check-strictly
  22. style="width: 100%;"
  23. :render-after-expand="true"
  24. />
  25. </el-form-item>
  26. <el-form-item label="环路类型" prop="loopTypes">
  27. <el-select v-model="ruleForm.loopTypes" placeholder="请选择环路类型" clearable size="default" style="width: 100%">
  28. <el-option label="一网" :value="1" />
  29. <el-option label="二网" :value="2" />
  30. </el-select>
  31. </el-form-item>
  32. <el-form-item label="节能类型" prop="energyTypes">
  33. <el-select v-model="ruleForm.energyTypes" placeholder="请选择节能类型" clearable size="default" style="width: 100%">
  34. <el-option label="节能" :value="1" />
  35. </el-select>
  36. </el-form-item>
  37. <el-row :gutter="10">
  38. <el-col :span="12">
  39. <el-form-item label="供暖对象" prop="heatingObject">
  40. <el-select v-model="ruleForm.heatingObject" placeholder="请选择供暖对象" clearable size="default" style="width: 100%">
  41. <el-option label="公建" :value="1" />
  42. <el-option label="居民" :value="2" />
  43. </el-select>
  44. </el-form-item>
  45. </el-col>
  46. <el-col :span="12">
  47. <el-form-item label="供暖类型" prop="heatingTypes">
  48. <el-select v-model="ruleForm.heatingTypes" placeholder="请选择供暖类型" clearable size="default" style="width: 100%">
  49. <el-option label="地暖" :value="1" />
  50. <el-option label="暖气片" :value="2" />
  51. </el-select>
  52. </el-form-item>
  53. </el-col>
  54. </el-row>
  55. <el-row :gutter="10">
  56. <el-col :span="12">
  57. <el-form-item label="供暖面积" prop="heatingArea">
  58. <el-input v-model="ruleForm.heatingArea" placeholder="请输入供暖面积" />
  59. </el-form-item>
  60. </el-col>
  61. <el-col :span="12">
  62. <el-form-item label="实际面积" prop="forRealArea">
  63. <el-input v-model="ruleForm.forRealArea" placeholder="请输入实际面积" />
  64. </el-form-item>
  65. </el-col>
  66. </el-row>
  67. <el-form-item label="环路年代" prop="decade">
  68. <el-input v-model="ruleForm.decade" placeholder="请输入环路年代" />
  69. </el-form-item>
  70. <el-form-item label="状态" prop="status">
  71. <el-radio v-model="ruleForm.status" :label="1">在线</el-radio>
  72. <el-radio v-model="ruleForm.status" :label="0">不在线</el-radio>
  73. </el-form-item>
  74. <!-- <el-form-item label="数据模型" prop="dataTemplateIds">
  75. <el-select v-model="ruleForm.dataTemplateIds" multiple clearable style="width: 100%;" placeholder="请选择">
  76. <el-option
  77. v-for="item in dataHubList"
  78. :key="item.id"
  79. :label="item.name"
  80. :value="item.id">
  81. </el-option>
  82. </el-select>
  83. </el-form-item> -->
  84. <el-form-item label="编辑路线信息" prop="">
  85. <div class="mb10">
  86. <el-button type="primary" @click="onAddPoint">添加途经点</el-button>
  87. </div>
  88. <div class="mb10" style="width: 100%">
  89. <div style="display: flex;" class="mb10" v-for="(item, index) in pointList" :key="index">
  90. <el-input v-model="item.position" :disabled="!item.editFalg" @change="onLocalChange(item, index)" placeholder="请输入关键字进行搜索" clearable style="flex: 1; margin-right: 10px"></el-input>
  91. <span>排序:</span>
  92. <el-input-number v-model="item.sort" :controls="false" :disabled="!item.editFalg" placeholder="排序" clearable style="width: 100px; margin-right: 10px"></el-input-number>
  93. <el-button type="primary" v-if="item.editFalg" @click="onSavePoint(item, index)">保存</el-button>
  94. <el-button type="primary" v-else @click="item.editFalg = true">修改</el-button>
  95. <el-button type="danger" @click="onRemovePoint(index)">删除</el-button>
  96. </div>
  97. </div>
  98. <div style="width: 100%; height: 300px" id="loop-map-container"></div>
  99. </el-form-item>
  100. </el-form>
  101. <template #footer>
  102. <span class="dialog-footer">
  103. <el-button @click="onCancel" size="default">取 消</el-button>
  104. <el-button type="primary" @click="onSubmit" size="default">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
  105. </span>
  106. </template>
  107. </el-dialog>
  108. </div>
  109. </template>
  110. <script lang="ts">
  111. import { reactive, toRefs, defineComponent, ref, unref, nextTick } from 'vue';
  112. import api from '/@/api/heatStation';
  113. import datahubApi from '/@/api/datahub';
  114. import { ElMessage } from 'element-plus';
  115. interface Point {
  116. sort?: number;
  117. lnt: number;
  118. lat: number
  119. }
  120. interface RuleFormState {
  121. id?: number;
  122. name: string;
  123. code: string;
  124. stationId: string;
  125. loopTypes: string;
  126. energyTypes: string;
  127. heatingObject: string;
  128. heatingTypes: string;
  129. heatingArea: string;
  130. forRealArea: string;
  131. viaPoint: Array<Point>;
  132. decade: string;
  133. status: number;
  134. }
  135. export default defineComponent({
  136. name: 'headStationLoop',
  137. setup(prop, { emit }) {
  138. const formRef = ref<HTMLElement | null>(null);
  139. const state = reactive({
  140. dialogVisible: false,
  141. ruleForm: {
  142. id: 0,
  143. name: '',
  144. code: '',
  145. stationId: '',
  146. loopTypes: '',
  147. energyTypes: '',
  148. heatingObject: '',
  149. heatingTypes: '',
  150. heatingArea: '',
  151. forRealArea: '',
  152. decade: '',
  153. viaPoint: [],
  154. status: 1
  155. },
  156. rules: {
  157. name: [{ required: true, message: '环路名称不能为空', trigger: ['blur', 'change'] }],
  158. code: [{ required: true, message: '环路编号不能为空', trigger: ['blur', 'change'] }],
  159. stationId: [{ required: true, message: '所属换热站不能为空', trigger: ['blur', 'change'] }],
  160. loopTypes: [{ required: true, message: '环路类型不能为空', trigger: ['blur', 'change'] }],
  161. energyTypes: [{ required: true, message: '节能类型不能为空', trigger: ['blur', 'change'] }],
  162. heatingObject: [{ required: true, message: '供暖对象不能为空', trigger: ['blur', 'change'] }],
  163. heatingTypes: [{ required: true, message: '供暖类型不能为空', trigger: ['blur', 'change'] }],
  164. heatingArea: [{ required: true, message: '供暖面积不能为空', trigger: ['blur', 'change'] }],
  165. forRealArea: [{ required: true, message: '实际面积不能为空', trigger: ['blur', 'change'] }],
  166. decade: [{ required: true, message: '年代不能为空', trigger: ['blur', 'change'] }],
  167. status: [{ required: true, message: '状态不能为空', trigger: ['blur', 'change'] }]
  168. },
  169. treeData: [],
  170. mapLocal: null as any, // 地图搜索
  171. pointList: [] as any,
  172. pointIndex: -1,
  173. dataHubList: []
  174. })
  175. // 打开弹窗
  176. const openDialog = (row: RuleFormState | null) => {
  177. resetForm()
  178. queryTree()
  179. // queryDataHubList()
  180. nextTick(() => {
  181. initMap()
  182. })
  183. if (row) {
  184. (state.ruleForm as any).id = row.id
  185. getDetail()
  186. }
  187. state.dialogVisible = true
  188. }
  189. const resetForm = () => {
  190. state.ruleForm = {
  191. id: 0,
  192. name: '',
  193. code: '',
  194. stationId: '',
  195. loopTypes: '',
  196. energyTypes: '',
  197. heatingObject: '',
  198. heatingTypes: '',
  199. heatingArea: '',
  200. forRealArea: '',
  201. viaPoint: [],
  202. decade: '',
  203. status: 1
  204. }
  205. }
  206. // 关闭弹窗
  207. const closeDialog = () => {
  208. state.dialogVisible = false
  209. state.pointList = [];
  210. (formRef.value as any).clearValidate()
  211. }
  212. // 取消
  213. const onCancel = () => {
  214. closeDialog()
  215. }
  216. const queryTree = () => {
  217. api.heatStation.getList({
  218. name: '',
  219. code: '',
  220. status: -1
  221. })
  222. .then((res: any) => {
  223. state.treeData = res || [];
  224. });
  225. };
  226. // const queryDataHubList = () => {
  227. // datahubApi.template.allList({})
  228. // .then((res: any) => {
  229. // state.dataHubList = res.list || [];
  230. // });
  231. // };
  232. const getDetail = () => {
  233. api.loop.detail(state.ruleForm.id)
  234. .then((res: any) => {
  235. state.ruleForm = {
  236. ...res
  237. }
  238. state.pointList = state.ruleForm.viaPoint.map((item: any) => ({
  239. ...item,
  240. editFlag: false
  241. }))
  242. })
  243. }
  244. // 新增
  245. const onSubmit = () => {
  246. const formWrap = unref(formRef) as any
  247. if (!formWrap) return;
  248. formWrap.validate((valid: boolean) => {
  249. if (valid) {
  250. if (!state.pointList.length) {
  251. ElMessage.warning('请选择途经点')
  252. return
  253. }
  254. for (let i = 0; i < state.pointList.length; i++) {
  255. let item = state.pointList[i]
  256. if (!item.lnt && !item.lat) {
  257. ElMessage.warning('途经点填错错误')
  258. return
  259. }
  260. }
  261. let params = { ...state.ruleForm }
  262. params.viaPoint = state.pointList.map((item: any, index: number) => ({
  263. sort: index + 1,
  264. lnt: item.lnt,
  265. lat: item.lat,
  266. position: item.position
  267. }))
  268. if (params.id) {
  269. //修改
  270. api.loop.edit(params).then(() => {
  271. ElMessage.success('环路修改成功')
  272. closeDialog() // 关闭弹窗
  273. emit('queryList')
  274. })
  275. } else {
  276. //添加
  277. api.loop.add(params).then(() => {
  278. ElMessage.success('环路添加成功')
  279. closeDialog() // 关闭弹窗
  280. emit('queryList')
  281. })
  282. }
  283. }
  284. })
  285. }
  286. // 新增途经点
  287. const onAddPoint = () => {
  288. state.pointList.push({
  289. sort: undefined,
  290. position: '',
  291. lnt: '',
  292. lat: '',
  293. editFalg: true
  294. })
  295. }
  296. // 保存途经点
  297. const onSavePoint = (item: any, index: number) => {
  298. item.editFalg = false
  299. }
  300. // 移除途经点
  301. const onRemovePoint = (index: number) => {
  302. state.pointList.splice(index, 1)
  303. }
  304. const initMap = () => {
  305. let BMapGL = (window as any).BMapGL
  306. let map = new BMapGL.Map("loop-map-container");
  307. // 116.404, 39.915
  308. let point = new BMapGL.Point(116.404, 39.915);
  309. let zoomCtrl = new BMapGL.ZoomControl(); // 添加缩放控件
  310. let cityCtrl = new BMapGL.CityListControl()
  311. map.centerAndZoom(point, 15);
  312. map.enableScrollWheelZoom(true); // 开启滚轮缩放
  313. map.addControl(zoomCtrl);
  314. map.addControl(cityCtrl);
  315. // if (state.ruleForm.lnt && state.ruleForm.lat) {
  316. // let marker = new BMapGL.Marker(new BMapGL.Point(state.ruleForm.lnt, state.ruleForm.lat));
  317. // // 在地图上添加点标记
  318. // map.addOverlay(marker);
  319. // }
  320. state.mapLocal = new BMapGL.LocalSearch(map, {
  321. renderOptions:{map: map}
  322. })
  323. console.log('map', map)
  324. map.addEventListener('click', (e: any) => {
  325. console.log('map--click', e)
  326. let point = e.latlng
  327. if (state.pointIndex > -1) {
  328. state.pointList[state.pointIndex].lnt = point.lng
  329. state.pointList[state.pointIndex].lat = point.lat
  330. let str = e.currentTarget.infoWindow.centerDiv.innerText
  331. let address = str.replace(/[^\s]+[\s\t\n]+([^\s\t\n]+)[\s\t\n]+.*/g, '$1')
  332. state.pointList[state.pointIndex].position = address
  333. }
  334. // state.ruleForm.lnt = point.lng
  335. // state.ruleForm.lat = point.lat
  336. // .replace(/[^\s]+[\s\t\n]+([^\s\t\n]+)[\s\t\n]+.*/g, '$1')
  337. })
  338. }
  339. const onLocalChange = (item: any, index: number) => {
  340. state.mapLocal.search(item.position)
  341. state.pointIndex = index
  342. }
  343. return {
  344. openDialog,
  345. closeDialog,
  346. onCancel,
  347. onSubmit,
  348. formRef,
  349. onLocalChange,
  350. onAddPoint,
  351. onRemovePoint,
  352. onSavePoint,
  353. ...toRefs(state)
  354. }
  355. }
  356. })
  357. </script>