index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. <template>
  2. <div class="create-farm">
  3. <custom-header name="创建农场"></custom-header
  4. ><!-- 地图 -->
  5. <div class="map-container" ref="mapContainer"></div>
  6. <div class="farm-content">
  7. <div class="farm-filter">
  8. <el-select
  9. v-model="locationVal"
  10. filterable
  11. remote
  12. reserve-keyword
  13. placeholder="搜索位置"
  14. :remote-method="remoteMethod"
  15. :loading="loading"
  16. @change="handleSearchRes"
  17. popper-class="location-search-popper"
  18. >
  19. <el-option
  20. v-for="(item, index) in locationOptions.list"
  21. :key="index"
  22. :label="item.title"
  23. :value="{ value: item.point, item }"
  24. >
  25. <span>{{ item.title }}</span>
  26. <span class="sub-title">{{ item.province }}{{ item.city }}{{ item.district }}</span>
  27. </el-option>
  28. </el-select>
  29. </div>
  30. <!-- 创建 -->
  31. <div class="create-wrap">
  32. <div class="create-box">
  33. <div class="box-content">
  34. <div class="create-title">
  35. <img class="title-icon" src="@/assets/img/home/create-icon.png" alt="" />
  36. 创建农场
  37. </div>
  38. <div class="create-content">
  39. <div class="create-from">
  40. <el-form
  41. ref="ruleFormRef"
  42. :model="ruleForm"
  43. :rules="rules"
  44. label-width="auto"
  45. class="demo-ruleForm"
  46. >
  47. <el-form-item label="农场位置" prop="position">
  48. <div class="position-wrap">
  49. <el-input
  50. placeholder="农场位置"
  51. readonly
  52. v-model="ruleForm.position"
  53. autocomplete="off"
  54. />
  55. <div class="draw-btn" @click="toSubPage">点击勾选地块</div>
  56. </div>
  57. </el-form-item>
  58. <el-form-item label="农场面积" prop="area">
  59. <el-input
  60. placeholder="勾选地块获得农场面积"
  61. v-model="ruleForm.area"
  62. autocomplete="off"
  63. />
  64. </el-form-item>
  65. <el-form-item label="种植作物" prop="period">
  66. <div class="select-wrap">
  67. <el-select v-model="ruleForm.type" placeholder="作物类型">
  68. <el-option label="荔枝" value="lichi" />
  69. <el-option label="龙眼" value="ly" />
  70. </el-select>
  71. <el-select
  72. v-model="ruleForm.period"
  73. placeholder="物候期"
  74. class="period-select"
  75. >
  76. <el-option label="秋梢期" value="秋梢期" />
  77. <el-option label="开花期" value="开花期" />
  78. <el-option label="膨果期" value="膨果期" />
  79. <el-option label="成熟期" value="成熟期" />
  80. </el-select>
  81. </div>
  82. </el-form-item>
  83. <el-form-item label="农场名称" prop="name">
  84. <el-input
  85. placeholder="请输入您的农场名称"
  86. v-model="ruleForm.name"
  87. autocomplete="off"
  88. />
  89. </el-form-item>
  90. </el-form>
  91. </div>
  92. <div class="create-btn">
  93. <div class="btn-item sencond-btn" @click="resetForm(ruleFormRef)">取消</div>
  94. <div class="btn-item primary-btn" @click="submitForm(ruleFormRef)">立即创建</div>
  95. </div>
  96. </div>
  97. </div>
  98. </div>
  99. </div>
  100. </div>
  101. </div>
  102. </template>
  103. <script setup>
  104. import customHeader from "@/components/customHeader.vue";
  105. import IndexMap from "./map/index.js";
  106. import { useRoute, useRouter } from "vue-router";
  107. import { onMounted, ref, reactive } from "vue";
  108. const route = useRoute();
  109. const router = useRouter();
  110. const indexMap = new IndexMap();
  111. const mapContainer = ref(null);
  112. onMounted(() => {
  113. indexMap.initMap("POINT (113.61702297075017 23.584863449735067)", mapContainer.value);
  114. });
  115. // 搜索
  116. const MAP_KEY = "CZLBZ-LJICQ-R4A5J-BN62X-YXCRJ-GNBUT";
  117. const locationVal = ref(null);
  118. const locationOptions = reactive({
  119. list: [],
  120. });
  121. const loading = ref(false);
  122. const remoteMethod = async (keyword) => {
  123. if (keyword) {
  124. locationOptions.list = [];
  125. loading.value = true;
  126. const params = {
  127. key: MAP_KEY,
  128. keyword,
  129. location: route.query.userLocation || "113.61702297075017,23.584863449735067",
  130. };
  131. await VE_API.old_mini_map.getCtiyList({ word: keyword }).then(({ data }) => {
  132. if (data && data.length) {
  133. data.forEach((item) => {
  134. item.point = item.location.lat + "," + item.location.lng;
  135. locationOptions.list.push(item);
  136. });
  137. }
  138. });
  139. VE_API.old_mini_map.search(params).then(({ data }) => {
  140. loading.value = false;
  141. data.forEach((item) => {
  142. item.point = item.location.lat + "," + item.location.lng;
  143. locationOptions.list.push(item);
  144. });
  145. });
  146. } else {
  147. locationOptions.list = [];
  148. }
  149. };
  150. const handleSearchRes = (v) => {
  151. const parts = v.value.split(",");
  152. const coordinateArray = [parseFloat(parts[1]), parseFloat(parts[0])];
  153. indexMap.setMapPosition(coordinateArray);
  154. ruleForm.position = v.item?.title || v.item?.address;
  155. };
  156. // 表单
  157. const ruleFormRef = ref(null);
  158. const ruleForm = reactive({
  159. position: "",
  160. area: "",
  161. type: "",
  162. period: "",
  163. name: "",
  164. });
  165. const rules = reactive({
  166. position: [{ required: true, message: "请选择农场位置", trigger: "blur" }],
  167. area: [{ required: true, message: "请勾选地块获得农场面积", trigger: "blur" }],
  168. type: [{ required: true, message: "请选择品类", trigger: "blur" }],
  169. period: [{ required: true, message: "请选择物候期", trigger: "blur" }],
  170. name: [{ required: true, message: "请输入您的农场名称", trigger: "blur" }],
  171. });
  172. const submitForm = (formEl) => {
  173. if (!formEl) return;
  174. formEl.validate((valid) => {
  175. if (valid) {
  176. console.log("submit!");
  177. } else {
  178. console.log("error submit!");
  179. }
  180. });
  181. };
  182. const resetForm = (formEl) => {
  183. if (!formEl) return;
  184. formEl.resetFields();
  185. router.go(-1)
  186. };
  187. function toSubPage() {
  188. router.push("/edit_map");
  189. }
  190. </script>
  191. <style lang="scss" scoped>
  192. .create-farm {
  193. position: relative;
  194. width: 100%;
  195. height: 100vh;
  196. overflow: hidden;
  197. .map-container {
  198. width: 100%;
  199. height: calc(100% - 240px);
  200. }
  201. .farm-content {
  202. position: absolute;
  203. top: 40px;
  204. left: 0;
  205. width: 100%;
  206. height: calc(100% - 40px);
  207. pointer-events: none;
  208. z-index: 2;
  209. }
  210. .farm-filter {
  211. pointer-events: all;
  212. margin: 12px;
  213. position: relative;
  214. background: rgba(0, 0, 0, 0.3);
  215. border-radius: 20px;
  216. border: 1px solid rgba(255, 255, 255, 0.4);
  217. &::before {
  218. content: "";
  219. position: absolute;
  220. left: 12px;
  221. top: 9px;
  222. width: 14px;
  223. height: 14px;
  224. background: url("@/assets/img/home/search.png") no-repeat center center / 100% 100%;
  225. }
  226. ::v-deep {
  227. .el-select__wrapper {
  228. background: none;
  229. box-shadow: none;
  230. padding-left: 34px;
  231. font-size: 12px;
  232. .el-select__selected-item,
  233. .el-select__placeholder,
  234. .el-select__input {
  235. color: rgba(255, 255, 255, 0.6);
  236. &.is-transparent {
  237. color: #ccc;
  238. font-size: 12px;
  239. }
  240. }
  241. }
  242. .el-select {
  243. transition: all 0.3s;
  244. .el-input.is-focus .el-input__wrapper {
  245. box-shadow: none !important;
  246. }
  247. }
  248. .el-input {
  249. .el-input__wrapper {
  250. background: none;
  251. box-shadow: none;
  252. padding-left: 18px;
  253. font-size: 11px;
  254. .el-input__inner {
  255. color: rgba(255, 255, 255, 0.6);
  256. }
  257. &.is-focus {
  258. .el-input__inner {
  259. color: #ccc;
  260. font-size: 11px;
  261. }
  262. }
  263. }
  264. }
  265. }
  266. }
  267. .create-wrap {
  268. position: absolute;
  269. bottom: 0px;
  270. left: 0;
  271. width: 100%;
  272. background: linear-gradient(180deg, transparent 0%, #f5f7fb 20%);
  273. }
  274. .create-box {
  275. pointer-events: all;
  276. margin: 0 12px 10px 12px;
  277. width: calc(100% - 24px);
  278. background: #e0f1fe;
  279. border-radius: 14px;
  280. .box-content {
  281. position: relative;
  282. &::after {
  283. position: absolute;
  284. right: 10px;
  285. top: 2px;
  286. content: "";
  287. width: 79px;
  288. height: 72px;
  289. background: url("@/assets/img/home/creat-bg.png") no-repeat center / 100% 100%;
  290. }
  291. }
  292. .create-title {
  293. display: flex;
  294. align-items: center;
  295. padding: 12px 6px 12px 12px;
  296. color: #0089f5;
  297. font-size: 18px;
  298. font-weight: bold;
  299. .title-icon {
  300. width: 18px;
  301. padding-right: 10px;
  302. }
  303. }
  304. .create-content {
  305. background: #fff;
  306. border-radius: 14px;
  307. padding: 12px;
  308. position: relative;
  309. z-index: 2;
  310. .create-from {
  311. .select-wrap {
  312. display: flex;
  313. // width: 86%;
  314. ::v-deep {
  315. .el-input__wrapper {
  316. background: none;
  317. box-shadow: none;
  318. }
  319. .el-input__inner {
  320. font-size: 14px;
  321. color: rgba(0, 0, 0, 0.5);
  322. }
  323. .el-select__wrapper {
  324. background: none;
  325. box-shadow: none;
  326. gap: 2px;
  327. padding: 4px 2px;
  328. justify-content: center;
  329. }
  330. .el-select__selection {
  331. flex: none;
  332. width: fit-content;
  333. }
  334. .el-select__placeholder {
  335. color: #000;
  336. position: static;
  337. transform: none;
  338. width: fit-content;
  339. }
  340. }
  341. // .select-item {
  342. // width: fit-content;
  343. // }
  344. .period-select {
  345. margin-left: 16px;
  346. }
  347. }
  348. ::v-deep {
  349. .el-form-item__label {
  350. color: #000;
  351. }
  352. .el-form-item__error {
  353. top: 117%;
  354. }
  355. .el-form-item {
  356. position: relative;
  357. &::after {
  358. content: "";
  359. position: absolute;
  360. left: 60px;
  361. bottom: -5px;
  362. width: calc(100% - 60px);
  363. height: 1px;
  364. background: rgba(0, 0, 0, 0.08);
  365. }
  366. }
  367. .el-input__wrapper {
  368. box-shadow: none;
  369. // border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  370. }
  371. }
  372. .position-wrap {
  373. display: flex;
  374. justify-content: space-between;
  375. align-items: center;
  376. .draw-btn {
  377. flex: none;
  378. padding: 0 12px;
  379. height: 30px;
  380. line-height: 30px;
  381. box-sizing: border-box;
  382. color: #2199f8;
  383. border: 1px solid #2199f8;
  384. background: rgba(33, 153, 248, 0.1);
  385. border-radius: 20px;
  386. font-size: 12px;
  387. }
  388. }
  389. }
  390. .create-btn {
  391. display: flex;
  392. align-items: center;
  393. width: 100%;
  394. padding-top: 10px;
  395. .btn-item {
  396. flex: 1;
  397. text-align: center;
  398. padding: 0 11px;
  399. height: 40px;
  400. line-height: 40px;
  401. border-radius: 34px;
  402. font-size: 16px;
  403. box-sizing: border-box;
  404. &.sencond-btn {
  405. border: 1px solid rgba(153, 153, 153, 0.5);
  406. color: #666666;
  407. }
  408. &.primary-btn {
  409. background: linear-gradient(180deg, #76c3ff, #2199f8);
  410. color: #fff;
  411. }
  412. }
  413. .btn-item + .btn-item {
  414. margin-left: 5px;
  415. }
  416. }
  417. }
  418. }
  419. }
  420. </style>
  421. <style lang="scss">
  422. .location-search-popper {
  423. .el-select-dropdown__list {
  424. max-width: 96vw;
  425. overflow-x: auto;
  426. }
  427. .sub-title {
  428. padding-left: 6px;
  429. font-size: 12px;
  430. color: #ccc;
  431. }
  432. }
  433. </style>