diff --git a/src/detail/detail.js b/src/detail/detail.js
new file mode 100644
index 0000000..a55d8dc
--- /dev/null
+++ b/src/detail/detail.js
@@ -0,0 +1,404 @@
+Page({
+ data: {
+ currentItem: {},
+ showMap: false,
+ mapLongitude: 117.352447, // 默认校区中心经度
+ mapLatitude: 39.111039, // 默认校区中心纬度
+ markers: [],
+ showClaimModal: false,
+ claimPhone: '',
+ phoneError: false,
+ apiBaseUrl: 'http://10.11.72.16:8000/api',
+ itemId: null // 新增:存储物品ID
+ },
+
+ onLoad(options) {
+ if (options.item) {
+ const item = JSON.parse(decodeURIComponent(options.item))
+ console.log('详情页接收到的数据:', item)
+
+ // 存储物品ID
+ this.setData({
+ itemId: item.id || item.number
+ })
+
+ // 直接从服务器获取最新数据,确保状态同步
+ this.fetchCompleteItemInfo(item.id || item.number)
+ } else if (options.id) {
+ // 如果直接传递ID,也支持
+ this.setData({
+ itemId: options.id
+ })
+ this.fetchCompleteItemInfo(options.id)
+ }
+ },
+
+ onShow() {
+ // 页面显示时重新获取数据,确保状态最新
+ if (this.data.itemId) {
+ this.fetchCompleteItemInfo(this.data.itemId)
+ }
+ },
+
+ // 从服务器获取完整的物品信息 - 优化版本
+ // 在 fetchCompleteItemInfo 方法中,修改状态处理部分
+fetchCompleteItemInfo(itemId) {
+ const that = this
+ console.log('🔄 开始获取物品详情,ID:', itemId)
+
+ wx.request({
+ url: `${this.data.apiBaseUrl}/items/`,
+ method: 'GET',
+ success(res) {
+ console.log('📡 服务器响应:', res)
+
+ if (res.data.success && res.data.data) {
+ // 在所有物品中查找匹配的完整信息
+ const completeItem = res.data.data.find(item => {
+ const match = (item.id === itemId) ||
+ (item.number === itemId) ||
+ (item.id && item.id.toString() === itemId.toString()) ||
+ (item.number && item.number.toString() === itemId.toString())
+ return match
+ })
+
+ if (completeItem) {
+ console.log('✅ 获取到完整物品信息:', completeItem)
+
+ // 状态值转换:将英文状态转换为中文
+ let stateDisplay = completeItem.state || '未领取';
+ if (stateDisplay === 'unclaimed') {
+ stateDisplay = '未领取';
+ } else if (stateDisplay === 'claimed') {
+ stateDisplay = '已领取';
+ }
+
+ // 构建完整的物品对象
+ const itemData = {
+ id: completeItem.id || completeItem.number,
+ name: completeItem.object || completeItem.name,
+ color: completeItem.color,
+ feature: completeItem.feature,
+ brand: completeItem.brand,
+ location: completeItem.location,
+ telephone: completeItem.telephone,
+ icon: that.generateItemIcon(completeItem.object || completeItem.name),
+ description: `${completeItem.color}的${completeItem.object || completeItem.name},${completeItem.feature},品牌:${completeItem.brand}`,
+ // 使用转换后的状态值
+ state: stateDisplay,
+ claim_phone: completeItem.claim_phone || '',
+ number: completeItem.number || `CAUC${(completeItem.id || completeItem.number).toString().padStart(8, '0')}`,
+ create_time: completeItem.create_time
+ }
+
+ that.setData({
+ currentItem: itemData
+ })
+ that.initMapMarkers(completeItem.location)
+
+ console.log('📊 最终设置的物品数据:', that.data.currentItem)
+ } else {
+ console.error('❌ 未找到对应的物品')
+ wx.showToast({
+ title: '物品信息获取失败',
+ icon: 'none'
+ })
+ }
+ } else {
+ console.error('❌ 服务器返回数据格式错误')
+ wx.showToast({
+ title: '数据格式错误',
+ icon: 'none'
+ })
+ }
+ },
+ fail(err) {
+ console.error('❌ 获取物品信息失败:', err)
+ wx.showToast({
+ title: '网络连接失败',
+ icon: 'none'
+ })
+ }
+ })
+ },
+
+ // 生成物品图标
+ generateItemIcon(itemName) {
+ const iconMap = {
+ '手机': '📱', '耳机': '🎧', '钱包': '👛', '钥匙': '🔑', '水杯': '🥤',
+ '书包': '🎒', '书本': '📚', '电脑': '💻', '眼镜': '👓', '手表': '⌚',
+ '校园卡': '💳', '身份证': '🆔', '充电宝': '🔋', 'U盘': '💾', '鼠标': '🖱️',
+ '保温杯': '🥤', '充电器': '🔌', '数据线': '🔗', '台灯': '💡', '雨伞': '☂️'
+ };
+
+ for (let key in iconMap) {
+ if (itemName.includes(key)) {
+ return iconMap[key];
+ }
+ }
+ return '📦';
+ },
+
+ // 初始化地图标记
+ initMapMarkers(location) {
+ // 中国民航大学东丽校区各公寓位置坐标
+ const locationCoordinates = {
+ '北教25A座': { latitude: 39.116404, longitude: 117.350928 },
+ '校史馆': { latitude: 39.113829, longitude: 117.349670 },
+ '航空工程学院': { latitude: 39.111647, longitude: 117.348411 },
+ '理学院': { latitude: 39.105889, longitude: 117.353043 },
+ '南9公寓': { latitude: 39.103560, longitude: 117.354630 },
+ '南7公寓': { latitude: 39.102861, longitude: 117.354008 },
+ '厦航天合餐厅': { latitude: 39.103335, longitude: 117.352625 },
+ '明德图书馆': { latitude: 39.101322, longitude: 117.354898 },
+ '南22公寓': { latitude: 39.101205, longitude: 117.352368 },
+ '北19公寓': { latitude: 39.111039, longitude: 117.352447 },
+ '北14公寓': { latitude: 39.110350, longitude: 117.350845 },
+ '北28公寓': { latitude: 39.112571, longitude: 117.353174 },
+ '北8公寓': { latitude: 39.114969, longitude: 117.351384 },
+ // 默认使用校区中心坐标
+ 'default': { latitude: 39.111039, longitude: 117.352447 }
+ }
+
+ // 查找匹配的位置(支持模糊匹配)
+ let coordinates = locationCoordinates['default'];
+ let matchedLocation = 'default';
+
+ // 遍历所有位置名称,查找匹配项
+ for (const key in locationCoordinates) {
+ if (key !== 'default' && location.includes(key)) {
+ coordinates = locationCoordinates[key];
+ matchedLocation = key;
+ break;
+ }
+ }
+
+ // 如果上面没有匹配到,再尝试精确匹配
+ if (matchedLocation === 'default' && locationCoordinates[location]) {
+ coordinates = locationCoordinates[location];
+ matchedLocation = location;
+ }
+
+ console.log('输入位置:', location, '匹配到:', matchedLocation, '坐标:', coordinates);
+
+ const markers = [{
+ id: 0,
+ latitude: coordinates.latitude,
+ longitude: coordinates.longitude,
+ title: matchedLocation === 'default' ? '校区中心' : matchedLocation,
+ iconPath: '/images/marker.png',
+ width: 35,
+ height: 35,
+ callout: {
+ content: matchedLocation === 'default' ? `📍 ${location}\n(使用默认位置)` : `📍 ${matchedLocation}`,
+ color: '#007AFF',
+ fontSize: 14,
+ borderRadius: 10,
+ bgColor: '#ffffff',
+ padding: 10,
+ display: 'ALWAYS'
+ }
+ }]
+
+ this.setData({
+ markers: markers,
+ mapLongitude: coordinates.longitude,
+ mapLatitude: coordinates.latitude
+ });
+
+ // 如果是地图视图,确保地图定位到正确位置
+ if (this.data.showMap) {
+ this.adjustMapPosition();
+ }
+ },
+
+ // 显示地图视图
+ showMapView() {
+ this.setData({
+ showMap: true
+ }, () => {
+ // 地图显示后确保定位准确
+ setTimeout(() => {
+ this.adjustMapPosition();
+ }, 300);
+ })
+ },
+
+ // 隐藏地图视图
+ hideMapView() {
+ this.setData({
+ showMap: false
+ })
+ },
+
+ // 调整地图位置到标记点
+ adjustMapPosition() {
+ const mapContext = wx.createMapContext('campusMap');
+ if (this.data.markers.length > 0) {
+ const marker = this.data.markers[0];
+ mapContext.moveToLocation({
+ longitude: marker.longitude,
+ latitude: marker.latitude,
+ success: () => {
+ console.log('地图定位成功');
+ },
+ fail: (err) => {
+ console.log('地图定位失败:', err);
+ }
+ });
+ }
+ },
+
+ // 标记点点击事件
+ onMarkerTap(e) {
+ console.log('标记点被点击', e.markerId);
+ const marker = this.data.markers.find(m => m.id === e.markerId);
+ if (marker) {
+ wx.showToast({
+ title: marker.title,
+ icon: 'none'
+ });
+ }
+ },
+
+ // 地图区域变化事件
+ onRegionChange(e) {
+ console.log('地图区域变化', e.type);
+ },
+
+ // 显示认领模态框
+ showClaimModal() {
+ const currentItem = this.data.currentItem;
+
+ // 检查物品状态
+ if (currentItem.state === '已领取') {
+ wx.showToast({
+ title: '该物品已被认领',
+ icon: 'none'
+ });
+ return;
+ }
+
+ this.setData({
+ showClaimModal: true,
+ claimPhone: '',
+ phoneError: false
+ });
+ },
+
+ // 隐藏认领模态框
+ hideClaimModal() {
+ this.setData({
+ showClaimModal: false,
+ claimPhone: '',
+ phoneError: false
+ });
+ },
+
+ // 认领手机号输入
+ onClaimPhoneInput(e) {
+ const phone = e.detail.value;
+ const phoneRegex = /^1[3-9]\d{9}$/;
+ const isValid = phoneRegex.test(phone);
+
+ this.setData({
+ claimPhone: phone,
+ phoneError: !isValid && phone.length > 0
+ });
+
+ if (phone.length === 11 && !isValid) {
+ wx.showToast({
+ title: '手机号格式错误',
+ icon: 'none'
+ });
+ }
+ },
+
+ // 确认认领
+ confirmClaim() {
+ const that = this;
+ const { claimPhone, currentItem, itemId } = this.data;
+
+ // 验证手机号
+ const phoneRegex = /^1[3-9]\d{9}$/;
+ if (!phoneRegex.test(claimPhone)) {
+ this.setData({
+ phoneError: true
+ });
+ wx.showToast({
+ title: '请输入正确的手机号',
+ icon: 'none'
+ });
+ return;
+ }
+
+ // 发送认领请求
+ wx.showLoading({
+ title: '认领中...',
+ mask: true
+ });
+
+ wx.request({
+ url: `${this.data.apiBaseUrl}/claim-item/`,
+ method: 'POST',
+ header: {
+ 'Content-Type': 'application/json'
+ },
+ data: {
+ item_id: itemId || currentItem.id || currentItem.number,
+ claim_phone: claimPhone
+ },
+ success(res) {
+ wx.hideLoading();
+
+ if (res.data.success) {
+ wx.showToast({
+ title: '认领成功',
+ icon: 'success',
+ duration: 2000
+ });
+
+ // 重新从服务器获取最新数据
+ setTimeout(() => {
+ that.fetchCompleteItemInfo(that.data.itemId);
+ }, 500);
+
+ that.setData({
+ showClaimModal: false
+ });
+ } else {
+ wx.showToast({
+ title: res.data.message || '认领失败',
+ icon: 'none',
+ duration: 3000
+ });
+ }
+ },
+ fail(err) {
+ wx.hideLoading();
+ wx.showToast({
+ title: '网络连接失败',
+ icon: 'none'
+ });
+ }
+ });
+ },
+
+ // 刷新数据
+ refreshData() {
+ if (this.data.itemId) {
+ this.fetchCompleteItemInfo(this.data.itemId);
+ wx.showToast({
+ title: '刷新成功',
+ icon: 'success'
+ });
+ }
+ },
+
+ onShareAppMessage() {
+ return {
+ title: `失物招领 - ${this.data.currentItem.name}`,
+ path: `/pages/detail/detail?item=${encodeURIComponent(JSON.stringify(this.data.currentItem))}`
+ }
+ }
+ })
\ No newline at end of file
diff --git a/src/detail/detail.json b/src/detail/detail.json
new file mode 100644
index 0000000..8b3f925
--- /dev/null
+++ b/src/detail/detail.json
@@ -0,0 +1,4 @@
+{
+ "usingComponents": {},
+ "navigationBarTitleText": "物品详情"
+}
\ No newline at end of file
diff --git a/src/detail/detail.wxml b/src/detail/detail.wxml
new file mode 100644
index 0000000..241f6c7
--- /dev/null
+++ b/src/detail/detail.wxml
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+ 物品名称:
+ {{currentItem.name}}
+
+
+
+ 颜色:
+ {{currentItem.color}}
+
+
+
+ 特征:
+ {{currentItem.feature}}
+
+
+
+ 品牌:
+ {{currentItem.brand}}
+
+
+
+ 联系方式:
+ {{currentItem.telephone}}
+
+
+
+ 当前位置:
+ {{currentItem.location}}
+
+
+
+ 详细描述:
+ {{currentItem.description}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 📍 {{currentItem.location}}
+ {{currentItem.name}} - {{currentItem.color}}
+
+
+
+
+
+
+
+
+
+ 物品状态:
+
+ {{currentItem.state || '未领取'}}
+
+
+
+
+ 认领人手机:
+ {{currentItem.claim_phone}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 请输入您的手机号进行认领:
+
+ 手机号格式不正确
+
+
+
+
+
\ No newline at end of file
diff --git a/src/detail/detail.wxss b/src/detail/detail.wxss
new file mode 100644
index 0000000..c003781
--- /dev/null
+++ b/src/detail/detail.wxss
@@ -0,0 +1,602 @@
+.container {
+ padding: 40rpx;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ min-height: 100vh;
+}
+
+.detail-card {
+ background: white;
+ border-radius: 32rpx;
+ padding: 60rpx 40rpx;
+ box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.1);
+ margin-top: 40rpx;
+}
+
+/* 物品头部 */
+.item-header {
+ text-align: center;
+ margin-bottom: 60rpx;
+ padding-bottom: 40rpx;
+ border-bottom: 2rpx solid #f0f0f0;
+}
+
+.item-icon {
+ font-size: 120rpx;
+ display: block;
+ margin-bottom: 20rpx;
+}
+
+.item-title {
+ font-size: 48rpx;
+ font-weight: bold;
+ color: #333;
+}
+
+/* 信息区域 */
+.info-section {
+ margin-bottom: 60rpx;
+}
+
+.info-row {
+ display: flex;
+ align-items: flex-start;
+ margin-bottom: 40rpx;
+ padding: 20rpx 0;
+ border-bottom: 1rpx solid #f8f8f8;
+}
+
+.info-row.full-width {
+ flex-direction: column;
+}
+
+.info-label {
+ width: 200rpx;
+ font-size: 28rpx;
+ color: #666;
+ font-weight: bold;
+ flex-shrink: 0;
+}
+
+.info-value {
+ flex: 1;
+ font-size: 28rpx;
+ color: #333;
+ line-height: 1.6;
+}
+
+.info-value.description {
+ background-color: #f8f8f8;
+ padding: 30rpx;
+ border-radius: 16rpx;
+ margin-top: 20rpx;
+}
+
+/* 操作按钮 */
+.action-buttons {
+ display: flex;
+ gap: 20rpx;
+}
+
+.contact-btn {
+ flex: 1;
+ background-color: #007AFF;
+ color: white;
+ border: none;
+ border-radius: 16rpx;
+ padding: 28rpx;
+ font-size: 32rpx;
+ font-weight: bold;
+}
+
+/* 地图容器 */
+.map-container {
+ height: 1300rpx;
+ background: white;
+ border-radius: 32rpx;
+ overflow: hidden;
+ margin-top: 20rpx;
+ box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.1);
+}
+
+.map-header {
+ display: flex;
+ align-items: center;
+ padding: 30rpx 40rpx;
+ background: linear-gradient(135deg, #007AFF 0%, #0056CC 100%);
+ color: white;
+}
+
+.back-btn {
+ display: flex;
+ align-items: center;
+ padding: 15rpx 25rpx;
+ background: rgba(255, 255, 255, 0.2);
+ border-radius: 25rpx;
+ margin-right: 30rpx;
+}
+
+.back-icon {
+ font-size: 32rpx;
+ margin-right: 10rpx;
+}
+
+.back-text {
+ font-size: 28rpx;
+}
+
+.map-title {
+ flex: 1;
+ font-size: 32rpx;
+ font-weight: bold;
+ text-align: center;
+}
+
+.campus-map {
+ width: 100%;
+ height: 1030rpx;
+}
+
+.map-info {
+ padding: 30rpx 40rpx;
+ background: #f8f8f8;
+}
+
+.location-info {
+ display: block;
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+ margin-bottom: 15rpx;
+}
+
+.item-info {
+ display: block;
+ font-size: 28rpx;
+ color: #666;
+}
+
+/* 在原有样式基础上添加以下样式 */
+
+/* 状态信息样式 */
+.status-section {
+ background: #fff;
+ padding: 20rpx;
+ margin: 20rpx;
+ border-radius: 10rpx;
+ box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
+ }
+
+ .status-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15rpx 0;
+ border-bottom: 1rpx solid #f5f5f5;
+ }
+
+ .status-item:last-child {
+ border-bottom: none;
+ }
+
+ .status-label {
+ font-size: 28rpx;
+ color: #666;
+ }
+
+ .status-value {
+ font-size: 28rpx;
+ font-weight: bold;
+ }
+
+ .status-value.unclaimed {
+ color: #e74c3c;
+ }
+
+ .status-value.claimed {
+ color: #27ae60;
+ }
+
+ .claim-phone {
+ font-size: 28rpx;
+ color: #27ae60;
+ font-weight: bold;
+ }
+
+ /* 认领按钮样式 */
+ .claim-section {
+ padding: 20rpx;
+ margin: 20rpx;
+ }
+
+ .claim-btn {
+ background: #07c160;
+ color: white;
+ border-radius: 50rpx;
+ font-size: 32rpx;
+ padding: 20rpx 0;
+ }
+
+ .claim-btn:active {
+ background: #06a952;
+ }
+
+ /* 模态框样式 */
+ .modal-mask {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 999;
+ }
+
+ .modal-content {
+ background: white;
+ border-radius: 20rpx;
+ width: 600rpx;
+ overflow: hidden;
+ }
+
+ .modal-header {
+ padding: 30rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+ text-align: center;
+ }
+
+ .modal-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+ }
+
+ .modal-body {
+ padding: 40rpx 30rpx;
+ }
+
+ .modal-tip {
+ font-size: 28rpx;
+ color: #666;
+ margin-bottom: 30rpx;
+ display: block;
+ }
+
+ .phone-input {
+ border: 2rpx solid #e0e0e0;
+ border-radius: 10rpx;
+ padding: 20rpx;
+ font-size: 28rpx;
+ margin-bottom: 10rpx;
+ }
+
+ .phone-input.error {
+ border-color: #e74c3c;
+ }
+
+ .error-text {
+ color: #e74c3c;
+ font-size: 24rpx;
+ }
+
+ .modal-footer {
+ display: flex;
+ border-top: 1rpx solid #f0f0f0;
+ }
+
+ .btn-cancel, .btn-confirm {
+ flex: 1;
+ border: none;
+ border-radius: 0;
+ padding: 25rpx 0;
+ font-size: 28rpx;
+ }
+
+ .btn-cancel {
+ background: #f8f8f8;
+ color: #666;
+ border-right: 1rpx solid #f0f0f0;
+ }
+
+ .btn-confirm {
+ background: #07c160;
+ color: white;
+ }
+
+ .btn-cancel:active {
+ background: #e8e8e8;
+ }
+
+ .btn-confirm:active {
+ background: #06a952;
+ }
+
+ /* 在原有样式基础上添加以下样式 */
+
+/* 在原有样式基础上添加以下样式 */
+
+.container {
+ padding-bottom: 40rpx;
+ }
+
+ .section-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20rpx;
+ }
+
+ .section-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+ }
+
+ .refresh-btn {
+ background: #1989fa;
+ color: white;
+ font-size: 24rpx;
+ padding: 10rpx 20rpx;
+ border-radius: 20rpx;
+ }
+
+ .item-card {
+ background: #fff;
+ padding: 30rpx;
+ margin: 20rpx;
+ border-radius: 15rpx;
+ box-shadow: 0 4rpx 15rpx rgba(0,0,0,0.1);
+ }
+
+ .item-header {
+ display: flex;
+ align-items: center;
+ margin-bottom: 20rpx;
+ }
+
+ .item-icon {
+ font-size: 48rpx;
+ margin-right: 20rpx;
+ }
+
+ .item-name {
+ font-size: 36rpx;
+ font-weight: bold;
+ color: #333;
+ }
+
+ .item-info {
+ margin-bottom: 25rpx;
+ }
+
+ .item-description {
+ font-size: 28rpx;
+ color: #666;
+ line-height: 1.5;
+ }
+
+ .item-details {
+ border-top: 1rpx solid #f0f0f0;
+ padding-top: 20rpx;
+ }
+
+ .detail-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 12rpx 0;
+ border-bottom: 1rpx solid #f8f8f8;
+ }
+
+ .detail-item:last-child {
+ border-bottom: none;
+ }
+
+ .detail-label {
+ font-size: 28rpx;
+ color: #666;
+ }
+
+ .detail-value {
+ font-size: 28rpx;
+ color: #333;
+ font-weight: 500;
+ }
+
+ .map-section {
+ background: #fff;
+ padding: 30rpx;
+ margin: 20rpx;
+ border-radius: 15rpx;
+ box-shadow: 0 4rpx 15rpx rgba(0,0,0,0.1);
+ }
+
+ .map-container {
+ margin-top: 20rpx;
+ }
+
+ .map-placeholder {
+ background: #f8f9fa;
+ border: 2rpx dashed #dee2e6;
+ border-radius: 10rpx;
+ padding: 60rpx 20rpx;
+ text-align: center;
+ }
+
+ .map-tip {
+ font-size: 28rpx;
+ color: #6c757d;
+ }
+
+ .map-actions {
+ margin-top: 20rpx;
+ text-align: center;
+ }
+
+ .btn-secondary {
+ background: #6c757d;
+ color: white;
+ font-size: 28rpx;
+ padding: 15rpx 30rpx;
+ border-radius: 25rpx;
+ }
+
+ /* 状态信息样式 */
+ .status-section {
+ background: #fff;
+ padding: 30rpx;
+ margin: 20rpx;
+ border-radius: 15rpx;
+ box-shadow: 0 4rpx 15rpx rgba(0,0,0,0.1);
+ }
+
+ .status-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20rpx 0;
+ border-bottom: 1rpx solid #f5f5f5;
+ }
+
+ .status-item:last-child {
+ border-bottom: none;
+ }
+
+ .status-label {
+ font-size: 28rpx;
+ color: #666;
+ font-weight: 500;
+ }
+
+ .status-value {
+ font-size: 28rpx;
+ font-weight: bold;
+ }
+
+ .status-value.unclaimed {
+ color: #e74c3c;
+ }
+
+ .status-value.claimed {
+ color: #27ae60;
+ }
+
+ .claim-phone {
+ font-size: 28rpx;
+ color: #27ae60;
+ font-weight: bold;
+ }
+
+ /* 认领按钮样式 */
+ .claim-section {
+ padding: 0 20rpx;
+ margin: 30rpx 20rpx;
+ }
+
+ .claim-btn {
+ background: #07c160;
+ color: white;
+ border-radius: 50rpx;
+ font-size: 32rpx;
+ padding: 25rpx 0;
+ font-weight: bold;
+ }
+
+ .claim-btn:active {
+ background: #06a952;
+ }
+
+ /* 模态框样式 */
+ .modal-mask {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 999;
+ }
+
+ .modal-content {
+ background: white;
+ border-radius: 20rpx;
+ width: 600rpx;
+ overflow: hidden;
+ }
+
+ .modal-header {
+ padding: 30rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+ text-align: center;
+ }
+
+ .modal-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+ }
+
+ .modal-body {
+ padding: 40rpx 30rpx;
+ }
+
+ .modal-tip {
+ font-size: 28rpx;
+ color: #666;
+ margin-bottom: 30rpx;
+ display: block;
+ }
+
+ .phone-input {
+ border: 2rpx solid #e0e0e0;
+ border-radius: 10rpx;
+ padding: 20rpx;
+ font-size: 28rpx;
+ margin-bottom: 10rpx;
+ }
+
+ .phone-input.error {
+ border-color: #e74c3c;
+ }
+
+ .error-text {
+ color: #e74c3c;
+ font-size: 24rpx;
+ }
+
+ .modal-footer {
+ display: flex;
+ border-top: 1rpx solid #f0f0f0;
+ }
+
+ .btn-cancel, .btn-confirm {
+ flex: 1;
+ border: none;
+ border-radius: 0;
+ padding: 25rpx 0;
+ font-size: 28rpx;
+ }
+
+ .btn-cancel {
+ background: #f8f8f8;
+ color: #666;
+ border-right: 1rpx solid #f0f0f0;
+ }
+
+ .btn-confirm {
+ background: #07c160;
+ color: white;
+ }
+
+ .btn-cancel:active {
+ background: #e8e8e8;
+ }
+
+ .btn-confirm:active {
+ background: #06a952;
+ }
\ No newline at end of file
diff --git a/src/index/index.js b/src/index/index.js
new file mode 100644
index 0000000..82b1440
--- /dev/null
+++ b/src/index/index.js
@@ -0,0 +1,218 @@
+// pages/home/home.js
+Page({
+ data: {
+ allItems: [],
+ isLoading: true,
+ apiBaseUrl: 'http://10.11.72.16:8000/api'
+ },
+
+ onLoad() {
+ this.loadAllItems();
+ },
+
+ onShow() {
+ // 每次页面显示时重新加载数据
+ this.loadAllItems();
+ },
+
+ // 加载所有物品(优先服务器,失败则使用本地)
+ loadAllItems() {
+ const that = this;
+ that.setData({ isLoading: true });
+
+ console.log('🔄 开始加载物品数据...');
+
+ // 优先从服务器加载
+ that.loadServerItems().then(serverItems => {
+ console.log('✅ 从服务器加载成功,物品数量:', serverItems.length);
+
+ that.setData({
+ allItems: serverItems,
+ isLoading: false
+ });
+
+ // 同时更新本地存储
+ that.updateLocalStorage(serverItems);
+
+ }).catch(err => {
+ console.log('❌ 服务器加载失败,尝试本地数据:', err);
+
+ // 服务器失败则使用本地数据
+ that.loadLocalItems().then(localItems => {
+ console.log('📱 从本地加载成功,物品数量:', localItems.length);
+
+ that.setData({
+ allItems: localItems,
+ isLoading: false
+ });
+
+ }).catch(localErr => {
+ console.log('❌ 本地加载也失败,使用默认数据:', localErr);
+ that.setDefaultItems();
+ });
+ });
+ },
+
+ // 加载本地物品
+ loadLocalItems() {
+ return new Promise((resolve, reject) => {
+ wx.getStorage({
+ key: 'lostItems',
+ success: (res) => {
+ if (res.data && res.data.length > 0) {
+ // 按时间倒序排序
+ const sortedItems = res.data.sort((a, b) =>
+ new Date(b.timestamp || 0) - new Date(a.timestamp || 0)
+ );
+ resolve(sortedItems);
+ } else {
+ resolve([]);
+ }
+ },
+ fail: () => {
+ resolve([]);
+ }
+ });
+ });
+ },
+
+ // 从服务器加载物品 - 修复版本
+ // 从服务器加载物品 - 修复字段映射
+loadServerItems() {
+ const that = this;
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `${this.data.apiBaseUrl}/items/`,
+ method: 'GET',
+ timeout: 10000,
+ success(res) {
+ console.log('🌐 服务器响应:', res);
+
+ if (res.data.success && res.data.data) {
+ // 转换服务器数据格式为前端格式 - 修复字段映射
+ const serverItems = res.data.data.map(item => ({
+ id: item.id || item.number,
+ name: item.object || item.name,
+ color: item.color,
+ feature: item.feature,
+ brand: item.brand,
+ number: item.number || `CAUC${(item.id || item.number).toString().padStart(8, '0')}`,
+ location: item.location,
+ telephone: item.telephone, // 正确映射联系方式字段
+ icon: that.generateItemIcon(item.object || item.name),
+ description: `${item.color}的${item.object || item.name},${item.feature},品牌:${item.brand}`,
+ timestamp: item.create_time || new Date().toISOString(),
+ fromServer: true
+ }));
+ console.log('📱 转换后的物品数据:', serverItems);
+ resolve(serverItems);
+ } else {
+ reject(new Error('服务器返回数据格式错误'));
+ }
+ },
+ fail(err) {
+ console.error('❌ 请求服务器失败:', err);
+ reject(err);
+ }
+ });
+ });
+},
+
+ // 更新本地存储
+ updateLocalStorage(items) {
+ wx.setStorage({
+ key: 'lostItems',
+ data: items,
+ success: () => {
+ console.log('💾 本地存储更新成功,物品数量:', items.length);
+ },
+ fail: (err) => {
+ console.error('❌ 本地存储更新失败:', err);
+ }
+ });
+ },
+
+ // 设置默认示例数据
+ setDefaultItems() {
+ const defaultItems = [
+ {
+ name: "耳机",
+ color: "黑色",
+ feature: "椭圆形",
+ number: "CAUC20240001",
+ location: "北苑19公寓",
+ icon: "🎧",
+ brand: "Sony",
+ description: "黑色椭圆形无线耳机,音质清晰,带有充电盒",
+ timestamp: new Date().toISOString()
+ },
+ {
+ name: "校园卡",
+ color: "蓝色",
+ feature: "矩形有外壳",
+ number: "CAUC20240002",
+ location: "南苑17公寓",
+ icon: "💳",
+ brand: "学校统一",
+ description: "蓝色校园卡,装在透明保护壳内,印有学校logo",
+ timestamp: new Date().toISOString()
+ }
+ ];
+
+ this.setData({
+ allItems: defaultItems,
+ isLoading: false
+ });
+
+ // 同时保存到本地存储
+ this.updateLocalStorage(defaultItems);
+ },
+
+ // 点击物品卡片跳转到详情页
+ onItemTap(e) {
+ const item = e.currentTarget.dataset.item;
+ wx.navigateTo({
+ url: `/pages/detail/detail?item=${encodeURIComponent(JSON.stringify(item))}`
+ });
+ },
+
+ // 生成物品图标(与identification.js保持一致)
+ generateItemIcon(itemName) {
+ const iconMap = {
+ '手机': '📱',
+ '耳机': '🎧',
+ '钱包': '👛',
+ '钥匙': '🔑',
+ '水杯': '🥤',
+ '书包': '🎒',
+ '书本': '📚',
+ '电脑': '💻',
+ '眼镜': '👓',
+ '手表': '⌚',
+ '校园卡': '💳',
+ '身份证': '🆔',
+ '充电宝': '🔋',
+ 'U盘': '💾',
+ '鼠标': '🖱️',
+ '发夹': '🎀',
+ '钥匙扣': '🔑'
+ };
+
+ for (let key in iconMap) {
+ if (itemName.includes(key)) {
+ return iconMap[key];
+ }
+ }
+
+ return '📦';
+ },
+
+ // 下拉刷新
+ onPullDownRefresh() {
+ console.log('🔄 手动刷新数据...');
+ this.loadAllItems();
+ setTimeout(() => {
+ wx.stopPullDownRefresh();
+ }, 2000);
+ }
+});
\ No newline at end of file
diff --git a/src/index/index.json b/src/index/index.json
new file mode 100644
index 0000000..a0ebf06
--- /dev/null
+++ b/src/index/index.json
@@ -0,0 +1,4 @@
+{
+ "usingComponents": {},
+ "navigationBarTitleText": "首页"
+}
\ No newline at end of file
diff --git a/src/index/index.wxml b/src/index/index.wxml
new file mode 100644
index 0000000..0f91ace
--- /dev/null
+++ b/src/index/index.wxml
@@ -0,0 +1,70 @@
+
+
+
+
+
+ 智能拾物登记
+
+
+
+
+
+
+
+ 搜索匹配
+
+
+
+
+
+
+
+
+
+ 所有物品
+
+
+
+ 加载中...
+
+
+
+
+ 暂无物品信息
+
+
+
+
+ {{item.icon}}
+ {{item.name}}
+ {{item.location}}
+
+
+
+
+
\ No newline at end of file
diff --git a/src/index/index.wxss b/src/index/index.wxss
new file mode 100644
index 0000000..667f4d8
--- /dev/null
+++ b/src/index/index.wxss
@@ -0,0 +1,279 @@
+/* pages/home/home.wxss */
+@import "/static/css/iconfont.wxss";
+
+.li navigator{
+ display: block;
+ line-height: 100rpx;
+ cursor: pointer;
+ height: 100rpx;
+ margin: auto;
+ padding: 10px;
+ background-position: center;
+ background-color: #B0E2FF;
+ border-radius: 20rpx;
+ padding-left: 20rpx;
+ border-bottom: solid black;
+ margin-top: 50rpx;
+}
+.li navigator:hover{
+ columns: #bb0000;
+}
+.function{
+ display: flex;
+ justify-content: space-between;
+}
+.li navigator .function view{
+ font-size: 50rpx;
+}
+
+/* 所有物品区域 */
+.all-items-section {
+ width: 90%;
+ margin: 40rpx auto;
+ background-color: white;
+ border-radius: 24rpx;
+ padding: 40rpx;
+ box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
+}
+
+.section-title {
+ font-size: 36rpx;
+ font-weight: bold;
+ color: #333;
+ margin-bottom: 30rpx;
+ display: block;
+}
+
+.items-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 20rpx;
+}
+
+.item-card {
+ background-color: #f8f8f8;
+ border-radius: 16rpx;
+ padding: 30rpx 20rpx;
+ text-align: center;
+ transition: all 0.3s;
+ border: 1rpx solid #e0e0e0;
+}
+
+.item-card:active {
+ background-color: #e0e0e0;
+ transform: scale(0.98);
+}
+
+.card-icon {
+ font-size: 48rpx;
+ margin-bottom: 16rpx;
+ display: block;
+}
+
+.card-name {
+ font-size: 28rpx;
+ font-weight: bold;
+ margin-bottom: 8rpx;
+ display: block;
+ color: #333;
+}
+
+.card-location {
+ font-size: 22rpx;
+ color: #666;
+ display: block;
+}
+
+.custom-tabbar {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 150rpx;
+ background: #ffffff;
+ display: flex;
+ border-top: 1rpx solid black;
+}
+
+.tab-item {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+}
+
+.tab-item image {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.tab-item text {
+ font-size: 40rpx;
+ margin-top: 4rpx;
+}
+
+/* 添加内容 */
+/* 加载状态 */
+.loading-section {
+ text-align: center;
+ padding: 40rpx;
+}
+
+.loading-text {
+ color: #666;
+ font-size: 28rpx;
+}
+
+/* 空状态 */
+.empty-section {
+ text-align: center;
+ padding: 80rpx 40rpx;
+}
+
+.empty-text {
+ color: #999;
+ font-size: 32rpx;
+}
+
+/* 来源标记 */
+.local-badge {
+ position: absolute;
+ top: 10rpx;
+ right: 10rpx;
+ background: #ff9500;
+ color: white;
+ font-size: 20rpx;
+ padding: 4rpx 8rpx;
+ border-radius: 8rpx;
+}
+
+.server-badge {
+ position: absolute;
+ top: 10rpx;
+ right: 10rpx;
+ background: #09BB07;
+ color: white;
+ font-size: 20rpx;
+ padding: 4rpx 8rpx;
+ border-radius: 8rpx;
+}
+
+.item-card {
+ position: relative; /* 为badge定位 */
+}
+
+/* 在原有 index.wxss 基础上添加 */
+
+.section-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 30rpx;
+}
+
+.refresh-area {
+ display: flex;
+ align-items: center;
+ padding: 15rpx 25rpx;
+ background: #f0f0f0;
+ border-radius: 25rpx;
+}
+
+.refresh-text {
+ font-size: 26rpx;
+ color: #666;
+ margin-right: 10rpx;
+}
+
+.refresh-icon {
+ font-size: 26rpx;
+}
+
+/* 加载状态 */
+.loading-section {
+ text-align: center;
+ padding: 80rpx 40rpx;
+}
+
+.loading-spinner {
+ width: 60rpx;
+ height: 60rpx;
+ border: 4rpx solid #f0f0f0;
+ border-top: 4rpx solid #09BB07;
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+ margin: 0 auto 20rpx;
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+.loading-text {
+ color: #666;
+ font-size: 28rpx;
+}
+
+/* 错误状态 */
+.error-section {
+ text-align: center;
+ padding: 80rpx 40rpx;
+}
+
+.error-icon {
+ font-size: 80rpx;
+ display: block;
+ margin-bottom: 20rpx;
+}
+
+.error-text {
+ color: #ff4d4f;
+ font-size: 32rpx;
+ display: block;
+ margin-bottom: 30rpx;
+}
+
+.retry-btn {
+ background: #09BB07;
+ color: white;
+ border: none;
+ border-radius: 10rpx;
+ padding: 20rpx 40rpx;
+ font-size: 28rpx;
+}
+
+/* 空状态 */
+.empty-section {
+ text-align: center;
+ padding: 100rpx 40rpx;
+}
+
+.empty-icon {
+ font-size: 100rpx;
+ display: block;
+ margin-bottom: 20rpx;
+ opacity: 0.5;
+}
+
+.empty-text {
+ color: #999;
+ font-size: 32rpx;
+ display: block;
+ margin-bottom: 10rpx;
+}
+
+.empty-subtext {
+ color: #ccc;
+ font-size: 26rpx;
+ display: block;
+}
+
+/* 时间显示 */
+.card-time {
+ font-size: 20rpx;
+ color: #999;
+ display: block;
+ margin-top: 8rpx;
+}
\ No newline at end of file