interact.vue 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968
  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. min-height: 80px;
  564. }
  565. .empty-data {
  566. text-align: center;
  567. font-size: 14px;
  568. color: #6f7274;
  569. padding: 20px 0;
  570. }
  571. .task-list {
  572. position: relative;
  573. background: #fff;
  574. padding: 12px 12px 8px 12px;
  575. }
  576. .list-filter {
  577. display: flex;
  578. align-items: center;
  579. justify-content: space-around;
  580. .filter-item {
  581. padding: 0 12px;
  582. height: 28px;
  583. color: rgba(0, 0, 0, 0.5);
  584. font-size: 14px;
  585. line-height: 28px;
  586. border-radius: 20px;
  587. &.active {
  588. color: #2199f8;
  589. background: rgba(33, 153, 248, 0.2);
  590. }
  591. }
  592. }
  593. .task-item {
  594. border-radius: 12px;
  595. border: 0.3px solid rgba(0, 0, 0, 0.2);
  596. padding: 12px;
  597. }
  598. .task-item + .task-item {
  599. margin-top: 10px;
  600. }
  601. .img-text-wrap {
  602. display: flex;
  603. align-items: flex-start;
  604. justify-content: space-between;
  605. padding-bottom: 10px;
  606. border-bottom: 0.5px solid rgba(0, 0, 0, 0.1);
  607. .left-wrap {
  608. display: flex;
  609. align-items: center;
  610. .left-img {
  611. width: 40px;
  612. height: 40px;
  613. border-radius: 6px;
  614. img {
  615. width: 100%;
  616. height: 100%;
  617. object-fit: contain;
  618. }
  619. }
  620. .right-text {
  621. padding-left: 8px;
  622. .farm-info {
  623. font-size: 14px;
  624. color: #1d2129;
  625. display: flex;
  626. align-items: center;
  627. .info-tag-wrap {
  628. margin-left: 10px;
  629. display: flex;
  630. align-items: center;
  631. gap: 4px;
  632. .tag-item {
  633. height: 20px;
  634. line-height: 20px;
  635. padding: 0 8px;
  636. border-radius: 2px;
  637. font-size: 12px;
  638. &.second {
  639. color: #ff953d;
  640. background: rgba(255, 149, 61, 0.1);
  641. }
  642. &.primary {
  643. color: #2199f8;
  644. background: #e8f3ff;
  645. }
  646. }
  647. }
  648. }
  649. .farm-addr {
  650. padding-top: 2px;
  651. font-size: 12px;
  652. color: #86909c;
  653. }
  654. }
  655. }
  656. .right-wrap {
  657. display: flex;
  658. align-items: center;
  659. justify-content: center;
  660. text-align: center;
  661. color: #fff;
  662. background: #2199f8;
  663. font-size: 12px;
  664. flex: none;
  665. width: 44px;
  666. height: 44px;
  667. padding: 8px;
  668. border-radius: 5px;
  669. box-sizing: border-box;
  670. .click-item {
  671. display: flex;
  672. align-items: center;
  673. gap: 2px;
  674. }
  675. .follow-text {
  676. color: #d0d0d0;
  677. }
  678. }
  679. }
  680. .item-bottom {
  681. padding-top: 10px;
  682. .bottom-tag {
  683. display: flex;
  684. gap: 10px;
  685. .tag-card {
  686. flex: 1;
  687. border-radius: 2px;
  688. padding: 4px;
  689. box-sizing: border-box;
  690. border: 0.4px solid rgba(215, 215, 215, 0.5);
  691. .card-content {
  692. display: flex;
  693. flex-direction: column;
  694. align-items: center;
  695. justify-content: center;
  696. text-align: center;
  697. .card-main-text {
  698. font-size: 16px;
  699. font-weight: 500;
  700. color: #202020;
  701. margin-bottom: 2px;
  702. }
  703. .card-sub-text {
  704. font-size: 10px;
  705. color: rgba(32, 32, 32, 0.4);
  706. display: flex;
  707. align-items: center;
  708. gap: 4px;
  709. .card-icon {
  710. display: inline-flex;
  711. align-items: center;
  712. justify-content: center;
  713. width: 12px;
  714. height: 12px;
  715. color: #2199f8;
  716. }
  717. }
  718. }
  719. &.active {
  720. background: rgba(33, 153, 248, 0.1);
  721. border: 0.5px solid #2199f8;
  722. .card-content {
  723. .card-main-text {
  724. color: #2199f8;
  725. }
  726. .card-sub-text {
  727. color: #2199f8;
  728. }
  729. }
  730. }
  731. }
  732. }
  733. .timeline {
  734. padding-top: 10px;
  735. .timeline-item {
  736. display: flex;
  737. align-items: flex-start;
  738. font-size: 14px;
  739. color: #ffffff;
  740. line-height: 22px;
  741. & + .timeline-item {
  742. margin-top: 10px;
  743. }
  744. .timeline-left {
  745. width: 22px;
  746. display: flex;
  747. flex-direction: column;
  748. align-items: center;
  749. .dot {
  750. width: 6px;
  751. height: 6px;
  752. border-radius: 50%;
  753. background: #A2D5FD;
  754. margin-top: 6px;
  755. }
  756. .line {
  757. border-left: 1px dashed #A2D5FD;
  758. margin-top: 4px;
  759. height: 28px;
  760. }
  761. }
  762. .timeline-right {
  763. padding-left: 5px;
  764. flex: 1;
  765. .date {
  766. color: #1D2129;
  767. font-weight: 500;
  768. font-size: 14px;
  769. line-height: 22px;
  770. }
  771. .text {
  772. font-size: 12px;
  773. color: #d7d7d7;
  774. .price {
  775. padding-left: 4px;
  776. }
  777. .action-detail {
  778. margin-left: 6px;
  779. color: #2199F8;
  780. border-bottom: 1px solid;
  781. }
  782. }
  783. .work-name {
  784. padding-left: 4px;
  785. }
  786. }
  787. .timeline-action {
  788. align-self: center;
  789. height: 28px;
  790. line-height: 28px;
  791. flex: none;
  792. background: rgba(33, 153, 248, 0.1);
  793. color: #2199F8;
  794. font-size: 12px;
  795. padding: 0px 11px;
  796. border-radius: 20px;
  797. }
  798. }
  799. }
  800. }
  801. .item-footer {
  802. margin-top: 10px;
  803. padding-top: 11px;
  804. border-top: 1px solid rgba(0, 0, 0, 0.1);
  805. display: flex;
  806. align-items: center;
  807. justify-content: space-between;
  808. font-size: 12px;
  809. .footer-l {
  810. color: #8b8b8b;
  811. font-size: 12px;
  812. &.primary-btn {
  813. display: inline-flex;
  814. align-items: center;
  815. border: 1px solid #2199f8;
  816. background: rgba(33, 153, 248, 0.1);
  817. padding: 0 12px;
  818. height: 32px;
  819. box-sizing: border-box;
  820. display: flex;
  821. align-items: center;
  822. border-radius: 20px;
  823. color: #2199f8;
  824. .share-icon {
  825. width: 12px;
  826. padding-right: 4px;
  827. }
  828. }
  829. &.farm-name-text {
  830. font-size: 14px;
  831. color: #6f7274;
  832. .name-text {
  833. padding-left: 4px;
  834. }
  835. }
  836. }
  837. .footer-r {
  838. display: flex;
  839. align-items: center;
  840. .btn {
  841. height: 32px;
  842. line-height: 32px;
  843. padding: 0 12px;
  844. border-radius: 20px;
  845. display: flex;
  846. align-items: center;
  847. box-sizing: border-box;
  848. &.second {
  849. // border: 1px solid #8B8B8B;
  850. // color: #8B8B8B;
  851. color: #2199f8;
  852. background: rgba(33, 153, 248, 0.1);
  853. }
  854. &.primary {
  855. background: #2199f8;
  856. color: #fff;
  857. }
  858. .btn-icon {
  859. padding-right: 4px;
  860. }
  861. &.warning {
  862. color: #ff953d;
  863. background: #fff;
  864. border: 1px solid #ff953d;
  865. }
  866. &.secondary-text {
  867. color: #2199f8;
  868. border: 1px solid #2199f8;
  869. }
  870. }
  871. .btn + .btn {
  872. margin-left: 8px;
  873. }
  874. }
  875. }
  876. }
  877. .task-tips-popup {
  878. width: 75%;
  879. padding: 28px 28px 20px;
  880. display: flex;
  881. flex-direction: column;
  882. align-items: center;
  883. justify-content: center;
  884. .create-farm-icon {
  885. width: 40px;
  886. height: 40px;
  887. margin-bottom: 12px;
  888. }
  889. .farm-check-icon {
  890. width: 68px;
  891. height: 68px;
  892. margin-bottom: 12px;
  893. }
  894. .create-farm-text {
  895. font-size: 20px;
  896. font-weight: 500;
  897. line-height: 40px;
  898. margin-bottom: 32px;
  899. text-align: center;
  900. &.success-text {
  901. font-size: 23px;
  902. font-weight: 400;
  903. }
  904. }
  905. .main-text {
  906. color: #2199f8;
  907. }
  908. .create-farm-btn {
  909. width: 100%;
  910. box-sizing: border-box;
  911. padding: 8px;
  912. border-radius: 25px;
  913. font-size: 16px;
  914. background: #2199f8;
  915. color: #fff;
  916. text-align: center;
  917. }
  918. }
  919. </style>