feat: 新增积分外部页面(免认证三页 + 配套基础设施)
前端: - 新增 EmptyLayout 空壳布局(无侧边栏/导航) - 新增 requestNoAuth Axios 实例(不注入 token) - 新增 integralExternal 路由模块(/integral-external/*) - permission.js 加入 whiteListPrefixes 前缀白名单跳过登录 - 新增 phoneDesensitize 手机号脱敏过滤器 - 新增三个免认证页面: · 积分订单页(/integral-external/order) · 用户积分页(/integral-external/user,手机号脱敏) · 用户积分明细子页(/integral-external/user/integral-detail) 后端: - 新增 ExternalIntegralController(无 @PreAuthorize) · GET /api/external/integral/order/list · GET /api/external/integral/user/list · POST /api/external/integral/log/list - WebSecurityConfig 加入 /api/external/integral/** permitAll 文档与工具: - 新增 coding plan、schedule、测试报告 - 新增 start-backend.sh / start-frontend.sh 本地启动脚本 - 新增 .mvn/wrapper/maven-wrapper.properties Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
254
backend-adminend/src/views/integral-external/order/index.vue
Normal file
254
backend-adminend/src/views/integral-external/order/index.vue
Normal file
@@ -0,0 +1,254 @@
|
||||
<template>
|
||||
<div class="divBox relative">
|
||||
<el-card class="box-card">
|
||||
<div class="clearfix">
|
||||
<div class="container">
|
||||
<el-form size="small" label-width="100px">
|
||||
<el-form-item label="订单类型:">
|
||||
<el-radio-group v-model="tableFrom.type" type="button" class="mr20" size="small" @change="seachList">
|
||||
<el-radio-button v-for="(item, i) in typeOptions" :key="i" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单状态:">
|
||||
<el-radio-group v-model="tableFrom.status" type="button" @change="seachList">
|
||||
<el-radio-button label="all">全部</el-radio-button>
|
||||
<el-radio-button label="unPaid">未支付</el-radio-button>
|
||||
<el-radio-button label="notShipped">未发货</el-radio-button>
|
||||
<el-radio-button label="spike">待收货</el-radio-button>
|
||||
<el-radio-button label="bargain">待评价</el-radio-button>
|
||||
<el-radio-button label="complete">交易完成</el-radio-button>
|
||||
<el-radio-button label="refunding">退款中</el-radio-button>
|
||||
<el-radio-button label="refunded">已退款</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="时间选择:" class="width100">
|
||||
<el-radio-group
|
||||
v-model="tableFrom.dateLimit"
|
||||
type="button"
|
||||
class="mr20"
|
||||
size="small"
|
||||
@change="selectChange(tableFrom.dateLimit)"
|
||||
>
|
||||
<el-radio-button v-for="(item, i) in fromList.fromTxt" :key="i" :label="item.val">
|
||||
{{ item.text }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-date-picker
|
||||
v-model="timeVal"
|
||||
value-format="yyyy-MM-dd"
|
||||
format="yyyy-MM-dd"
|
||||
size="small"
|
||||
type="daterange"
|
||||
placement="bottom-end"
|
||||
placeholder="自定义时间"
|
||||
style="width: 220px"
|
||||
@change="onchangeTime"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单号:" class="width100">
|
||||
<el-input
|
||||
v-model="tableFrom.orderNo"
|
||||
placeholder="请输入订单号"
|
||||
class="selWidth"
|
||||
size="small"
|
||||
clearable
|
||||
>
|
||||
<el-button slot="append" icon="el-icon-search" size="small" @click="seachList" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt10">
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="tableData.data"
|
||||
size="mini"
|
||||
class="table"
|
||||
highlight-current-row
|
||||
:header-cell-style="{ fontWeight: 'bold' }"
|
||||
>
|
||||
<el-table-column label="订单号" min-width="210">
|
||||
<template slot-scope="scope">
|
||||
<span style="display: block">{{ scope.row.orderId }}</span>
|
||||
<span v-if="scope.row.isDel" style="color: #ed4014; display: block">用户已删除</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="orderType" label="订单类型" min-width="110" />
|
||||
<el-table-column prop="realName" label="收货人" min-width="100" />
|
||||
<el-table-column label="商品信息" min-width="280">
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.productList && scope.row.productList.length">
|
||||
<div
|
||||
v-for="(val, i) in scope.row.productList"
|
||||
:key="i"
|
||||
class="tabBox acea-row row-middle"
|
||||
style="flex-wrap: inherit; margin-bottom: 4px"
|
||||
>
|
||||
<div class="demo-image__preview mr10" style="width: 40px; height: 40px; flex-shrink: 0">
|
||||
<el-image :src="val.info.image" :preview-src-list="[val.info.image]" style="width: 40px; height: 40px" />
|
||||
</div>
|
||||
<div class="text_overflow">
|
||||
<span class="tabBox_tit mr10">{{ val.info.productName }}</span>
|
||||
<span class="tabBox_pice">¥{{ val.info.price }} × {{ val.info.payNum }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="payPrice" label="实际支付" min-width="90">
|
||||
<template slot-scope="scope">
|
||||
<span>¥{{ scope.row.payPrice }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付方式" min-width="90">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.payTypeStr || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订单状态" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<span :class="scope.row.refundStatus === 1 || scope.row.refundStatus === 2 ? 'refund-tag' : ''">
|
||||
{{ scope.row.statusStr ? scope.row.statusStr.value : '-' }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="下单时间" min-width="150" />
|
||||
</el-table>
|
||||
|
||||
<div class="block mt20">
|
||||
<el-pagination
|
||||
:page-sizes="[15, 30, 45, 60]"
|
||||
:page-size="tableFrom.limit"
|
||||
:current-page="tableFrom.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableData.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getExternalOrderList } from '@/api/integralExternal';
|
||||
|
||||
export default {
|
||||
name: 'IntegralExternalOrder',
|
||||
data() {
|
||||
return {
|
||||
listLoading: false,
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
},
|
||||
tableFrom: {
|
||||
type: '',
|
||||
status: 'all',
|
||||
dateLimit: '',
|
||||
orderNo: '',
|
||||
page: 1,
|
||||
limit: 15,
|
||||
},
|
||||
timeVal: [],
|
||||
fromList: {
|
||||
fromTxt: [
|
||||
{ text: '全部', val: '' },
|
||||
{ text: '今天', val: 'today' },
|
||||
{ text: '昨天', val: 'yesterday' },
|
||||
{ text: '最近7天', val: 'lately7' },
|
||||
{ text: '最近30天', val: 'lately30' },
|
||||
{ text: '本月', val: 'month' },
|
||||
{ text: '本年', val: 'year' },
|
||||
],
|
||||
},
|
||||
typeOptions: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '普通订单', value: '0' },
|
||||
{ label: '秒杀订单', value: '1' },
|
||||
{ label: '砍价订单', value: '2' },
|
||||
{ label: '拼团订单', value: '3' },
|
||||
{ label: '视频号订单', value: '4' },
|
||||
],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.listLoading = true;
|
||||
const params = { ...this.tableFrom };
|
||||
if (!params.type) delete params.type;
|
||||
if (!params.dateLimit) delete params.dateLimit;
|
||||
if (!params.orderNo) delete params.orderNo;
|
||||
|
||||
getExternalOrderList(params)
|
||||
.then((res) => {
|
||||
this.tableData.data = res.list || [];
|
||||
this.tableData.total = res.total || 0;
|
||||
})
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
this.listLoading = false;
|
||||
});
|
||||
},
|
||||
seachList() {
|
||||
this.tableFrom.page = 1;
|
||||
this.getList();
|
||||
},
|
||||
selectChange(val) {
|
||||
if (val) this.timeVal = [];
|
||||
this.tableFrom.dateLimit = val;
|
||||
this.seachList();
|
||||
},
|
||||
onchangeTime(e) {
|
||||
this.timeVal = e;
|
||||
this.tableFrom.dateLimit = e ? e.join(',') : '';
|
||||
this.seachList();
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.tableFrom.limit = val;
|
||||
this.getList();
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.tableFrom.page = val;
|
||||
this.getList();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mt10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.mt20 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.refund-tag {
|
||||
color: #f124c7;
|
||||
font-weight: bold;
|
||||
}
|
||||
.tabBox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.tabBox_tit {
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
}
|
||||
.tabBox_pice {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
.block {
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user