interact.vue 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969
  1. <template>
  2. <div class="task-page" :style="{ height: `calc(100vh - ${tabBarHeight}px - 50px)` }">
  3. <div class="task-top">
  4. <div class="map-container" ref="mapContainer"></div>
  5. </div>
  6. <div class="task-list">
  7. <div class="list-filter">
  8. <div class="filter-item" :class="{ active: activeIndex === 0 }" @click="handleActiveFilter(0)">
  9. 待确认({{ taskCounts[0] || 0 }})
  10. </div>
  11. <!-- <div class="filter-item" :class="{ active: activeIndex === 1 }" @click="handleActiveFilter(1)">
  12. 已确认({{ taskCounts[1] || 0 }})
  13. </div> -->
  14. <div class="filter-item" :class="{ active: activeIndex === 2 }" @click="handleActiveFilter(2)">
  15. 已确认({{ taskCounts[2] || 0 }})
  16. </div>
  17. <div class="filter-item" :class="{ active: activeIndex === 3 }" @click="handleActiveFilter(3)">
  18. 待提醒({{ taskCounts[3] || 0 }})
  19. </div>
  20. </div>
  21. <div class="select-group">
  22. <el-select
  23. class="select-item"
  24. v-model="selectParma.farmWorkTypeId"
  25. placeholder="用户类型"
  26. @change="getSimpleList"
  27. >
  28. <el-option v-for="item in farmWorkTypeList" :key="item.id" :label="item.name" :value="item.id" />
  29. </el-select>
  30. <el-select
  31. class="select-item"
  32. v-model="selectParma.districtCode"
  33. placeholder="切换作物"
  34. @change="getSimpleList"
  35. >
  36. <el-option v-for="item in districtList" :key="item.code" :label="item.name" :value="item.code" />
  37. </el-select>
  38. </div>
  39. <!-- <div class="task-content-loading" v-if="loading && noData" v-loading="loading">
  40. </div> -->
  41. <div class="task-content" v-loading="loading">
  42. <div class="task-item" v-for="(item, index) in taskList" :key="index">
  43. <div class="img-text-wrap">
  44. <div class="left-wrap">
  45. <div class="left-img">
  46. <img src="@/assets/img/home/farm.png" alt="" />
  47. </div>
  48. <div class="right-text">
  49. <div class="farm-info">
  50. {{ item?.farmName }}
  51. <div class="info-tag-wrap">
  52. <div class="tag-item primary">
  53. {{ item?.typeName }}
  54. </div>
  55. <div class="tag-item second">托管客户</div>
  56. </div>
  57. </div>
  58. <div class="farm-addr">{{ item?.address }}</div>
  59. </div>
  60. </div>
  61. <div class="right-wrap">提醒客户</div>
  62. </div>
  63. <div class="item-bottom">
  64. <div class="bottom-tag">
  65. <div class="tag-card active">
  66. <div class="card-content">
  67. <div class="card-main-text">花芽分化</div>
  68. <div class="card-sub-text">
  69. 当前物候期
  70. <span class="card-icon" @click="handleSelectCurrentPhenology(item)">
  71. <el-icon><Edit /></el-icon>
  72. </span>
  73. </div>
  74. </div>
  75. </div>
  76. <div class="tag-card">
  77. <div class="card-content">
  78. <div class="card-main-text">蒂蛀虫</div>
  79. <div class="card-sub-text">预计风险</div>
  80. </div>
  81. </div>
  82. <div class="tag-card">
  83. <div class="card-content">
  84. <div class="card-main-text">5天</div>
  85. <div class="card-sub-text">预计下次物候</div>
  86. </div>
  87. </div>
  88. </div>
  89. <div class="timeline">
  90. <div class="timeline-item" v-for="item in timelineList" :key="item.id">
  91. <div class="timeline-left">
  92. <div class="dot"></div>
  93. <div class="line"></div>
  94. </div>
  95. <div class="timeline-right">
  96. <div class="date">预计{{ item.date }}天后触发<span class="work-name">{{ item.workName }}</span></div>
  97. <div class="text">
  98. 预计报价<span class="price">{{ item.price }}元</span>
  99. <span class="action-detail">查看报价单</span>
  100. </div>
  101. </div>
  102. <div class="timeline-action" @click="handleTimelineAction(item)">转入农事任务</div>
  103. </div>
  104. </div>
  105. </div>
  106. </div>
  107. <div class="empty-data" v-if="noData">暂无数据</div>
  108. </div>
  109. </div>
  110. </div>
  111. <upload-execute ref="uploadExecuteRef" :onlyShare="onlyShare" @uploadSuccess="handleUploadSuccess" />
  112. <popup v-model:show="showTaskPopup" round class="task-tips-popup">
  113. <template v-if="taskPopupType === 'warning'">
  114. <img class="create-farm-icon" src="@/assets/img/home/create-farm-icon.png" alt="" />
  115. <div class="create-farm-text">
  116. <div>
  117. 您确认忽略 <span class="main-text">{{ currentTask?.farmName }}</span> 的
  118. <span class="main-text">{{ currentTask?.farmWorkName }}</span> 农事吗
  119. </div>
  120. </div>
  121. </template>
  122. <template v-else>
  123. <img class="farm-check-icon" src="@/assets/img/home/right.png" alt="" />
  124. <div class="create-farm-text success-text">农事已下发成功</div>
  125. </template>
  126. <div class="create-farm-btn" @click="handlePopupBtn">
  127. {{ taskPopupType === "warning" ? "确认忽略" : "我知道了" }}
  128. </div>
  129. </popup>
  130. <!-- 服务报价单 -->
  131. <price-sheet-popup :key="activeIndex" ref="priceSheetPopupRef"></price-sheet-popup>
  132. <!-- 新增:激活上传弹窗 -->
  133. <active-upload-popup ref="activeUploadPopupRef" @handleUploadSuccess="handleUploadSuccess"></active-upload-popup>
  134. </template>
  135. <script setup>
  136. import eventBus from "@/api/eventBus";
  137. import { computed, nextTick, onMounted, ref, watch } from "vue";
  138. import { useStore } from "vuex";
  139. import { Popup } from "vant";
  140. import IndexMap from "../../farm_manage/map/index";
  141. import { useRouter } from "vue-router";
  142. import uploadExecute from "./uploadExecute.vue";
  143. import priceSheetPopup from "@/components/popup/priceSheetPopup.vue";
  144. import { ElMessage } from "element-plus";
  145. import activeUploadPopup from "@/components/popup/activeUploadPopup.vue";
  146. const store = useStore();
  147. const router = useRouter();
  148. const indexMap = new IndexMap();
  149. const mapContainer = ref(null);
  150. const tabBarHeight = computed(() => store.state.home.tabBarHeight);
  151. const uploadExecuteRef = ref(null);
  152. const selectParma = ref({
  153. farmWorkTypeId: null,
  154. districtCode: null,
  155. });
  156. // 任务列表数据(用于显示,可能被筛选)
  157. const taskList = ref([]);
  158. // 各状态任务数量
  159. const taskCounts = ref([0, 0, 0]);
  160. // 当前选中的筛选索引
  161. const activeIndex = ref(0);
  162. const noData = ref(false);
  163. const loading = ref(false);
  164. const showTaskPopup = ref(false);
  165. const taskPopupType = ref("warning");
  166. // 根据 activeIndex 计算 startFlowStatus
  167. const getStartFlowStatus = (index) => {
  168. const statusMap = {
  169. 0: 0, // 待确认
  170. 1: "1,2,3", // 待完成
  171. 2: 4, // 待完成
  172. 3: 5, // 已完成
  173. };
  174. return statusMap[index] ?? 0;
  175. };
  176. const timelineList = ref([
  177. {
  178. date: "3",
  179. workName: "梢期杀虫",
  180. price: "1258"
  181. },
  182. {
  183. date: "5",
  184. workName: "梢期营养",
  185. price: "1758"
  186. },
  187. ])
  188. // 获取单个状态的任务数量
  189. function getTaskCount(flowStatus, index) {
  190. const location = store.state.home.miniUserLocationPoint;
  191. return VE_API.z_farm_work_record
  192. .getSimpleList({ role: 2, location, flowStatus })
  193. .then(({ data }) => {
  194. data = [
  195. ...data,
  196. {
  197. address: "深圳世界之窗",
  198. executeDate: "2025-12-29",
  199. executeEvidence: "",
  200. farmArea: "40.100412863459745",
  201. farmId: 93651,
  202. farmMiniUserId: 91344,
  203. farmMiniUserName: "舒浩农资",
  204. farmName: "世界之窗荔枝农场",
  205. farmWorkArrangeId: null,
  206. farmWorkLibId: "756894717878210560",
  207. farmWorkName: "二梢营养",
  208. id: "276563",
  209. isFollow: null,
  210. isIgnored: 0,
  211. isPublic: 0,
  212. orderId: "778920749103583232",
  213. point: "POINT(113.96804666992188 22.537601205078126)",
  214. quoteCount: "0",
  215. typeId: "2",
  216. typeName: "糯米糍",
  217. },
  218. {
  219. address: "汕尾市海丰县赤坑镇S241妙荔现代农业园",
  220. executeDate: "2025-12-27",
  221. executeEvidence: "",
  222. farmArea: "",
  223. farmId: 43318,
  224. farmMiniUserId: 81818,
  225. farmMiniUserName: "",
  226. farmName: "汕尾妙荔果园",
  227. farmWorkArrangeId: null,
  228. farmWorkLibId: "708734452137725956",
  229. farmWorkName: "杀梢",
  230. id: "277160",
  231. isFollow: null,
  232. isIgnored: 0,
  233. isPublic: 0,
  234. orderId: "781556915820826624",
  235. point: "POINT(115.455766 22.883073)",
  236. quoteCount: "0",
  237. typeId: "4",
  238. typeName: "仙进奉",
  239. },
  240. ];
  241. if (Array.isArray(data)) {
  242. taskCounts.value[index] = data.length;
  243. if (index === 2) {
  244. indexMap.initData(data);
  245. }
  246. } else if (data?.total !== undefined) {
  247. taskCounts.value[index] = data.total;
  248. } else {
  249. taskCounts.value[index] = 0;
  250. }
  251. })
  252. .catch((error) => {
  253. console.error(`获取状态${index}任务数量失败:`, error);
  254. taskCounts.value[index] = 0;
  255. });
  256. }
  257. const taskItemRefs = ref([]);
  258. const setTaskItemRef = (el, index) => {
  259. if (el) {
  260. taskItemRefs.value[index] = el;
  261. }
  262. };
  263. const handleUploadSuccess = async () => {
  264. // 先保存当前需要更新的 item id
  265. const currentItemIds = taskList.value.map((item) => item.id || item.workRecordId);
  266. // 刷新列表
  267. await getSimpleList();
  268. // 等待 DOM 更新完成,refs 被重新收集
  269. await nextTick();
  270. // 更新所有task-item的triggerImg
  271. taskItemRefs.value.forEach((ref) => {
  272. if (ref && ref.updateTriggerImg) {
  273. ref.updateTriggerImg();
  274. }
  275. });
  276. };
  277. const cityCode = ref("");
  278. //根据城市的坐标返回区县列表
  279. const districtList = ref([]);
  280. function getDistrictListByCity() {
  281. VE_API.z_farm_work_record.getDistrictListByCity({ point: mapPoint.value }).then(({ data }) => {
  282. districtList.value = data || [];
  283. // cityCode.value = data[0].code.slice(0, -2);
  284. cityCode.value = "";
  285. districtList.value.unshift({ code: cityCode.value, name: "全部" });
  286. selectParma.value.districtCode = cityCode.value;
  287. getSimpleList();
  288. });
  289. }
  290. //农事类型列表
  291. const farmWorkTypeList = ref([]);
  292. function getFarmWorkTypeList() {
  293. VE_API.z_farm_work_record.getFarmWorkTypeList().then(({ data }) => {
  294. farmWorkTypeList.value = data;
  295. farmWorkTypeList.value.unshift({ id: 0, name: "全部" });
  296. });
  297. }
  298. // 初始化时获取所有状态的任务数量
  299. function initTaskCounts() {
  300. const location = store.state.home.miniUserLocationPoint;
  301. // 并行请求三个状态的数量
  302. Promise.all([
  303. getTaskCount(0, 0), // 待确认
  304. getTaskCount("1,2,3", 1), // 待确认
  305. getTaskCount(4, 2), // 待完成
  306. getTaskCount(5, 3), // 已完成
  307. ]);
  308. }
  309. const mapPoint = ref(null);
  310. onMounted(() => {
  311. mapPoint.value = store.state.home.miniUserLocationPoint;
  312. // 初始化时获取所有状态的数量
  313. initTaskCounts();
  314. // 加载当前选中状态的数据列表
  315. getSimpleList();
  316. getDistrictListByCity();
  317. getFarmWorkTypeList();
  318. nextTick(() => {
  319. indexMap.initMap(mapPoint.value, mapContainer.value, true);
  320. });
  321. });
  322. // 监听 activeIndex 变化,重新加载数据
  323. watch(activeIndex, () => {
  324. getSimpleList();
  325. });
  326. function getSimpleList() {
  327. loading.value = true;
  328. noData.value = false;
  329. // 清空refs数组,避免索引错乱
  330. taskItemRefs.value = [];
  331. const startFlowStatus = getStartFlowStatus(activeIndex.value);
  332. const params = {
  333. ...selectParma.value,
  334. role: 2,
  335. location: mapPoint.value,
  336. flowStatus: startFlowStatus,
  337. farmWorkTypeId: selectParma.value.farmWorkTypeId || null,
  338. };
  339. return VE_API.z_farm_work_record
  340. .getSimpleList(params)
  341. .then(({ data }) => {
  342. loading.value = false;
  343. // 假设返回的数据结构是 { list: [], total: 0 } 或者直接是数组
  344. let filteredData = data;
  345. // 如果是"待确认"状态,过滤掉 isIgnored 为 1 的数据
  346. if (activeIndex.value === 0 && Array.isArray(data)) {
  347. filteredData = data.filter((item) => item.isIgnored !== 1);
  348. }
  349. if (Array.isArray(filteredData) && filteredData.length > 0) {
  350. taskList.value = filteredData;
  351. // 更新当前状态的数量
  352. taskCounts.value[activeIndex.value] = filteredData.length;
  353. if (activeIndex.value === 2) {
  354. // 地图使用筛选后的数据
  355. indexMap.initData(taskList.value);
  356. }
  357. } else {
  358. noData.value = true;
  359. taskList.value = [];
  360. taskCounts.value[activeIndex.value] = 0;
  361. }
  362. })
  363. .catch((error) => {
  364. console.error("获取任务列表失败:", error);
  365. loading.value = false;
  366. taskList.value = [];
  367. taskCounts.value[activeIndex.value] = 0;
  368. if (activeIndex.value === 2) {
  369. indexMap.initData(taskList.value);
  370. }
  371. noData.value = true;
  372. });
  373. }
  374. function handleActiveFilter(i) {
  375. activeIndex.value = i;
  376. selectParma.value.districtCode = cityCode.value;
  377. selectParma.value.farmWorkTypeId = null;
  378. }
  379. function toPage(item) {
  380. // router.push("/servicZes_agri")
  381. // if (activeIndex.value === 2) {
  382. // } else {
  383. // // 下发农事请求
  384. // const data = {
  385. // id: item.id,
  386. // };
  387. // VE_API.z_farm_work_record.issueFarmWorkRecord(data).then((res) => {
  388. // if (res.code === 0) {
  389. // taskPopupType.value = "success";
  390. // showTaskPopup.value = true;
  391. // getSimpleList();
  392. // }
  393. // });
  394. // }
  395. }
  396. const showUploadExecutePopup = (item) => {
  397. if (item?.executeEvidence.length) {
  398. onlyShare.value = true;
  399. } else {
  400. onlyShare.value = false;
  401. }
  402. setTimeout(() => {
  403. uploadExecuteRef.value.showPopup(item);
  404. }, 10);
  405. };
  406. function toDetail(item) {
  407. if (activeIndex.value === 0) {
  408. router.push({
  409. path: "/modify_work",
  410. query: { id: item.id },
  411. });
  412. } else {
  413. router.push({
  414. path: "/completed_work",
  415. query: { miniJson: JSON.stringify({ id: item.id }) },
  416. });
  417. }
  418. }
  419. const priceSheetPopupRef = ref(null);
  420. const showPriceSheetPopup = (item) => {
  421. VE_API.z_farm_work_record.getDetail({ id: item.id }).then(({ data }) => {
  422. const res = data[0];
  423. priceSheetPopupRef.value.handleShowPopup(res);
  424. });
  425. };
  426. const onlyShare = ref(false);
  427. const currentTask = ref(null);
  428. function handleAction(item) {
  429. if (activeIndex.value === 0) {
  430. taskPopupType.value = "warning";
  431. showTaskPopup.value = true;
  432. currentTask.value = item;
  433. } else {
  434. onlyShare.value = true;
  435. setTimeout(() => {
  436. uploadExecuteRef.value.showPopup(item, "share-sheet");
  437. }, 10);
  438. }
  439. }
  440. function handlePopupBtn() {
  441. showTaskPopup.value = false;
  442. if (taskPopupType.value === "warning") {
  443. // 确认忽略
  444. VE_API.z_farm_work_record.ignoreFarmWorkRecord({ farmWorkRecordId: currentTask.value.id }).then((res) => {
  445. if (res.code === 0) {
  446. ElMessage.success("操作成功");
  447. getSimpleList();
  448. }
  449. });
  450. }
  451. }
  452. function handleForward(item) {
  453. if (item.quoteCount && item.quoteCount != 0) {
  454. onlyShare.value = true;
  455. setTimeout(() => {
  456. uploadExecuteRef.value.showPopup(
  457. { ...item, type: "quotation", farmWorkOrderId: item.orderId },
  458. "share-sheet"
  459. );
  460. }, 10);
  461. } else {
  462. ElMessage.warning("暂无报价数据,无法分享");
  463. return;
  464. }
  465. }
  466. const executorList = ref([{
  467. id: 1,
  468. name: "张三",
  469. phone: "13800138000",
  470. }, {
  471. id: 2,
  472. name: "李四",
  473. phone: "13800138001",
  474. }])
  475. function handleTimelineAction(item) {
  476. // activeUploadPopupRef.value.triggerFarmWork({
  477. // farmId: item.farmId,
  478. // workName: item.workName,
  479. // });
  480. eventBus.emit("activeUpload:show", {
  481. gardenIdVal: item.farmId,
  482. needExecutorVal: true,
  483. problemTitleVal: '请选择 ' + item.workName + ' 执行截止时间',
  484. imgDescVal: '请上传凭证(转入农事任务凭证)',
  485. arrangeIdVal: item.farmWorkArrangeId,
  486. executorListVal: executorList.value,
  487. });
  488. }
  489. const phenologyList = ref([{
  490. id: 1,
  491. name: "花芽分化",
  492. }, {
  493. id: 2,
  494. name: "开花",
  495. }, {
  496. id: 3,
  497. name: "成熟",
  498. }]);
  499. function handleSelectCurrentPhenology(item) {
  500. eventBus.emit("activeUpload:show", {
  501. gardenIdVal: item.farmId,
  502. problemTitleVal: '进入 物候期 的时间',
  503. imgDescVal: '请上传凭证(转入农事任务凭证)',
  504. arrangeIdVal: item.farmWorkArrangeId,
  505. selectCurrentPhenologyVal: true,
  506. phenologyListVal: phenologyList.value,
  507. });
  508. }
  509. </script>
  510. <style lang="scss" scoped>
  511. .task-page {
  512. width: 100%;
  513. height: calc(100vh - 50px - 50px);
  514. overflow: auto;
  515. box-sizing: border-box;
  516. background: #f5f7fb;
  517. .map-container {
  518. width: 100%;
  519. height: 162px;
  520. clip-path: inset(0px round 8px);
  521. }
  522. .select-group {
  523. display: flex;
  524. padding: 8px 12px 0 12px;
  525. .select-item {
  526. width: 100%;
  527. ::v-deep {
  528. .el-select__wrapper {
  529. text-align: center;
  530. gap: 2px;
  531. box-shadow: none;
  532. justify-content: center;
  533. background: none;
  534. }
  535. .el-select__selection {
  536. flex: none;
  537. width: fit-content;
  538. }
  539. .el-select__placeholder {
  540. position: static;
  541. transform: none;
  542. width: fit-content;
  543. color: rgba(0, 0, 0, 0.2);
  544. }
  545. .el-select__caret {
  546. color: rgba(0, 0, 0, 0.2);
  547. }
  548. }
  549. }
  550. }
  551. .task-top {
  552. padding: 10px 12px 0 12px;
  553. }
  554. .task-content-loading {
  555. height: 80px;
  556. border-radius: 8px;
  557. position: absolute;
  558. top: 60px;
  559. left: 0;
  560. width: 100%;
  561. }
  562. .task-content {
  563. border-top: 1px solid rgba(0, 0, 0, 0.1);
  564. min-height: 80px;
  565. }
  566. .empty-data {
  567. text-align: center;
  568. font-size: 14px;
  569. color: #6f7274;
  570. padding: 20px 0;
  571. }
  572. .task-list {
  573. position: relative;
  574. background: #fff;
  575. padding: 12px 12px 8px 12px;
  576. }
  577. .list-filter {
  578. display: flex;
  579. align-items: center;
  580. justify-content: space-around;
  581. .filter-item {
  582. padding: 0 12px;
  583. height: 28px;
  584. color: rgba(0, 0, 0, 0.5);
  585. font-size: 14px;
  586. line-height: 28px;
  587. border-radius: 20px;
  588. &.active {
  589. color: #2199f8;
  590. background: rgba(33, 153, 248, 0.2);
  591. }
  592. }
  593. }
  594. .task-item {
  595. border-radius: 12px;
  596. border: 0.3px solid rgba(0, 0, 0, 0.2);
  597. padding: 12px;
  598. }
  599. .task-item + .task-item {
  600. margin-top: 10px;
  601. }
  602. .img-text-wrap {
  603. display: flex;
  604. align-items: flex-start;
  605. justify-content: space-between;
  606. padding-bottom: 10px;
  607. border-bottom: 0.5px solid rgba(0, 0, 0, 0.1);
  608. .left-wrap {
  609. display: flex;
  610. align-items: center;
  611. .left-img {
  612. width: 40px;
  613. height: 40px;
  614. border-radius: 6px;
  615. img {
  616. width: 100%;
  617. height: 100%;
  618. object-fit: contain;
  619. }
  620. }
  621. .right-text {
  622. padding-left: 8px;
  623. .farm-info {
  624. font-size: 14px;
  625. color: #1d2129;
  626. display: flex;
  627. align-items: center;
  628. .info-tag-wrap {
  629. margin-left: 10px;
  630. display: flex;
  631. align-items: center;
  632. gap: 4px;
  633. .tag-item {
  634. height: 20px;
  635. line-height: 20px;
  636. padding: 0 8px;
  637. border-radius: 2px;
  638. font-size: 12px;
  639. &.second {
  640. color: #ff953d;
  641. background: rgba(255, 149, 61, 0.1);
  642. }
  643. &.primary {
  644. color: #2199f8;
  645. background: #e8f3ff;
  646. }
  647. }
  648. }
  649. }
  650. .farm-addr {
  651. padding-top: 2px;
  652. font-size: 12px;
  653. color: #86909c;
  654. }
  655. }
  656. }
  657. .right-wrap {
  658. display: flex;
  659. align-items: center;
  660. justify-content: center;
  661. text-align: center;
  662. color: #fff;
  663. background: #2199f8;
  664. font-size: 12px;
  665. flex: none;
  666. width: 44px;
  667. height: 44px;
  668. padding: 8px;
  669. border-radius: 5px;
  670. box-sizing: border-box;
  671. .click-item {
  672. display: flex;
  673. align-items: center;
  674. gap: 2px;
  675. }
  676. .follow-text {
  677. color: #d0d0d0;
  678. }
  679. }
  680. }
  681. .item-bottom {
  682. padding-top: 10px;
  683. .bottom-tag {
  684. display: flex;
  685. gap: 10px;
  686. .tag-card {
  687. flex: 1;
  688. border-radius: 2px;
  689. padding: 4px;
  690. box-sizing: border-box;
  691. border: 0.4px solid rgba(215, 215, 215, 0.5);
  692. .card-content {
  693. display: flex;
  694. flex-direction: column;
  695. align-items: center;
  696. justify-content: center;
  697. text-align: center;
  698. .card-main-text {
  699. font-size: 16px;
  700. font-weight: 500;
  701. color: #202020;
  702. margin-bottom: 2px;
  703. }
  704. .card-sub-text {
  705. font-size: 10px;
  706. color: rgba(32, 32, 32, 0.4);
  707. display: flex;
  708. align-items: center;
  709. gap: 4px;
  710. .card-icon {
  711. display: inline-flex;
  712. align-items: center;
  713. justify-content: center;
  714. width: 12px;
  715. height: 12px;
  716. color: #2199f8;
  717. }
  718. }
  719. }
  720. &.active {
  721. background: rgba(33, 153, 248, 0.1);
  722. border: 0.5px solid #2199f8;
  723. .card-content {
  724. .card-main-text {
  725. color: #2199f8;
  726. }
  727. .card-sub-text {
  728. color: #2199f8;
  729. }
  730. }
  731. }
  732. }
  733. }
  734. .timeline {
  735. padding-top: 10px;
  736. .timeline-item {
  737. display: flex;
  738. align-items: flex-start;
  739. font-size: 14px;
  740. color: #ffffff;
  741. line-height: 22px;
  742. & + .timeline-item {
  743. margin-top: 10px;
  744. }
  745. .timeline-left {
  746. width: 22px;
  747. display: flex;
  748. flex-direction: column;
  749. align-items: center;
  750. .dot {
  751. width: 6px;
  752. height: 6px;
  753. border-radius: 50%;
  754. background: #A2D5FD;
  755. margin-top: 6px;
  756. }
  757. .line {
  758. border-left: 1px dashed #A2D5FD;
  759. margin-top: 4px;
  760. height: 28px;
  761. }
  762. }
  763. .timeline-right {
  764. padding-left: 5px;
  765. flex: 1;
  766. .date {
  767. color: #1D2129;
  768. font-weight: 500;
  769. font-size: 14px;
  770. line-height: 22px;
  771. }
  772. .text {
  773. font-size: 12px;
  774. color: #d7d7d7;
  775. .price {
  776. padding-left: 4px;
  777. }
  778. .action-detail {
  779. margin-left: 6px;
  780. color: #2199F8;
  781. border-bottom: 1px solid;
  782. }
  783. }
  784. .work-name {
  785. padding-left: 4px;
  786. }
  787. }
  788. .timeline-action {
  789. align-self: center;
  790. height: 28px;
  791. line-height: 28px;
  792. flex: none;
  793. background: rgba(33, 153, 248, 0.1);
  794. color: #2199F8;
  795. font-size: 12px;
  796. padding: 0px 11px;
  797. border-radius: 20px;
  798. }
  799. }
  800. }
  801. }
  802. .item-footer {
  803. margin-top: 10px;
  804. padding-top: 11px;
  805. border-top: 1px solid rgba(0, 0, 0, 0.1);
  806. display: flex;
  807. align-items: center;
  808. justify-content: space-between;
  809. font-size: 12px;
  810. .footer-l {
  811. color: #8b8b8b;
  812. font-size: 12px;
  813. &.primary-btn {
  814. display: inline-flex;
  815. align-items: center;
  816. border: 1px solid #2199f8;
  817. background: rgba(33, 153, 248, 0.1);
  818. padding: 0 12px;
  819. height: 32px;
  820. box-sizing: border-box;
  821. display: flex;
  822. align-items: center;
  823. border-radius: 20px;
  824. color: #2199f8;
  825. .share-icon {
  826. width: 12px;
  827. padding-right: 4px;
  828. }
  829. }
  830. &.farm-name-text {
  831. font-size: 14px;
  832. color: #6f7274;
  833. .name-text {
  834. padding-left: 4px;
  835. }
  836. }
  837. }
  838. .footer-r {
  839. display: flex;
  840. align-items: center;
  841. .btn {
  842. height: 32px;
  843. line-height: 32px;
  844. padding: 0 12px;
  845. border-radius: 20px;
  846. display: flex;
  847. align-items: center;
  848. box-sizing: border-box;
  849. &.second {
  850. // border: 1px solid #8B8B8B;
  851. // color: #8B8B8B;
  852. color: #2199f8;
  853. background: rgba(33, 153, 248, 0.1);
  854. }
  855. &.primary {
  856. background: #2199f8;
  857. color: #fff;
  858. }
  859. .btn-icon {
  860. padding-right: 4px;
  861. }
  862. &.warning {
  863. color: #ff953d;
  864. background: #fff;
  865. border: 1px solid #ff953d;
  866. }
  867. &.secondary-text {
  868. color: #2199f8;
  869. border: 1px solid #2199f8;
  870. }
  871. }
  872. .btn + .btn {
  873. margin-left: 8px;
  874. }
  875. }
  876. }
  877. }
  878. .task-tips-popup {
  879. width: 75%;
  880. padding: 28px 28px 20px;
  881. display: flex;
  882. flex-direction: column;
  883. align-items: center;
  884. justify-content: center;
  885. .create-farm-icon {
  886. width: 40px;
  887. height: 40px;
  888. margin-bottom: 12px;
  889. }
  890. .farm-check-icon {
  891. width: 68px;
  892. height: 68px;
  893. margin-bottom: 12px;
  894. }
  895. .create-farm-text {
  896. font-size: 20px;
  897. font-weight: 500;
  898. line-height: 40px;
  899. margin-bottom: 32px;
  900. text-align: center;
  901. &.success-text {
  902. font-size: 23px;
  903. font-weight: 400;
  904. }
  905. }
  906. .main-text {
  907. color: #2199f8;
  908. }
  909. .create-farm-btn {
  910. width: 100%;
  911. box-sizing: border-box;
  912. padding: 8px;
  913. border-radius: 25px;
  914. font-size: 16px;
  915. background: #2199f8;
  916. color: #fff;
  917. text-align: center;
  918. }
  919. }
  920. </style>