复制
<template>
  <div class="task-page">
    <!-- 顶部导航 -->
    <s-header :name="$t('taskMessage.taskMessage')" :noback="false"></s-header>

    <div class="task-container">
      <van-list
        v-model:loading="loading"
        v-model:error="error"
        :error-text="$t('common.reqFailClkReload')"
        :finished="finished"
        :finished-text="$t('common.noMoreTxt')"
        offset="300"
        :immediate-check="false"
        @load="onLoad"
      >
        <!-- 顶部筛选和信息区域 -->
        <div class="header-info">
          <div class="total-card">
            <div class="icon-box">
              <van-icon name="todo-list" class="equipment-icon" />
            </div>
            <div class="total-info">
              {{ $t("taskMessage.total") }}
              <span class="highlight">{{ alarmHistoryTotal }}</span>
              {{ $t("taskMessage.recordsInTotal") }}
            </div>
          </div>

          <div class="actions">
            <van-button
              round
              size="small"
              plain
              class="action-btn"
              @click="reviewedClk"
            >
              {{ $t("taskMessage.toViewAppro") }}
            </van-button>
            <van-button
              round
              size="small"
              plain
              class="action-btn"
              @click="noticeClk"
            >
              <van-icon name="search" size="20" />
            </van-button>
          </div>
        </div>

        <!-- 设备申请列表 -->
        <div class="list-container">
          <div
            v-for="(item, index) in alarmHistoryList"
            :key="index"
            class="list-card"
            :class="{
              pending: item.statusType === 1,
              rejected: item.statusType === 2,
              approved: item.statusType === 3,
            }"
          >
            <div class="card-header">
              <div class="status-tag">
                {{ showItemType(item.statusType) }}
              </div>
              <div class="time-label">
                {{ $t("taskMessage.applicationTime") }}:
                {{ showDateTime(item.createDate) }}
              </div>
            </div>

            <div class="card-content">
              <div class="info-row">
                <van-icon name="shop-o" class="row-icon" />
                <div class="row-content">
                  <span class="label"
                    >{{ $t("taskMessage.affiliatedMerchants") }}:&nbsp;</span
                  >
                  <span class="value">{{ item.adminUserName }}</span>
                </div>
              </div>

              <div class="info-row">
                <van-icon name="setting-o" class="row-icon" />
                <div class="row-content">
                  <span class="label"
                    >{{ $t("taskMessage.equipmentNo") }}:&nbsp;</span
                  >
                  <span class="value">{{ item.clientId }}</span>
                </div>
              </div>

              <div class="info-row">
                <van-icon name="idcard" class="row-icon" />
                <div class="row-content">
                  <span class="label"
                    >{{ $t("taskMessage.managementSystemID") }}:&nbsp;</span
                  >
                  <span class="value">{{ item.managerId }}</span>
                </div>
              </div>

              <template v-if="item.statusType !== 1">
                <div class="info-row">
                  <van-icon name="clock-o" class="row-icon" />
                  <div class="row-content">
                    <span class="label"
                      >{{ $t("taskMessage.approvalTime") }}:&nbsp;</span
                    >
                    <span class="value">{{
                      showDateTime(item.modifyDate)
                    }}</span>
                  </div>
                </div>
              </template>
            </div>

            <!-- 审批操作按钮 -->
            <div v-if="item.statusType === 1 && isOper" class="card-actions">
              <van-button
                round
                size="small"
                class="reject-btn"
                @click="changeStatusFun(item, 'unAgreed')"
              >
                <van-icon name="close" size="20" class="btn-icon" />
                {{ $t("taskMessage.refuse") }}
              </van-button>
              <van-button
                round
                size="small"
                class="approve-btn"
                @click="changeStatusFun(item, 'agreed')"
              >
                <van-icon name="passed" size="20" class="btn-icon" />
                {{ $t("taskMessage.agree") }}
              </van-button>
            </div>
          </div>
        </div>
      </van-list>
    </div>

    <!-- 筛选弹窗 -->
    <kDialog
      :dialogTitle="$t('taskMessage.equipmentInit.searchPop.title')"
      :confirmBtnTxt="$t('taskMessage.equipmentInit.searchPop.filterBtn')"
      ref="kDialogRef"
      @confirmclk="confirmClk"
    >
      <template #content>
        <div class="dialog-content">
          <van-field
            clearable
            v-model="searchForm.equipmentNo"
            :placeholder="
              $t('taskMessage.equipmentInit.searchPop.equipmentNoPlace')
            "
            :label="$t('taskMessage.equipmentInit.searchPop.equipmentNo')"
          />

          <van-field
            clearable
            v-model="searchForm.managementSystemID"
            :placeholder="
              $t('taskMessage.equipmentInit.searchPop.managementSystemIDPlace')
            "
            :label="
              $t('taskMessage.equipmentInit.searchPop.managementSystemID')
            "
          />

          <van-field
            clearable
            v-model="searchForm.merchantName"
            :placeholder="
              $t('taskMessage.equipmentInit.searchPop.merchantNamePlace')
            "
            :label="$t('taskMessage.equipmentInit.searchPop.merchantName')"
          />

          <van-field
            @click-input="busiInpClk"
            readonly
            clearable
            v-model="searchForm.stateName"
            :placeholder="$t('taskMessage.equipmentInit.searchPop.statePlace')"
            :label="$t('taskMessage.equipmentInit.searchPop.state')"
          >
            <template #right-icon>
              <div class="icon-container">
                <van-icon
                  v-if="searchForm.stateName"
                  @click.stop="clearState"
                  class="clear-icon"
                  name="clear"
                />
                <van-icon @click.stop="busiInpClk" name="arrow-down" />
              </div>
            </template>
          </van-field>
        </div>
      </template>
    </kDialog>

    <!-- 状态选择框 -->
    <van-popup v-model:show="busiPopShow" position="bottom" round>
      <van-picker
        :title="$t('taskMessage.equipmentInit.searchPop.statePlace')"
        :columns="busiPopList"
        :columns-field-names="busiPopFieldName"
        @confirm="busiPopConfirm"
        @cancel="busiPopShow = false"
      />
    </van-popup>
  </div>
</template>

<script>
import { onMounted, reactive, ref } from "vue";
import sHeader from "@/components/SimpleHeader";
import { getTaskEquipmentList, changeStatus } from "@/service/taskMessage";
import { showSuccessToast, showFailToast } from "vant";
import { getLoginUser } from "@/common/js/utils";
import dateUtil from "@/utils/dateUtil";
import kDialog from "@/components/commom/kDialog/index.vue";
import { useI18n } from "vue-i18n";
import { useRouter } from "vue-router";

export default {
  components: { sHeader, kDialog },
  setup() {
    const { t } = useI18n();
    const router = useRouter();
    // 筛选弹窗
    const busiPopList = reactive([
      {
        name: t("taskMessage.toBeApproved"),
        id: "1",
      },
      {
        name: t("taskMessage.rejected"),
        id: "2",
      },
      {
        name: t("taskMessage.agreed"),
        id: "3",
      },
    ]);
    const busiPopFieldName = reactive({
      text: "name",
      value: "id",
    });
    const kDialogRef = ref(null);
    const busiPopShow = ref(false);
    // 筛选条件
    const searchForm = reactive({
      equipmentNo: "",
      managementSystemID: "",
      merchantName: "",
      state: "",
      stateName: "",
    });
    // 点击状态输入框
    const busiInpClk = () => {
      busiPopShow.value = true;
    };
    const busiPopConfirm = ({ selectedOptions }) => {
      busiPopShow.value = false;
      searchForm.state = selectedOptions[0].id;
      searchForm.stateName = selectedOptions[0].name;
    };
    // 点击筛选
    const noticeClk = () => {
      kDialogRef.value.openDialog();
    };
    // 点击查询按钮
    const confirmClk = () => {
      isClkReview.value = false;
      searchGetList();
    };
    // 是否点击待审核
    const isClkReview = ref(true);
    // 点击查看待审核
    const reviewedClk = () => {
      isClkReview.value = true;
      searchParams.statusType = "1";
      // 清空弹窗的查询条件
      searchForm.state = "";
      searchForm.stateName = "";
      searchGetList();
    };
    const user = getLoginUser();
    const loading = ref(false); // 加载状态
    const error = ref(false); // 错误状态
    const finished = ref(false); // 结束翻页状态
    const alarmHistoryList = ref([]); // 列表集合
    const alarmHistoryTotal = ref(0); // 列表总数
    let searchParams = reactive({
      clientId: "", // 设备编号_支持模糊查询
      current: 1, // 页数
      size: 20, // 页大小
      userName: "", // 用户登录名
      statusType: "", // 审核状态 1 - 申请中 2 - 已拒绝 3 - 已同意
      managerId: "", // 管理系统ID
    });
    // 滚动加载
    const onLoad = () => {
      if (!finished.value) {
        searchParams.current = searchParams.current + 1;
        getList();
      }
    };
    // 查询列表
    const searchGetList = () => {
      alarmHistoryList.value = [];
      searchParams.current = 1;
      getList();
    };
    // 获取设备初始化审批列表数据
    const getList = async () => {
      // 把弹窗的筛选条件组合到请求参数里面
      if (!isClkReview.value) {
        searchParams.statusType = searchForm.state;
      }
      searchParams.clientId = searchForm.equipmentNo;
      searchParams.userName = searchForm.merchantName;
      searchParams.managerId = searchForm.managementSystemID;
      const { data } = await getTaskEquipmentList(
        Object.assign({}, searchParams)
      );
      if (data.code === "00000") {
        // 列表值叠加
        alarmHistoryList.value = alarmHistoryList.value.concat(
          data.data.records
        );
        alarmHistoryTotal.value = data.data.total;
        if (alarmHistoryList.value.length === data.data.total) {
          finished.value = true;
        }
        loading.value = false;
      } else {
        showFailToast(data.message);
      }
    };
    const showDateTime = (date) => {
      return date
        ? dateUtil.formateDate(new Date(date), "yyyy/MM/dd hh:mm:ss")
        : "";
    };
    const showItemType = (type) => {
      if (type === 1) {
        return t("taskMessage.toBeApproved");
      }
      if (type === 2) {
        return t("taskMessage.rejected");
      }
      if (type === 3) {
        return t("taskMessage.agreed");
      }
      return "";
    };
    const changeStatusFun = async (item, status) => {
      try {
        const res = await changeStatus({ id: item.id, status: status });
        showSuccessToast({
          message: res.data.message,
          forbidClick: true,
          duration: 1500,
        });
        setTimeout(() => {
          router.go(0); // 刷新当前页面
        }, 1500); // 延迟1.5秒后执行刷新操作
      } catch (error) {
        console.error(error);
        // 处理错误情况
      }
      // changeStatus({ id: item.id, status: status }).then((res) => {
      //   getList();
      // });
    };
    // 是否有操作的权限
    const isOper = ref(true);
    // 初始化页面获取列表
    onMounted(async () => {
      if (user) {
        searchParams.adminId = user.id;
        searchGetList();
        // 如果是type大于1，那么不能有操作的权限
        if (user.type > 1) {
          isOper.value = false;
        }
      }
    });
    return {
      loading,
      error,
      finished,
      onLoad,
      alarmHistoryList,
      alarmHistoryTotal,
      showDateTime,
      showItemType,
      changeStatusFun,
      kDialogRef,
      noticeClk,
      confirmClk,
      busiInpClk,
      busiPopConfirm,
      busiPopShow,
      searchForm,
      busiPopList,
      busiPopFieldName,
      reviewedClk,
      isOper,
    };
  },
};
</script>

<style lang="less" scoped>
@theme-color: #4d6add;
@pending-color: #ff9800;
@approved-color: #4caf50;
@rejected-color: #f44336;
@light-bg: #f5f8ff;
@card-shadow: 0 3px 10px rgba(77, 106, 221, 0.15);
@hover-shadow: 0 8px 15px rgba(77, 106, 221, 0.2);
@transition: all 0.3s ease;
@text-dark: #333;
@text-light: #666;
@text-lighter: #999;
@border-radius: 12px;

.task-page {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background-color: @light-bg;
}

.task-container {
  flex: 1;
  padding: 15px;
  overflow-y: auto;
}

.header-info {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding: 12px 15px;
  background: white;
  border-radius: @border-radius;
  box-shadow: @card-shadow;
}

.total-card {
  display: flex;
  align-items: center;
}

.icon-box {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: fade(@theme-color, 8%);
  border-radius: 10px;
  margin-right: 12px;

  .equipment-icon {
    color: @theme-color;
    font-size: 24px;
  }
}

.total-info {
  font-size: 12px;
  color: @text-dark;

  .highlight {
    color: @theme-color;
    font-size: 15px;
    font-weight: bold;
    margin: 0 3px;
  }
}

.actions {
  display: flex;
  gap: 10px;
}

.action-btn {
  height: 32px;
  padding: 0 12px;
  border-color: fade(@theme-color, 50%);
  color: @theme-color;

}

.list-container {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.list-card {
  background: white;
  border-radius: @border-radius;
  box-shadow: @card-shadow;
  padding: 16px;
  transition: @transition;
  position: relative;
  overflow: hidden;

  &.pending {
    border-left: 3px solid @pending-color;

    .status-tag {
      background-color: fade(@pending-color, 15%);
      color: darken(@pending-color, 10%);
    }
  }

  &.approved {
    border-left: 3px solid @approved-color;

    .status-tag {
      background-color: fade(@approved-color, 15%);
      color: darken(@approved-color, 10%);
    }
  }

  &.rejected {
    border-left: 3px solid @rejected-color;

    .status-tag {
      background-color: fade(@rejected-color, 15%);
      color: darken(@rejected-color, 10%);
    }
  }

  &:hover {
    transform: translateY(-2px);
    box-shadow: @hover-shadow;
  }
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
  padding-bottom: 12px;
  border-bottom: 1px solid fade(@theme-color, 10%);
}

.status-tag {
  padding: 4px 10px;
  border-radius: 30px;
  font-size: 13px;
  font-weight: 600;
  min-width: 60px;
  text-align: center;
}

.time-label {
  font-size: 12px;
  color: @text-lighter;
}

.card-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.info-row {
  display: flex;
  align-items: flex-start;

  .row-icon {
    flex-shrink: 0;
    font-size: 18px;
    color: @theme-color;
    margin-right: 10px;
    margin-top: 2px;
  }

  .row-content {
    flex: 1;
    font-size: 14px;
  }

  .label {
    color: @text-light;
    min-width: 90px;
    display: inline-block;
  }

  .value {
    color: @text-dark;
    word-break: break-all;
  }
}

.card-actions {
  display: flex;
  justify-content: flex-end;
  gap: 15px;
  margin-top: 15px;
  padding-top: 15px;
  border-top: 1px dashed fade(@theme-color, 15%);

  .reject-btn,
  .approve-btn {
    min-width: 90px;
    height: 34px;
    padding: 0 15px;
    font-size: 13px;

    .btn-icon {
      vertical-align: -2px;
      margin-right: 5px;
    }
  }

  .reject-btn {
    border-color: fade(@rejected-color, 50%);
    color: @rejected-color;
    background-color: fade(@rejected-color, 8%);
  }

  .approve-btn {
    border-color: fade(@approved-color, 50%);
    color: @approved-color;
    background-color: fade(@approved-color, 8%);
  }
}

.dialog-content {
  padding: 10px 0;

  :deep(.van-cell) {
    padding: 12px 0;
    border-bottom: 1px solid rgba(0, 0, 0, 0.05);
  }
}

.icon-container {
  display: flex;
  align-items: center;

  .clear-icon {
    color: #999;
    margin-right: 8px;
  }
}

/* 空状态样式 */
.empty-list {
  text-align: center;
  padding: 40px 20px;

  .empty-icon {
    font-size: 80px;
    color: fade(@theme-color, 20%);
    margin-bottom: 15px;
  }

  .empty-text {
    color: @text-light;
    font-size: 16px;
  }
}

/* 动画效果 */
@keyframes cardEntry {
  0% {
    transform: translateY(15px);
    opacity: 0;
  }
  100% {
    transform: translateY(0);
    opacity: 1;
  }
}

.list-card {
  animation: cardEntry 0.4s ease-out forwards;
  opacity: 0;
}
</style>
