| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965 |
- <template>
- <div class="task-page" :style="{ height: `calc(100vh - ${tabBarHeight}px)` }">
- <div class="task-top">
- <div class="map-container" ref="mapContainer"></div>
- </div>
- <div class="calendar-container">
- <customCalendar ref="calendarRef" @dateSelect="handleDateSelect"></customCalendar>
- </div>
- <div class="task-list">
- <div class="list-filter">
- <div
- v-for="item in filterTabs"
- :key="item.value"
- class="filter-item"
- :class="{ active: activeIndex === item.value }"
- @click="handleActiveFilter(item.value)"
- >
- {{ t(item.labelKey) }}({{ taskCounts[item.value] || 0 }})
- </div>
- </div>
- <div class="list-box">
- <div class="list-header">
- <div class="select-group">
- <el-select class="select-item" v-model="selectParma.farmWorkTypeId" :placeholder="t('workExecute.farmWorkType')"
- @change="resetAndLoad">
- <el-option v-for="item in farmWorkTypeList" :key="item.id"
- :label="item.id === 0 ? t('workExecute.all') : item.name"
- :value="item.id" />
- </el-select>
- <el-select class="select-item" v-model="selectParma.districtCode" :placeholder="t('workExecute.farmFilter')"
- @change="resetAndLoad">
- <el-option v-for="item in districtList" :key="item.code" :label="item.name"
- :value="item.code" />
- </el-select>
- </div>
- <!-- <div class="action-btn">{{ t("workExecute.batchAccept") }}</div> -->
- </div>
- <!-- 任务列表 -->
- <div class="work-task-list" v-loading="loading" element-loading-background="rgba(0, 0, 0, 0.3)">
- <div class="task-item" v-for="(item, index) in taskList" :key="index"
- :class="[
- isAcceptOvertime(item) ? 'timeout-item' : '',
- locale === 'en' ? 'task-item--en' : '',
- ]" @click="handleItem(item, index)">
- <div class="item-title" :class="{ 'item-title--en': locale === 'en' }">
- <img class="task-icon" src="@/assets/img/home/task.png" alt="">
- <div class="item-title-main">
- <span class="title-text">{{ item?.operation?.name }}</span>
- <span class="task-status" :class="`task-status--${getWorkType(item.operation?.type)}`">{{
- item.operation?.type }}</span>
- </div>
- </div>
- <span class="task-tag timeout" v-if="isAcceptOvertime(item)">
- <el-icon>
- <WarningFilled />
- </el-icon>
- {{ t("workExecute.acceptTimeout") }}
- </span>
- <span class="task-tag" v-else :class="`task-tag--${getStatusTagClass()}`">
- <el-icon v-if="activeStatus === '已完成'" class="task-tag__icon">
- <CircleCheck />
- </el-icon>
- {{ getStatusLabel(activeStatus) }}
- </span>
- <div class="item-content">
- <div class="item-info">
- <div class="info-item">
- <div class="info-name">{{ t("workExecute.responsible") }}</div><span class="val-text">
- {{ item.operation?.executor }}</span>
- </div>
- <div class="info-item" v-if="mode !== 'review'">
- <div class="info-name">{{ t("workExecute.farmWorkDetail") }}</div><span class="val-text">
- {{ item.operation?.work_detail }}</span>
- </div>
- <div class="info-item">
- <div class="info-name">{{ t("workExecute.farmSituation") }}</div><span class="val-text">
- {{ item.operation?.work_reason }}</span>
- </div>
- </div>
- <div class="excutor-info">
- <div class="executor-stats">
- <div class="stat-cell">
- <div class="stat-value">
- {{ item.time ? formatGMTToYMD(item.time) : "--" }}
- </div>
- <div class="stat-label">{{ t("workExecute.executeTime") }}</div>
- </div>
- <div class="cell-line"></div>
- <div class="stat-cell">
- <div class="stat-value">{{ item.geohash_sample || "--" }}</div>
- <div class="stat-label">{{ t("workExecute.executeArea") }}</div>
- </div>
- <div class="cell-line"></div>
- <div class="stat-cell">
- <div class="stat-value">{{ item.operation?.machine_code || "--" }}</div>
- <div class="stat-label">{{ t("workExecute.executeMachine") }}</div>
- </div>
- </div>
- </div>
- </div>
- <div
- v-if="activeStatus === '已完成'"
- class="execute-photos"
- @click.stop
- >
- <div class="execute-photos__wrap">
- <span class="execute-photos__label">{{ t('workExecute.executePhotos') }}</span>
- <div class="execute-photos__list">
- <div
- v-for="(photo, photoIndex) in getExecutePhotoList(item)"
- :key="photoIndex"
- class="execute-photos__item"
- >
- <img :src="photo" alt="" />
- </div>
- </div>
- </div>
- </div>
- <div class="unqualified-reason" v-if="activeStatus === '未达标'">
- {{ t("workExecute.unqualifiedReason") }}{{ item.operation?.reason || t("workExecute.defaultUnqualifiedReason") }}
- </div>
- <div class="compare-imgs" v-if="activeStatus === '未达标' && (item.beforeImage || item.afterImage)"
- @click.stop>
- <div class="img-tag">{{ t("workExecute.before") }}</div>
- <div class="img-tag right-tag">{{ t("workExecute.after") }}</div>
- <div class="img-item" v-if="item.beforeImage">
- <img :src="getWorkImageUrl(item.beforeImage)" alt="" />
- </div>
- <div class="img-item" v-if="item.afterImage">
- <img :src="getWorkImageUrl(item.afterImage)" alt="" />
- </div>
- </div>
- <div class="task-footer">
- <div class="farm-info">{{ t("workExecute.fromFarm") }}</div>
- <div class="btn-group" v-if="getItemStatusButtons(item).length">
- <div v-for="btn in getItemStatusButtons(item)" :key="btn.label" class="edit-btn"
- :class="btn.type" @click.stop="handleStatusBtn(btn, item, index)">
- {{ btn.label }}
- </div>
- </div>
- </div>
- </div>
- <div class="empty-tip" v-if="!loading && taskList.length === 0">{{ t("workExecute.noData") }}</div>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- import { computed, nextTick, onActivated, onMounted, ref, watch } from "vue";
- import { useStore } from "vuex";
- import IndexMap from "./index";
- import { useRouter } from "vue-router";
- import { WarningFilled, CircleCheck } from "@element-plus/icons-vue";
- import { ElMessage } from "element-plus";
- import config from "@/api/config.js";
- import customCalendar from "./components/calendar.vue";
- import { useI18n } from "@/i18n";
- import executePhotoPlaceholder1 from "@/assets/img/common/sd-1.jpg";
- import executePhotoPlaceholder2 from "@/assets/img/common/sd-2.jpg";
- import executePhotoPlaceholder3 from "@/assets/img/common/sd-3.jpg";
- import executePhotoPlaceholder4 from "@/assets/img/common/sd-4.jpg";
- const EXECUTE_PHOTO_PLACEHOLDERS = [
- executePhotoPlaceholder1,
- executePhotoPlaceholder2,
- executePhotoPlaceholder3,
- executePhotoPlaceholder4,
- ];
- const { t, locale } = useI18n();
- const store = useStore();
- const router = useRouter();
- const indexMap = new IndexMap();
- const mapContainer = ref(null);
- const tabBarHeight = computed(() => store.state.home.tabBarHeight);
- const selectParma = ref({
- farmWorkTypeId: null,
- districtCode: null,
- });
- const taskList = ref([])
- const mode = "execute";
- const activeStatus = ref("待接受");
- const STATUS_BTN_MAP = {
- 待接受: [
- { labelKey: "workExecute.modifyInfo", type: "normal", action: "redispatch" },
- { labelKey: "workExecute.acceptTask", type: "primary", action: "remindAccept" },
- ],
- 已接受: [
- { labelKey: "workExecute.modifyInfo", type: "normal", action: "redispatch" },
- { labelKey: "workExecute.startExecute", type: "primary-blue", action: "startExecute" },
- ],
- 执行中: [{ labelKey: "workExecute.markComplete", type: "primary-green", action: "markComplete" }],
- 已超时: [
- { labelKey: "workExecute.redispatch", type: "normal", action: "redispatch" },
- { labelKey: "workExecute.remindAccept", type: "primary", action: "remindAccept" },
- ],
- 未达标: [{ labelKey: "workExecute.redispatchAgain", type: "primary", action: "redispatch" }],
- };
- const STATUS_LABEL_MAP = {
- 待接受: "workExecute.pending",
- 已接受: "workExecute.accepted",
- 执行中: "workExecute.executing",
- 已完成: "workExecute.completed",
- 已超时: "workExecute.timeout",
- 未达标: "workExecute.unqualified",
- };
- const getStatusLabel = (status) => t(STATUS_LABEL_MAP[status] || status);
- const STATUS_TAG_CLASS_MAP = {
- 待接受: "pending",
- 已接受: "accepted",
- 执行中: "executing",
- 已完成: "completed",
- };
- const getStatusTagClass = () => STATUS_TAG_CLASS_MAP[activeStatus.value] || "pending";
- const isAcceptOvertime = (item) => Number(item?.operation?.is_aovertime) === 1;
- const mapStatusButtons = (buttons) =>
- buttons.map((btn) => ({
- ...btn,
- label: t(btn.labelKey),
- }));
- const getItemStatusButtons = (item) => {
- if (isAcceptOvertime(item)) {
- return [];
- }
- return mapStatusButtons(STATUS_BTN_MAP[activeStatus.value] || []);
- };
- const formatGMTToYMD = (gmtString) => {
- const date = new Date(gmtString);
- return date.toISOString().split("T")[0];
- };
- const getWorkImageUrl = (image) => {
- if (!image?.cloud_filename) return "";
- return config.base_img_url3 + image.cloud_filename;
- };
- const resolveExecutePhotoUrl = (src) => {
- if (!src) return "";
- if (typeof src === "object" && src.cloud_filename) {
- return config.base_img_url3 + src.cloud_filename;
- }
- if (typeof src === "string") {
- if (src.startsWith("http")) return src;
- return config.base_img_url2 + src;
- }
- return "";
- };
- const getExecutePhotoList = (item) => {
- const operation = item?.operation || {};
- const raw =
- operation.execute_evidence ??
- operation.executeEvidence ??
- item.execute_evidence ??
- item.executeEvidence;
- let photos = [];
- if (raw) {
- if (Array.isArray(raw)) {
- photos = raw.map(resolveExecutePhotoUrl).filter(Boolean);
- } else if (typeof raw === "string") {
- try {
- const parsed = JSON.parse(raw);
- if (Array.isArray(parsed)) {
- photos = parsed.map(resolveExecutePhotoUrl).filter(Boolean);
- }
- } catch {
- const url = resolveExecutePhotoUrl(raw);
- if (url) photos = [url];
- }
- }
- }
- return (photos.length ? photos : EXECUTE_PHOTO_PLACEHOLDERS).slice(0, 4);
- };
- const handleItem = (item, index) => {
- const statusStr = item.operation?.is_aovertime ? '接受超时' : activeStatus.value;
- const status = item.operation?.is_aovertime ? 1 : activeIndex.value;
- router.push({
- path: "/agri_record_detail",
- query: {
- id: item.operation?.work_id,
- status,
- statusStr,
- },
- });
- };
- const handleStatusBtn = (btn, item, index) => {
- if (btn.action === "redispatch") {
- ElMessage.info(t("workExecute.redispatchMsg", { name: item.operation?.name }));
- } else {
- ElMessage.success(t("workExecute.remindSuccess"));
- }
- };
- const formatDateYMD = (date = new Date()) =>
- `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
- const calendarRef = ref(null);
- const filterDate = ref(formatDateYMD());
- const fullTaskList = ref([]);
- const getCalendarTaskList = (list) => {
- return list.map((item) => ({
- expectedExecuteDate: item.time,
- executeDeadlineDate: item.time,
- }));
- };
- const syncCalendarData = () => {
- nextTick(() => {
- calendarRef.value?.setSolarTerm(getCalendarTaskList(fullTaskList.value));
- });
- };
- const handleDateSelect = (date) => {
- filterDate.value = date ?? formatDateYMD();
- resetAndLoad();
- syncCalendarData();
- };
- // 各状态任务数量,key 为 work_operation_type:0待接受 1执行中 2已接受 3已完成
- const taskCounts = ref({ 0: 0, 1: 0, 2: 0, 3: 0 });
- const STATUS_TAB_VALUES = [0, 2, 1, 3];
- const filterTabs = [
- { value: 0, labelKey: "workExecute.pending" },
- { value: 2, labelKey: "workExecute.accepted" },
- { value: 1, labelKey: "workExecute.executing" },
- { value: 3, labelKey: "workExecute.completed" },
- ];
- // 当前选中的筛选索引
- const activeIndex = ref(0);
- const loading = ref(false);
- const cityCode = ref("");
- //根据城市的坐标返回区县列表
- const districtList = ref([]);
- //农事类型列表
- const farmWorkTypeList = ref([]);
- function getFarmWorkTypeList() {
- VE_API.z_farm_work_record.getFarmWorkTypeList().then(({ data }) => {
- farmWorkTypeList.value = data;
- farmWorkTypeList.value.unshift({ id: 0, name: "全部" });
- });
- }
- const mapPoint = ref(null);
- onMounted(() => {
- mapPoint.value = store.state.home.miniUserLocationPoint;
- getFarmWorkTypeList();
- syncCalendarData();
- nextTick(() => {
- indexMap.initMap(mapPoint.value, mapContainer.value, true);
- indexMap.initData(taskList.value, '', 'farmPoint');
- });
- });
- onActivated(() => {
- resetAndLoad();
- nextTick(() => {
- if (!indexMap.kmap) {
- if (mapContainer.value) {
- mapPoint.value = store.state.home.miniUserLocationPoint;
- indexMap.initMap(mapPoint.value, mapContainer.value, true);
- }
- return;
- }
- if (mapContainer.value && indexMap.kmap.map) {
- const checkAndUpdateSize = () => {
- const container = mapContainer.value;
- if (!container) return;
- const rect = container.getBoundingClientRect();
- if (rect.width > 0 && rect.height > 0) {
- indexMap.kmap.map.updateSize();
- } else {
- setTimeout(checkAndUpdateSize, 100);
- }
- };
- setTimeout(checkAndUpdateSize, 200);
- }
- });
- });
- const getRegionRecordList = (data) => {
- if (!Array.isArray(data)) return [];
- return data.filter((item) => item.operation !== null);
- };
- const getRegionRecordParams = (workOperationType) => ({
- farm_id: localStorage.getItem('selectedFarmId'),
- time: filterDate.value,
- work_operation_type: workOperationType,
- // farm_id: '320',
- // time: '2026-06-30',
- // work_operation_type: workOperationType,
- });
- const taskListsByType = ref({ 0: [], 1: [], 2: [], 3: [] });
- const loadPageData = async () => {
- loading.value = true;
- try {
- const results = await Promise.all(
- STATUS_TAB_VALUES.map((type) => VE_API.farm.getRegionRecord(getRegionRecordParams(type)))
- );
- const counts = { 0: 0, 1: 0, 2: 0, 3: 0 };
- const listsByType = { 0: [], 1: [], 2: [], 3: [] };
- STATUS_TAB_VALUES.forEach((type, index) => {
- const { code, data } = results[index] || {};
- const list = code === 200 ? getRegionRecordList(data) : [];
- listsByType[type] = list;
- counts[type] = list.length;
- });
- taskListsByType.value = listsByType;
- taskCounts.value = counts;
- taskList.value = listsByType[activeIndex.value] || [];
- } finally {
- loading.value = false;
- }
- };
- // 监听 activeIndex 变化,切换 Tab 时复用已请求的数据
- watch(activeIndex, () => {
- taskList.value = taskListsByType.value[activeIndex.value] || [];
- });
- // 重置并重新加载
- const resetAndLoad = () => {
- loadPageData();
- };
- function handleActiveFilter(i) {
- activeIndex.value = i;
- selectParma.value.districtCode = cityCode.value;
- selectParma.value.farmWorkTypeId = null;
- const statusMap = { 0: "待接受", 1: "执行中", 2: "已接受", 3: "已完成" };
- activeStatus.value = statusMap[i] || "待接受";
- syncCalendarData();
- }
- const getWorkType = (type) => {
- const map = {
- '标准防治类': 1,
- '标准施肥类': 2,
- '标准调节类': 3,
- }
- return map[type] || type;
- }
- </script>
- <style lang="scss" scoped>
- .task-page {
- width: 100%;
- height: calc(100vh - 50px);
- overflow: auto;
- box-sizing: border-box;
- background: #FFFFFF;
- .map-container {
- width: 100%;
- height: 162px;
- clip-path: inset(0px round 8px);
- }
- .list-box {
- background: #F1F3F4;
- padding: 12px 12px 8px 12px;
- .list-header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- .action-btn {
- box-sizing: border-box;
- height: 32px;
- line-height: 30px;
- color: #2199F8;
- font-size: 14px;
- border-radius: 5px;
- padding: 0 10px;
- background: #FFFFFF;
- border: 1px solid #2199F8;
- color: #2199F8;
- }
- }
- }
- .select-group {
- display: flex;
- padding: 0px 12px 0 12px;
- .select-item {
- width: 100%;
- ::v-deep {
- .el-select__wrapper {
- text-align: center;
- gap: 2px;
- box-shadow: none;
- justify-content: center;
- background: none;
- }
- .el-select__selection {
- flex: none;
- width: fit-content;
- }
- .el-select__placeholder {
- position: static;
- transform: none;
- width: fit-content;
- color: rgba(0, 0, 0, 0.2);
- }
- .el-select__caret {
- color: rgba(0, 0, 0, 0.2);
- }
- }
- }
- }
- .calendar-container {
- padding: 4px 12px 8px 12px;
- }
- .task-top {
- padding: 10px 12px 0 12px;
- }
- .task-content-loading {
- height: 80px;
- border-radius: 8px;
- position: absolute;
- top: 60px;
- left: 0;
- width: 100%;
- }
- .task-content {
- min-height: 80px;
- }
- .empty-data {
- text-align: center;
- font-size: 14px;
- color: #6f7274;
- padding: 20px 0;
- }
- .task-list {
- position: relative;
- background: #fff;
- }
- .list-filter {
- display: flex;
- align-items: center;
- justify-content: space-around;
- margin-top: 10px;
- .filter-item {
- padding: 0 6px;
- height: 32px;
- color: #1D2129;
- font-size: 14px;
- border-radius: 20px;
- position: relative;
- &.active {
- color: #2199f8;
- &::after {
- content: "";
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- height: 2px;
- background: #2199f8;
- }
- }
- }
- }
- .work-task-list {
- margin-top: 10px;
- .task-item {
- margin-top: 10px;
- background: #fff;
- border-radius: 8px;
- padding: 12px 16px;
- border: 1px solid rgba(0, 0, 0, 0.08);
- position: relative;
- &.timeout-item {
- border: 1px solid #f74e4e;
- }
- &--en {
- padding-top: 22px;
- }
- .item-title {
- display: flex;
- align-items: center;
- gap: 8px;
- padding-bottom: 10px;
- border-bottom: 1px solid rgba(0, 0, 0, 0.06);
- color: #1d2129;
- font-size: 16px;
- .task-icon {
- width: 16px;
- flex-shrink: 0;
- }
- .item-title-main {
- flex: 1;
- min-width: 0;
- display: flex;
- align-items: center;
- gap: 8px;
- }
- &--en {
- align-items: flex-start;
- .task-icon {
- margin-top: 2px;
- }
- .item-title-main {
- flex-direction: column;
- align-items: flex-start;
- gap: 4px;
- }
- .task-status {
- margin-left: 0;
- }
- }
- .title-text {
- min-width: 0;
- }
- .task-status {
- margin-left: 0;
- border-radius: 2px;
- height: 20px;
- line-height: 20px;
- padding: 1px 6px;
- box-sizing: border-box;
- font-size: 12px;
- color: #ffb32f;
- background: rgba(255, 179, 47, 0.1);
- &.task-status--1 {
- background: rgba(33, 153, 248, 0.1);
- color: #2199f8;
- }
- &.task-status--2 {
- background: rgba(255, 179, 47, 0.1);
- color: #FFB32F;
- }
- &.task-status--3 {
- background: rgba(58, 173, 148, 0.1);
- color: #3AAD94;
- }
- }
- }
- .task-tag {
- position: absolute;
- right: 0;
- top: 0;
- background: rgba(255, 149, 61, 0.1);
- color: #F46E00;
- font-size: 12px;
- padding: 0 10px;
- height: 25px;
- line-height: 25px;
- border-radius: 0 8px 0 8px;
- &.timeout {
- background: rgba(255, 106, 106, 0.1);
- color: #FF6A6A;
- display: flex;
- align-items: center;
- gap: 2px;
- }
- &--pending {
- background: rgba(255, 149, 61, 0.1);
- color: #F46E00;
- }
- &--accepted {
- background: rgba(33, 153, 248, 0.1);
- color: #2199F8;
- }
- &--executing {
- background: rgba(33, 153, 248, 0.1);
- color: #2199F8;
- }
- &--completed {
- background: rgba(74, 191, 50, 0.1);
- color: #4ABF32;
- display: flex;
- align-items: center;
- gap: 2px;
- .task-tag__icon {
- font-size: 12px;
- }
- }
- }
- .execute-photos {
- margin: 8px 0 4px;
- &__wrap {
- background: #ebf5ff;
- border: 1px solid rgba(33, 153, 248, 0.15);
- border-radius: 12px;
- padding: 12px;
- }
- &__label {
- display: inline-block;
- padding: 4px 10px;
- background: #2199f8;
- color: #fff;
- font-size: 12px;
- line-height: 18px;
- border-radius: 4px;
- margin-bottom: 8px;
- }
- &__list {
- display: flex;
- gap: 8px;
- background: #fff;
- border-radius: 10px;
- padding: 10px;
- }
- &__item {
- flex: 1;
- aspect-ratio: 1;
- border-radius: 8px;
- overflow: hidden;
- img {
- display: block;
- width: 100%;
- height: 100%;
- object-fit: cover;
- }
- }
- }
- .item-content {
- padding: 12px 0;
- .excutor-info {
- margin-top: 12px;
- background: rgba(189, 189, 189, 0.1);
- border-radius: 6px;
- padding-bottom: 12px;
- .excutor-info-top {
- padding: 12px 12px 0 12px;
- }
- }
- .executor-stats {
- display: flex;
- align-items: center;
- padding-top: 10px;
- justify-content: space-around;
- }
- .cell-line {
- height: 20px;
- width: 1px;
- background: #e5e6eb;
- }
- .stat-value {
- font-size: 14px;
- font-weight: 500;
- color: #0B0B0B;
- margin-bottom: 4px;
- word-break: break-all;
- }
- .stat-label {
- font-size: 12px;
- line-height: 20px;
- color: rgba(107, 107, 107, 0.5);
- text-align: center;
- }
- }
- .item-info {
- color: rgba(111, 114, 116, 0.6);
- font-size: 14px;
- line-height: 21px;
- .info-item {
- display: flex;
- .info-name {
- flex: none;
- }
- }
- .val-text {
- // color: #1d2129;
- }
- .info-item+.info-item {
- padding-top: 6px;
- }
- }
- .task-footer {
- padding-top: 4px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- .farm-info {
- font-size: 14px;
- color: rgba(32, 32, 32, 0.4);
- }
- }
- .btn-group {
- display: flex;
- align-items: center;
- justify-content: end;
- gap: 10px;
- }
- .edit-btn {
- height: 30px;
- padding: 0 16px;
- border-radius: 24px;
- text-align: center;
- line-height: 30px;
- font-size: 14px;
- &.normal {
- background: #F6F6F6;
- color: #000000;
- }
- &.primary {
- background: #FF953D;
- color: #fff;
- }
- &.primary-blue {
- background: #2199F8;
- color: #fff;
- }
- &.primary-green {
- background: #37C11B;
- color: #fff;
- }
- }
- .compare-imgs {
- display: flex;
- align-items: center;
- gap: 10px;
- position: relative;
- margin: 10px 0;
- .img-tag {
- position: absolute;
- z-index: 10;
- top: 0;
- left: 0;
- font-size: 12px;
- color: #fff;
- background: rgba(0, 0, 0, 0.7);
- border-radius: 5px 0 5px 0;
- padding: 0 8px;
- height: 15px;
- line-height: 15px;
- &.right-tag {
- right: 0;
- left: auto;
- border-radius: 0 5px 0 5px;
- }
- }
- .img-item {
- flex: 1;
- height: 120px;
- overflow: hidden;
- border: 0.5px solid rgba(0, 0, 0, 0.1);
- border-radius: 5px;
- img {
- width: 100%;
- height: 100%;
- border-radius: 5px;
- object-fit: cover;
- }
- }
- }
- }
- .unqualified-reason {
- color: #f74e4e;
- font-size: 12px;
- padding: 4px 10px;
- background: rgba(247, 78, 78, 0.08);
- border-radius: 4px;
- line-height: 18px;
- }
- .empty-tip {
- text-align: center;
- color: #86909c;
- font-size: 14px;
- padding: 20px 0;
- }
- }
- }
- </style>
|