CalendarColorPicker.vue 5.78 KB
<!-- CalendarColorPicker.vue 独立可复用组件 -->
<template>
  <!-- 设置日历颜色弹窗 -->
  <view v-if="visible" class="color-popup-overlay" @click="close">
    <view class="color-popup" @click.stop>
      <view class="color-popup-header">
        <text class="color-popup-title">设置日历颜色</text>
        <view class="color-popup-close" @click="close">
          <uni-icons type="close" size="24" color="#333"></uni-icons>
        </view>
      </view>

      <view class="color-grid">
        <view class="color-item" v-for="color in colorList" :key="color" :style="{ backgroundColor: color }"
          :class="{ active: selectedColor === color }" @click="selectColor(color)">
          <up-icon v-if="selectedColor === color" name="checkbox-mark" size="24" color="#333"></up-icon>
        </view>
      </view>

      <view class="color-popup-footer">
        <button class="color-btn reset-btn" @click="resetColor">恢复默认</button>
        <button class="color-btn confirm-btn" @click="confirmColor">确认选择</button>
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, onMounted, watch } from 'vue'
import dailytemplateApi from '@/sheep/api/Template/Dailytemplate'

import TemplatesApi from '@/sheep/api/Template/Templates';

const props = defineProps({
  // 控制显示隐藏
  visible: {
    type: Boolean,
    default: false
  },
  // 要设置颜色的每日训练ID
  dailyTemplateId: {
    type: [String, Number],
    required: true
  },
  currentColor: {
    type: String,
    default: '#ffd60a'
  },
  isTemplate: {
    type: Boolean,
    required: false,
    default: false
  }
})


// 监听弹窗打开,每次打开都重置为当前颜色
watch(
  () => props.visible,
  (newVal) => {
    if (newVal) {
      // 弹窗打开时,把选中色重置为父组件传来的当前颜色
      selectedColor.value = props.currentColor || '#ffd60a'
    }
  }
)

const emit = defineEmits(['success', 'update:visible'])

// 颜色列表
const colorList = ref([
  '#ffd60a', '#ffea66', '#fff1a3', '#ffbc42', '#ffce7b', '#ffdd9e',
  '#e6a84e', '#e6c89c', '#e6d4b8', '#7dd87d', '#95e095', '#b0e8b0',
  '#4cd9d9', '#75e0e0', '#9de8e8', '#99b9ff', '#b0c8ff', '#c8d8ff',
  '#b388ff', '#c49fff', '#d4b8ff', '#ff7ab8', '#ff96c8', '#ffb0d0',
  '#ff7a7a', '#ff9696', '#ffb0b0', '#ff8a5b', '#ffa07a', '#ffb89c'
])

// 默认颜色
const selectedColor = ref(props.currentColor)

// 选择颜色
const selectColor = (color) => {
  selectedColor.value = color
}

// 关闭弹窗
const close = () => {
  emit('update:visible', false)
}

// 恢复默认颜色
const resetColor = async () => {
  if (!props.dailyTemplateId) {
    uni.showToast({ title: '未找到ID', icon: 'none' })
    return
  }
  try {
    const defaultColor = '#ffd60a'

    if (props.isTemplate) {
      await TemplatesApi.putCalendarColor(
        props.dailyTemplateId,
        defaultColor
      )
    } else {
      await dailytemplateApi.backgroundColor({
        dailyTemplateId: props.dailyTemplateId,
        backgroundColor: defaultColor
      })
    }

    selectedColor.value = defaultColor
    uni.showToast({ title: '已恢复默认', icon: 'success' })
    emit('success')
  } catch (err) {
    console.error('恢复失败:', err)
    uni.showToast({ title: '恢复失败', icon: 'none' })
  }
}

// 确认选择
const confirmColor = async () => {
  if (!props.dailyTemplateId) {
    uni.showToast({ title: '未找到ID', icon: 'none' })
    return
  }
  try {
    // 判断:是模板就用模板接口,不是就用原来接口
    if (props.isTemplate) {
      await TemplatesApi.putCalendarColor(
        props.dailyTemplateId,
        selectedColor.value
      )
    } else {
      await dailytemplateApi.backgroundColor({
        dailyTemplateId: props.dailyTemplateId,
        backgroundColor: selectedColor.value
      })
    }

    uni.showToast({ title: '颜色已设置', icon: 'success' })
    emit('success')
    close()
  } catch (err) {
    console.error('设置失败:', err)
    uni.showToast({ title: '设置失败', icon: 'none' })
  }
}

onMounted(() => {
  console.log('✅ CalendarColorPicker 组件已挂载')
  console.log('接收的 dailyTemplateId:', props.dailyTemplateId)
  console.log('接收的 visible:', props.visible)
})


</script>

<style lang="scss" scoped>
.color-popup-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.4);
  z-index: 9999;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.color-popup {
  width: 100%;
  background: #fff;
  border-radius: 32rpx 32rpx 0 0;
  padding: 40rpx 30rpx;
  box-sizing: border-box;
}

.color-popup-header {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 40rpx;
  position: relative;
}

.color-popup-title {
  font-size: 34rpx;
  font-weight: 600;
  color: #111;
}

.color-popup-close {
  position: absolute;
  right: 10rpx;
  top: 50%;
  transform: translateY(-50%);
  width: 60rpx;
  height: 60rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.color-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 24rpx;
  margin-bottom: 60rpx;
}

.color-item {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;

  &.active {
    border: 4rpx solid rgba(0, 0, 0, 0.1);
  }
}

.color-popup-footer {
  display: flex;
  gap: 20rpx;
  margin-top: 40rpx;
}

.color-btn {
  flex: 1;
  height: 88rpx;
  border-radius: 44rpx;
  font-size: 30rpx;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  margin: 0;
  line-height: 1;
}

.reset-btn {
  background: #f8f8f8;
  color: #333;
  border: 1rpx solid #eee;
}

.confirm-btn {
  background: #ffd60a;
  color: #000;
  font-weight: 500;
}
</style>