Browse Source

fix: 同步 pages/wealth/index 路径与远程一致

User 2 tháng trước cách đây
mục cha
commit
a949deed84

+ 6 - 3
cfc-backend/.classpath

@@ -36,18 +36,21 @@
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
+	<classpathentry kind="src" path="target/generated-sources/annotations">
 		<attributes>
 			<attribute name="optional" value="true"/>
-			<attribute name="test" value="true"/>
 			<attribute name="maven.pomderived" value="true"/>
 			<attribute name="ignore_optional_problems" value="true"/>
 			<attribute name="m2e-apt" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="src" path="target/generated-sources/annotations">
+	<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
 		<attributes>
 			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="ignore_optional_problems" value="true"/>
+			<attribute name="m2e-apt" value="true"/>
+			<attribute name="test" value="true"/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>

+ 3 - 2
cfc-frontend/pages.json

@@ -43,7 +43,7 @@
         "navigationBarTitleText": "智"
       }
     },
-    {
+{
       "path": "pages/wealth/index",
       "style": {
         "navigationBarTitleText": "富"
@@ -833,7 +833,7 @@
       ]
     },
     {
-      "root": "pages/wealth",
+      "root": "pages/wealth-sub",
       "pages": [
         {
           "path": "checkin",
@@ -1251,6 +1251,7 @@
     "backgroundColor": "#F8F8F8"
   },
   "lazyCodeLoading": "requiredComponents",
+  "customTabBar": true,
   "tabBar": {
     "color": "#7A7E83",
     "selectedColor": "#F97316",

+ 0 - 366
cfc-frontend/pages/wealth/checkin.vue

@@ -1,366 +0,0 @@
-<template>
-  <scroll-view class="container" scroll-y>
-    <!-- 能量提示 -->
-    <view class="energy-tip">
-      <text class="energy-tip-text">⚡ 每次打卡可获得 5 能量值</text>
-    </view>
-
-    <!-- 快速打卡 -->
-    <view class="quick-checkin">
-      <view class="section-title">
-        <text class="section-title-text">今日打卡</text>
-      </view>
-      <view class="checkin-types">
-        <view
-          v-for="(item, index) in checkinTypes"
-          :key="index"
-          class="checkin-btn"
-          :class="{ disabled: todayTimer }"
-          @click="doCheckin(item.type)">
-          <text class="checkin-icon">{{ item.icon }}</text>
-          <text class="checkin-label">{{ item.label }}</text>
-        </view>
-      </view>
-      <view v-if="todayCount > 0" class="today-count">
-        <text>今日已打卡 {{ todayCount }} 次</text>
-      </view>
-    </view>
-
-    <!-- 统计卡片 -->
-    <view class="stats-card">
-      <view class="stat-item">
-        <text class="stat-value">{{ stats.totalCheckins || 0 }}</text>
-        <text class="stat-label">总打卡</text>
-      </view>
-      <view class="stat-divider"></view>
-      <view class="stat-item">
-        <text class="stat-value">{{ stats.totalEnergy || 0 }}</text>
-        <text class="stat-label">总能量</text>
-      </view>
-      <view class="stat-divider"></view>
-      <view class="stat-item">
-        <text class="stat-value">{{ stats.dailyPlanCount || 0 }}</text>
-        <text class="stat-label">计划</text>
-      </view>
-      <view class="stat-divider"></view>
-      <view class="stat-item">
-        <text class="stat-value">{{ stats.savingCount || 0 }}</text>
-        <text class="stat-label">储蓄</text>
-      </view>
-    </view>
-
-    <!-- 打卡记录 -->
-    <view class="record-section">
-      <view class="section-title">
-        <text class="section-title-text">打卡记录</text>
-      </view>
-      <view v-if="checkins.length === 0" class="empty-state">
-        <text>暂无打卡记录,开始打卡吧!</text>
-      </view>
-      <view
-        v-for="(item, index) in checkins"
-        :key="index"
-        class="record-item"
-        @longpress="confirmDelete(item)">
-        <view class="record-left">
-          <text class="record-icon">{{ getTypeIcon(item.checkinType) }}</text>
-          <view class="record-info">
-            <text class="record-type">{{ getTypeLabel(item.checkinType) }}</text>
-            <text class="record-date">{{ formatDate(item.createdAt) }}</text>
-          </view>
-        </view>
-        <view class="record-right">
-          <text class="record-energy">+{{ item.earnedEnergy || 5 }}</text>
-        </view>
-      </view>
-    </view>
-  </scroll-view>
-</template>
-
-<script>
-import { getCheckinList, getCheckinStats, createCheckin, deleteCheckin } from '../../utils/api'
-
-export default {
-  data() {
-    return {
-      checkinTypes: [
-        { type: 'daily_plan', label: '记账规划', icon: '📋' },
-        { type: 'saving', label: '储蓄记录', icon: '💰' },
-        { type: 'expense', label: '消费记录', icon: '🛒' },
-        { type: 'review', label: '财务回顾', icon: '📊' }
-      ],
-      checkins: [],
-      stats: {},
-      todayTimer: null,
-      todayCount: 0
-    }
-  },
-
-  onShow() {
-    this.loadData()
-  },
-
-  methods: {
-    async loadData() {
-      try {
-        const res = await getCheckinList({})
-        if (res && res.code === 200) {
-          this.checkins = res.data || []
-        }
-        const statsRes = await getCheckinStats({})
-        if (statsRes && statsRes.code === 200) {
-          this.stats = statsRes.data || {}
-        }
-        this.calcTodayCount()
-      } catch (e) {
-        console.error('加载打卡数据失败', e)
-      }
-    },
-
-    calcTodayCount() {
-      const today = new Date()
-      const todayStr = today.toISOString().split('T')[0]
-      this.todayCount = this.checkins.filter(function(c) {
-        if (!c.createdAt) return false
-        return c.createdAt.indexOf(todayStr) === 0
-      }).length
-    },
-
-    async doCheckin(type) {
-      if (this.todayTimer) {
-        uni.showToast({ title: '操作太频繁,请稍后', icon: 'none' })
-        return
-      }
-      try {
-        const res = await createCheckin({
-          checkinType: type,
-          checkinDate: new Date().toISOString().split('T')[0],
-          earnedEnergy: 5
-        })
-        if (res && res.code === 200) {
-          uni.showToast({ title: '打卡成功!+5能量', icon: 'success' })
-          this.loadData()
-        } else {
-          uni.showToast({ title: res && res.message || '打卡失败', icon: 'none' })
-        }
-      } catch (e) {
-        uni.showToast({ title: '网络错误', icon: 'none' })
-      }
-    },
-
-    confirmDelete(item) {
-      var self = this
-      uni.showModal({
-        title: '提示',
-        content: '确定删除此打卡记录?',
-        success: function(res) {
-          if (res.confirm) {
-            self.deleteRecord(item)
-          }
-        }
-      })
-    },
-
-    async deleteRecord(item) {
-      try {
-        const res = await deleteCheckin(item.id)
-        if (res && res.code === 200) {
-          uni.showToast({ title: '已删除', icon: 'success' })
-          this.loadData()
-        }
-      } catch (e) {
-        console.error('删除失败', e)
-      }
-    },
-
-    getTypeIcon(type) {
-      const map = { daily_plan: '📋', saving: '💰', expense: '🛒', review: '📊' }
-      return map[type] || '📌'
-    },
-
-    getTypeLabel(type) {
-      const map = { daily_plan: '记账规划', saving: '储蓄记录', expense: '消费记录', review: '财务回顾' }
-      return map[type] || type
-    },
-
-    formatDate(dateStr) {
-      if (!dateStr) return ''
-      return dateStr.substring(0, 16).replace('T', ' ')
-    }
-  }
-}
-</script>
-
-<style>
-.container {
-  min-height: 100vh;
-  background: #f5f7fa;
-  padding: 20rpx 30rpx 120rpx;
-}
-
-.energy-tip {
-  background: linear-gradient(135deg, #F97316, #FB923C);
-  border-radius: 16rpx;
-  padding: 20rpx 30rpx;
-  margin-bottom: 24rpx;
-}
-
-.energy-tip-text {
-  color: #fff;
-  font-size: 26rpx;
-  font-weight: 500;
-}
-
-.section-title {
-  margin-bottom: 20rpx;
-}
-
-.section-title-text {
-  font-size: 30rpx;
-  font-weight: 600;
-  color: #333;
-}
-
-.quick-checkin {
-  background: #fff;
-  border-radius: 20rpx;
-  padding: 24rpx;
-  margin-bottom: 24rpx;
-}
-
-.checkin-types {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-}
-
-.checkin-btn {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  width: 150rpx;
-  height: 120rpx;
-  background: #FFF7ED;
-  border-radius: 16rpx;
-  border: 2rpx solid #FED7AA;
-}
-
-.checkin-btn.disabled {
-  opacity: 0.5;
-}
-
-.checkin-icon {
-  font-size: 40rpx;
-  margin-bottom: 8rpx;
-}
-
-.checkin-label {
-  font-size: 24rpx;
-  color: #666;
-}
-
-.today-count {
-  text-align: center;
-  margin-top: 16rpx;
-  font-size: 24rpx;
-  color: #999;
-}
-
-.stats-card {
-  background: #fff;
-  border-radius: 20rpx;
-  padding: 24rpx;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-around;
-  align-items: center;
-  margin-bottom: 24rpx;
-}
-
-.stat-item {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-}
-
-.stat-value {
-  font-size: 36rpx;
-  font-weight: 700;
-  color: #F97316;
-}
-
-.stat-label {
-  font-size: 24rpx;
-  color: #999;
-  margin-top: 4rpx;
-}
-
-.stat-divider {
-  width: 2rpx;
-  height: 60rpx;
-  background: #eee;
-}
-
-.record-section {
-  background: #fff;
-  border-radius: 20rpx;
-  padding: 24rpx;
-}
-
-.empty-state {
-  text-align: center;
-  padding: 48rpx 0;
-  color: #999;
-  font-size: 26rpx;
-}
-
-.record-item {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  padding: 20rpx 0;
-  border-bottom: 2rpx solid #f5f5f5;
-}
-
-.record-item:last-child {
-  border-bottom: none;
-}
-
-.record-left {
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-}
-
-.record-icon {
-  font-size: 36rpx;
-  margin-right: 16rpx;
-}
-
-.record-info {
-  display: flex;
-  flex-direction: column;
-}
-
-.record-type {
-  font-size: 28rpx;
-  color: #333;
-  font-weight: 500;
-}
-
-.record-date {
-  font-size: 22rpx;
-  color: #999;
-  margin-top: 4rpx;
-}
-
-.record-right {}
-
-.record-energy {
-  font-size: 28rpx;
-  color: #F97316;
-  font-weight: 600;
-}
-</style>

+ 0 - 312
cfc-frontend/pages/wealth/insurance-add.vue

@@ -1,312 +0,0 @@
-<template>
-  <scroll-view class="container" scroll-y>
-    <view class="form-card">
-      <view class="form-group">
-        <text class="form-label">保单名称 <text class="required">*</text></text>
-        <input class="form-input" v-model="form.policyName" placeholder="请输入保单名称" />
-      </view>
-
-      <view class="form-group">
-        <text class="form-label">保险公司</text>
-        <input class="form-input" v-model="form.insuranceCompany" placeholder="请输入保险公司名称" />
-      </view>
-
-      <view class="form-group">
-        <text class="form-label">保单类型</text>
-        <picker class="form-picker" :value="policyTypeIndex" :range="policyTypes" @change="onTypeChange">
-          <view class="picker-value">{{ policyTypes[policyTypeIndex] || '请选择保单类型' }}</view>
-        </picker>
-      </view>
-
-      <view class="form-group">
-        <text class="form-label">被保人 <text class="required">*</text></text>
-        <input class="form-input" v-model="form.insuredPerson" placeholder="请输入被保人姓名" />
-      </view>
-
-      <view class="form-row">
-        <view class="form-group half">
-          <text class="form-label">保费</text>
-          <input class="form-input" v-model="form.premium" placeholder="0.00" type="digit" />
-        </view>
-        <view class="form-group half">
-          <text class="form-label">保额</text>
-          <input class="form-input" v-model="form.sumInsured" placeholder="0.00" type="digit" />
-        </view>
-      </view>
-
-      <view class="form-row">
-        <view class="form-group half">
-          <text class="form-label">生效日期</text>
-          <picker class="form-picker" mode="date" :value="form.startDate" @change="onStartDateChange">
-            <view class="picker-value">{{ form.startDate || '请选择' }}</view>
-          </picker>
-        </view>
-        <view class="form-group half">
-          <text class="form-label">到期日期</text>
-          <picker class="form-picker" mode="date" :value="form.endDate" @change="onEndDateChange">
-            <view class="picker-value">{{ form.endDate || '请选择' }}</view>
-          </picker>
-        </view>
-      </view>
-
-      <view class="form-group">
-        <text class="form-label">续费类型</text>
-        <picker class="form-picker" :value="renewalTypeIndex" :range="renewalTypes" @change="onRenewalChange">
-          <view class="picker-value">{{ renewalTypes[renewalTypeIndex] || '请选择续费类型' }}</view>
-        </picker>
-      </view>
-
-      <view class="form-group">
-        <text class="form-label">保单号</text>
-        <input class="form-input" v-model="form.policyNo" placeholder="请输入保单号" />
-      </view>
-
-      <view class="form-group">
-        <text class="form-label">备注</text>
-        <textarea class="form-textarea" v-model="form.remark" placeholder="备注信息" />
-      </view>
-    </view>
-
-    <view class="submit-btn-wrap">
-      <button class="submit-btn" :loading="submitting" @click="submitForm">
-        {{ isEdit ? '更新保单' : '提交保存' }}
-      </button>
-    </view>
-  </scroll-view>
-</template>
-
-<script>
-import { getInsuranceDetail, createInsurance, updateInsurance } from '../../utils/api'
-
-export default {
-  data() {
-    return {
-      isEdit: false,
-      submitting: false,
-      policyTypes: ['医疗险', '重疾险', '意外险', '教育金', '养老险'],
-      policyTypeValues: ['medical', 'life', 'accident', 'education', 'endowment'],
-      policyTypeIndex: -1,
-      renewalTypes: ['年缴', '月缴', '趸交'],
-      renewalTypeValues: ['annual', 'monthly', 'single'],
-      renewalTypeIndex: -1,
-      form: {
-        policyName: '',
-        insuranceCompany: '',
-        policyType: '',
-        insuredPerson: '',
-        premium: '',
-        sumInsured: '',
-        startDate: '',
-        endDate: '',
-        renewalType: 'annual',
-        policyNo: '',
-        remark: ''
-      }
-    }
-  },
-
-  onLoad(options) {
-    if (options && options.id) {
-      this.isEdit = true
-      this.loadDetail(options.id)
-    }
-  },
-
-  methods: {
-    async loadDetail(id) {
-      try {
-        const res = await getInsuranceDetail(id)
-        if (res && res.code === 200 && res.data) {
-          const data = res.data
-          this.form.policyName = data.policyName || ''
-          this.form.insuranceCompany = data.insuranceCompany || ''
-          this.form.policyType = data.policyType || ''
-          this.form.insuredPerson = data.insuredPerson || ''
-          this.form.premium = data.premium ? String(data.premium) : ''
-          this.form.sumInsured = data.sumInsured ? String(data.sumInsured) : ''
-          this.form.startDate = data.startDate ? data.startDate.substring(0, 10) : ''
-          this.form.endDate = data.endDate ? data.endDate.substring(0, 10) : ''
-          this.form.renewalType = data.renewalType || 'annual'
-          this.form.policyNo = data.policyNo || ''
-          this.form.remark = data.remark || ''
-
-          this.policyTypeIndex = this.policyTypeValues.indexOf(data.policyType)
-          this.renewalTypeIndex = this.renewalTypeValues.indexOf(data.renewalType)
-
-          uni.setNavigationBarTitle({ title: '保单详情' })
-        }
-      } catch (e) {
-        console.error('加载保单详情失败', e)
-      }
-    },
-
-    onTypeChange(e) {
-      this.policyTypeIndex = parseInt(e.detail.value)
-      this.form.policyType = this.policyTypeValues[this.policyTypeIndex]
-    },
-
-    onRenewalChange(e) {
-      this.renewalTypeIndex = parseInt(e.detail.value)
-      this.form.renewalType = this.renewalTypeValues[this.renewalTypeIndex]
-    },
-
-    onStartDateChange(e) {
-      this.form.startDate = e.detail.value
-    },
-
-    onEndDateChange(e) {
-      this.form.endDate = e.detail.value
-    },
-
-    async submitForm() {
-      if (!this.form.policyName) {
-        uni.showToast({ title: '请输入保单名称', icon: 'none' })
-        return
-      }
-      if (!this.form.insuredPerson) {
-        uni.showToast({ title: '请输入被保人姓名', icon: 'none' })
-        return
-      }
-
-      this.submitting = true
-      try {
-        var payload = {
-          policyName: this.form.policyName,
-          insuranceCompany: this.form.insuranceCompany,
-          policyType: this.form.policyType,
-          insuredPerson: this.form.insuredPerson,
-          premium: this.form.premium ? parseFloat(this.form.premium) : null,
-          sumInsured: this.form.sumInsured ? parseFloat(this.form.sumInsured) : null,
-          startDate: this.form.startDate || null,
-          endDate: this.form.endDate || null,
-          renewalType: this.form.renewalType,
-          policyNo: this.form.policyNo,
-          remark: this.form.remark
-        }
-
-        var res
-        if (this.isEdit) {
-          payload.id = this.$mp.query && this.$mp.query.id
-          res = await updateInsurance(payload)
-        } else {
-          res = await createInsurance(payload)
-        }
-
-        if (res && res.code === 200) {
-          uni.showToast({ title: this.isEdit ? '更新成功' : '创建成功', icon: 'success' })
-          setTimeout(function() {
-            uni.navigateBack()
-          }, 1500)
-        } else {
-          uni.showToast({ title: res && res.message || '提交失败', icon: 'none' })
-        }
-      } catch (e) {
-        uni.showToast({ title: '网络错误', icon: 'none' })
-      } finally {
-        this.submitting = false
-      }
-    }
-  }
-}
-</script>
-
-<style>
-.container {
-  min-height: 100vh;
-  background: #f5f7fa;
-  padding: 20rpx 30rpx 120rpx;
-}
-
-.form-card {
-  background: #fff;
-  border-radius: 20rpx;
-  padding: 30rpx;
-  margin-bottom: 24rpx;
-}
-
-.form-group {
-  margin-bottom: 28rpx;
-}
-
-.form-label {
-  display: block;
-  font-size: 28rpx;
-  color: #333;
-  font-weight: 500;
-  margin-bottom: 12rpx;
-}
-
-.required {
-  color: #DC2626;
-}
-
-.form-input {
-  width: 100%;
-  height: 80rpx;
-  line-height: 80rpx;
-  background: #F5F7FA;
-  border-radius: 12rpx;
-  padding: 0 20rpx;
-  font-size: 28rpx;
-  color: #333;
-  box-sizing: border-box;
-}
-
-.form-picker {
-  width: 100%;
-  height: 80rpx;
-  line-height: 80rpx;
-  background: #F5F7FA;
-  border-radius: 12rpx;
-  padding: 0 20rpx;
-  box-sizing: border-box;
-}
-
-.picker-value {
-  font-size: 28rpx;
-  color: #333;
-  line-height: 80rpx;
-}
-
-.form-textarea {
-  width: 100%;
-  height: 160rpx;
-  background: #F5F7FA;
-  border-radius: 12rpx;
-  padding: 20rpx;
-  font-size: 28rpx;
-  color: #333;
-  box-sizing: border-box;
-}
-
-.form-row {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-}
-
-.form-group.half {
-  width: 48%;
-}
-
-.submit-btn-wrap {
-  padding: 20rpx 0 40rpx;
-}
-
-.submit-btn {
-  width: 100%;
-  height: 88rpx;
-  line-height: 88rpx;
-  text-align: center;
-  background: #F97316;
-  color: #fff;
-  font-size: 30rpx;
-  font-weight: 600;
-  border-radius: 44rpx;
-  border: none;
-}
-
-.submit-btn::after {
-  border: none;
-}
-</style>

+ 0 - 296
cfc-frontend/pages/wealth/insurance-list.vue

@@ -1,296 +0,0 @@
-<template>
-  <scroll-view class="container" scroll-y>
-    <!-- 状态过滤 -->
-    <view class="filter-tabs">
-      <view
-        v-for="(tab, index) in filterTabs"
-        :key="index"
-        class="filter-tab"
-        :class="{ active: currentFilter === tab.value }"
-        @click="currentFilter = tab.value; loadPolicies()">
-        <text>{{ tab.label }}</text>
-      </view>
-    </view>
-
-    <!-- 保单列表 -->
-    <view v-if="policies.length === 0" class="empty-state">
-      <text class="empty-icon">📋</text>
-      <text class="empty-text">暂无保单</text>
-      <text class="empty-hint">点击下方按钮添加保单</text>
-    </view>
-
-    <view
-      v-for="(item, index) in policies"
-      :key="index"
-      class="policy-card"
-      @click="viewDetail(item)">
-      <view class="policy-header">
-        <text class="policy-name">{{ item.policyName }}</text>
-        <text class="policy-status" :class="item.status === 'active' ? 'status-active' : item.status === 'expired' ? 'status-expired' : 'status-cancelled'">{{ getStatusLabel(item.status) }}</text>
-      </view>
-      <view class="policy-body">
-        <view class="policy-row">
-          <text class="policy-label">保险公司</text>
-          <text class="policy-value">{{ item.insuranceCompany || '未知' }}</text>
-        </view>
-        <view class="policy-row">
-          <text class="policy-label">被保人</text>
-          <text class="policy-value">{{ item.insuredPerson }}</text>
-        </view>
-        <view class="policy-row">
-          <text class="policy-label">保费</text>
-          <text class="policy-value orange">{{ formatPriceWithSymbol(item.premium || 0) }}</text>
-        </view>
-        <view class="policy-row">
-          <text class="policy-label">到期日</text>
-          <text class="policy-value">{{ item.endDate ? item.endDate.substring(0, 10) : '长期' }}</text>
-        </view>
-      </view>
-      <view class="policy-footer" @click.stop="deletePolicy(item)">
-        <text class="delete-btn">删除</text>
-      </view>
-    </view>
-
-    <!-- 新增按钮 -->
-    <view class="add-btn-wrap">
-      <button class="add-btn" @click="addPolicy">+ 新增保单</button>
-    </view>
-  </scroll-view>
-</template>
-
-<script>
-import { getInsuranceList, deleteInsurance } from '../../utils/api'
-
-export default {
-  data() {
-    return {
-      filterTabs: [
-        { label: '全部', value: '' },
-        { label: '有效', value: 'active' },
-        { label: '已过期', value: 'expired' },
-        { label: '已取消', value: 'cancelled' }
-      ],
-      currentFilter: '',
-      policies: []
-    }
-  },
-
-  onShow() {
-    this.loadPolicies()
-  },
-
-  methods: {
-    async loadPolicies() {
-      try {
-        const res = await getInsuranceList({ status: this.currentFilter || undefined })
-        if (res && res.code === 200) {
-          this.policies = res.data || []
-        }
-      } catch (e) {
-        console.error('加载保单失败', e)
-      }
-    },
-
-    viewDetail(item) {
-      uni.navigateTo({
-        url: '/pages/wealth/insurance-add?id=' + item.id
-      })
-    },
-
-    addPolicy() {
-      uni.navigateTo({
-        url: '/pages/wealth/insurance-add'
-      })
-    },
-
-    deletePolicy(item) {
-      var self = this
-      uni.showModal({
-        title: '提示',
-        content: '确定删除该保单?',
-        success: async function(res) {
-          if (res.confirm) {
-            try {
-              const result = await deleteInsurance(item.id)
-              if (result && result.code === 200) {
-                uni.showToast({ title: '已删除', icon: 'success' })
-                self.loadPolicies()
-              }
-            } catch (e) {
-              console.error('删除失败', e)
-            }
-          }
-        }
-      })
-    },
-
-    getStatusClass(status) {
-      return status === 'active' ? 'status-active' : status === 'expired' ? 'status-expired' : 'status-cancelled'
-    },
-
-    getStatusLabel(status) {
-      return status === 'active' ? '有效' : status === 'expired' ? '已过期' : '已取消'
-    }
-  }
-}
-</script>
-
-<style>
-.container {
-  min-height: 100vh;
-  background: #f5f7fa;
-  padding: 20rpx 30rpx 120rpx;
-}
-
-.filter-tabs {
-  display: flex;
-  flex-direction: row;
-  background: #fff;
-  border-radius: 16rpx;
-  padding: 12rpx;
-  margin-bottom: 24rpx;
-}
-
-.filter-tab {
-  flex: 1;
-  text-align: center;
-  padding: 12rpx 0;
-  font-size: 26rpx;
-  color: #666;
-  border-radius: 12rpx;
-}
-
-.filter-tab.active {
-  background: #F97316;
-  color: #fff;
-  font-weight: 600;
-}
-
-.empty-state {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  padding: 80rpx 0;
-}
-
-.empty-icon {
-  font-size: 80rpx;
-  margin-bottom: 20rpx;
-}
-
-.empty-text {
-  font-size: 30rpx;
-  color: #999;
-}
-
-.empty-hint {
-  font-size: 24rpx;
-  color: #ccc;
-  margin-top: 8rpx;
-}
-
-.policy-card {
-  background: #fff;
-  border-radius: 20rpx;
-  padding: 24rpx;
-  margin-bottom: 20rpx;
-}
-
-.policy-header {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 16rpx;
-  padding-bottom: 16rpx;
-  border-bottom: 2rpx solid #f5f5f5;
-}
-
-.policy-name {
-  font-size: 30rpx;
-  font-weight: 600;
-  color: #333;
-}
-
-.policy-status {
-  font-size: 24rpx;
-  padding: 4rpx 16rpx;
-  border-radius: 8rpx;
-}
-
-.status-active {
-  background: #DCFCE7;
-  color: #16A34A;
-}
-
-.status-expired {
-  background: #FEF2F2;
-  color: #DC2626;
-}
-
-.status-cancelled {
-  background: #F5F5F5;
-  color: #999;
-}
-
-.policy-body {
-  margin-bottom: 12rpx;
-}
-
-.policy-row {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  padding: 8rpx 0;
-}
-
-.policy-label {
-  font-size: 26rpx;
-  color: #999;
-}
-
-.policy-value {
-  font-size: 26rpx;
-  color: #333;
-}
-
-.policy-value.orange {
-  color: #F97316;
-  font-weight: 600;
-}
-
-.policy-footer {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-end;
-  padding-top: 12rpx;
-  border-top: 2rpx solid #f5f5f5;
-}
-
-.delete-btn {
-  font-size: 24rpx;
-  color: #DC2626;
-  padding: 8rpx 20rpx;
-}
-
-.add-btn-wrap {
-  padding: 20rpx 0 40rpx;
-}
-
-.add-btn {
-  width: 100%;
-  height: 88rpx;
-  line-height: 88rpx;
-  text-align: center;
-  background: #F97316;
-  color: #fff;
-  font-size: 30rpx;
-  font-weight: 600;
-  border-radius: 44rpx;
-  border: none;
-}
-
-.add-btn::after {
-  border: none;
-}
-</style>