Files
vue3-element-admin/src/views/lab/seata/index.vue
郝先瑞 47ed525fcd refactor: keepalive无效问题修复和代码vue社区代码规范调整
Former-commit-id: f661982d54f1738ff9739f1afc993181a466f052
2022-04-24 00:08:25 +08:00

316 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 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>