From 4071a902f383275b7ed284876bbdf3e19cfa3522 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期一, 09 二月 2026 18:02:15 +0800
Subject: [PATCH] Merge branch 'dev_new' of http://114.132.189.42:9002/r/product-inventory-APP-before into dev_new

---
 src/pages/attendance/report.vue |  446 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 446 insertions(+), 0 deletions(-)

diff --git a/src/pages/attendance/report.vue b/src/pages/attendance/report.vue
new file mode 100644
index 0000000..7d50294
--- /dev/null
+++ b/src/pages/attendance/report.vue
@@ -0,0 +1,446 @@
+<template>
+  <view class="attendance-report">
+    <!-- 椤甸潰澶撮儴 -->
+    <PageHeader title="鑰冨嫟鏃ユ姤"
+                @back="goBack" />
+    <!-- 鎼滅储鍜岀瓫閫夊尯鍩� -->
+    <view class="search-section">
+      <view class="search-bar">
+        <view @click="selectDate"
+              class="search-input">
+          <view class="search-text">{{ searchForm.date? searchForm.date : '璇烽�夋嫨鏃ユ湡' }}</view>
+        </view>
+        <view class="filter-button"
+              @click="clearDate">
+          <u-icon name="close-circle"
+                  size="24"
+                  color="#999"></u-icon>
+        </view>
+      </view>
+    </view>
+    <!-- 鏃ユ湡閫夋嫨鍣� -->
+    <up-datetime-picker :show="showDatePicker"
+                        mode="date"
+                        v-model="currentDate"
+                        @confirm="handleDateConfirm"
+                        @cancel="showDatePicker = false"
+                        title="鎼滅储鏃ユ湡" />
+    <view class="record-list">
+      <view v-for="(item) in tableData"
+            :key="item.id"
+            class="record-item-card"
+            :class="{ 'abnormal': item.status !== 'normal' }">
+        <view class="record-item-header">
+          <text class="record-date">{{ item.date }}</text>
+          <u-tag :type="item.status === 'normal' ? 'success' : 'error'"
+                 size="small">
+            {{ item.statusText }}
+          </u-tag>
+        </view>
+        <view class="record-item-body">
+          <view class="record-detail">
+            <text class="detail-label">鍛樺伐</text>
+            <text class="detail-value">{{ item.name }} ({{ item.no }})</text>
+          </view>
+          <view class="record-detail">
+            <text class="detail-label">閮ㄩ棬</text>
+            <text class="detail-value">{{ item.dept }}</text>
+          </view>
+          <view class="record-detail">
+            <text class="detail-label">涓婄彮鏃堕棿</text>
+            <text class="detail-value">{{ item.checkInTime ? item.checkInTime : '缂哄崱' }}</text>
+          </view>
+          <view class="record-detail">
+            <text class="detail-label">涓嬬彮鏃堕棿</text>
+            <text class="detail-value">{{ item.checkOutTime? item.checkOutTime : '缂哄崱' }}</text>
+          </view>
+          <view class="record-detail">
+            <text class="detail-label">宸ユ椂</text>
+            <text class="detail-value">{{ item.workHours ? item.workHours + '灏忔椂' : '-' }}</text>
+          </view>
+          <view v-if="item.remark"
+                class="record-detail">
+            <text class="detail-label">澶囨敞</text>
+            <text class="detail-value">{{ item.remark }}</text>
+          </view>
+        </view>
+      </view>
+      <!-- 绌虹姸鎬� -->
+      <view v-if="tableData.length === 0"
+            class="empty-state">
+        <u-icon name="clock-o"
+                size="60"
+                color="#999"></u-icon>
+        <text class="empty-text">鏆傛棤鑰冨嫟璁板綍</text>
+      </view>
+    </view>
+    <!-- 瀵煎嚭鎸夐挳 -->
+    <!-- <view class="export-section">
+      <u-button type="default"
+                size="medium"
+                text="瀵煎嚭鑰冨嫟鏃ユ姤"
+                @click="handleExport"
+                class="export-btn"></u-button>
+    </view> -->
+  </view>
+</template>
+
+<script setup>
+  import { ref, reactive, onMounted } from "vue";
+  import PageHeader from "@/components/PageHeader.vue";
+  import dayjs from "dayjs";
+
+  // 妯℃嫙褰撳墠鐧诲綍鍛樺伐
+  const currentUser = reactive({
+    id: 1,
+    name: "寮犱笁",
+    no: "E10001",
+    dept: "鐢熶骇涓�閮�",
+  });
+
+  // 妯℃嫙鑰冨嫟鍘熷鏁版嵁
+  const rawAttendance = ref([
+    {
+      id: 1,
+      date: "2026-02-09",
+      userId: 1,
+      name: "寮犱笁",
+      no: "E10001",
+      dept: "鐢熶骇涓�閮�",
+      checkInTime: "08:58",
+      checkOutTime: "",
+      workHours: null,
+      status: "normal",
+      statusText: "姝e父",
+      remark: "",
+    },
+    {
+      id: 2,
+      date: "2026-02-08",
+      userId: 1,
+      name: "寮犱笁",
+      no: "E10001",
+      dept: "鐢熶骇涓�閮�",
+      checkInTime: "09:15",
+      checkOutTime: "18:05",
+      workHours: 8.8,
+      status: "late",
+      statusText: "杩熷埌",
+      remark: "鍥犱氦閫氭嫢鍫佃繜鍒�",
+    },
+    {
+      id: 3,
+      date: "2026-02-07",
+      userId: 1,
+      name: "寮犱笁",
+      no: "E10001",
+      dept: "鐢熶骇涓�閮�",
+      checkInTime: "08:45",
+      checkOutTime: "18:30",
+      workHours: 9.7,
+      status: "normal",
+      statusText: "姝e父",
+      remark: "鍔犵彮0.5灏忔椂",
+    },
+    {
+      id: 4,
+      date: "2026-02-06",
+      userId: 1,
+      name: "寮犱笁",
+      no: "E10001",
+      dept: "鐢熶骇涓�閮�",
+      checkInTime: "08:50",
+      checkOutTime: "17:45",
+      workHours: 8.9,
+      status: "early",
+      statusText: "鏃╅��",
+      remark: "瀹朵腑鏈変簨鎻愬墠绂诲紑",
+    },
+    {
+      id: 5,
+      date: "2026-02-05",
+      userId: 1,
+      name: "寮犱笁",
+      no: "E10001",
+      dept: "鐢熶骇涓�閮�",
+      checkInTime: "08:40",
+      checkOutTime: "18:20",
+      workHours: 9.7,
+      status: "normal",
+      statusText: "姝e父",
+      remark: "鍔犵彮0.5灏忔椂",
+    },
+  ]);
+
+  // 鏌ヨ琛ㄥ崟
+  const searchForm = reactive({
+    date: "",
+  });
+
+  // 琛ㄦ牸鏁版嵁
+  const tableData = ref([]);
+
+  // 杩斿洖涓婁竴椤�
+  const goBack = () => {
+    uni.navigateBack();
+  };
+
+  // 鏃ユ湡閫夋嫨鍣�
+  const showDatePicker = ref(false);
+  const currentDate = ref(new Date());
+
+  // 澶勭悊鏃ユ湡閫夋嫨
+  const handleDateConfirm = e => {
+    currentDate.value = e.value;
+    searchForm.date = dayjs(e.value).format("YYYY-MM-DD");
+    showDatePicker.value = false;
+    handleQuery();
+  };
+
+  // 鏄剧ず鏃ユ湡閫夋嫨鍣�
+  const selectDate = () => {
+    showDatePicker.value = true;
+  };
+
+  // 娓呴櫎鏃ユ湡閫夋嫨
+  const clearDate = () => {
+    searchForm.date = "";
+    handleQuery();
+  };
+
+  // 鏌ヨ
+  const recomputeTable = () => {
+    const list = rawAttendance.value.filter(item => {
+      if (searchForm.date && item.date !== searchForm.date) {
+        return false;
+      }
+      return true;
+    });
+    tableData.value = list;
+  };
+
+  const handleQuery = () => {
+    recomputeTable();
+  };
+
+  onMounted(() => {
+    recomputeTable();
+  });
+</script>
+
+<style scoped lang="scss">
+  // 鍏ㄥ眬鍙橀噺
+  $primary-color: #2c7be5;
+  $primary-light: #4a90e2;
+  $success-color: #4cd964;
+  $warning-color: #ff9500;
+  $danger-color: #ff3b30;
+  $text-primary: #333333;
+  $text-secondary: #666666;
+  $text-tertiary: #999999;
+  $bg-color: #f5f7fa;
+  $card-bg: #ffffff;
+  $border-color: #e8e8e8;
+  $shadow-sm: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
+  $shadow-md: 0 4rpx 16rpx rgba(0, 0, 0, 0.12);
+  $shadow-lg: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
+
+  .attendance-report {
+    min-height: 100vh;
+    background-color: $bg-color;
+    padding-bottom: 30rpx;
+    background-image: linear-gradient(135deg, #f5f7fa 0%, #e4e8f0 100%);
+  }
+
+  /* 鎼滅储鍜岀瓫閫夊尯鍩� */
+  .search-section {
+    background-color: $card-bg;
+    margin: 20rpx;
+    border-radius: 16rpx;
+    box-shadow: $shadow-md;
+    padding: 20rpx;
+    margin-bottom: 24rpx;
+    transition: all 0.3s ease;
+  }
+
+  .search-section:hover {
+    box-shadow: $shadow-lg;
+    transform: translateY(-2rpx);
+  }
+
+  .search-bar {
+    display: flex;
+    align-items: center;
+    background-color: rgba($primary-color, 0.05);
+    border-radius: 8rpx;
+    padding: 0 16rpx;
+    height: 70rpx;
+  }
+
+  .search-input {
+    flex: 1;
+    height: 100%;
+    display: flex;
+    align-items: center;
+  }
+
+  .search-text {
+    font-size: 14px;
+    color: $text-tertiary;
+    height: 70rpx;
+    line-height: 70rpx;
+    margin-left: 8rpx;
+  }
+
+  .filter-button {
+    padding: 8rpx;
+    transition: all 0.3s ease;
+  }
+
+  .filter-button:hover {
+    background-color: rgba($primary-color, 0.1);
+    border-radius: 4rpx;
+  }
+
+  /* 璁板綍鍒楄〃 */
+  .record-list {
+    margin: 0 20rpx 24rpx;
+  }
+
+  .record-item-card {
+    background-color: $card-bg;
+    border-radius: 16rpx;
+    box-shadow: $shadow-md;
+    margin-bottom: 24rpx;
+    overflow: hidden;
+    transition: all 0.3s ease;
+  }
+
+  .record-item-card:hover {
+    box-shadow: $shadow-lg;
+    transform: translateY(-2rpx);
+  }
+
+  .record-item-card.abnormal {
+    background-color: rgba($danger-color, 0.05);
+    border-left: 4rpx solid $danger-color;
+  }
+
+  .record-item-header {
+    background-color: rgba($primary-color, 0.05);
+    padding: 20rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    border-bottom: 1rpx solid $border-color;
+  }
+
+  .record-date {
+    font-size: 14px;
+    font-weight: 600;
+    color: $text-primary;
+  }
+
+  .record-item-body {
+    padding: 24rpx;
+  }
+
+  .record-detail {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 16rpx;
+    padding: 8rpx 0;
+    border-bottom: 1rpx solid rgba($border-color, 0.5);
+  }
+
+  .record-detail:last-child {
+    margin-bottom: 0;
+    border-bottom: none;
+  }
+
+  .detail-label {
+    font-size: 13px;
+    color: $text-secondary;
+    font-weight: 500;
+  }
+
+  .detail-value {
+    font-size: 13px;
+    color: $text-primary;
+    font-weight: 500;
+  }
+
+  /* 绌虹姸鎬� */
+  .empty-state {
+    background-color: $card-bg;
+    border-radius: 16rpx;
+    box-shadow: $shadow-md;
+    text-align: center;
+    padding: 120rpx 0;
+    margin: 0 20rpx;
+    transition: all 0.3s ease;
+  }
+
+  .empty-state:hover {
+    box-shadow: $shadow-lg;
+  }
+
+  .empty-text {
+    font-size: 14px;
+    color: $text-tertiary;
+    margin-top: 24rpx;
+    font-weight: 500;
+  }
+
+  /* 鍝嶅簲寮忚皟鏁� */
+  @media (max-width: 375px) {
+    .search-section,
+    .record-list,
+    .empty-state {
+      margin: 12rpx;
+    }
+
+    .search-section {
+      padding: 16rpx;
+    }
+
+    .record-item-body {
+      padding: 20rpx;
+    }
+  }
+
+  /* 鍔ㄧ敾鏁堟灉 */
+  @keyframes fadeInUp {
+    from {
+      opacity: 0;
+      transform: translateY(20rpx);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+
+  .search-section,
+  .record-item-card,
+  .empty-state {
+    animation: fadeInUp 0.5s ease-out;
+  }
+
+  .record-item-card {
+    animation-delay: 0.1s;
+  }
+
+  .record-item-card:nth-child(2) {
+    animation-delay: 0.2s;
+  }
+
+  .record-item-card:nth-child(3) {
+    animation-delay: 0.3s;
+  }
+
+  .empty-state {
+    animation-delay: 0.2s;
+  }
+</style>
\ No newline at end of file

--
Gitblit v1.9.3