<template>
  <XtfConfigProvider class="demo-theme-root" :theme="demoTheme">
  <scroll-view class="crop-demo-scroll xtf-page-scroll" direction="vertical">
    <view class="crop-demo-page xtf-page-scroll-content">
      <text class="crop-demo-title">图片裁剪</text>
      <view class="crop-demo-controls">
        <text class="crop-demo-label">形状</text>
        <radio-group class="crop-demo-row" @change="setShape"><label class="crop-demo-option"><radio value="rect" :checked="shape == 'rect'" /><text class="crop-demo-text">矩形</text></label><label class="crop-demo-option"><radio value="circle" :checked="shape == 'circle'" /><text class="crop-demo-text">圆形</text></label></radio-group>
        <text class="crop-demo-label">裁剪比例</text>
        <radio-group class="crop-demo-row" @change="setRatio"><label v-for="item in ratios" :key="item.key" class="crop-demo-option"><radio :value="item.key" :checked="ratioKey == item.key" :disabled="shape == 'circle'" /><text class="crop-demo-text">{{ item.key }}</text></label></radio-group>
        <view class="crop-demo-row"><text class="crop-demo-text">移动 / 缩放裁剪框</text><switch class="crop-demo-switch" :checked="resizable" @change="setResizable" /></view>
        <text class="crop-demo-label">输出尺寸</text>
        <radio-group class="crop-demo-row" @change="setSize"><label class="crop-demo-option"><radio value="320" :checked="outputWidth == 320" /><text class="crop-demo-text">320</text></label><label class="crop-demo-option"><radio value="640" :checked="outputWidth == 640" /><text class="crop-demo-text">640</text></label></radio-group>
        <text class="crop-demo-value">{{ outputWidth }} × {{ outputHeight }} px</text>
        <text class="crop-demo-label">格式</text>
        <radio-group class="crop-demo-row" @change="setFormat"><label class="crop-demo-option"><radio value="png" :checked="format == 'png'" /><text class="crop-demo-text">PNG</text></label><label class="crop-demo-option"><radio value="jpeg" :checked="format == 'jpeg'" /><text class="crop-demo-text">JPEG</text></label></radio-group>
        <text class="crop-demo-label">JPEG 质量 {{ quality }}%</text>
        <slider class="crop-demo-quality" :value="quality" :min="10" :max="100" :step="10" :disabled="format != 'jpeg'" @change="setQuality" />
        <text class="crop-demo-label">背景</text>
        <radio-group class="crop-demo-row" @change="setBackground"><label class="crop-demo-option"><radio value="" :checked="background == ''" /><text class="crop-demo-text">默认</text></label><label class="crop-demo-option"><radio value="#ffffff" :checked="background == '#ffffff'" /><view class="crop-demo-swatch crop-demo-white"></view><text class="crop-demo-text">白</text></label><label class="crop-demo-option"><radio value="#22c55e" :checked="background == '#22c55e'" /><view class="crop-demo-swatch crop-demo-green"></view><text class="crop-demo-text">绿</text></label></radio-group>
        <view class="crop-demo-row"><button class="crop-demo-button" size="mini" @click="reset">重置</button><button class="crop-demo-error-button" size="mini" @click="testError">触发图片错误</button></view>
      </view>
      <XtfImageCrop :key="resetKey" :src="src" :crop-shape="shape" :crop-width="cropWidth" :crop-height="cropHeight" :crop-resizable="resizable" :width="outputWidth" :height="outputHeight" :export-format="format" :export-quality="quality / 100" :background-color="background" confirm-text="导出" @ready="onReady" @change="onChange" @error="onError" @confirm="onConfirm" />
      <text class="crop-demo-heading">导出结果</text>
      <text class="crop-demo-result">{{ resultText }}</text>
      <view v-if="preview.length > 0" class="crop-demo-preview-stage"><image class="crop-demo-preview" :src="preview" mode="aspectFit" /></view>
      <text class="crop-demo-heading">事件</text>
      <text class="crop-demo-ready">{{ readyText }}</text>
      <text class="crop-demo-change">{{ changeText }}</text>
      <text class="crop-demo-error">{{ errorText }}</text>
      <text class="crop-demo-confirm">{{ confirmText }}</text>
    </view>
  </scroll-view>
  </XtfConfigProvider>
</template>
<script setup lang="uts">
import { useDemoTheme } from '@/pages/demo-theme.uts'
import XtfConfigProvider from '@/uni_modules/xtf-linkuiunix/components/xtf-config-provider/xtf-config-provider.uvue'
const demoTheme = useDemoTheme()
import { computed, ref } from "vue"
import XtfImageCrop from "@/uni_modules/xtf-linkuiunix/components/xtf-image-crop/xtf-image-crop.uvue"
const src = ref("/static/logo.png")
const shape = ref("rect")
const ratioKey = ref("4:3")
const ratios = [{ key: "1:1", width: 1, height: 1 }, { key: "4:3", width: 4, height: 3 }, { key: "16:9", width: 16, height: 9 }]
const cropWidth = computed((): number => ratioKey.value == "16:9" ? 16 : (ratioKey.value == "4:3" ? 4 : 1))
const cropHeight = computed((): number => ratioKey.value == "16:9" ? 9 : (ratioKey.value == "4:3" ? 3 : 1))
const resizable = ref(true)
const outputWidth = ref(640)
const outputHeight = computed((): number => shape.value == "circle" ? outputWidth.value : Math.round(outputWidth.value * cropHeight.value / cropWidth.value))
const format = ref("png")
const quality = ref(90)
const background = ref("")
const resetKey = ref(0)
const preview = ref("")
const resultText = ref("尚未导出")
const readyText = ref("ready: 等待图片")
const changeText = ref("change: 等待选区")
const errorText = ref("error: 无")
const confirmText = ref("confirm: 0")
let confirmCount = 0
let changeCount = 0
function setShape(event: UniRadioGroupChangeEvent): void { shape.value = event.detail.value }
function setRatio(event: UniRadioGroupChangeEvent): void { ratioKey.value = event.detail.value }
function setSize(event: UniRadioGroupChangeEvent): void { outputWidth.value = Number(event.detail.value) }
function setFormat(event: UniRadioGroupChangeEvent): void { format.value = event.detail.value }
function setBackground(event: UniRadioGroupChangeEvent): void { background.value = event.detail.value }
function setResizable(event: UniSwitchChangeEvent): void { resizable.value = event.detail.value }
function setQuality(event: UniSliderChangeEvent): void { quality.value = event.detail.value }
function reset(): void { src.value = "/static/logo.png"; preview.value = ""; resultText.value = "尚未导出"; errorText.value = "error: 无"; resetKey.value++ }
function testError(): void { src.value = "/static/crop-demo-missing-image.png"; errorText.value = "error: 等待加载失败" }
function onReady(payload: any): void { readyText.value = "ready: " + payload.width.toString() + " × " + payload.height.toString() }
function onChange(payload: any): void { changeCount++; changeText.value = "change: " + changeCount.toString() + " | x=" + Math.round(Number(payload.x)).toString() + " y=" + Math.round(Number(payload.y)).toString() + " | " + Math.round(Number(payload.width)).toString() + " × " + Math.round(Number(payload.height)).toString() }
function onError(payload: any): void { errorText.value = "error: " + payload.type }
function onConfirm(payload: any): void { confirmCount++; preview.value = payload.dataUrl; resultText.value = payload.width.toString() + " × " + payload.height.toString() + " px · " + payload.format; confirmText.value = "confirm: " + confirmCount.toString(); errorText.value = "error: 无" }
</script>
<style>
.crop-demo-scroll { display: flex; flex-direction: column; flex: 1; width: 100%; height: 100%; }
.crop-demo-page { display: flex; flex-direction: column; width: 100%; max-width: 900px; align-self: center; padding: 24rpx; background-color: var(--xtf-color-page, #f6f7f8); }
.crop-demo-title { color: var(--xtf-color-text, #20252b); font-size: 36rpx; font-weight: 700; margin-bottom: 20rpx; }
.crop-demo-controls { display: flex; flex-direction: column; padding-bottom: 20rpx; }
.crop-demo-label { color: var(--xtf-color-text-secondary, #444b55); font-size: 26rpx; margin-top: 16rpx; margin-bottom: 8rpx; }
.crop-demo-row { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; }
.crop-demo-option { display: flex; flex-direction: row; align-items: center; margin-right: 20rpx; min-height: 44px; }
.crop-demo-text { color: var(--xtf-color-text, #303844); font-size: 26rpx; }
.crop-demo-switch { margin-left: 20rpx; }
.crop-demo-value { color: #2563eb; font-size: 24rpx; }
.crop-demo-quality { width: 100%; margin: 12rpx 0px; }
.crop-demo-swatch { width: 14px; height: 14px; margin-right: 6rpx; border-width: 1px; border-style: solid; border-color: var(--xtf-color-border, #a8afb8); }
.crop-demo-white { background-color: #ffffff; }
.crop-demo-green { background-color: #22c55e; }
.crop-demo-button { margin: 12rpx 16rpx 0px 0px; }
.crop-demo-error-button { margin: 12rpx 0px 0px 0px; }
.crop-demo-heading { color: var(--xtf-color-text, #20252b); font-size: 28rpx; font-weight: 600; margin-top: 24rpx; margin-bottom: 12rpx; }
.crop-demo-result { color: var(--xtf-color-text-secondary, #444b55); font-size: 24rpx; margin-bottom: 12rpx; }
.crop-demo-preview-stage { display: flex; flex-direction: column; align-items: center; justify-content: center; width: 100%; height: 360rpx; background-color: #d9dfe6; }
.crop-demo-preview { width: 100%; height: 100%; }
.crop-demo-ready { color: #15803d; font-size: 24rpx; margin-bottom: 8rpx; }
.crop-demo-change { color: var(--xtf-color-text-secondary, #444b55); font-size: 24rpx; margin-bottom: 8rpx; }
.crop-demo-error { color: #b91c1c; font-size: 24rpx; margin-bottom: 8rpx; }
.crop-demo-confirm { color: #2563eb; font-size: 24rpx; margin-bottom: 32rpx; }
</style>
