<!-- setup 无法设置组件名称，组件名称keepAlive必须 -->
<script lang="ts">
export default {
  name: "seata"
};
</script>

<script setup lang="ts">
import { reactive, onMounted, toRefs } from 'vue';
import SvgIcon from '@/components/SvgIcon/index.vue';
import {
    Money,
    Refresh,
    RefreshLeft,
    Right,
    CircleCheckFilled,
    CircleCloseFilled
} from "@element-plus/icons-vue";
import {
    payOrder,
    getSeataData,
    resetSeataData
} from "@/api/lab/seata";
import { ElMessage, ElMessageBox } from 'element-plus';
import { SeataFormData } from "@/types";

const state = reactive({
    // 保留改变前数据
    cacheSeataData: {
        status: undefined,
        stockNum: undefined,
        balance: undefined
    },
    seataData: {
        orderInfo: {
            orderSn: undefined,
            status: undefined
        },
        skuInfo: {
            name: undefined,
            picUrl: undefined,
            stockNum: undefined
        },
        memberInfo: {
            nickName: undefined,
            avatarUrl: undefined,
            balance: undefined
        }
    },

    loading: false,

    submitData: {
        openTx: true, // 是否开启事务
        orderEx: true // 订单修改异常
    } as SeataFormData
})

const { cacheSeataData, seataData, loading, submitData } = toRefs(state)

/**
 * 订单支付(模拟)
 */
function handleOrderPay() {

    // 数据校验
    if (seataData.value.skuInfo.stockNum && seataData.value.skuInfo.stockNum != 999
        || (seataData.value.memberInfo.balance && seataData.value.memberInfo.balance != 1000000000)
        || (seataData.value.orderInfo.status && seataData.value.orderInfo.status != 101)
    ) {
        ElMessageBox.confirm(
            '检查到当前数据已被污染，请先重置数据后尝试提交?',
            '警告',
            {
                confirmButtonText: '重置数据',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                handleDataReset()
            }).catch(() => {
            })
    } else {
        // 订单支付模拟提交

        loading.value = true
        payOrder(submitData.value).then(() => {
            ElMessage.success('订单支付成功')
        }).finally(() => {
            cacheSeataData.value = {
                status: seataData.value.orderInfo.status,
                stockNum: seataData.value.skuInfo.stockNum,
                balance: seataData.value.memberInfo.balance
            }
            loadData();
        })
    }
}

/**
 * 加载数据
 */
function loadData() {
    loading.value = true
    getSeataData().then((response: any) => {
        seataData.value = response.data
        loading.value = false
    })
}

/**
 * 刷新数据
 */
function handleDataRefresh() {
    loading.value = true
    loadData();
}

/**
 * 数据重置
 */
function handleDataReset() {
    loading.value = true
    resetSeataData().then(() => {
        ElMessage.success('数据还原成功')
        loading.value = false;
        cacheSeataData.value = {
            status: undefined,
            stockNum: undefined,
            balance: undefined
        }
        loadData();
    })
}

onMounted(() => {
    // 第一次加载重置数据测试
    handleDataReset();
});
</script>

<template>
    <div class="app-container">
        <el-alert type="info">
            <p style="font-size: 16px;">
                <b>模拟订单支付流程：</b>
                扣减商品库存 → 扣减会员余额 → 修改订单状态
            </p>
            <p style="font-size: 14px;">
                <b> 分布式事务生效判断：</b>
                <el-link :icon="CircleCheckFilled" type="success">全部成功</el-link>
                或
                <el-link type="danger" :icon="CircleCloseFilled">全部失败</el-link>
            </p>

            <p style="font-size: 14px;">
                <b> 博客教程：</b>
                <el-link type="primary" href="https://www.cnblogs.com/haoxianrui/" target="_blank">
                    https://www.cnblogs.com/haoxianrui</el-link>
            </p>
        </el-alert>

        <el-card class="box-card" shadow="always" style="margin-top:20px;">
            <el-form :inline="true">
                <el-row>
                    <el-col :span="20">
                        <el-form-item>
                            <el-switch v-model="submitData.openTx" active-value="" active-text="开启事务"
                                inactive-text="关闭事务" />
                        </el-form-item>

                        <el-form-item>
                            <el-button type="primary" :icon="Money" @click="handleOrderPay">订单支付</el-button>
                            <el-button :icon="Refresh" @click="handleDataRefresh">刷新数据</el-button>
                        </el-form-item>
                    </el-col>
                    <el-col :span="4" style="text-align: right;">
                        <el-button :icon="RefreshLeft" @click="handleDataReset">重置数据</el-button>
                    </el-col>
                </el-row>
            </el-form>
        </el-card>

        <el-row :gutter="10" style="margin-top:20px;" v-loading="loading">
            <el-col :span="8" :xs="24" class="card-panel__col">
                <el-card class="box-card" shadow="always">
                    <template #header>
                        <svg-icon icon-class="goods" />
                        商品信息
                    </template>

                    <div style="display: flex;">
                        <el-image style="width: 100px; height: 100px" :src="seataData.skuInfo.picUrl" fit="fill" />
                        <div style="margin-left: 10px;">
                            <el-form-item label="商品名称:">
                                {{ seataData.skuInfo.name }}
                            </el-form-item>
                            <el-form-item label="库存数量:" style="display: flex;">
                                <div v-if="cacheSeataData.stockNum != null">
                                    {{ cacheSeataData.stockNum }} 部
                                    <el-icon>
                                        <right />
                                    </el-icon>
                                </div>

                                {{ seataData.skuInfo.stockNum }} 部

                                <div v-if="cacheSeataData.stockNum" style="margin-left: 50px;">
                                    <el-link v-if="cacheSeataData.stockNum != seataData.skuInfo.stockNum" type="success"
                                        :underline="false" :icon="CircleCheckFilled">
                                        修改成功
                                    </el-link>
                                    <el-link v-else-if="cacheSeataData.stockNum == seataData.skuInfo.stockNum"
                                        type="danger" :underline="false" :icon="CircleCloseFilled">
                                        修改失败
                                    </el-link>
                                </div>
                            </el-form-item>

                        </div>
                    </div>
                </el-card>
            </el-col>

            <el-col :span="8" :xs="24" class="card-panel__col">
                <el-card class="box-card" shadow="always">
                    <template #header>
                        <svg-icon icon-class="user" />
                        会员信息
                    </template>

                    <div style="display: flex;">
                        <el-image style="width: 100px; height: 100px" :src="seataData.memberInfo.avatarUrl"
                            fit="fill" />
                        <div style="margin-left: 10px;">
                            <el-form-item label="会员昵称:">
                                {{ seataData.memberInfo.nickName }}
                            </el-form-item>
                            <el-form-item label="会员余额:">
                                <div v-if="cacheSeataData.balance != null">
                                    {{ (cacheSeataData.balance as any) / 100 }} 元
                                    <el-icon>
                                        <right />
                                    </el-icon>
                                </div>
                                {{ (seataData.memberInfo.balance as any) / 100 }} 元

                                <div v-if="cacheSeataData.balance" style="margin-left: 50px;">
                                    <el-link v-if="cacheSeataData.balance != seataData.memberInfo.balance"
                                        type="success" :underline="false" :icon="CircleCheckFilled">
                                        修改成功
                                    </el-link>
                                    <el-link v-else-if="cacheSeataData.balance == seataData.memberInfo.balance"
                                        type="danger" :underline="false" :icon="CircleCloseFilled">
                                        修改失败
                                    </el-link>
                                </div>
                            </el-form-item>
                        </div>
                    </div>

                </el-card>
            </el-col>

            <el-col :span="8" :xs="24" class="card-panel__col">
                <el-card class="box-card" shadow="always">
                    <template #header>
                        <svg-icon icon-class="order" />
                        订单信息
                        <el-checkbox v-model="submitData.orderEx" :label="true" style="float: right;color: #F56C6C;">
                            搞点异常</el-checkbox>
                    </template>
                    <el-form-item label="订单编号:">
                        {{ seataData.orderInfo.orderSn }}
                    </el-form-item>

                    <el-form-item label="订单状态:">
                        <div v-if="cacheSeataData.status == 101">
                            <el-tag type="info">
                                待支付
                            </el-tag>
                            <el-icon>
                                <right />
                            </el-icon>
                        </div>
                        <el-tag v-if="seataData.orderInfo.status == 101" type="info">待支付</el-tag>
                        <el-tag v-else-if="seataData.orderInfo.status == 201" type="success">已支付</el-tag>

                        <div v-if="cacheSeataData.balance" style="margin-left: 50px;">
                            <el-link v-if="cacheSeataData.status != seataData.orderInfo.status" type="success"
                                :underline="false" :icon="CircleCheckFilled">
                                修改成功
                            </el-link>
                            <el-link v-else type="danger" :underline="false" :icon="CircleCloseFilled">
                                修改失败
                            </el-link>
                        </div>
                    </el-form-item>

                </el-card>
            </el-col>

        </el-row>
    </div>
</template>

<style lang="scss" scoped>
.card-panel__col {
    margin-bottom: 12px;

    .el-link {
        font-size: 16px;
        margin-right: 8px;
    }

}
</style>