mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-13 12:28:54 +08:00
refactor: 四端完成 Options API → script setup + vuex → pinia 迁移
- buyer(95) / seller(169) / im(53) / manager(280) 共 597 个组件全部从 Options API 转换为 <script setup> - 四端 vuex 全部移除,状态管理统一迁移至 pinia 4(stores/ 目录) - util.js 等基础设施去除 vm 首参依赖;全局属性($Message/$filters 等)在 script 内改为具名导入 - 被外部 ref 访问的公共组件均已补齐 defineExpose(清单见各端 MIGRATION-VUE3.md) - 各端 eslint 启用 vue/component-api-style 防止新代码回退 Options API - 四端 yarn build 全部通过;迁移约定与注意事项已更新至各端 MIGRATION-VUE3.md
This commit is contained in:
@@ -44,88 +44,84 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Bell } from "@element-plus/icons-vue";
|
||||
import storage from "@/plugins/storage";
|
||||
import { getOrderList } from "@/api/order";
|
||||
import { afterSaleList, getMembersWallet, memberCouponList } from "@/api/member";
|
||||
import { refreshUnreadMessage } from "@/utils/unreadMessage";
|
||||
import { useAppStore } from "@/stores/app";
|
||||
|
||||
defineOptions({ name: "UserCenterHome" });
|
||||
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
|
||||
function totalOf(res) {
|
||||
return res && res.success ? Number(res.result && res.result.total) || 0 : 0;
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "UserCenterHome",
|
||||
components: { Bell },
|
||||
data() {
|
||||
return {
|
||||
displayName: "会员",
|
||||
waitPay: 0,
|
||||
waitShip: 0,
|
||||
waitReceive: 0,
|
||||
afterSale: 0,
|
||||
couponCount: 0,
|
||||
balance: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
unreadMsg() {
|
||||
return Number(this.$store.state.unreadMsg) || 0;
|
||||
},
|
||||
unreadLabel() {
|
||||
return this.unreadMsg > 99 ? "99+" : String(this.unreadMsg);
|
||||
},
|
||||
orderStats() {
|
||||
return [
|
||||
{ key: "pay", label: "待付款", count: this.waitPay, action: () => this.goOrder("WAIT_PAY") },
|
||||
{ key: "ship", label: "待发货", count: this.waitShip, action: () => this.goOrder("WAIT_SHIP") },
|
||||
{ key: "receive", label: "待收货", count: this.waitReceive, action: () => this.goOrder("WAIT_USE") },
|
||||
{ key: "after", label: "售后", count: this.afterSale, action: () => this.go("AfterSale") },
|
||||
];
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.readUser();
|
||||
this.loadSummary();
|
||||
},
|
||||
methods: {
|
||||
readUser() {
|
||||
try {
|
||||
const raw = storage.getItem("userInfo");
|
||||
const user = raw ? JSON.parse(raw) : {};
|
||||
this.displayName = user.nickName || user.username || "会员";
|
||||
} catch {
|
||||
this.displayName = "会员";
|
||||
}
|
||||
},
|
||||
loadSummary() {
|
||||
const page = { pageNumber: 1, pageSize: 1 };
|
||||
Promise.all([
|
||||
getOrderList({ ...page, tag: "WAIT_PAY" }).catch(() => null),
|
||||
getOrderList({ ...page, tag: "WAIT_SHIP" }).catch(() => null),
|
||||
getOrderList({ ...page, tag: "WAIT_USE" }).catch(() => null),
|
||||
afterSaleList({ ...page, sort: "createTime", order: "desc" }).catch(() => null),
|
||||
memberCouponList({ ...page, memberCouponStatus: "NEW" }).catch(() => null),
|
||||
getMembersWallet().catch(() => null),
|
||||
refreshUnreadMessage(),
|
||||
]).then(([pay, ship, receive, afterSale, coupon, wallet]) => {
|
||||
this.waitPay = totalOf(pay);
|
||||
this.waitShip = totalOf(ship);
|
||||
this.waitReceive = totalOf(receive);
|
||||
this.afterSale = totalOf(afterSale);
|
||||
this.couponCount = totalOf(coupon);
|
||||
this.balance = wallet && wallet.success ? wallet.result.memberWallet || 0 : 0;
|
||||
});
|
||||
},
|
||||
go(name) {
|
||||
this.$router.push({ name });
|
||||
},
|
||||
goOrder(tag) {
|
||||
this.$router.push({ name: "MyOrder", query: { tag } });
|
||||
},
|
||||
},
|
||||
};
|
||||
const displayName = ref("会员");
|
||||
const waitPay = ref(0);
|
||||
const waitShip = ref(0);
|
||||
const waitReceive = ref(0);
|
||||
const afterSale = ref(0);
|
||||
const couponCount = ref(0);
|
||||
const balance = ref(0);
|
||||
|
||||
const unreadMsg = computed(() => appStore.unreadMsg);
|
||||
const unreadLabel = computed(() => (unreadMsg.value > 99 ? "99+" : String(unreadMsg.value)));
|
||||
const orderStats = computed(() => [
|
||||
{ key: "pay", label: "待付款", count: waitPay.value, action: () => goOrder("WAIT_PAY") },
|
||||
{ key: "ship", label: "待发货", count: waitShip.value, action: () => goOrder("WAIT_SHIP") },
|
||||
{ key: "receive", label: "待收货", count: waitReceive.value, action: () => goOrder("WAIT_USE") },
|
||||
{ key: "after", label: "售后", count: afterSale.value, action: () => go("AfterSale") },
|
||||
]);
|
||||
|
||||
function readUser() {
|
||||
try {
|
||||
const raw = storage.getItem("userInfo");
|
||||
const user = raw ? JSON.parse(raw) : {};
|
||||
displayName.value = user.nickName || user.username || "会员";
|
||||
} catch {
|
||||
displayName.value = "会员";
|
||||
}
|
||||
}
|
||||
|
||||
function loadSummary() {
|
||||
const page = { pageNumber: 1, pageSize: 1 };
|
||||
Promise.all([
|
||||
getOrderList({ ...page, tag: "WAIT_PAY" }).catch(() => null),
|
||||
getOrderList({ ...page, tag: "WAIT_SHIP" }).catch(() => null),
|
||||
getOrderList({ ...page, tag: "WAIT_USE" }).catch(() => null),
|
||||
afterSaleList({ ...page, sort: "createTime", order: "desc" }).catch(() => null),
|
||||
memberCouponList({ ...page, memberCouponStatus: "NEW" }).catch(() => null),
|
||||
getMembersWallet().catch(() => null),
|
||||
refreshUnreadMessage(),
|
||||
]).then(([pay, ship, receive, afterSaleRes, coupon, wallet]) => {
|
||||
waitPay.value = totalOf(pay);
|
||||
waitShip.value = totalOf(ship);
|
||||
waitReceive.value = totalOf(receive);
|
||||
afterSale.value = totalOf(afterSaleRes);
|
||||
couponCount.value = totalOf(coupon);
|
||||
balance.value = wallet && wallet.success ? wallet.result.memberWallet || 0 : 0;
|
||||
});
|
||||
}
|
||||
|
||||
function go(name) {
|
||||
router.push({ name });
|
||||
}
|
||||
|
||||
function goOrder(tag) {
|
||||
router.push({ name: "MyOrder", query: { tag } });
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
readUser();
|
||||
loadSummary();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -77,191 +77,187 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { computed, nextTick, onMounted, reactive, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
import { Key, Link } from '@element-plus/icons-vue';
|
||||
// import { getPwdStatus } from '@/api/account';
|
||||
import storage from '@/plugins/storage'
|
||||
import { bindThirdAccount, getThirdAccountBindList, getWechatH5QrCode, unbindThirdAccount } from '@/api/login.js'
|
||||
export default {
|
||||
components: { Key, Link },
|
||||
name: 'AccountSafe',
|
||||
data () {
|
||||
return {
|
||||
pwdStatus: '',
|
||||
connectLoading: false,
|
||||
bindModalVisible: false,
|
||||
bindSubmitLoading: false,
|
||||
connectBoundTypes: [],
|
||||
thirdAccountTypes: [
|
||||
{ type: 'WECHAT', label: '微信' }
|
||||
],
|
||||
qrCodeLoading: false,
|
||||
qrCodeBase64: '',
|
||||
bindForm: {
|
||||
type: '',
|
||||
typeLabel: '',
|
||||
unionID: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
wechatConnect () {
|
||||
return this.thirdAccountTypes[0]
|
||||
},
|
||||
qrCodeSrc () {
|
||||
if (!this.qrCodeBase64) return ''
|
||||
if (this.qrCodeBase64.startsWith('data:image')) return this.qrCodeBase64
|
||||
return `data:image/png;base64,${this.qrCodeBase64}`
|
||||
},
|
||||
bindModalOkText () {
|
||||
if (this.bindForm.type === 'WECHAT') return '我已完成绑定'
|
||||
return '确定'
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getPwdStatus()
|
||||
this.refreshConnectBinds()
|
||||
},
|
||||
methods: {
|
||||
// 设置支付密码
|
||||
goModifyPwd () {
|
||||
this.$router.push({name: 'ModifyPwd', query: { status: 2 }})
|
||||
},
|
||||
modifyPwd () { // 修改密码
|
||||
this.$router.push({name: 'ModifyPwd', query: { status: 1 }})
|
||||
},
|
||||
// 获取密码状态
|
||||
getPwdStatus () {},
|
||||
// getPwdStatus () {
|
||||
// getPwdStatus().then(res => {
|
||||
// if (res) {
|
||||
// this.pwdStatus = '修改密码'
|
||||
// } else {
|
||||
// this.pwdStatus = '设置密码'
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
isBound (type) {
|
||||
return this.connectBoundTypes.includes(type)
|
||||
},
|
||||
refreshConnectBinds () {
|
||||
this.connectLoading = true
|
||||
return getThirdAccountBindList()
|
||||
.then(res => {
|
||||
if (res && res.success) {
|
||||
this.connectBoundTypes = Array.isArray(res.result) ? res.result : []
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.connectLoading = false
|
||||
})
|
||||
},
|
||||
openBindModal (item) {
|
||||
this.bindForm.type = item.type
|
||||
this.bindForm.typeLabel = item.label
|
||||
this.bindForm.unionID = ''
|
||||
this.qrCodeBase64 = ''
|
||||
this.bindModalVisible = true
|
||||
if (item.type === 'WECHAT') {
|
||||
this.fetchWechatQrCode()
|
||||
}
|
||||
},
|
||||
resetBindForm () {
|
||||
this.bindForm.type = ''
|
||||
this.bindForm.typeLabel = ''
|
||||
this.bindForm.unionID = ''
|
||||
this.qrCodeLoading = false
|
||||
this.qrCodeBase64 = ''
|
||||
this.bindSubmitLoading = false
|
||||
},
|
||||
fetchWechatQrCode () {
|
||||
if (this.bindForm.type !== 'WECHAT') return
|
||||
const rawUserInfo = storage.getItem('userInfo')
|
||||
const userInfo = rawUserInfo ? JSON.parse(rawUserInfo) : null
|
||||
const userId = userInfo && userInfo.id ? String(userInfo.id) : ''
|
||||
if (!userId) {
|
||||
this.qrCodeBase64 = ''
|
||||
Message.error('未获取到当前用户ID,请重新登录后重试')
|
||||
return
|
||||
}
|
||||
this.qrCodeLoading = true
|
||||
getWechatH5QrCode({ scene: userId })
|
||||
.then(res => {
|
||||
if (res && res.success) {
|
||||
this.qrCodeBase64 = res.result || ''
|
||||
return
|
||||
}
|
||||
this.qrCodeBase64 = ''
|
||||
Message.error((res && res.message) || '二维码获取失败')
|
||||
})
|
||||
.catch(() => {
|
||||
this.qrCodeBase64 = ''
|
||||
})
|
||||
.finally(() => {
|
||||
this.qrCodeLoading = false
|
||||
})
|
||||
},
|
||||
submitBind () {
|
||||
if (this.bindSubmitLoading) return
|
||||
if (this.bindForm.type === 'WECHAT' && !this.bindForm.unionID) {
|
||||
this.bindSubmitLoading = true
|
||||
this.refreshConnectBinds()
|
||||
.then(() => {
|
||||
if (this.isBound(this.bindForm.type)) {
|
||||
Message.success('绑定成功')
|
||||
this.bindModalVisible = false
|
||||
this.resetBindForm()
|
||||
return
|
||||
}
|
||||
Message.warning('暂未检测到绑定,请扫码后重试')
|
||||
this.$nextTick(() => {
|
||||
this.bindModalVisible = true
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
this.bindSubmitLoading = false
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!this.bindForm.type) {
|
||||
Message.error('绑定类型不能为空')
|
||||
return
|
||||
}
|
||||
if (!this.bindForm.unionID) {
|
||||
Message.error('OpenID/UnionID 不能为空')
|
||||
this.$nextTick(() => {
|
||||
this.bindModalVisible = true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this.bindSubmitLoading = true
|
||||
bindThirdAccount({ unionID: this.bindForm.unionID, type: this.bindForm.type })
|
||||
.then(() => {
|
||||
Message.success('绑定成功')
|
||||
this.bindModalVisible = false
|
||||
this.resetBindForm()
|
||||
this.refreshConnectBinds()
|
||||
})
|
||||
.finally(() => {
|
||||
this.bindSubmitLoading = false
|
||||
})
|
||||
},
|
||||
confirmUnbind (item) {
|
||||
Modal.confirm({
|
||||
title: '解绑确认',
|
||||
content: `<p>确定解绑 ${item.label} 吗?</p>`,
|
||||
onOk: () => {
|
||||
unbindThirdAccount({ type: item.type }).then(() => {
|
||||
Message.success('解绑成功')
|
||||
this.refreshConnectBinds()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
defineOptions({ name: 'AccountSafe' });
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const pwdStatus = ref('');
|
||||
const connectLoading = ref(false);
|
||||
const bindModalVisible = ref(false);
|
||||
const bindSubmitLoading = ref(false);
|
||||
const connectBoundTypes = ref([]);
|
||||
const thirdAccountTypes = ref([
|
||||
{ type: 'WECHAT', label: '微信' }
|
||||
]);
|
||||
const qrCodeLoading = ref(false);
|
||||
const qrCodeBase64 = ref('');
|
||||
const bindForm = reactive({
|
||||
type: '',
|
||||
typeLabel: '',
|
||||
unionID: ''
|
||||
});
|
||||
|
||||
const wechatConnect = computed(() => thirdAccountTypes.value[0]);
|
||||
const qrCodeSrc = computed(() => {
|
||||
if (!qrCodeBase64.value) return ''
|
||||
if (qrCodeBase64.value.startsWith('data:image')) return qrCodeBase64.value
|
||||
return `data:image/png;base64,${qrCodeBase64.value}`
|
||||
});
|
||||
const bindModalOkText = computed(() => {
|
||||
if (bindForm.type === 'WECHAT') return '我已完成绑定'
|
||||
return '确定'
|
||||
});
|
||||
|
||||
// 设置支付密码
|
||||
function goModifyPwd () {
|
||||
router.push({name: 'ModifyPwd', query: { status: 2 }})
|
||||
}
|
||||
function modifyPwd () { // 修改密码
|
||||
router.push({name: 'ModifyPwd', query: { status: 1 }})
|
||||
}
|
||||
// 获取密码状态
|
||||
function getPwdStatus () {}
|
||||
// function getPwdStatus () {
|
||||
// getPwdStatus().then(res => {
|
||||
// if (res) {
|
||||
// pwdStatus.value = '修改密码'
|
||||
// } else {
|
||||
// pwdStatus.value = '设置密码'
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
function isBound (type) {
|
||||
return connectBoundTypes.value.includes(type)
|
||||
}
|
||||
function refreshConnectBinds () {
|
||||
connectLoading.value = true
|
||||
return getThirdAccountBindList()
|
||||
.then(res => {
|
||||
if (res && res.success) {
|
||||
connectBoundTypes.value = Array.isArray(res.result) ? res.result : []
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
connectLoading.value = false
|
||||
})
|
||||
}
|
||||
function openBindModal (item) {
|
||||
bindForm.type = item.type
|
||||
bindForm.typeLabel = item.label
|
||||
bindForm.unionID = ''
|
||||
qrCodeBase64.value = ''
|
||||
bindModalVisible.value = true
|
||||
if (item.type === 'WECHAT') {
|
||||
fetchWechatQrCode()
|
||||
}
|
||||
}
|
||||
function resetBindForm () {
|
||||
bindForm.type = ''
|
||||
bindForm.typeLabel = ''
|
||||
bindForm.unionID = ''
|
||||
qrCodeLoading.value = false
|
||||
qrCodeBase64.value = ''
|
||||
bindSubmitLoading.value = false
|
||||
}
|
||||
function fetchWechatQrCode () {
|
||||
if (bindForm.type !== 'WECHAT') return
|
||||
const rawUserInfo = storage.getItem('userInfo')
|
||||
const userInfo = rawUserInfo ? JSON.parse(rawUserInfo) : null
|
||||
const userId = userInfo && userInfo.id ? String(userInfo.id) : ''
|
||||
if (!userId) {
|
||||
qrCodeBase64.value = ''
|
||||
Message.error('未获取到当前用户ID,请重新登录后重试')
|
||||
return
|
||||
}
|
||||
qrCodeLoading.value = true
|
||||
getWechatH5QrCode({ scene: userId })
|
||||
.then(res => {
|
||||
if (res && res.success) {
|
||||
qrCodeBase64.value = res.result || ''
|
||||
return
|
||||
}
|
||||
qrCodeBase64.value = ''
|
||||
Message.error((res && res.message) || '二维码获取失败')
|
||||
})
|
||||
.catch(() => {
|
||||
qrCodeBase64.value = ''
|
||||
})
|
||||
.finally(() => {
|
||||
qrCodeLoading.value = false
|
||||
})
|
||||
}
|
||||
function submitBind () {
|
||||
if (bindSubmitLoading.value) return
|
||||
if (bindForm.type === 'WECHAT' && !bindForm.unionID) {
|
||||
bindSubmitLoading.value = true
|
||||
refreshConnectBinds()
|
||||
.then(() => {
|
||||
if (isBound(bindForm.type)) {
|
||||
Message.success('绑定成功')
|
||||
bindModalVisible.value = false
|
||||
resetBindForm()
|
||||
return
|
||||
}
|
||||
Message.warning('暂未检测到绑定,请扫码后重试')
|
||||
nextTick(() => {
|
||||
bindModalVisible.value = true
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
bindSubmitLoading.value = false
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!bindForm.type) {
|
||||
Message.error('绑定类型不能为空')
|
||||
return
|
||||
}
|
||||
if (!bindForm.unionID) {
|
||||
Message.error('OpenID/UnionID 不能为空')
|
||||
nextTick(() => {
|
||||
bindModalVisible.value = true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
bindSubmitLoading.value = true
|
||||
bindThirdAccount({ unionID: bindForm.unionID, type: bindForm.type })
|
||||
.then(() => {
|
||||
Message.success('绑定成功')
|
||||
bindModalVisible.value = false
|
||||
resetBindForm()
|
||||
refreshConnectBinds()
|
||||
})
|
||||
.finally(() => {
|
||||
bindSubmitLoading.value = false
|
||||
})
|
||||
}
|
||||
function confirmUnbind (item) {
|
||||
Modal.confirm({
|
||||
title: '解绑确认',
|
||||
content: `<p>确定解绑 ${item.label} 吗?</p>`,
|
||||
onOk: () => {
|
||||
unbindThirdAccount({ type: item.type }).then(() => {
|
||||
Message.success('解绑成功')
|
||||
refreshConnectBinds()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getPwdStatus()
|
||||
refreshConnectBinds()
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -50,52 +50,55 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {evolutionList} from '@/api/order.js';
|
||||
export default {
|
||||
name: 'CommentList',
|
||||
data () {
|
||||
return {
|
||||
commentWay: [`待评价`, `待追评`, `已评价`], // 评价分类
|
||||
loading: false, // 加载状态
|
||||
list: [], // 评价列表
|
||||
total: 0, // 评价总数
|
||||
params: { // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList () { // 获取评价列表
|
||||
evolutionList(this.params).then(res => {
|
||||
if (res.success) {
|
||||
const list = res.result.records;
|
||||
list.forEach(element => {
|
||||
element.descriptionScore = Number(element.descriptionScore)
|
||||
});
|
||||
this.list = list;
|
||||
this.total = res.result.total
|
||||
}
|
||||
})
|
||||
},
|
||||
changePageNum (val) { // 修改页码
|
||||
this.params.pageNumber = val;
|
||||
this.getList()
|
||||
},
|
||||
changePageSize (val) { // 修改页数
|
||||
this.params.pageNumber = 1;
|
||||
this.params.pageSize = val;
|
||||
this.getList()
|
||||
},
|
||||
evaluateDetail (id) { // 跳转评价详情
|
||||
this.$router.push({path: '/home/evalDetail', query: { id }})
|
||||
<script setup>
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { evolutionList } from '@/api/order.js';
|
||||
|
||||
defineOptions({ name: 'CommentList' });
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const commentWay = ref([`待评价`, `待追评`, `已评价`]); // 评价分类
|
||||
const loading = ref(false); // 加载状态
|
||||
const list = ref([]); // 评价列表
|
||||
const total = ref(0); // 评价总数
|
||||
const params = reactive({ // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
});
|
||||
|
||||
function getList () { // 获取评价列表
|
||||
evolutionList(params).then(res => {
|
||||
if (res.success) {
|
||||
const records = res.result.records;
|
||||
records.forEach(element => {
|
||||
element.descriptionScore = Number(element.descriptionScore)
|
||||
});
|
||||
list.value = records;
|
||||
total.value = res.result.total
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
function changePageNum (val) { // 修改页码
|
||||
params.pageNumber = val;
|
||||
getList()
|
||||
}
|
||||
|
||||
function changePageSize (val) { // 修改页数
|
||||
params.pageNumber = 1;
|
||||
params.pageSize = val;
|
||||
getList()
|
||||
}
|
||||
|
||||
function evaluateDetail (id) { // 跳转评价详情
|
||||
router.push({path: '/home/evalDetail', query: { id }})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -129,75 +129,74 @@
|
||||
</UserCenterLayout>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { Message } from "@/utils/message";
|
||||
import { View } from '@element-plus/icons-vue';
|
||||
import {getComplainDetail} from '@/api/member.js';
|
||||
import {communication} from '@/api/order';
|
||||
export default {
|
||||
components: { View },
|
||||
data () {
|
||||
return {
|
||||
detail: {}, // 评价详情
|
||||
visible: false, // 图片预览
|
||||
previewImage: '', // 预览图片地址
|
||||
loading: false, // 加载状态
|
||||
submitLoading: false, // 回复消息loading
|
||||
// 状态
|
||||
statusLabel: {
|
||||
NO_APPLY: '未申请',
|
||||
APPLYING: '申请中',
|
||||
COMPLETE: '已完成',
|
||||
EXPIRED: '已失效',
|
||||
CANCEL: '已取消',
|
||||
NEW: '待审核'
|
||||
},
|
||||
// 商家回复内容
|
||||
params: {
|
||||
content: '',
|
||||
complainId: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDetail () { // 获取投诉详情
|
||||
getComplainDetail(this.$route.query.id).then(res => {
|
||||
if (res.success) this.detail = res.result
|
||||
})
|
||||
},
|
||||
goGoodsDetail (skuId, goodsId) { // 跳转商品详情
|
||||
let routerUrl = this.$router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: {skuId, goodsId}
|
||||
})
|
||||
window.open(routerUrl.href, '_blank')
|
||||
},
|
||||
handleView (name) { // 预览图片
|
||||
this.previewImage = name;
|
||||
this.visible = true;
|
||||
},
|
||||
// 回复消息
|
||||
handleSubmit () {
|
||||
if (this.params.content === '') {
|
||||
Message.error('请填写对话内容');
|
||||
return;
|
||||
}
|
||||
this.submitLoading = true;
|
||||
this.params.complainId = this.$route.query.id;
|
||||
communication(this.params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
Message.success('对话成功');
|
||||
this.params.content = '';
|
||||
this.getDetail();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getDetail()
|
||||
}
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const detail = ref({}); // 评价详情
|
||||
const visible = ref(false); // 图片预览
|
||||
const previewImage = ref(''); // 预览图片地址
|
||||
const loading = ref(false); // 加载状态
|
||||
const submitLoading = ref(false); // 回复消息loading
|
||||
// 状态
|
||||
const statusLabel = {
|
||||
NO_APPLY: '未申请',
|
||||
APPLYING: '申请中',
|
||||
COMPLETE: '已完成',
|
||||
EXPIRED: '已失效',
|
||||
CANCEL: '已取消',
|
||||
NEW: '待审核'
|
||||
};
|
||||
// 商家回复内容
|
||||
const params = reactive({
|
||||
content: '',
|
||||
complainId: ''
|
||||
});
|
||||
|
||||
function getDetail () { // 获取投诉详情
|
||||
getComplainDetail(route.query.id).then(res => {
|
||||
if (res.success) detail.value = res.result
|
||||
})
|
||||
}
|
||||
function goGoodsDetail (skuId, goodsId) { // 跳转商品详情
|
||||
let routerUrl = router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: {skuId, goodsId}
|
||||
})
|
||||
window.open(routerUrl.href, '_blank')
|
||||
}
|
||||
function handleView (name) { // 预览图片
|
||||
previewImage.value = name;
|
||||
visible.value = true;
|
||||
}
|
||||
// 回复消息
|
||||
function handleSubmit () {
|
||||
if (params.content === '') {
|
||||
Message.error('请填写对话内容');
|
||||
return;
|
||||
}
|
||||
submitLoading.value = true;
|
||||
params.complainId = route.query.id;
|
||||
communication(params).then((res) => {
|
||||
submitLoading.value = false;
|
||||
if (res.success) {
|
||||
Message.success('对话成功');
|
||||
params.content = '';
|
||||
getDetail();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDetail()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.speak-way {
|
||||
|
||||
@@ -58,72 +58,75 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { reactive, ref, onMounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
import {complainList, clearComplain} from '@/api/member.js';
|
||||
export default {
|
||||
name: 'ComplainList',
|
||||
data () {
|
||||
return {
|
||||
loading: false, // 加载状态
|
||||
list: [], // 投诉列表
|
||||
statusLabel: { // 投诉状态
|
||||
NO_APPLY: '未申请',
|
||||
APPLYING: '申请中',
|
||||
COMPLETE: '已完成',
|
||||
EXPIRED: '已失效',
|
||||
CANCEL: '已取消',
|
||||
NEW: '新订单'
|
||||
},
|
||||
total: 0, // 投诉总数
|
||||
params: { // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList () { // 获取投诉列表
|
||||
complainList(this.params).then(res => {
|
||||
import { complainList, clearComplain } from '@/api/member.js';
|
||||
|
||||
defineOptions({ name: 'ComplainList' });
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const loading = ref(false); // 加载状态
|
||||
const list = ref([]); // 投诉列表
|
||||
const statusLabel = { // 投诉状态
|
||||
NO_APPLY: '未申请',
|
||||
APPLYING: '申请中',
|
||||
COMPLETE: '已完成',
|
||||
EXPIRED: '已失效',
|
||||
CANCEL: '已取消',
|
||||
NEW: '新订单'
|
||||
};
|
||||
const total = ref(0); // 投诉总数
|
||||
const params = reactive({ // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
});
|
||||
|
||||
function getList() { // 获取投诉列表
|
||||
complainList(params).then(res => {
|
||||
if (res.success) {
|
||||
list.value = res.result.records;
|
||||
total.value = res.result.total
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function changePageNum(val) { // 改变页码
|
||||
params.pageNumber = val;
|
||||
getList()
|
||||
}
|
||||
|
||||
function changePageSize(val) { // 改变页数
|
||||
params.pageNumber = 1;
|
||||
params.pageSize = val;
|
||||
getList()
|
||||
}
|
||||
|
||||
function cancel(id) { // 取消投诉
|
||||
Modal.confirm({
|
||||
title: '取消投诉',
|
||||
content: '确定取消投诉吗?',
|
||||
onOk: () => {
|
||||
clearComplain(id).then((res) => {
|
||||
if (res.success) {
|
||||
const list = res.result.records;
|
||||
this.list = list;
|
||||
this.total = res.result.total
|
||||
Message.success('取消投诉成功');
|
||||
getList();
|
||||
}
|
||||
})
|
||||
},
|
||||
changePageNum (val) { // 改变页码
|
||||
this.params.pageNumber = val;
|
||||
this.getList()
|
||||
},
|
||||
changePageSize (val) { // 改变页数
|
||||
this.params.pageNumber = 1;
|
||||
this.params.pageSize = val;
|
||||
this.getList()
|
||||
},
|
||||
cancel (id) { // 取消投诉
|
||||
Modal.confirm({
|
||||
title: '取消投诉',
|
||||
content: '确定取消投诉吗?',
|
||||
onOk: () => {
|
||||
clearComplain(id).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success('取消投诉成功');
|
||||
this.getList();
|
||||
}
|
||||
});
|
||||
},
|
||||
onCancel: () => { }
|
||||
});
|
||||
},
|
||||
goDetail (id) { // 跳转投诉详情
|
||||
this.$router.push({path: '/home/complainDetail', query: { id }})
|
||||
}
|
||||
}
|
||||
};
|
||||
onCancel: () => { }
|
||||
});
|
||||
}
|
||||
|
||||
function goDetail(id) { // 跳转投诉详情
|
||||
router.push({ path: '/home/complainDetail', query: { id } })
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -84,136 +84,144 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { Modal } from "@/utils/message";
|
||||
import { collectList, cancelCollect, storeCollectList, cancelStoreCollect } from '@/api/member.js'
|
||||
export default {
|
||||
name: 'Favorites',
|
||||
props: {
|
||||
homePage: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
favoriteWay: ['收藏商品', '收藏店铺'], // 收藏分类
|
||||
list: [], // 收藏列表
|
||||
total: 0, // 收藏总数
|
||||
params: { // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
type: this.$route.query.type || 'GOODS'
|
||||
},
|
||||
spinShow: false // 加载状态
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
activeTabIndex() {
|
||||
return this.params.type === 'STORE' ? 1 : 0;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
loadFavorites() {
|
||||
if (this.params.type === 'STORE') {
|
||||
this.getStoreList();
|
||||
} else {
|
||||
this.getList();
|
||||
}
|
||||
},
|
||||
getList() { // 获取商品收藏列表
|
||||
this.spinShow = true
|
||||
collectList(this.params).then(res => {
|
||||
if (res.success && res.result) {
|
||||
this.list = res.result.records || [];
|
||||
}
|
||||
}).catch(() => {
|
||||
this.list = [];
|
||||
}).finally(() => {
|
||||
this.spinShow = false
|
||||
})
|
||||
},
|
||||
getStoreList() { // 获取店铺收藏列表
|
||||
this.spinShow = true
|
||||
storeCollectList(this.params).then(res => {
|
||||
if (res.success && res.result) {
|
||||
this.list = res.result.records || [];
|
||||
}
|
||||
}).catch(() => {
|
||||
this.list = [];
|
||||
}).finally(() => {
|
||||
this.spinShow = false
|
||||
})
|
||||
},
|
||||
change(index) { // tab栏切换
|
||||
if (index === 0) { this.params.type = 'GOODS', this.getList() }
|
||||
if (index === 1) { this.params.type = 'STORE', this.getStoreList() }
|
||||
},
|
||||
cancel(id) { // 取消收藏
|
||||
let typeName = this.params.type === 'GOODS' ? '商品' : '店铺'
|
||||
Modal.confirm({
|
||||
title: '取消收藏',
|
||||
content: `确定取消收藏该${typeName}吗?`,
|
||||
onOk: () => {
|
||||
cancelCollect(this.params.type, id).then(res => {
|
||||
if (res.success) {
|
||||
this.getList();
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
cancelStore(id) { // 取消收藏
|
||||
let typeName = this.params.type === 'GOODS' ? '商品' : '店铺'
|
||||
Modal.confirm({
|
||||
title: '取消收藏',
|
||||
content: `确定取消收藏该${typeName}吗?`,
|
||||
onOk: () => {
|
||||
cancelStoreCollect(this.params.type, id).then(res => {
|
||||
if (res.success) {
|
||||
this.getStoreList();
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
openItem (item) {
|
||||
if (this.params.type === 'STORE') {
|
||||
this.goShop(item.id)
|
||||
return
|
||||
}
|
||||
this.buynow(item.skuId, item.goodsId)
|
||||
},
|
||||
buynow(skuId, goodsId,storeId) { // 跳转详情
|
||||
let url
|
||||
if (this.params.type === 'STORE') {
|
||||
url = this.$router.resolve({
|
||||
path: '/merchant',
|
||||
query: { 'id': storeId }
|
||||
})
|
||||
} else {
|
||||
url = this.$router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: { skuId, goodsId }
|
||||
})
|
||||
defineOptions({ name: 'Favorites' });
|
||||
|
||||
}
|
||||
window.open(url.href, '_blank')
|
||||
|
||||
},
|
||||
goShop(id) { // 跳转店铺页面
|
||||
this.$router.push({
|
||||
path: '/merchant',
|
||||
query: { id }
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.homePage) this.params.pageSize = 5;
|
||||
this.loadFavorites();
|
||||
const props = defineProps({
|
||||
homePage: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const favoriteWay = ref(['收藏商品', '收藏店铺']); // 收藏分类
|
||||
const list = ref([]); // 收藏列表
|
||||
const total = ref(0); // 收藏总数
|
||||
const params = reactive({ // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
type: route.query.type || 'GOODS'
|
||||
});
|
||||
const spinShow = ref(false); // 加载状态
|
||||
|
||||
const activeTabIndex = computed(() => {
|
||||
return params.type === 'STORE' ? 1 : 0;
|
||||
});
|
||||
|
||||
function loadFavorites() {
|
||||
if (params.type === 'STORE') {
|
||||
getStoreList();
|
||||
} else {
|
||||
getList();
|
||||
}
|
||||
}
|
||||
|
||||
function getList() { // 获取商品收藏列表
|
||||
spinShow.value = true
|
||||
collectList(params).then(res => {
|
||||
if (res.success && res.result) {
|
||||
list.value = res.result.records || [];
|
||||
}
|
||||
}).catch(() => {
|
||||
list.value = [];
|
||||
}).finally(() => {
|
||||
spinShow.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function getStoreList() { // 获取店铺收藏列表
|
||||
spinShow.value = true
|
||||
storeCollectList(params).then(res => {
|
||||
if (res.success && res.result) {
|
||||
list.value = res.result.records || [];
|
||||
}
|
||||
}).catch(() => {
|
||||
list.value = [];
|
||||
}).finally(() => {
|
||||
spinShow.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function change(index) { // tab栏切换
|
||||
if (index === 0) { params.type = 'GOODS', getList() }
|
||||
if (index === 1) { params.type = 'STORE', getStoreList() }
|
||||
}
|
||||
|
||||
function cancel(id) { // 取消收藏
|
||||
let typeName = params.type === 'GOODS' ? '商品' : '店铺'
|
||||
Modal.confirm({
|
||||
title: '取消收藏',
|
||||
content: `确定取消收藏该${typeName}吗?`,
|
||||
onOk: () => {
|
||||
cancelCollect(params.type, id).then(res => {
|
||||
if (res.success) {
|
||||
getList();
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function cancelStore(id) { // 取消收藏
|
||||
let typeName = params.type === 'GOODS' ? '商品' : '店铺'
|
||||
Modal.confirm({
|
||||
title: '取消收藏',
|
||||
content: `确定取消收藏该${typeName}吗?`,
|
||||
onOk: () => {
|
||||
cancelStoreCollect(params.type, id).then(res => {
|
||||
if (res.success) {
|
||||
getStoreList();
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function openItem (item) {
|
||||
if (params.type === 'STORE') {
|
||||
goShop(item.id)
|
||||
return
|
||||
}
|
||||
buynow(item.skuId, item.goodsId)
|
||||
}
|
||||
|
||||
function buynow(skuId, goodsId, storeId) { // 跳转详情
|
||||
let url
|
||||
if (params.type === 'STORE') {
|
||||
url = router.resolve({
|
||||
path: '/merchant',
|
||||
query: { 'id': storeId }
|
||||
})
|
||||
} else {
|
||||
url = router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: { skuId, goodsId }
|
||||
})
|
||||
|
||||
}
|
||||
window.open(url.href, '_blank')
|
||||
|
||||
}
|
||||
|
||||
function goShop(id) { // 跳转店铺页面
|
||||
router.push({
|
||||
path: '/merchant',
|
||||
query: { id }
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.homePage) params.pageSize = 5;
|
||||
loadFavorites();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -74,206 +74,218 @@
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { computed, onMounted, reactive, ref } from 'vue'
|
||||
import { memberGradeCurrent, memberGradeList, memberGradeRules } from '@/api/member.js'
|
||||
|
||||
export default {
|
||||
name: 'MemberGrade',
|
||||
data () {
|
||||
return {
|
||||
ruleList: [],
|
||||
rulesLoading: false,
|
||||
rulesDescription: '',
|
||||
/** 接口返回 List MemberGradeDetailVO,每项 { grade, benefits } */
|
||||
gradeDetails: [],
|
||||
gradeList: [],
|
||||
currentGrade: {},
|
||||
currentExperience: 0,
|
||||
currentGradeId: '',
|
||||
selectedRuleKey: '',
|
||||
activeGradeTab: 'rules',
|
||||
logLoading: false,
|
||||
gradeLoading: false,
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
},
|
||||
experienceLogs: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
rulesMap () {
|
||||
const map = {}
|
||||
this.ruleList.forEach(item => {
|
||||
map[item.ruleKey] = item.ruleName
|
||||
})
|
||||
return map
|
||||
},
|
||||
sortedGradeList () {
|
||||
const list = Array.isArray(this.gradeList) ? this.gradeList.slice() : []
|
||||
list.sort((a, b) => {
|
||||
const sa = a && a.gradeSort != null ? Number(a.gradeSort) : 0
|
||||
const sb = b && b.gradeSort != null ? Number(b.gradeSort) : 0
|
||||
if (sa !== sb) return sa - sb
|
||||
const ea = a && a.requiredExperience != null ? Number(a.requiredExperience) : 0
|
||||
const eb = b && b.requiredExperience != null ? Number(b.requiredExperience) : 0
|
||||
return ea - eb
|
||||
})
|
||||
return list
|
||||
},
|
||||
currentGradeIndex () {
|
||||
if (!this.currentGradeId) return -1
|
||||
return this.sortedGradeList.findIndex(g => g && g.id === this.currentGradeId)
|
||||
},
|
||||
nextGrade () {
|
||||
const idx = this.currentGradeIndex
|
||||
if (idx < 0) return null
|
||||
return this.sortedGradeList[idx + 1] || null
|
||||
},
|
||||
diffExperience () {
|
||||
if (!this.nextGrade || this.nextGrade.requiredExperience == null) return 0
|
||||
const diff = Number(this.nextGrade.requiredExperience) - Number(this.currentExperience || 0)
|
||||
return diff > 0 ? diff : 0
|
||||
},
|
||||
/** 当前等级在列表详情中对应的启用权益(顺序与后台 benefits 一致) */
|
||||
currentGradeBenefits () {
|
||||
const id = this.currentGradeId
|
||||
if (!id || !Array.isArray(this.gradeDetails) || !this.gradeDetails.length) return []
|
||||
const detail = this.gradeDetails.find(
|
||||
(d) => d && d.grade && String(d.grade.id) === String(id)
|
||||
)
|
||||
const list = detail && Array.isArray(detail.benefits) ? detail.benefits : []
|
||||
return list.filter((b) => b && b.benefitState === 'OPEN')
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
this.loadRules()
|
||||
this.loadGradeList()
|
||||
this.loadCurrent()
|
||||
},
|
||||
loadRules () {
|
||||
this.rulesLoading = true
|
||||
memberGradeRules()
|
||||
.then(res => {
|
||||
if (res && res.success) {
|
||||
const items = res.result && Array.isArray(res.result.items) ? res.result.items : []
|
||||
this.rulesDescription = (res.result && res.result.description) || ''
|
||||
this.ruleList = items
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.rulesLoading = false
|
||||
})
|
||||
},
|
||||
loadGradeList () {
|
||||
this.gradeLoading = true
|
||||
memberGradeList()
|
||||
.then(res => {
|
||||
if (res && res.success) {
|
||||
const raw = Array.isArray(res.result) ? res.result : []
|
||||
this.gradeDetails = raw
|
||||
.map((item) => {
|
||||
if (!item) return null
|
||||
if (item.grade != null) {
|
||||
return {
|
||||
grade: item.grade,
|
||||
benefits: Array.isArray(item.benefits) ? item.benefits : []
|
||||
}
|
||||
}
|
||||
return { grade: item, benefits: [] }
|
||||
})
|
||||
.filter(Boolean)
|
||||
this.gradeList = this.gradeDetails.map((d) => d.grade).filter(Boolean)
|
||||
} else {
|
||||
this.gradeDetails = []
|
||||
this.gradeList = []
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.gradeLoading = false
|
||||
})
|
||||
},
|
||||
loadCurrent () {
|
||||
this.logLoading = true
|
||||
const params = {
|
||||
pageNumber: this.params.pageNumber,
|
||||
pageSize: this.params.pageSize
|
||||
defineOptions({ name: 'MemberGrade' })
|
||||
|
||||
const ruleList = ref([])
|
||||
const rulesLoading = ref(false)
|
||||
const rulesDescription = ref('')
|
||||
/** 接口返回 List MemberGradeDetailVO,每项 { grade, benefits } */
|
||||
const gradeDetails = ref([])
|
||||
const gradeList = ref([])
|
||||
const currentGrade = ref({})
|
||||
const currentExperience = ref(0)
|
||||
const currentGradeId = ref('')
|
||||
const selectedRuleKey = ref('')
|
||||
const activeGradeTab = ref('rules')
|
||||
const logLoading = ref(false)
|
||||
const gradeLoading = ref(false)
|
||||
const params = reactive({
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
})
|
||||
const experienceLogs = ref({})
|
||||
|
||||
const rulesMap = computed(() => {
|
||||
const map = {}
|
||||
ruleList.value.forEach(item => {
|
||||
map[item.ruleKey] = item.ruleName
|
||||
})
|
||||
return map
|
||||
})
|
||||
|
||||
const sortedGradeList = computed(() => {
|
||||
const list = Array.isArray(gradeList.value) ? gradeList.value.slice() : []
|
||||
list.sort((a, b) => {
|
||||
const sa = a && a.gradeSort != null ? Number(a.gradeSort) : 0
|
||||
const sb = b && b.gradeSort != null ? Number(b.gradeSort) : 0
|
||||
if (sa !== sb) return sa - sb
|
||||
const ea = a && a.requiredExperience != null ? Number(a.requiredExperience) : 0
|
||||
const eb = b && b.requiredExperience != null ? Number(b.requiredExperience) : 0
|
||||
return ea - eb
|
||||
})
|
||||
return list
|
||||
})
|
||||
|
||||
const currentGradeIndex = computed(() => {
|
||||
if (!currentGradeId.value) return -1
|
||||
return sortedGradeList.value.findIndex(g => g && g.id === currentGradeId.value)
|
||||
})
|
||||
|
||||
const nextGrade = computed(() => {
|
||||
const idx = currentGradeIndex.value
|
||||
if (idx < 0) return null
|
||||
return sortedGradeList.value[idx + 1] || null
|
||||
})
|
||||
|
||||
const diffExperience = computed(() => {
|
||||
if (!nextGrade.value || nextGrade.value.requiredExperience == null) return 0
|
||||
const diff = Number(nextGrade.value.requiredExperience) - Number(currentExperience.value || 0)
|
||||
return diff > 0 ? diff : 0
|
||||
})
|
||||
|
||||
/** 当前等级在列表详情中对应的启用权益(顺序与后台 benefits 一致) */
|
||||
const currentGradeBenefits = computed(() => {
|
||||
const id = currentGradeId.value
|
||||
if (!id || !Array.isArray(gradeDetails.value) || !gradeDetails.value.length) return []
|
||||
const detail = gradeDetails.value.find(
|
||||
(d) => d && d.grade && String(d.grade.id) === String(id)
|
||||
)
|
||||
const list = detail && Array.isArray(detail.benefits) ? detail.benefits : []
|
||||
return list.filter((b) => b && b.benefitState === 'OPEN')
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
function init () {
|
||||
loadRules()
|
||||
loadGradeList()
|
||||
loadCurrent()
|
||||
}
|
||||
|
||||
function loadRules () {
|
||||
rulesLoading.value = true
|
||||
memberGradeRules()
|
||||
.then(res => {
|
||||
if (res && res.success) {
|
||||
const items = res.result && Array.isArray(res.result.items) ? res.result.items : []
|
||||
rulesDescription.value = (res.result && res.result.description) || ''
|
||||
ruleList.value = items
|
||||
}
|
||||
if (this.selectedRuleKey) params.ruleKey = this.selectedRuleKey
|
||||
memberGradeCurrent(params)
|
||||
.then(res => {
|
||||
if (res && res.success && res.result) {
|
||||
this.currentGrade = res.result.grade || {}
|
||||
this.currentExperience = res.result.experience || 0
|
||||
this.currentGradeId = res.result.gradeId || (this.currentGrade && this.currentGrade.id) || ''
|
||||
this.experienceLogs = res.result.experienceLogs || {}
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.logLoading = false
|
||||
})
|
||||
},
|
||||
selectRule (ruleKey) {
|
||||
this.selectedRuleKey = ruleKey || ''
|
||||
this.params.pageNumber = 1
|
||||
this.loadCurrent()
|
||||
},
|
||||
changePage (val) {
|
||||
this.params.pageNumber = val
|
||||
this.loadCurrent()
|
||||
},
|
||||
changePageSize (val) {
|
||||
this.params.pageSize = val
|
||||
this.params.pageNumber = 1
|
||||
this.loadCurrent()
|
||||
},
|
||||
getRuleName (ruleKey) {
|
||||
if (!ruleKey) return '-'
|
||||
return this.rulesMap[ruleKey] || ruleKey
|
||||
},
|
||||
getRuleDesc (ruleKey) {
|
||||
const map = {
|
||||
CONSUME: '客户消费1元可获取经验值,向下取整',
|
||||
REGISTER: '会员注册成功后可获取经验值',
|
||||
SIGN_IN: '客户每日签到后可获取的经验值',
|
||||
COMMENT: '对已购买商品完成发表评价获取经验值;仅针对评论字数大于30字的评论进行发放',
|
||||
SHARE: '会员分享商城页面可获取的经验值',
|
||||
PROFILE: '完善个人基本信息可获得经验值,每个会员仅可获得一次',
|
||||
FOLLOW_STORE: '关注店铺可获得经验值,每个客户ID同店铺仅第一次关注可进行获得',
|
||||
BIND_WECHAT: '绑定微信成功后获得经验值,每个会员仅可获得一次',
|
||||
ADD_ADDRESS: '添加收货地址可获得经验值,每个会员仅可获得一次',
|
||||
SHARE_REGISTER: '仅被注册成功后可获得相应奖励经验值',
|
||||
SHARE_BUY: '仅被购买成功后可获得相应奖励经验值'
|
||||
})
|
||||
.finally(() => {
|
||||
rulesLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function loadGradeList () {
|
||||
gradeLoading.value = true
|
||||
memberGradeList()
|
||||
.then(res => {
|
||||
if (res && res.success) {
|
||||
const raw = Array.isArray(res.result) ? res.result : []
|
||||
gradeDetails.value = raw
|
||||
.map((item) => {
|
||||
if (!item) return null
|
||||
if (item.grade != null) {
|
||||
return {
|
||||
grade: item.grade,
|
||||
benefits: Array.isArray(item.benefits) ? item.benefits : []
|
||||
}
|
||||
}
|
||||
return { grade: item, benefits: [] }
|
||||
})
|
||||
.filter(Boolean)
|
||||
gradeList.value = gradeDetails.value.map((d) => d.grade).filter(Boolean)
|
||||
} else {
|
||||
gradeDetails.value = []
|
||||
gradeList.value = []
|
||||
}
|
||||
if (!ruleKey) return '-'
|
||||
return map[ruleKey] || '-'
|
||||
},
|
||||
getLogDeltaRaw (row) {
|
||||
if (!row) return 0
|
||||
const candidate = row.variableExperience != null ? row.variableExperience : (row.changeExperience != null ? row.changeExperience : (row.experience != null ? row.experience : row.value))
|
||||
if (candidate == null) return 0
|
||||
const num = Number(candidate)
|
||||
if (Number.isNaN(num)) return 0
|
||||
if (row.type === 'DECREASE') return -Math.abs(num)
|
||||
if (row.type === 'INCREASE') return Math.abs(num)
|
||||
return num
|
||||
},
|
||||
getLogDeltaSign (row) {
|
||||
const num = this.getLogDeltaRaw(row)
|
||||
return num >= 0 ? '+' : '-'
|
||||
},
|
||||
getLogDeltaAbsValue (row) {
|
||||
const num = this.getLogDeltaRaw(row)
|
||||
return Math.abs(num)
|
||||
},
|
||||
getLogDeltaColor (row) {
|
||||
return this.getLogDeltaRaw(row) >= 0 ? 'green' : 'red'
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
gradeLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function loadCurrent () {
|
||||
logLoading.value = true
|
||||
const reqParams = {
|
||||
pageNumber: params.pageNumber,
|
||||
pageSize: params.pageSize
|
||||
}
|
||||
if (selectedRuleKey.value) reqParams.ruleKey = selectedRuleKey.value
|
||||
memberGradeCurrent(reqParams)
|
||||
.then(res => {
|
||||
if (res && res.success && res.result) {
|
||||
currentGrade.value = res.result.grade || {}
|
||||
currentExperience.value = res.result.experience || 0
|
||||
currentGradeId.value = res.result.gradeId || (currentGrade.value && currentGrade.value.id) || ''
|
||||
experienceLogs.value = res.result.experienceLogs || {}
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
logLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function selectRule (ruleKey) {
|
||||
selectedRuleKey.value = ruleKey || ''
|
||||
params.pageNumber = 1
|
||||
loadCurrent()
|
||||
}
|
||||
|
||||
function changePage (val) {
|
||||
params.pageNumber = val
|
||||
loadCurrent()
|
||||
}
|
||||
|
||||
function changePageSize (val) {
|
||||
params.pageSize = val
|
||||
params.pageNumber = 1
|
||||
loadCurrent()
|
||||
}
|
||||
|
||||
function getRuleName (ruleKey) {
|
||||
if (!ruleKey) return '-'
|
||||
return rulesMap.value[ruleKey] || ruleKey
|
||||
}
|
||||
|
||||
function getRuleDesc (ruleKey) {
|
||||
const map = {
|
||||
CONSUME: '客户消费1元可获取经验值,向下取整',
|
||||
REGISTER: '会员注册成功后可获取经验值',
|
||||
SIGN_IN: '客户每日签到后可获取的经验值',
|
||||
COMMENT: '对已购买商品完成发表评价获取经验值;仅针对评论字数大于30字的评论进行发放',
|
||||
SHARE: '会员分享商城页面可获取的经验值',
|
||||
PROFILE: '完善个人基本信息可获得经验值,每个会员仅可获得一次',
|
||||
FOLLOW_STORE: '关注店铺可获得经验值,每个客户ID同店铺仅第一次关注可进行获得',
|
||||
BIND_WECHAT: '绑定微信成功后获得经验值,每个会员仅可获得一次',
|
||||
ADD_ADDRESS: '添加收货地址可获得经验值,每个会员仅可获得一次',
|
||||
SHARE_REGISTER: '仅被注册成功后可获得相应奖励经验值',
|
||||
SHARE_BUY: '仅被购买成功后可获得相应奖励经验值'
|
||||
}
|
||||
if (!ruleKey) return '-'
|
||||
return map[ruleKey] || '-'
|
||||
}
|
||||
|
||||
function getLogDeltaRaw (row) {
|
||||
if (!row) return 0
|
||||
const candidate = row.variableExperience != null ? row.variableExperience : (row.changeExperience != null ? row.changeExperience : (row.experience != null ? row.experience : row.value))
|
||||
if (candidate == null) return 0
|
||||
const num = Number(candidate)
|
||||
if (Number.isNaN(num)) return 0
|
||||
if (row.type === 'DECREASE') return -Math.abs(num)
|
||||
if (row.type === 'INCREASE') return Math.abs(num)
|
||||
return num
|
||||
}
|
||||
|
||||
function getLogDeltaSign (row) {
|
||||
const num = getLogDeltaRaw(row)
|
||||
return num >= 0 ? '+' : '-'
|
||||
}
|
||||
|
||||
function getLogDeltaAbsValue (row) {
|
||||
const num = getLogDeltaRaw(row)
|
||||
return Math.abs(num)
|
||||
}
|
||||
|
||||
function getLogDeltaColor (row) {
|
||||
return getLogDeltaRaw(row) >= 0 ? 'green' : 'red'
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout>
|
||||
<!-- 手机号验证 -->
|
||||
<el-form ref="formData" :model="formData" label-position="left" label-width="100px" :rules="ruleInLines"
|
||||
<el-form ref="formDataRef" :model="formData" label-position="left" label-width="100px" :rules="ruleInLines"
|
||||
v-if="(status == 2 || status == 3) && !showPwd">
|
||||
<el-form-item label="手机号">
|
||||
<div class="phone">{{ displayMobile }}</div>
|
||||
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 修改 -->
|
||||
<el-form ref="formRegister" :model="formRegister" :rules="ruleInline" label-width="80px" v-if="status == 1 && !showPwd">
|
||||
<el-form ref="formRegisterRef" :model="formRegister" :rules="ruleInline" label-width="80px" v-if="status == 1 && !showPwd">
|
||||
<el-form-item label="旧密码" prop="password">
|
||||
<el-input type="password" v-model="formRegister.password" clearable size="large" placeholder="请输入旧密码"
|
||||
style="width: 300px"
|
||||
@@ -49,7 +49,7 @@
|
||||
<el-button type="primary" class="ml_10" @click="handleRegist">修改</el-button>
|
||||
</div>
|
||||
<!-- 设置&修改的第二种情况 -->
|
||||
<el-form ref="formDataUpdate" :model="formDataUpdate" label-position="left" label-width="100px" :rules="ruleIn"
|
||||
<el-form ref="formDataUpdateRef" :model="formDataUpdate" label-position="left" label-width="100px" :rules="ruleIn"
|
||||
v-if="showPwd">
|
||||
<el-form-item label="新密码" prop="newPassword">
|
||||
<el-input type="password" v-model="formDataUpdate.newPassword" clearable size="large" placeholder="请输入新密码"
|
||||
@@ -73,7 +73,9 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { Message } from "@/utils/message";
|
||||
import { Lock } from '@element-plus/icons-vue';
|
||||
import {
|
||||
@@ -82,166 +84,171 @@ import {
|
||||
} from '@/api/account';
|
||||
import { getMemberMsg } from '@/api/login.js';
|
||||
import storage from '@/plugins/storage.js';
|
||||
import {md5} from '@/plugins/md5.js'
|
||||
import { md5 } from '@/plugins/md5.js'
|
||||
import { secrecyMobile } from '@/plugins/filters.js'
|
||||
|
||||
export default {
|
||||
components: { Lock },
|
||||
name: 'modifyPwd',
|
||||
data () {
|
||||
return {
|
||||
// 1为修改 2为设置 3为提交校验的下一步
|
||||
status: '',
|
||||
mobile: '',
|
||||
showPwd: false, // 显示密码
|
||||
formData: { // 验证表单
|
||||
picture: '',
|
||||
msg: ''
|
||||
},
|
||||
formDataUpdate: { // 直接输入新密码表单
|
||||
newPassword: '',
|
||||
againPassword: ''
|
||||
},
|
||||
formRegister: { // 第三步 新密码表单
|
||||
password: '',
|
||||
againPassword: '',
|
||||
newPassword: ''
|
||||
},
|
||||
ruleInLines: { // 验证规则
|
||||
picture: [
|
||||
{required: true, message: '请输入图片验证码', trigger: 'blur'}
|
||||
],
|
||||
msg: [
|
||||
{required: true, message: '请输入短信验证码', trigger: 'blur'}
|
||||
]
|
||||
},
|
||||
ruleIn: { // 验证规则
|
||||
newPassword: [
|
||||
{required: true, message: '请输入新密码', trigger: 'blur'},
|
||||
{type: 'string', min: 6, message: '密码不能少于6位'}
|
||||
],
|
||||
againPassword: [
|
||||
{required: true, message: '请输入新密码', trigger: 'blur'},
|
||||
{type: 'string', min: 6, message: '密码不能少于6位'}
|
||||
]
|
||||
},
|
||||
ruleInline: { // 验证规则
|
||||
password: [
|
||||
{required: true, message: '请输入旧密码', trigger: 'blur'}
|
||||
],
|
||||
newPassword: [
|
||||
{required: true, message: '请输入新密码', trigger: 'blur'},
|
||||
{type: 'string', min: 6, message: '密码不能少于6位'}
|
||||
],
|
||||
againPassword: [
|
||||
{required: true, message: '请确认新密码', trigger: 'blur'},
|
||||
{type: 'string', min: 6, message: '密码不能少于6位'}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
displayMobile () {
|
||||
if (!this.mobile) return '未绑定手机号';
|
||||
return this.$filters.secrecyMobile(this.mobile);
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.status = this.$route.query.status
|
||||
this.loadMobile()
|
||||
},
|
||||
methods: {
|
||||
loadMobile () {
|
||||
const rawUserInfo = storage.getItem('userInfo');
|
||||
if (rawUserInfo) {
|
||||
try {
|
||||
const userInfo = JSON.parse(rawUserInfo);
|
||||
if (userInfo && userInfo.mobile) this.mobile = userInfo.mobile;
|
||||
} catch {
|
||||
// 缓存的用户信息解析失败时忽略,改走接口获取
|
||||
}
|
||||
}
|
||||
if (!storage.getItem('accessToken')) return;
|
||||
getMemberMsg().then(res => {
|
||||
if (res.success && res.result) {
|
||||
storage.setItem('userInfo', res.result);
|
||||
this.mobile = res.result.mobile || '';
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.warn('获取会员信息失败', err);
|
||||
});
|
||||
},
|
||||
normalizePwdError (message) {
|
||||
if (!message) return '修改失败,请稍后重试';
|
||||
if (String(message).includes('旧密码') || String(message).includes('密码不正确')) {
|
||||
return '旧密码不正确';
|
||||
}
|
||||
return message;
|
||||
},
|
||||
// 修改
|
||||
handleRegist () {
|
||||
this.$refs['formRegister'].validate((valid) => {
|
||||
if (valid) {
|
||||
const {newPassword, againPassword, password} = this.formRegister
|
||||
if (newPassword !== againPassword) {
|
||||
Message.error({
|
||||
content: '新密码和确认密码不一致'
|
||||
});
|
||||
return
|
||||
}
|
||||
const params = {newPassword, password}
|
||||
params.newPassword = md5(newPassword)
|
||||
params.password = md5(password)
|
||||
editPwd(params).then(res => {
|
||||
if (res.success && res.result) {
|
||||
Message.success('修改密码成功');
|
||||
this.$router.push('/home')
|
||||
} else {
|
||||
Message.error(this.normalizePwdError(res.message));
|
||||
}
|
||||
}).catch((err) => {
|
||||
Message.error(this.normalizePwdError(err?.message || err?.data?.message));
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
// 提交验证
|
||||
submitRegister () {
|
||||
this.$refs['formData'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.showPwd = true
|
||||
}
|
||||
})
|
||||
},
|
||||
// 设置密码
|
||||
setPassword () {
|
||||
this.$refs['formDataUpdate'].validate((valid) => {
|
||||
if (valid) {
|
||||
const {newPassword, againPassword} = this.formDataUpdate
|
||||
if (newPassword === '') {
|
||||
Message.error({
|
||||
content: '请输入密码'
|
||||
});
|
||||
return
|
||||
}
|
||||
if (newPassword !== againPassword) {
|
||||
Message.error({
|
||||
content: '新密码和确认密码不一致'
|
||||
});
|
||||
return
|
||||
}
|
||||
const params = {password: newPassword}
|
||||
params.password = md5(newPassword)
|
||||
setPwd(params).then(res => {
|
||||
if (res.message === 'success' && res.result) {
|
||||
Message.success('支付密码设置成功');
|
||||
this.$router.push('/home')
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
defineOptions({ name: 'modifyPwd' });
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
// 1为修改 2为设置 3为提交校验的下一步
|
||||
const status = ref('');
|
||||
const mobile = ref('');
|
||||
const showPwd = ref(false); // 显示密码
|
||||
const formData = reactive({ // 验证表单
|
||||
picture: '',
|
||||
msg: ''
|
||||
});
|
||||
const formDataUpdate = reactive({ // 直接输入新密码表单
|
||||
newPassword: '',
|
||||
againPassword: ''
|
||||
});
|
||||
const formRegister = reactive({ // 第三步 新密码表单
|
||||
password: '',
|
||||
againPassword: '',
|
||||
newPassword: ''
|
||||
});
|
||||
const ruleInLines = { // 验证规则
|
||||
picture: [
|
||||
{required: true, message: '请输入图片验证码', trigger: 'blur'}
|
||||
],
|
||||
msg: [
|
||||
{required: true, message: '请输入短信验证码', trigger: 'blur'}
|
||||
]
|
||||
};
|
||||
const ruleIn = { // 验证规则
|
||||
newPassword: [
|
||||
{required: true, message: '请输入新密码', trigger: 'blur'},
|
||||
{type: 'string', min: 6, message: '密码不能少于6位'}
|
||||
],
|
||||
againPassword: [
|
||||
{required: true, message: '请输入新密码', trigger: 'blur'},
|
||||
{type: 'string', min: 6, message: '密码不能少于6位'}
|
||||
]
|
||||
};
|
||||
const ruleInline = { // 验证规则
|
||||
password: [
|
||||
{required: true, message: '请输入旧密码', trigger: 'blur'}
|
||||
],
|
||||
newPassword: [
|
||||
{required: true, message: '请输入新密码', trigger: 'blur'},
|
||||
{type: 'string', min: 6, message: '密码不能少于6位'}
|
||||
],
|
||||
againPassword: [
|
||||
{required: true, message: '请确认新密码', trigger: 'blur'},
|
||||
{type: 'string', min: 6, message: '密码不能少于6位'}
|
||||
]
|
||||
};
|
||||
|
||||
const formDataRef = ref(null);
|
||||
const formRegisterRef = ref(null);
|
||||
const formDataUpdateRef = ref(null);
|
||||
|
||||
const displayMobile = computed(() => {
|
||||
if (!mobile.value) return '未绑定手机号';
|
||||
return secrecyMobile(mobile.value);
|
||||
});
|
||||
|
||||
function loadMobile () {
|
||||
const rawUserInfo = storage.getItem('userInfo');
|
||||
if (rawUserInfo) {
|
||||
try {
|
||||
const userInfo = JSON.parse(rawUserInfo);
|
||||
if (userInfo && userInfo.mobile) mobile.value = userInfo.mobile;
|
||||
} catch {
|
||||
// 缓存的用户信息解析失败时忽略,改走接口获取
|
||||
}
|
||||
}
|
||||
if (!storage.getItem('accessToken')) return;
|
||||
getMemberMsg().then(res => {
|
||||
if (res.success && res.result) {
|
||||
storage.setItem('userInfo', res.result);
|
||||
mobile.value = res.result.mobile || '';
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.warn('获取会员信息失败', err);
|
||||
});
|
||||
}
|
||||
|
||||
function normalizePwdError (message) {
|
||||
if (!message) return '修改失败,请稍后重试';
|
||||
if (String(message).includes('旧密码') || String(message).includes('密码不正确')) {
|
||||
return '旧密码不正确';
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
// 修改
|
||||
function handleRegist () {
|
||||
formRegisterRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
const {newPassword, againPassword, password} = formRegister
|
||||
if (newPassword !== againPassword) {
|
||||
Message.error({
|
||||
content: '新密码和确认密码不一致'
|
||||
});
|
||||
return
|
||||
}
|
||||
const params = {newPassword, password}
|
||||
params.newPassword = md5(newPassword)
|
||||
params.password = md5(password)
|
||||
editPwd(params).then(res => {
|
||||
if (res.success && res.result) {
|
||||
Message.success('修改密码成功');
|
||||
router.push('/home')
|
||||
} else {
|
||||
Message.error(normalizePwdError(res.message));
|
||||
}
|
||||
}).catch((err) => {
|
||||
Message.error(normalizePwdError(err?.message || err?.data?.message));
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 提交验证
|
||||
function submitRegister () {
|
||||
formDataRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
showPwd.value = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 设置密码
|
||||
function setPassword () {
|
||||
formDataUpdateRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
const {newPassword, againPassword} = formDataUpdate
|
||||
if (newPassword === '') {
|
||||
Message.error({
|
||||
content: '请输入密码'
|
||||
});
|
||||
return
|
||||
}
|
||||
if (newPassword !== againPassword) {
|
||||
Message.error({
|
||||
content: '新密码和确认密码不一致'
|
||||
});
|
||||
return
|
||||
}
|
||||
const params = {password: newPassword}
|
||||
params.password = md5(newPassword)
|
||||
setPwd(params).then(res => {
|
||||
if (res.message === 'success' && res.result) {
|
||||
Message.success('支付密码设置成功');
|
||||
router.push('/home')
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
status.value = route.query.status
|
||||
loadMobile()
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -42,48 +42,47 @@
|
||||
</UserCenterLayout>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {memberPoint, memberPointHistory} from '@/api/member.js'
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { memberPoint, memberPointHistory } from '@/api/member.js'
|
||||
|
||||
export default {
|
||||
name: 'Point',
|
||||
data () {
|
||||
return {
|
||||
logData: {}, // 积分日志
|
||||
pointObj: {}, // 积分明细
|
||||
loading: false, // 请求接口加载框
|
||||
params: { // 积分列表请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getHistory()
|
||||
this.getPoint()
|
||||
},
|
||||
methods: {
|
||||
getHistory () { // 获取积分历史
|
||||
memberPointHistory(this.params).then(res => {
|
||||
this.logData = res.result;
|
||||
})
|
||||
},
|
||||
getPoint () { // 获取积分详情
|
||||
memberPoint().then(res => {
|
||||
if (res.success) this.pointObj = res.result
|
||||
})
|
||||
},
|
||||
changePage (val) { // 修改页码
|
||||
this.params.pageNumber = val
|
||||
this.getHistory()
|
||||
},
|
||||
changePageSize (val) { // 修改页数
|
||||
this.params.pageSize = val
|
||||
this.params.pageNumber = 1
|
||||
this.getHistory()
|
||||
}
|
||||
}
|
||||
defineOptions({ name: "Point" });
|
||||
|
||||
const logData = ref({}); // 积分日志
|
||||
const pointObj = ref({}); // 积分明细
|
||||
const loading = ref(false); // 请求接口加载框
|
||||
const params = reactive({ // 积分列表请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
});
|
||||
|
||||
function getHistory() { // 获取积分历史
|
||||
memberPointHistory(params).then(res => {
|
||||
logData.value = res.result;
|
||||
})
|
||||
}
|
||||
|
||||
function getPoint() { // 获取积分详情
|
||||
memberPoint().then(res => {
|
||||
if (res.success) pointObj.value = res.result
|
||||
})
|
||||
}
|
||||
|
||||
function changePage(val) { // 修改页码
|
||||
params.pageNumber = val
|
||||
getHistory()
|
||||
}
|
||||
|
||||
function changePageSize(val) { // 修改页数
|
||||
params.pageSize = val
|
||||
params.pageNumber = 1
|
||||
getHistory()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getHistory()
|
||||
getPoint()
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
h3 {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<UserCenterLayout>
|
||||
<el-form class="profile-form" :model="formItem" :rules="rules" ref="form" label-width="72px" label-position="left">
|
||||
<el-form class="profile-form" :model="formItem" :rules="rules" ref="formRef" label-width="72px" label-position="left">
|
||||
<el-form-item label="头像" class="avatar-form-item">
|
||||
<div class="avatar-upload">
|
||||
<el-avatar v-if="formItem.face" :src="formItem.face" :size="72" />
|
||||
@@ -42,114 +42,115 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { Message } from "@/utils/message";
|
||||
import { editMemberInfo } from '@/api/account.js';
|
||||
import { getMemberMsg } from '@/api/login.js';
|
||||
import { buyerUrl } from '@/plugins/request.js';
|
||||
import storage from '@/plugins/storage.js';
|
||||
import { User } from '@element-plus/icons-vue';
|
||||
export default {
|
||||
components: { User },
|
||||
name: 'Profile',
|
||||
data () {
|
||||
return {
|
||||
rules: { // 验证规则
|
||||
nickName: [{required: true, message: '用户昵称不能为空'}, { max: 16, message: '用户昵称不能超过15个字符' }]
|
||||
},
|
||||
formItem: {}, // 表单数据
|
||||
action: buyerUrl + '/buyer/common/upload/file', // 上传接口
|
||||
accessToken: {} // 验证token
|
||||
|
||||
defineOptions({ name: 'Profile' });
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const formRef = ref(null);
|
||||
|
||||
const rules = { // 验证规则
|
||||
nickName: [{required: true, message: '用户昵称不能为空'}, { max: 16, message: '用户昵称不能超过15个字符' }]
|
||||
};
|
||||
const formItem = ref({}); // 表单数据
|
||||
const action = buyerUrl + '/buyer/common/upload/file'; // 上传接口
|
||||
const accessToken = reactive({}); // 验证token
|
||||
|
||||
onMounted(() => {
|
||||
accessToken.accessToken = storage.getItem('accessToken');
|
||||
loadUserInfo();
|
||||
});
|
||||
|
||||
function loadUserInfo () {
|
||||
const rawUserInfo = storage.getItem('userInfo');
|
||||
if (rawUserInfo) {
|
||||
applyUserInfo(JSON.parse(rawUserInfo));
|
||||
return;
|
||||
}
|
||||
if (!storage.getItem('accessToken')) {
|
||||
redirectToLogin();
|
||||
return;
|
||||
}
|
||||
getMemberMsg().then(res => {
|
||||
if (res.success && res.result) {
|
||||
storage.setItem('userInfo', res.result);
|
||||
applyUserInfo(res.result);
|
||||
} else {
|
||||
redirectToLogin();
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.accessToken.accessToken = storage.getItem('accessToken');
|
||||
this.loadUserInfo();
|
||||
},
|
||||
methods: {
|
||||
loadUserInfo () {
|
||||
const rawUserInfo = storage.getItem('userInfo');
|
||||
if (rawUserInfo) {
|
||||
this.applyUserInfo(JSON.parse(rawUserInfo));
|
||||
return;
|
||||
}).catch(() => {
|
||||
redirectToLogin();
|
||||
});
|
||||
}
|
||||
function applyUserInfo (userInfo) {
|
||||
formItem.value = { ...userInfo };
|
||||
formItem.value.birthday = normalizeBirthday(formItem.value.birthday);
|
||||
}
|
||||
function redirectToLogin () {
|
||||
router.push({
|
||||
path: '/login',
|
||||
query: {
|
||||
rePath: route.path,
|
||||
query: JSON.stringify(route.query || {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
function normalizeBirthday (value) {
|
||||
if (!value) return ''
|
||||
if (value instanceof Date) return value
|
||||
if (typeof value === 'number') return new Date(value)
|
||||
if (typeof value === 'string') {
|
||||
const m = value.match(/^(\d{4})-(\d{2})-(\d{2})/)
|
||||
if (m) return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]))
|
||||
const d = new Date(value)
|
||||
return isNaN(d.getTime()) ? '' : d
|
||||
}
|
||||
return ''
|
||||
}
|
||||
function formatBirthday (value) {
|
||||
if (!value) return null
|
||||
if (typeof value === 'string') {
|
||||
const m = value.match(/^(\d{4})-(\d{2})-(\d{2})/)
|
||||
return m ? `${m[1]}-${m[2]}-${m[3]}` : null
|
||||
}
|
||||
const d = value instanceof Date ? value : new Date(value)
|
||||
if (isNaN(d.getTime())) return null
|
||||
const yyyy = d.getFullYear()
|
||||
const mm = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const dd = String(d.getDate()).padStart(2, '0')
|
||||
return `${yyyy}-${mm}-${dd}`
|
||||
}
|
||||
function save () { // 保存
|
||||
formRef.value.validate(valid => {
|
||||
if (valid) {
|
||||
let params = {
|
||||
birthday: formatBirthday(formItem.value.birthday),
|
||||
face: formItem.value.face,
|
||||
nickName: formItem.value.nickName,
|
||||
sex: formItem.value.sex
|
||||
}
|
||||
if (!storage.getItem('accessToken')) {
|
||||
this.redirectToLogin();
|
||||
return;
|
||||
}
|
||||
getMemberMsg().then(res => {
|
||||
if (res.success && res.result) {
|
||||
storage.setItem('userInfo', res.result);
|
||||
this.applyUserInfo(res.result);
|
||||
} else {
|
||||
this.redirectToLogin();
|
||||
}
|
||||
}).catch(() => {
|
||||
this.redirectToLogin();
|
||||
});
|
||||
},
|
||||
applyUserInfo (userInfo) {
|
||||
this.formItem = { ...userInfo };
|
||||
this.formItem.birthday = this.normalizeBirthday(this.formItem.birthday);
|
||||
},
|
||||
redirectToLogin () {
|
||||
this.$router.push({
|
||||
path: '/login',
|
||||
query: {
|
||||
rePath: this.$route.path,
|
||||
query: JSON.stringify(this.$route.query || {}),
|
||||
},
|
||||
});
|
||||
},
|
||||
normalizeBirthday (value) {
|
||||
if (!value) return ''
|
||||
if (value instanceof Date) return value
|
||||
if (typeof value === 'number') return new Date(value)
|
||||
if (typeof value === 'string') {
|
||||
const m = value.match(/^(\d{4})-(\d{2})-(\d{2})/)
|
||||
if (m) return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]))
|
||||
const d = new Date(value)
|
||||
return isNaN(d.getTime()) ? '' : d
|
||||
}
|
||||
return ''
|
||||
},
|
||||
formatBirthday (value) {
|
||||
if (!value) return null
|
||||
if (typeof value === 'string') {
|
||||
const m = value.match(/^(\d{4})-(\d{2})-(\d{2})/)
|
||||
return m ? `${m[1]}-${m[2]}-${m[3]}` : null
|
||||
}
|
||||
const d = value instanceof Date ? value : new Date(value)
|
||||
if (isNaN(d.getTime())) return null
|
||||
const yyyy = d.getFullYear()
|
||||
const mm = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const dd = String(d.getDate()).padStart(2, '0')
|
||||
return `${yyyy}-${mm}-${dd}`
|
||||
},
|
||||
save () { // 保存
|
||||
this.$refs.form.validate(valid => {
|
||||
if (valid) {
|
||||
let params = {
|
||||
birthday: this.formatBirthday(this.formItem.birthday),
|
||||
face: this.formItem.face,
|
||||
nickName: this.formItem.nickName,
|
||||
sex: this.formItem.sex
|
||||
}
|
||||
editMemberInfo(params).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('修改个人资料成功')
|
||||
storage.setItem('userInfo', res.result)
|
||||
this.$router.go(0)
|
||||
}
|
||||
})
|
||||
editMemberInfo(params).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('修改个人资料成功')
|
||||
storage.setItem('userInfo', res.result)
|
||||
router.go(0)
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSuccess (res, file) { // 上传成功
|
||||
this.formItem['face'] = res.result
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
function handleSuccess (res, file) { // 上传成功
|
||||
formItem.value['face'] = res.result
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -74,119 +74,125 @@
|
||||
</UserCenterLayout>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script setup>
|
||||
import { getCurrentInstance, onMounted, reactive, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { Message, Notice } from "@/utils/message";
|
||||
import { Camera, Delete, View } from '@element-plus/icons-vue';
|
||||
import { orderDetail } from '@/api/order.js';
|
||||
import { addEvaluation } from '@/api/member.js';
|
||||
import { buyerUrl } from '@/plugins/request.js';
|
||||
import storage from '@/plugins/storage';
|
||||
export default {
|
||||
components: { Camera, Delete, View },
|
||||
data () {
|
||||
return {
|
||||
order: {}, // 订单详情
|
||||
orderGoods: {}, // 订单商品
|
||||
form: { // 评分展示
|
||||
deliveryScore: 5,
|
||||
serviceScore: 5,
|
||||
descriptionScore: 5
|
||||
}, // 表单
|
||||
visible: false, // 图片预览
|
||||
action: buyerUrl + '/buyer/common/upload/file', // 上传地址
|
||||
accessToken: {}, // 验证token
|
||||
previewImage: '', // 预览图片地址
|
||||
loading: false, // 提交加载状态
|
||||
// el-rate SVG 通过 colors 写入 fill-color,跟随平台主题色
|
||||
rateThemeColors: ['var(--theme-color)', 'var(--theme-color)', 'var(--theme-color)']
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
const order = ref({}); // 订单详情
|
||||
const orderGoods = ref({}); // 订单商品
|
||||
const form = reactive({ // 评分展示
|
||||
deliveryScore: 5,
|
||||
serviceScore: 5,
|
||||
descriptionScore: 5
|
||||
}); // 表单
|
||||
const visible = ref(false); // 图片预览
|
||||
const action = buyerUrl + '/buyer/common/upload/file'; // 上传地址
|
||||
const accessToken = reactive({}); // 验证token
|
||||
const previewImage = ref(''); // 预览图片地址
|
||||
const loading = ref(false); // 提交加载状态
|
||||
// el-rate SVG 通过 colors 写入 fill-color,跟随平台主题色
|
||||
const rateThemeColors = ['var(--theme-color)', 'var(--theme-color)', 'var(--theme-color)'];
|
||||
|
||||
function getOrderDetail () { // 获取订单详情
|
||||
orderDetail(route.query.sn).then(res => {
|
||||
order.value = res.result
|
||||
orderGoods.value = res.result.orderItems[route.query.index]
|
||||
orderGoods.value['grade'] = 'GOOD'
|
||||
orderGoods.value.uploadList = []
|
||||
})
|
||||
}
|
||||
|
||||
function save () { // 保存评价
|
||||
if (!form.serviceScore || !form.deliveryScore) {
|
||||
Message.warning('物流服务评价不能为空')
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!form.descriptionScore) {
|
||||
Message.warning('描述评价不能为空')
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!orderGoods.value.content || !String(orderGoods.value.content).trim()) {
|
||||
Message.warning('评论内容不能为空')
|
||||
return false;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
let goods = orderGoods.value
|
||||
let params = {
|
||||
goodsId: goods.goodsId,
|
||||
orderItemSn: goods.sn,
|
||||
skuId: goods.skuId,
|
||||
descriptionScore: form.descriptionScore,
|
||||
serviceScore: form.serviceScore,
|
||||
deliveryScore: form.deliveryScore,
|
||||
grade: goods.grade,
|
||||
content: goods.content.trim(),
|
||||
images: goods.uploadList.length ? goods.uploadList.join(',') : ''
|
||||
}
|
||||
addEvaluation(params).then(res => {
|
||||
loading.value = false
|
||||
if (res.success) {
|
||||
Message.success('评价成功')
|
||||
router.push('/home/CommentList')
|
||||
} else {
|
||||
Message.error(res.message || '评价失败,请稍后重试')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getOrderDetail () { // 获取订单详情
|
||||
orderDetail(this.$route.query.sn).then(res => {
|
||||
this.order = res.result
|
||||
this.orderGoods = res.result.orderItems[this.$route.query.index]
|
||||
this.orderGoods['grade'] = 'GOOD'
|
||||
this.orderGoods.uploadList = []
|
||||
})
|
||||
},
|
||||
save () { // 保存评价
|
||||
if (!this.form.serviceScore || !this.form.deliveryScore) {
|
||||
Message.warning('物流服务评价不能为空')
|
||||
return false;
|
||||
}
|
||||
}).catch((err) => {
|
||||
loading.value = false;
|
||||
Message.error(err?.message || '评价失败,请稍后重试')
|
||||
})
|
||||
}
|
||||
|
||||
if (!this.form.descriptionScore) {
|
||||
Message.warning('描述评价不能为空')
|
||||
return false;
|
||||
}
|
||||
function goGoodsDetail (skuId, goodsId) { // 跳转商品详情
|
||||
let routerUrl = router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: {skuId, goodsId}
|
||||
})
|
||||
window.open(routerUrl.href, '_blank')
|
||||
}
|
||||
|
||||
if (!this.orderGoods.content || !String(this.orderGoods.content).trim()) {
|
||||
Message.warning('评论内容不能为空')
|
||||
return false;
|
||||
}
|
||||
function handleView (name) { // 预览图片
|
||||
previewImage.value = name;
|
||||
visible.value = true;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
let goods = this.orderGoods
|
||||
let params = {
|
||||
goodsId: goods.goodsId,
|
||||
orderItemSn: goods.sn,
|
||||
skuId: goods.skuId,
|
||||
descriptionScore: this.form.descriptionScore,
|
||||
serviceScore: this.form.serviceScore,
|
||||
deliveryScore: this.form.deliveryScore,
|
||||
grade: goods.grade,
|
||||
content: goods.content.trim(),
|
||||
images: goods.uploadList.length ? goods.uploadList.join(',') : ''
|
||||
}
|
||||
addEvaluation(params).then(res => {
|
||||
this.loading = false
|
||||
if (res.success) {
|
||||
Message.success('评价成功')
|
||||
this.$router.push('/home/CommentList')
|
||||
} else {
|
||||
Message.error(res.message || '评价失败,请稍后重试')
|
||||
}
|
||||
}).catch((err) => {
|
||||
this.loading = false;
|
||||
Message.error(err?.message || '评价失败,请稍后重试')
|
||||
})
|
||||
},
|
||||
goGoodsDetail (skuId, goodsId) { // 跳转商品详情
|
||||
let routerUrl = this.$router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: {skuId, goodsId}
|
||||
})
|
||||
window.open(routerUrl.href, '_blank')
|
||||
},
|
||||
handleView (name) { // 预览图片
|
||||
this.previewImage = name;
|
||||
this.visible = true;
|
||||
},
|
||||
handleRemove (index) { // 移除图片
|
||||
this.orderGoods.uploadList.splice(index, 1)
|
||||
this.$forceUpdate()
|
||||
},
|
||||
handleSuccess (res, file) { // 上传成功回调
|
||||
this.orderGoods.uploadList.push(res.result)
|
||||
this.$forceUpdate()
|
||||
},
|
||||
handleBeforeUpload () { // 上传之前钩子
|
||||
const check = this.orderGoods.uploadList.length < 9;
|
||||
if (!check) {
|
||||
Notice.warning({
|
||||
title: '最多可以上传九张图片'
|
||||
});
|
||||
return check;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
window.scrollTo(0, 0)
|
||||
this.accessToken.accessToken = storage.getItem('accessToken');
|
||||
this.getOrderDetail()
|
||||
function handleRemove (index) { // 移除图片
|
||||
orderGoods.value.uploadList.splice(index, 1)
|
||||
instance.proxy.$forceUpdate()
|
||||
}
|
||||
|
||||
function handleSuccess (res, file) { // 上传成功回调
|
||||
orderGoods.value.uploadList.push(res.result)
|
||||
instance.proxy.$forceUpdate()
|
||||
}
|
||||
|
||||
function handleBeforeUpload () { // 上传之前钩子
|
||||
const check = orderGoods.value.uploadList.length < 9;
|
||||
if (!check) {
|
||||
Notice.warning({
|
||||
title: '最多可以上传九张图片'
|
||||
});
|
||||
return check;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.scrollTo(0, 0)
|
||||
accessToken.accessToken = storage.getItem('accessToken');
|
||||
getOrderDetail()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.delivery-rate {
|
||||
|
||||
@@ -79,51 +79,50 @@
|
||||
</UserCenterLayout>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script setup>
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { evaluationDetail } from "@/api/member.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
order: {}, // 订单详情
|
||||
orderGoods: {}, // 订单商品
|
||||
visible: false, // 图片预览
|
||||
previewImage: "", // 预览图片链接
|
||||
loading: false, // 加载状态
|
||||
// el-rate SVG 通过 colors 写入 fill-color,跟随平台主题色
|
||||
rateThemeColors: ["var(--theme-color)", "var(--theme-color)", "var(--theme-color)"],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
gradeText () {
|
||||
const map = { GOOD: '好评', MODERATE: '中评', WORSE: '差评' }
|
||||
return map[this.orderGoods.grade] || '评价详情'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDetail() {
|
||||
// 获取评价详情
|
||||
evaluationDetail(this.$route.query.id).then((res) => {
|
||||
if (res.success) this.orderGoods = res.result;
|
||||
});
|
||||
},
|
||||
goGoodsDetail(skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routerUrl = this.$router.resolve({
|
||||
path: "/goodsDetail",
|
||||
query: { skuId, goodsId },
|
||||
});
|
||||
window.open(routerUrl.href, "_blank");
|
||||
},
|
||||
handleView(name) {
|
||||
// 预览图片
|
||||
this.previewImage = name;
|
||||
this.visible = true;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getDetail();
|
||||
},
|
||||
};
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const order = ref({}); // 订单详情
|
||||
const orderGoods = ref({}); // 订单商品
|
||||
const visible = ref(false); // 图片预览
|
||||
const previewImage = ref(""); // 预览图片链接
|
||||
const loading = ref(false); // 加载状态
|
||||
// el-rate SVG 通过 colors 写入 fill-color,跟随平台主题色
|
||||
const rateThemeColors = ref(["var(--theme-color)", "var(--theme-color)", "var(--theme-color)"]);
|
||||
|
||||
const gradeText = computed(() => {
|
||||
const map = { GOOD: '好评', MODERATE: '中评', WORSE: '差评' }
|
||||
return map[orderGoods.value.grade] || '评价详情'
|
||||
});
|
||||
|
||||
function getDetail() {
|
||||
// 获取评价详情
|
||||
evaluationDetail(route.query.id).then((res) => {
|
||||
if (res.success) orderGoods.value = res.result;
|
||||
});
|
||||
}
|
||||
function goGoodsDetail(skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routerUrl = router.resolve({
|
||||
path: "/goodsDetail",
|
||||
query: { skuId, goodsId },
|
||||
});
|
||||
window.open(routerUrl.href, "_blank");
|
||||
}
|
||||
function handleView(name) {
|
||||
// 预览图片
|
||||
previewImage.value = name;
|
||||
visible.value = true;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDetail();
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.add-eval {
|
||||
|
||||
@@ -22,86 +22,90 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
import { delMemberMsg, getMemberMessage, readMemberMsg } from '@/api/member.js';
|
||||
import { refreshUnreadMessage } from '@/utils/unreadMessage';
|
||||
|
||||
defineOptions({ name: 'MsgDetail' });
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const CACHE_KEY = 'buyer-member-message';
|
||||
|
||||
export default {
|
||||
name: 'MsgDetail',
|
||||
data () {
|
||||
return {
|
||||
detail: {},
|
||||
loaded: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.loadDetail()
|
||||
},
|
||||
methods: {
|
||||
loadDetail () {
|
||||
const id = this.$route.query.id
|
||||
if (!id) {
|
||||
this.loaded = true
|
||||
return
|
||||
}
|
||||
const cached = this.readCache(id)
|
||||
if (cached) this.detail = cached
|
||||
getMemberMessage(id).then(res => {
|
||||
if (res && res.success && res.result && res.result.id) {
|
||||
this.detail = res.result
|
||||
sessionStorage.setItem(CACHE_KEY, JSON.stringify(res.result))
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.warn('获取消息详情失败', err)
|
||||
}).finally(() => {
|
||||
this.loaded = true
|
||||
this.markRead()
|
||||
})
|
||||
},
|
||||
readCache (id) {
|
||||
try {
|
||||
const raw = sessionStorage.getItem(CACHE_KEY)
|
||||
if (!raw) return null
|
||||
const message = JSON.parse(raw)
|
||||
return message && String(message.id) === String(id) ? message : null
|
||||
} catch (e) {
|
||||
return null
|
||||
}
|
||||
},
|
||||
markRead () {
|
||||
if (!this.detail.id || this.detail.status !== 'UN_READY') return
|
||||
readMemberMsg(this.detail.id).then(res => {
|
||||
if (res && res.success) {
|
||||
this.detail.status = 'ALREADY_READY'
|
||||
refreshUnreadMessage()
|
||||
}
|
||||
}).catch(() => {
|
||||
// 标记已读为尽力而为操作,失败可忽略
|
||||
})
|
||||
},
|
||||
goBack () {
|
||||
this.$router.push({ name: 'MsgList' })
|
||||
},
|
||||
removeMessage () {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '确认要删除此消息?',
|
||||
loading: true,
|
||||
onOk: () =>
|
||||
delMemberMsg(this.detail.id).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success('消息已成功放入回收站')
|
||||
refreshUnreadMessage()
|
||||
this.goBack()
|
||||
}
|
||||
})
|
||||
})
|
||||
const detail = ref({});
|
||||
const loaded = ref(false);
|
||||
|
||||
function loadDetail () {
|
||||
const id = route.query.id
|
||||
if (!id) {
|
||||
loaded.value = true
|
||||
return
|
||||
}
|
||||
const cached = readCache(id)
|
||||
if (cached) detail.value = cached
|
||||
getMemberMessage(id).then(res => {
|
||||
if (res && res.success && res.result && res.result.id) {
|
||||
detail.value = res.result
|
||||
sessionStorage.setItem(CACHE_KEY, JSON.stringify(res.result))
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.warn('获取消息详情失败', err)
|
||||
}).finally(() => {
|
||||
loaded.value = true
|
||||
markRead()
|
||||
})
|
||||
}
|
||||
|
||||
function readCache (id) {
|
||||
try {
|
||||
const raw = sessionStorage.getItem(CACHE_KEY)
|
||||
if (!raw) return null
|
||||
const message = JSON.parse(raw)
|
||||
return message && String(message.id) === String(id) ? message : null
|
||||
} catch (e) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function markRead () {
|
||||
if (!detail.value.id || detail.value.status !== 'UN_READY') return
|
||||
readMemberMsg(detail.value.id).then(res => {
|
||||
if (res && res.success) {
|
||||
detail.value.status = 'ALREADY_READY'
|
||||
refreshUnreadMessage()
|
||||
}
|
||||
}).catch(() => {
|
||||
// 标记已读为尽力而为操作,失败可忽略
|
||||
})
|
||||
}
|
||||
|
||||
function goBack () {
|
||||
router.push({ name: 'MsgList' })
|
||||
}
|
||||
|
||||
function removeMessage () {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '确认要删除此消息?',
|
||||
loading: true,
|
||||
onOk: () =>
|
||||
delMemberMsg(detail.value.id).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success('消息已成功放入回收站')
|
||||
refreshUnreadMessage()
|
||||
goBack()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadDetail()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -47,85 +47,85 @@
|
||||
</UserCenterLayout>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script setup>
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
import {memberMsgList, readMemberMsg, delMemberMsg} from '@/api/member.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
messageData: {},
|
||||
status: ['未读', '已读', '回收站'],
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
status: 'UN_READY'
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
activeStatusIndex () {
|
||||
const map = ['UN_READY', 'ALREADY_READY', 'ALREADY_REMOVE'];
|
||||
const index = map.indexOf(this.params.status);
|
||||
return index > -1 ? index : 0;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
statusChange (index) {
|
||||
if (index === 0) { this.params.status = 'UN_READY' }
|
||||
if (index === 1) { this.params.status = 'ALREADY_READY' }
|
||||
if (index === 2) { this.params.status = 'ALREADY_REMOVE' }
|
||||
this.params.pageNumber = 1
|
||||
this.getList()
|
||||
},
|
||||
changePage (v) {
|
||||
this.params.pageNumber = v;
|
||||
this.getList();
|
||||
},
|
||||
changePageSize (v) {
|
||||
this.params.pageNumber = 1
|
||||
this.params.pageSize = v;
|
||||
this.getList();
|
||||
},
|
||||
openDetail (row) {
|
||||
sessionStorage.setItem('buyer-member-message', JSON.stringify(row))
|
||||
this.$router.push({ name: 'MsgDetail', query: { id: row.id } })
|
||||
},
|
||||
getList () {
|
||||
memberMsgList(this.params).then(res => {
|
||||
if (res.success) {
|
||||
this.messageData = res.result;
|
||||
if (this.params.status === 'UN_READY') {
|
||||
this.$store.commit('SET_UNREAD_MSG', Number(res.result.total) || 0);
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
setRead (id) {
|
||||
readMemberMsg(id).then(res => {
|
||||
if (res.success) {
|
||||
this.getList()
|
||||
}
|
||||
})
|
||||
},
|
||||
removeMessage (id) {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '确认要删除此消息?',
|
||||
loading: true,
|
||||
onOk: () =>
|
||||
delMemberMsg(id).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success('消息已成功放入回收站');
|
||||
this.getList();
|
||||
}
|
||||
}),
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getList()
|
||||
}
|
||||
import { useAppStore } from "@/stores/app";
|
||||
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const messageData = ref({});
|
||||
const status = ref(['未读', '已读', '回收站']);
|
||||
const params = reactive({
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
status: 'UN_READY'
|
||||
});
|
||||
|
||||
const activeStatusIndex = computed(() => {
|
||||
const map = ['UN_READY', 'ALREADY_READY', 'ALREADY_REMOVE'];
|
||||
const index = map.indexOf(params.status);
|
||||
return index > -1 ? index : 0;
|
||||
});
|
||||
|
||||
function statusChange (index) {
|
||||
if (index === 0) { params.status = 'UN_READY' }
|
||||
if (index === 1) { params.status = 'ALREADY_READY' }
|
||||
if (index === 2) { params.status = 'ALREADY_REMOVE' }
|
||||
params.pageNumber = 1
|
||||
getList()
|
||||
}
|
||||
function changePage (v) {
|
||||
params.pageNumber = v;
|
||||
getList();
|
||||
}
|
||||
function changePageSize (v) {
|
||||
params.pageNumber = 1
|
||||
params.pageSize = v;
|
||||
getList();
|
||||
}
|
||||
function openDetail (row) {
|
||||
sessionStorage.setItem('buyer-member-message', JSON.stringify(row))
|
||||
router.push({ name: 'MsgDetail', query: { id: row.id } })
|
||||
}
|
||||
function getList () {
|
||||
memberMsgList(params).then(res => {
|
||||
if (res.success) {
|
||||
messageData.value = res.result;
|
||||
if (params.status === 'UN_READY') {
|
||||
appStore.setUnreadMsg(Number(res.result.total) || 0);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
function setRead (id) {
|
||||
readMemberMsg(id).then(res => {
|
||||
if (res.success) {
|
||||
getList()
|
||||
}
|
||||
})
|
||||
}
|
||||
function removeMessage (id) {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '确认要删除此消息?',
|
||||
loading: true,
|
||||
onOk: () =>
|
||||
delMemberMsg(id).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success('消息已成功放入回收站');
|
||||
getList();
|
||||
}
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.msg-table {
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
<div>
|
||||
<UserCenterLayout>
|
||||
<div class="add-box">
|
||||
<el-form :model="formData" ref="form" label-position="left" label-width="100px" :rules="ruleInline">
|
||||
<el-form :model="formData" ref="formRef" label-position="left" label-width="100px" :rules="ruleInline">
|
||||
<el-form-item label="收件人" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入收件人姓名" style="width: 600px"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="收件地区" prop="address">
|
||||
<span>{{ formData.address || '暂无地址' }}</span>
|
||||
|
||||
<el-button type="default" style="margin-left: 10px;" size="small" @click="$refs.map.open()">选择</el-button>
|
||||
<el-button type="default" style="margin-left: 10px;" size="small" @click="mapRef.open()">选择</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="详细地址" prop="detail">
|
||||
<el-input v-model="formData.detail" placeholder="请输入详细地址" style="width: 600px"></el-input>
|
||||
@@ -32,11 +32,13 @@
|
||||
</div>
|
||||
</UserCenterLayout>
|
||||
|
||||
<multipleMap ref="map" @callback="getAddress" />
|
||||
<multipleMap ref="mapRef" @callback="getAddress" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import multipleMap from "@/components/map/multiple-map";
|
||||
import * as RegExp from "@/plugins/RegExp.js";
|
||||
import {
|
||||
@@ -44,108 +46,107 @@ import {
|
||||
editMemberAddress,
|
||||
getAddrDetail,
|
||||
} from "@/api/address";
|
||||
export default {
|
||||
name: "AddAddress",
|
||||
data() {
|
||||
return {
|
||||
formData: {
|
||||
// 添加地址表单
|
||||
isDefault: false,
|
||||
},
|
||||
ruleInline: {
|
||||
// 验证规则
|
||||
name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
|
||||
address: [{ required: true, message: "请输入地址", trigger: "change" }],
|
||||
detail: [
|
||||
{ required: true, message: "请输入详细地址", trigger: "blur" },
|
||||
],
|
||||
mobile: [
|
||||
{ required: true, message: "请输入手机号码" },
|
||||
{
|
||||
pattern: RegExp.mobile,
|
||||
trigger: "blur",
|
||||
message: "请输入正确的手机号",
|
||||
},
|
||||
],
|
||||
},
|
||||
loading: false, // 加载状态
|
||||
mapMsg: {}, // 地图信息
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
// 保存地址
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
const params = JSON.parse(JSON.stringify(this.formData));
|
||||
params.consigneeAddressPath = params.address.replace(/\s/g, ",");
|
||||
delete params.address;
|
||||
this.loading = true;
|
||||
if (this.$route.query.id) {
|
||||
editMemberAddress(params)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.$router.push("/home/MyAddress");
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
} else {
|
||||
newMemberAddress(params)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.$router.push("/home/MyAddress");
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getAddrById(id) {
|
||||
// 获取地址详情
|
||||
getAddrDetail(id).then((res) => {
|
||||
if (res.success) {
|
||||
const data = res.result;
|
||||
data.address = res.result.consigneeAddressPath.replace(/,/g, " ");
|
||||
this.formData = data;
|
||||
}
|
||||
});
|
||||
},
|
||||
getAddress(val) {
|
||||
// 获取地图选择信息
|
||||
if(val.type === 'select'){
|
||||
const paths = val.data.map(item => item.name).join(',')
|
||||
const ids = val.data.map(item => item.id).join(',')
|
||||
this.formData['address'] = paths
|
||||
this.formData['consigneeAddressIdPath'] = ids
|
||||
const coord = val.data[val.data.length - 1].center.split(',')
|
||||
this.formData.lat = coord[1]
|
||||
this.formData.lon = coord[0]
|
||||
}else{
|
||||
this.formData["address"] = val.data.addr;
|
||||
this.formData["consigneeAddressIdPath"] = val.data.addrId;
|
||||
this.formData["detail"] = val.data.address;
|
||||
this.formData.lat = val.data.position.lat;
|
||||
this.formData.lon = val.data.position.lng;
|
||||
}
|
||||
|
||||
defineOptions({ name: "AddAddress" });
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const formRef = ref(null);
|
||||
const mapRef = ref(null);
|
||||
|
||||
const formData = ref({
|
||||
// 添加地址表单
|
||||
isDefault: false,
|
||||
});
|
||||
const ruleInline = {
|
||||
// 验证规则
|
||||
name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
|
||||
address: [{ required: true, message: "请输入地址", trigger: "change" }],
|
||||
detail: [
|
||||
{ required: true, message: "请输入详细地址", trigger: "blur" },
|
||||
],
|
||||
mobile: [
|
||||
{ required: true, message: "请输入手机号码" },
|
||||
{
|
||||
pattern: RegExp.mobile,
|
||||
trigger: "blur",
|
||||
message: "请输入正确的手机号",
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
const id = this.$route.query.id;
|
||||
if (id) this.getAddrById(id);
|
||||
},
|
||||
components: {
|
||||
multipleMap
|
||||
},
|
||||
],
|
||||
};
|
||||
const loading = ref(false); // 加载状态
|
||||
const mapMsg = ref({}); // 地图信息
|
||||
|
||||
// 保存地址
|
||||
function save() {
|
||||
formRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
const params = JSON.parse(JSON.stringify(formData.value));
|
||||
params.consigneeAddressPath = params.address.replace(/\s/g, ",");
|
||||
delete params.address;
|
||||
loading.value = true;
|
||||
if (route.query.id) {
|
||||
editMemberAddress(params)
|
||||
.then((res) => {
|
||||
loading.value = false;
|
||||
if (res.success) {
|
||||
router.push("/home/MyAddress");
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
} else {
|
||||
newMemberAddress(params)
|
||||
.then((res) => {
|
||||
loading.value = false;
|
||||
if (res.success) {
|
||||
router.push("/home/MyAddress");
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function getAddrById(id) {
|
||||
// 获取地址详情
|
||||
getAddrDetail(id).then((res) => {
|
||||
if (res.success) {
|
||||
const data = res.result;
|
||||
data.address = res.result.consigneeAddressPath.replace(/,/g, " ");
|
||||
formData.value = data;
|
||||
}
|
||||
});
|
||||
}
|
||||
function getAddress(val) {
|
||||
// 获取地图选择信息
|
||||
if(val.type === 'select'){
|
||||
const paths = val.data.map(item => item.name).join(',')
|
||||
const ids = val.data.map(item => item.id).join(',')
|
||||
formData.value['address'] = paths
|
||||
formData.value['consigneeAddressIdPath'] = ids
|
||||
const coord = val.data[val.data.length - 1].center.split(',')
|
||||
formData.value.lat = coord[1]
|
||||
formData.value.lon = coord[0]
|
||||
}else{
|
||||
formData.value["address"] = val.data.addr;
|
||||
formData.value["consigneeAddressIdPath"] = val.data.addrId;
|
||||
formData.value["detail"] = val.data.address;
|
||||
formData.value.lat = val.data.position.lat;
|
||||
formData.value.lon = val.data.position.lng;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const id = route.query.id;
|
||||
if (id) getAddrById(id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-form ref="form" :model="form" label-position="left" label-width="100px" :rules="rules">
|
||||
<el-form ref="formRef" :model="form" label-position="left" label-width="100px" :rules="rules">
|
||||
<el-form-item label="物流公司" prop="logisticsId">
|
||||
<el-select v-model="form.logisticsId" placeholder="请选择物流公司">
|
||||
<el-option v-for="item in companyList" :value="item.id" :key="item.id">{{ item.name }}</el-option>
|
||||
@@ -131,170 +131,169 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { nextTick, onMounted, reactive, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
import {afterSaleList, cancelAfterSale} from '@/api/member.js';
|
||||
import {afterSaleDelivery, getLogisticsCompany} from '@/api/order.js';
|
||||
import {afterSaleStatusList} from '../enumeration.js'
|
||||
|
||||
export default {
|
||||
name: 'AfterSale',
|
||||
data() {
|
||||
return {
|
||||
orderList: [], // 订单列表
|
||||
params: { // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
keywords: '',
|
||||
sn: '',
|
||||
sort: 'createTime',
|
||||
order: 'desc'
|
||||
},
|
||||
// 状态数组
|
||||
afterSaleStatusList,
|
||||
total: 0, // 订单总数
|
||||
spinShow: false, // 加载状态
|
||||
companyList: [], // 物流公司列表
|
||||
logisticsShow: false, // 物流信息modal
|
||||
singleOrder: {}, // 单独的售后信息
|
||||
form: { // 物流信息数据
|
||||
afterSaleSn: '',
|
||||
logisticsId: '',
|
||||
logisticsNo: '',
|
||||
mDeliverTime: ''
|
||||
},
|
||||
rules: { // 必填校验
|
||||
logisticsId: [{required: true, message: '请选择物流公司'}],
|
||||
logisticsNo: [{required: true, message: '请填写物流编号'}],
|
||||
mDeliverTime: [{required: true, message: '请选择发货时间'}]
|
||||
},
|
||||
submitLoading: false, // 提交加载状态
|
||||
changeWay: [
|
||||
{ name: '全部', status: '' },
|
||||
{ name: '申请中', status: 'APPLY' },
|
||||
{ name: '通过', status: 'PASS' },
|
||||
{ name: '完成售后', status: 'COMPLETE' },
|
||||
],
|
||||
activeTab: 0,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
goDetail(sn) { // 跳转售后详情
|
||||
this.$router.push({
|
||||
name: 'AfterSaleDetail',
|
||||
query: {sn}
|
||||
})
|
||||
},
|
||||
cancel(sn) { // 取消售后申请
|
||||
Modal.confirm({
|
||||
title: '取消',
|
||||
content: '确定取消此次售后申请吗?',
|
||||
onOk: () => {
|
||||
cancelAfterSale(sn).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('取消售后申请成功')
|
||||
this.getList()
|
||||
}
|
||||
})
|
||||
},
|
||||
onCancel: () => {
|
||||
}
|
||||
});
|
||||
},
|
||||
goodsDetail(skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routeUrl = this.$router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: {skuId, goodsId}
|
||||
});
|
||||
window.open(routeUrl.href, '_blank');
|
||||
},
|
||||
// 跳转店铺首页
|
||||
shopPage(id) {
|
||||
this.$router.push({
|
||||
path: '/merchant',
|
||||
query: {id: id}
|
||||
});
|
||||
},
|
||||
change(index) {
|
||||
this.activeTab = index
|
||||
this.params.pageNumber = 1
|
||||
const current = this.changeWay[index]
|
||||
if (!current || !current.status) {
|
||||
delete this.params.serviceStatus
|
||||
} else {
|
||||
this.params.serviceStatus = current.status
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
getList() { // 获取售后列表
|
||||
this.spinShow = true;
|
||||
let params = JSON.parse(JSON.stringify(this.params))
|
||||
afterSaleList(params).then(res => {
|
||||
this.spinShow = false
|
||||
if (res.success) {
|
||||
this.orderList = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
changePageNum(val) { // 修改页码
|
||||
this.params.pageNumber = val;
|
||||
this.getList()
|
||||
},
|
||||
changePageSize(val) { // 修改页数
|
||||
this.params.pageNumber = 1;
|
||||
this.params.pageSize = val;
|
||||
this.getList()
|
||||
},
|
||||
filterOrderStatus(status) { // 获取订单状态中文
|
||||
const ob = this.afterSaleStatusList.filter(e => {
|
||||
return e.status === status
|
||||
});
|
||||
return ob && ob[0] ? ob[0].name : status
|
||||
},
|
||||
// 获取物流公司列表
|
||||
getCompany() {
|
||||
getLogisticsCompany().then(res => {
|
||||
if (res.success) {
|
||||
this.companyList = res.result
|
||||
}
|
||||
})
|
||||
},
|
||||
// 提交物流信息
|
||||
submitDelivery() {
|
||||
this.$refs.form?.validate((valid) => {
|
||||
if (!valid) return;
|
||||
this.submitLoading = true;
|
||||
afterSaleDelivery(this.form).then(res => {
|
||||
if (res.success) {
|
||||
this.logisticsShow = false;
|
||||
Message.success('提交成功');
|
||||
this.getList();
|
||||
}
|
||||
this.submitLoading = false;
|
||||
}).catch(() => {
|
||||
this.submitLoading = false;
|
||||
});
|
||||
});
|
||||
},
|
||||
// 提交物流modal
|
||||
openModal(row) {
|
||||
this.singleOrder = row;
|
||||
this.logisticsShow = true;
|
||||
if (!this.companyList.length) {
|
||||
this.getCompany();
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs.form?.resetFields();
|
||||
this.form.afterSaleSn = row.sn;
|
||||
});
|
||||
}
|
||||
}
|
||||
defineOptions({ name: 'AfterSale' });
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const formRef = ref(null);
|
||||
|
||||
const orderList = ref([]); // 订单列表
|
||||
const params = reactive({ // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
keywords: '',
|
||||
sn: '',
|
||||
sort: 'createTime',
|
||||
order: 'desc'
|
||||
});
|
||||
const total = ref(0); // 订单总数
|
||||
const spinShow = ref(false); // 加载状态
|
||||
const companyList = ref([]); // 物流公司列表
|
||||
const logisticsShow = ref(false); // 物流信息modal
|
||||
const singleOrder = ref({}); // 单独的售后信息
|
||||
const form = reactive({ // 物流信息数据
|
||||
afterSaleSn: '',
|
||||
logisticsId: '',
|
||||
logisticsNo: '',
|
||||
mDeliverTime: ''
|
||||
});
|
||||
const rules = { // 必填校验
|
||||
logisticsId: [{required: true, message: '请选择物流公司'}],
|
||||
logisticsNo: [{required: true, message: '请填写物流编号'}],
|
||||
mDeliverTime: [{required: true, message: '请选择发货时间'}]
|
||||
};
|
||||
const submitLoading = ref(false); // 提交加载状态
|
||||
const changeWay = [
|
||||
{ name: '全部', status: '' },
|
||||
{ name: '申请中', status: 'APPLY' },
|
||||
{ name: '通过', status: 'PASS' },
|
||||
{ name: '完成售后', status: 'COMPLETE' },
|
||||
];
|
||||
const activeTab = ref(0);
|
||||
|
||||
function goDetail(sn) { // 跳转售后详情
|
||||
router.push({
|
||||
name: 'AfterSaleDetail',
|
||||
query: {sn}
|
||||
})
|
||||
}
|
||||
function cancel(sn) { // 取消售后申请
|
||||
Modal.confirm({
|
||||
title: '取消',
|
||||
content: '确定取消此次售后申请吗?',
|
||||
onOk: () => {
|
||||
cancelAfterSale(sn).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('取消售后申请成功')
|
||||
getList()
|
||||
}
|
||||
})
|
||||
},
|
||||
onCancel: () => {
|
||||
}
|
||||
});
|
||||
}
|
||||
function goodsDetail(skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routeUrl = router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: {skuId, goodsId}
|
||||
});
|
||||
window.open(routeUrl.href, '_blank');
|
||||
}
|
||||
// 跳转店铺首页
|
||||
function shopPage(id) {
|
||||
router.push({
|
||||
path: '/merchant',
|
||||
query: {id: id}
|
||||
});
|
||||
}
|
||||
function change(index) {
|
||||
activeTab.value = index
|
||||
params.pageNumber = 1
|
||||
const current = changeWay[index]
|
||||
if (!current || !current.status) {
|
||||
delete params.serviceStatus
|
||||
} else {
|
||||
params.serviceStatus = current.status
|
||||
}
|
||||
getList()
|
||||
}
|
||||
function getList() { // 获取售后列表
|
||||
spinShow.value = true;
|
||||
let paramsData = JSON.parse(JSON.stringify(params))
|
||||
afterSaleList(paramsData).then(res => {
|
||||
spinShow.value = false
|
||||
if (res.success) {
|
||||
orderList.value = res.result.records;
|
||||
total.value = res.result.total;
|
||||
}
|
||||
});
|
||||
}
|
||||
function changePageNum(val) { // 修改页码
|
||||
params.pageNumber = val;
|
||||
getList()
|
||||
}
|
||||
function changePageSize(val) { // 修改页数
|
||||
params.pageNumber = 1;
|
||||
params.pageSize = val;
|
||||
getList()
|
||||
}
|
||||
function filterOrderStatus(status) { // 获取订单状态中文
|
||||
const ob = afterSaleStatusList.filter(e => {
|
||||
return e.status === status
|
||||
});
|
||||
return ob && ob[0] ? ob[0].name : status
|
||||
}
|
||||
// 获取物流公司列表
|
||||
function getCompany() {
|
||||
getLogisticsCompany().then(res => {
|
||||
if (res.success) {
|
||||
companyList.value = res.result
|
||||
}
|
||||
})
|
||||
}
|
||||
// 提交物流信息
|
||||
function submitDelivery() {
|
||||
formRef.value?.validate((valid) => {
|
||||
if (!valid) return;
|
||||
submitLoading.value = true;
|
||||
afterSaleDelivery(form).then(res => {
|
||||
if (res.success) {
|
||||
logisticsShow.value = false;
|
||||
Message.success('提交成功');
|
||||
getList();
|
||||
}
|
||||
submitLoading.value = false;
|
||||
}).catch(() => {
|
||||
submitLoading.value = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
// 提交物流modal
|
||||
function openModal(row) {
|
||||
singleOrder.value = row;
|
||||
logisticsShow.value = true;
|
||||
if (!companyList.value.length) {
|
||||
getCompany();
|
||||
}
|
||||
nextTick(() => {
|
||||
formRef.value?.resetFields();
|
||||
form.afterSaleSn = row.sn;
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
<span>提交物流信息</span>
|
||||
</p></template>
|
||||
<div>
|
||||
<el-form ref="form" :model="form" label-position="left" label-width="100px" :rules="rules">
|
||||
<el-form ref="formRef" :model="form" label-position="left" label-width="100px" :rules="rules">
|
||||
<el-form-item label="物流公司" prop="logisticsId">
|
||||
<el-select v-model="form.logisticsId" placeholder="请选择物流公司">
|
||||
<el-option v-for="item in companyList" :value="item.id" :key="item.id">{{ item.name }}</el-option>
|
||||
@@ -135,150 +135,151 @@
|
||||
</UserCenterLayout>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script setup>
|
||||
import { computed, nextTick, onMounted, reactive, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
import { afterSaleDetail, afterSaleLog, afterSaleReason, cancelAfterSale } from '@/api/member.js';
|
||||
import { afterSaleDelivery, getLogisticsCompany } from '@/api/order.js';
|
||||
import { afterSaleStatusList } from '../enumeration.js'
|
||||
export default {
|
||||
name: 'aftersale-detail',
|
||||
data () {
|
||||
return {
|
||||
afterSale: {}, // 售后详情数据
|
||||
logList: [], // 日志
|
||||
reasonList: [], // 售后原因列表
|
||||
afterSaleStatusList, // 售后状态列表
|
||||
companyList: [], // 物流公司列表
|
||||
logisticsShow: false, // 物流信息modal
|
||||
form: { // 物流信息数据
|
||||
afterSaleSn: '',
|
||||
logisticsId: '',
|
||||
logisticsNo: '',
|
||||
mDeliverTime: ''
|
||||
},
|
||||
rules: { // 必填校验
|
||||
logisticsId: [{ required: true, message: '请选择物流公司' }],
|
||||
logisticsNo: [{ required: true, message: '请填写物流编号' }],
|
||||
mDeliverTime: [{ required: true, message: '请选择发货时间' }]
|
||||
},
|
||||
submitLoading: false // 提交加载状态
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
canSubmitLogistics () {
|
||||
return this.afterSale.serviceStatus == 'PASS' && this.afterSale.serviceType != 'RETURN_MONEY'
|
||||
},
|
||||
canCancel () {
|
||||
return this.afterSale.afterSaleAllowOperationVO && this.afterSale.afterSaleAllowOperationVO.cancel
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDetail () { // 售后详情
|
||||
afterSaleDetail(this.$route.query.sn).then(res => {
|
||||
if (res.success) {
|
||||
this.afterSale = res.result;
|
||||
this.afterSale.serviceName = this.filterOrderStatus(this.afterSale.serviceStatus)
|
||||
// 如果是原因id,则调接口查询原因中文释义
|
||||
const pattern3 = new RegExp('[0-9]+');
|
||||
if (pattern3.test(this.afterSale.reason)) {
|
||||
this.getReason(this.afterSale.serviceType)
|
||||
} else {
|
||||
this.afterSale['reasonName'] = this.afterSale.reason
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
getReason (type) { // 获取售后原因
|
||||
afterSaleReason(type).then(res => {
|
||||
if (res.success) {
|
||||
this.reasonList = res.result
|
||||
this.reasonList.forEach(e => {
|
||||
if (e.id === this.afterSale.reason) {
|
||||
this.afterSale['reasonName'] = e.reason
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
getLog () { // 获取售后日志
|
||||
afterSaleLog(this.$route.query.sn).then(res => {
|
||||
this.logList = (res.result || []).slice().sort((a, b) => {
|
||||
return new Date(a.createTime).getTime() - new Date(b.createTime).getTime()
|
||||
})
|
||||
})
|
||||
},
|
||||
logDesc (log) {
|
||||
const operator = log.operatorName ? `操作人:${log.operatorName}` : ''
|
||||
return [operator, log.createTime].filter(Boolean).join(' ')
|
||||
},
|
||||
shopPage (id) {
|
||||
if (!id) return
|
||||
this.$router.push({
|
||||
path: '/merchant',
|
||||
query: { id }
|
||||
})
|
||||
},
|
||||
filterOrderStatus (status) { // 获取订单状态中文
|
||||
const ob = this.afterSaleStatusList.filter(e => { return e.status === status });
|
||||
if (ob.length) return ob[0].name
|
||||
},
|
||||
perviewImg (img) { // 查看图片
|
||||
window.open(img, '_blank')
|
||||
},
|
||||
cancel (sn) { // 取消售后申请
|
||||
Modal.confirm({
|
||||
title: '取消',
|
||||
content: '<p>确定取消此次售后申请吗?</p>',
|
||||
onOk: () => {
|
||||
cancelAfterSale(sn).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('取消售后申请成功')
|
||||
this.getDetail()
|
||||
}
|
||||
})
|
||||
},
|
||||
onCancel: () => {}
|
||||
});
|
||||
},
|
||||
// 获取物流公司列表
|
||||
getCompany () {
|
||||
getLogisticsCompany().then(res => {
|
||||
if (res.success) {
|
||||
this.companyList = res.result
|
||||
}
|
||||
})
|
||||
},
|
||||
// 提交物流信息
|
||||
submitDelivery () {
|
||||
this.submitLoading = true
|
||||
afterSaleDelivery(this.form).then(res => {
|
||||
if (res.success) {
|
||||
this.logisticsShow = false;
|
||||
Message.success('提交成功')
|
||||
this.getDetail()
|
||||
}
|
||||
this.submitLoading = false
|
||||
}).catch(() => {
|
||||
this.submitLoading = false
|
||||
})
|
||||
},
|
||||
// 提交物流modal
|
||||
openModal () {
|
||||
this.logisticsShow = true;
|
||||
if (!this.companyList.length) {
|
||||
this.getCompany();
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs.form?.resetFields();
|
||||
this.form.afterSaleSn = this.afterSale.sn;
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getDetail();
|
||||
this.getLog()
|
||||
}
|
||||
|
||||
defineOptions({ name: 'aftersale-detail' });
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const afterSale = ref({}); // 售后详情数据
|
||||
const logList = ref([]); // 日志
|
||||
const reasonList = ref([]); // 售后原因列表
|
||||
const companyList = ref([]); // 物流公司列表
|
||||
const logisticsShow = ref(false); // 物流信息modal
|
||||
const form = reactive({ // 物流信息数据
|
||||
afterSaleSn: '',
|
||||
logisticsId: '',
|
||||
logisticsNo: '',
|
||||
mDeliverTime: ''
|
||||
});
|
||||
const rules = { // 必填校验
|
||||
logisticsId: [{ required: true, message: '请选择物流公司' }],
|
||||
logisticsNo: [{ required: true, message: '请填写物流编号' }],
|
||||
mDeliverTime: [{ required: true, message: '请选择发货时间' }]
|
||||
};
|
||||
const submitLoading = ref(false); // 提交加载状态
|
||||
|
||||
const formRef = ref(null);
|
||||
|
||||
const canSubmitLogistics = computed(() => {
|
||||
return afterSale.value.serviceStatus == 'PASS' && afterSale.value.serviceType != 'RETURN_MONEY'
|
||||
});
|
||||
const canCancel = computed(() => {
|
||||
return afterSale.value.afterSaleAllowOperationVO && afterSale.value.afterSaleAllowOperationVO.cancel
|
||||
});
|
||||
|
||||
function getDetail () { // 售后详情
|
||||
afterSaleDetail(route.query.sn).then(res => {
|
||||
if (res.success) {
|
||||
afterSale.value = res.result;
|
||||
afterSale.value.serviceName = filterOrderStatus(afterSale.value.serviceStatus)
|
||||
// 如果是原因id,则调接口查询原因中文释义
|
||||
const pattern3 = new RegExp('[0-9]+');
|
||||
if (pattern3.test(afterSale.value.reason)) {
|
||||
getReason(afterSale.value.serviceType)
|
||||
} else {
|
||||
afterSale.value['reasonName'] = afterSale.value.reason
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
function getReason (type) { // 获取售后原因
|
||||
afterSaleReason(type).then(res => {
|
||||
if (res.success) {
|
||||
reasonList.value = res.result
|
||||
reasonList.value.forEach(e => {
|
||||
if (e.id === afterSale.value.reason) {
|
||||
afterSale.value['reasonName'] = e.reason
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
function getLog () { // 获取售后日志
|
||||
afterSaleLog(route.query.sn).then(res => {
|
||||
logList.value = (res.result || []).slice().sort((a, b) => {
|
||||
return new Date(a.createTime).getTime() - new Date(b.createTime).getTime()
|
||||
})
|
||||
})
|
||||
}
|
||||
function logDesc (log) {
|
||||
const operator = log.operatorName ? `操作人:${log.operatorName}` : ''
|
||||
return [operator, log.createTime].filter(Boolean).join(' ')
|
||||
}
|
||||
function shopPage (id) {
|
||||
if (!id) return
|
||||
router.push({
|
||||
path: '/merchant',
|
||||
query: { id }
|
||||
})
|
||||
}
|
||||
function filterOrderStatus (status) { // 获取订单状态中文
|
||||
const ob = afterSaleStatusList.filter(e => { return e.status === status });
|
||||
if (ob.length) return ob[0].name
|
||||
}
|
||||
function perviewImg (img) { // 查看图片
|
||||
window.open(img, '_blank')
|
||||
}
|
||||
function cancel (sn) { // 取消售后申请
|
||||
Modal.confirm({
|
||||
title: '取消',
|
||||
content: '<p>确定取消此次售后申请吗?</p>',
|
||||
onOk: () => {
|
||||
cancelAfterSale(sn).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('取消售后申请成功')
|
||||
getDetail()
|
||||
}
|
||||
})
|
||||
},
|
||||
onCancel: () => {}
|
||||
});
|
||||
}
|
||||
// 获取物流公司列表
|
||||
function getCompany () {
|
||||
getLogisticsCompany().then(res => {
|
||||
if (res.success) {
|
||||
companyList.value = res.result
|
||||
}
|
||||
})
|
||||
}
|
||||
// 提交物流信息
|
||||
function submitDelivery () {
|
||||
submitLoading.value = true
|
||||
afterSaleDelivery(form).then(res => {
|
||||
if (res.success) {
|
||||
logisticsShow.value = false;
|
||||
Message.success('提交成功')
|
||||
getDetail()
|
||||
}
|
||||
submitLoading.value = false
|
||||
}).catch(() => {
|
||||
submitLoading.value = false
|
||||
})
|
||||
}
|
||||
// 提交物流modal
|
||||
function openModal () {
|
||||
logisticsShow.value = true;
|
||||
if (!companyList.value.length) {
|
||||
getCompany();
|
||||
}
|
||||
nextTick(() => {
|
||||
formRef.value?.resetFields();
|
||||
form.afterSaleSn = afterSale.value.sn;
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDetail();
|
||||
getLog()
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.order-detail {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<el-table-column prop="num" label="购买数量" />
|
||||
</el-table>
|
||||
<div>
|
||||
<el-form :model="form" ref="form" class="mt_10" :rules="rules" label-width="80px">
|
||||
<el-form :model="form" ref="formRef" class="mt_10" :rules="rules" label-width="80px">
|
||||
<el-form-item label="售后类别">
|
||||
<el-radio-group v-model="form.serviceType" @change="changeReason" type="button" button-style="solid">
|
||||
<el-radio v-if="info.returnGoods" label="RETURN_GOODS">退货</el-radio>
|
||||
@@ -101,125 +101,125 @@
|
||||
</UserCenterLayout>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script setup>
|
||||
import { nextTick, onMounted, reactive, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { Message, Notice } from "@/utils/message";
|
||||
import { Camera, Delete, View } from '@element-plus/icons-vue';
|
||||
import { afterSaleReason, afterSaleInfo, applyAfterSale } from '@/api/member.js'
|
||||
import { buyerUrl } from '@/plugins/request.js';
|
||||
import storage from '@/plugins/storage';
|
||||
import * as RegExp from '@/plugins/RegExp'
|
||||
export default {
|
||||
components: { Camera, Delete, View },
|
||||
data () {
|
||||
const checkNum = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请填写提交数量'));
|
||||
} else if (value > this.info.num) {
|
||||
callback(new Error('提交数量不能大于购买数量'));
|
||||
} else if (!RegExp.integer.test(value)) {
|
||||
callback(new Error('提交数量必须为正整数'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return {
|
||||
goodsData: [], // 商品数据
|
||||
reasonList: [], // 售后原因列表
|
||||
info: {}, // 售后信息
|
||||
form: { // 售后数据
|
||||
serviceType: 'RETURN_GOODS',
|
||||
num: 1
|
||||
},
|
||||
uploadList: [], // 上传列表
|
||||
action: buyerUrl + '/buyer/common/upload/file', // 上传地址
|
||||
accessToken: {}, // 验证token
|
||||
visible: false, // 图片预览
|
||||
previewImage: '', // 预览图片url
|
||||
rules: { // 验证规则
|
||||
num: [{ validator: checkNum }],
|
||||
reason: [{ required: true, message: '请选择提交原因' }],
|
||||
problemDesc: [{ required: true, message: '请输入问题描述' }],
|
||||
bankAccountNumber: [
|
||||
{ required: true, message: '请输入银行卡号' },
|
||||
{
|
||||
type: 'string',
|
||||
pattern: /^[0-9]\d*$/,
|
||||
message: '请输入正确的银行卡号'
|
||||
}
|
||||
],
|
||||
bankAccountName: [{ required: true, message: '请输入银行开户名' }],
|
||||
bankDepositName: [{ required: true, message: '请输入银行开户行' }]
|
||||
}
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const formRef = ref(null);
|
||||
|
||||
const goodsData = ref([]); // 商品数据
|
||||
const reasonList = ref([]); // 售后原因列表
|
||||
const info = ref({}); // 售后信息
|
||||
const form = reactive({ // 售后数据
|
||||
serviceType: 'RETURN_GOODS',
|
||||
num: 1
|
||||
});
|
||||
const uploadList = ref([]); // 上传列表
|
||||
const action = buyerUrl + '/buyer/common/upload/file'; // 上传地址
|
||||
const accessToken = reactive({}); // 验证token
|
||||
const visible = ref(false); // 图片预览
|
||||
const previewImage = ref(''); // 预览图片url
|
||||
|
||||
const checkNum = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请填写提交数量'));
|
||||
} else if (value > info.value.num) {
|
||||
callback(new Error('提交数量不能大于购买数量'));
|
||||
} else if (!RegExp.integer.test(value)) {
|
||||
callback(new Error('提交数量必须为正整数'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const rules = { // 验证规则
|
||||
num: [{ validator: checkNum }],
|
||||
reason: [{ required: true, message: '请选择提交原因' }],
|
||||
problemDesc: [{ required: true, message: '请输入问题描述' }],
|
||||
bankAccountNumber: [
|
||||
{ required: true, message: '请输入银行卡号' },
|
||||
{
|
||||
type: 'string',
|
||||
pattern: /^[0-9]\d*$/,
|
||||
message: '请输入正确的银行卡号'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getInfo () { // 获取售后信息
|
||||
afterSaleInfo(this.$route.query.sn).then(res => {
|
||||
],
|
||||
bankAccountName: [{ required: true, message: '请输入银行开户名' }],
|
||||
bankDepositName: [{ required: true, message: '请输入银行开户行' }]
|
||||
};
|
||||
|
||||
function getInfo () { // 获取售后信息
|
||||
afterSaleInfo(route.query.sn).then(res => {
|
||||
if (res.success) {
|
||||
info.value = res.result
|
||||
goodsData.value.push(res.result)
|
||||
if (!info.value.returnGoods && info.value.returnMoney) {
|
||||
form.serviceType = 'RETURN_MONEY'
|
||||
}
|
||||
getReason(form.serviceType)
|
||||
}
|
||||
})
|
||||
}
|
||||
function getReason (type) { // 获取售后原因
|
||||
afterSaleReason(type).then(res => {
|
||||
if (res.success) reasonList.value = res.result
|
||||
})
|
||||
}
|
||||
function changeReason (type) { // 改变售后原因列表
|
||||
form.reason = undefined
|
||||
getReason(type)
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate('reason')
|
||||
})
|
||||
}
|
||||
function apply () { // 售后申请提交
|
||||
formRef.value.validate(valid => {
|
||||
if (valid) {
|
||||
let params = Object.assign(info.value, form)
|
||||
params.images = uploadList.value.toString()
|
||||
params.orderItemSn = route.query.sn
|
||||
params.reason = reasonList.value.find(item => item.id == params.reason).reason
|
||||
applyAfterSale(params).then(res => {
|
||||
if (res.success) {
|
||||
this.info = res.result
|
||||
this.goodsData.push(res.result)
|
||||
if (!this.info.returnGoods && this.info.returnMoney) {
|
||||
this.form.serviceType = 'RETURN_MONEY'
|
||||
}
|
||||
this.getReason(this.form.serviceType)
|
||||
Message.success('售后申请提交成功,请到售后订单查看!')
|
||||
router.push({name: 'AfterSale'})
|
||||
}
|
||||
})
|
||||
},
|
||||
getReason (type) { // 获取售后原因
|
||||
afterSaleReason(type).then(res => {
|
||||
if (res.success) this.reasonList = res.result
|
||||
})
|
||||
},
|
||||
changeReason (type) { // 改变售后原因列表
|
||||
this.form.reason = undefined
|
||||
this.getReason(type)
|
||||
this.$nextTick(() => {
|
||||
this.$refs.form?.clearValidate('reason')
|
||||
})
|
||||
},
|
||||
apply () { // 售后申请提交
|
||||
this.$refs.form.validate(valid => {
|
||||
if (valid) {
|
||||
let params = Object.assign(this.info, this.form)
|
||||
params.images = this.uploadList.toString()
|
||||
params.orderItemSn = this.$route.query.sn
|
||||
params.reason = this.reasonList.find(item => item.id == params.reason).reason
|
||||
applyAfterSale(params).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('售后申请提交成功,请到售后订单查看!')
|
||||
this.$router.push({name: 'AfterSale'})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleView (name) { // 预览图片
|
||||
this.previewImage = name;
|
||||
this.visible = true;
|
||||
},
|
||||
handleRemove (index) { // 移除图片
|
||||
this.uploadList.splice(index, 1)
|
||||
this.$forceUpdate()
|
||||
},
|
||||
handleSuccess (res, file) { // 上传成功回调
|
||||
this.uploadList.push(res.result)
|
||||
this.$forceUpdate()
|
||||
},
|
||||
handleBeforeUpload () { // 上传之前钩子函数
|
||||
const check = this.uploadList.length < 6;
|
||||
if (!check) {
|
||||
Notice.warning({
|
||||
title: '最多可以上传5张图片'
|
||||
});
|
||||
return check;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.accessToken.accessToken = storage.getItem('accessToken');
|
||||
this.getInfo()
|
||||
})
|
||||
}
|
||||
function handleView (name) { // 预览图片
|
||||
previewImage.value = name;
|
||||
visible.value = true;
|
||||
}
|
||||
function handleRemove (index) { // 移除图片
|
||||
uploadList.value.splice(index, 1)
|
||||
}
|
||||
function handleSuccess (res, file) { // 上传成功回调
|
||||
uploadList.value.push(res.result)
|
||||
}
|
||||
function handleBeforeUpload () { // 上传之前钩子函数
|
||||
const check = uploadList.value.length < 6;
|
||||
if (!check) {
|
||||
Notice.warning({
|
||||
title: '最多可以上传5张图片'
|
||||
});
|
||||
return check;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
accessToken.accessToken = storage.getItem('accessToken');
|
||||
getInfo()
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
|
||||
@@ -61,101 +61,107 @@
|
||||
</UserCenterLayout>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script setup>
|
||||
import { getCurrentInstance, onMounted, reactive, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { Message, Notice } from "@/utils/message";
|
||||
import { Camera, Delete, View } from '@element-plus/icons-vue';
|
||||
import { orderDetail } from '@/api/order.js';
|
||||
import { afterSaleReason, handleComplain } from '@/api/member.js';
|
||||
import { buyerUrl } from '@/plugins/request.js';
|
||||
import storage from '@/plugins/storage';
|
||||
export default {
|
||||
components: { Camera, Delete, View },
|
||||
data () {
|
||||
return {
|
||||
order: {}, // 订单详情
|
||||
orderGoods: {}, // 订单商品
|
||||
form: { // 投诉表单
|
||||
complainTopic: '',
|
||||
content: ''
|
||||
}, // 表单
|
||||
visible: false, // 图片预览
|
||||
action: buyerUrl + '/buyer/common/upload/file', // 上传地址
|
||||
accessToken: {}, // 验证token
|
||||
previewImage: '', // 图片地址
|
||||
loading: false, // 加载状态
|
||||
reasonList: [] // 投诉原因
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
const order = ref({}); // 订单详情
|
||||
const orderGoods = ref({}); // 订单商品
|
||||
const form = reactive({ // 投诉表单
|
||||
complainTopic: '',
|
||||
content: ''
|
||||
}); // 表单
|
||||
const visible = ref(false); // 图片预览
|
||||
const action = ref(buyerUrl + '/buyer/common/upload/file'); // 上传地址
|
||||
const accessToken = reactive({}); // 验证token
|
||||
const previewImage = ref(''); // 图片地址
|
||||
const loading = ref(false); // 加载状态
|
||||
const reasonList = ref([]); // 投诉原因
|
||||
|
||||
function getOrderDetail() { // 获取订单详情
|
||||
orderDetail(route.query.sn).then(res => {
|
||||
order.value = res.result
|
||||
orderGoods.value = res.result.orderItems[route.query.index]
|
||||
orderGoods.value.uploadList = []
|
||||
})
|
||||
afterSaleReason('COMPLAIN').then(res => {
|
||||
if (res.success) {
|
||||
reasonList.value = res.result
|
||||
form['complainTopic'] = res.result[0].reason
|
||||
instance.proxy.$forceUpdate()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getOrderDetail () { // 获取订单详情
|
||||
orderDetail(this.$route.query.sn).then(res => {
|
||||
this.order = res.result
|
||||
this.orderGoods = res.result.orderItems[this.$route.query.index]
|
||||
this.orderGoods.uploadList = []
|
||||
})
|
||||
afterSaleReason('COMPLAIN').then(res => {
|
||||
if (res.success) {
|
||||
this.reasonList = res.result
|
||||
this.form['complainTopic'] = res.result[0].reason
|
||||
this.$forceUpdate()
|
||||
}
|
||||
})
|
||||
},
|
||||
save () { // 提交投诉信息
|
||||
if (!this.form.content || !String(this.form.content).trim()) {
|
||||
Message.warning('投诉内容不能为空')
|
||||
return
|
||||
}
|
||||
let params = {
|
||||
goodsId: this.orderGoods.goodsId,
|
||||
complainTopic: this.form.complainTopic,
|
||||
content: this.form.content,
|
||||
images: this.orderGoods.uploadList.toString(),
|
||||
orderSn: this.$route.query.sn,
|
||||
skuId: this.orderGoods.skuId
|
||||
}
|
||||
handleComplain(params).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('投诉申请已提交,感谢您的反馈')
|
||||
this.$router.push({name: 'ComplainList'})
|
||||
}
|
||||
})
|
||||
},
|
||||
goGoodsDetail (skuId, goodsId) { // 跳转商品详情
|
||||
let routerUrl = this.$router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: {skuId, goodsId}
|
||||
})
|
||||
window.open(routerUrl.href, '_blank')
|
||||
},
|
||||
handleView (name) { // 预览图片
|
||||
this.previewImage = name;
|
||||
this.visible = true;
|
||||
},
|
||||
handleRemove (index) { // 移除图片
|
||||
this.orderGoods.uploadList.splice(index, 1)
|
||||
this.$forceUpdate()
|
||||
},
|
||||
handleSuccess (res, file) { // 上传成功回调
|
||||
this.orderGoods.uploadList.push(res.result)
|
||||
this.$forceUpdate()
|
||||
},
|
||||
handleBeforeUpload () { // 上传之前钩子函数
|
||||
const check = this.orderGoods.uploadList.length < 6;
|
||||
if (!check) {
|
||||
Notice.warning({
|
||||
title: '最多可以上传五张图片'
|
||||
});
|
||||
return check;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function save() { // 提交投诉信息
|
||||
if (!form.content || !String(form.content).trim()) {
|
||||
Message.warning('投诉内容不能为空')
|
||||
return
|
||||
}
|
||||
let params = {
|
||||
goodsId: orderGoods.value.goodsId,
|
||||
complainTopic: form.complainTopic,
|
||||
content: form.content,
|
||||
images: orderGoods.value.uploadList.toString(),
|
||||
orderSn: route.query.sn,
|
||||
skuId: orderGoods.value.skuId
|
||||
}
|
||||
handleComplain(params).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('投诉申请已提交,感谢您的反馈')
|
||||
router.push({name: 'ComplainList'})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.accessToken.accessToken = storage.getItem('accessToken');
|
||||
this.getOrderDetail()
|
||||
window.scrollTo(0, 0)
|
||||
})
|
||||
}
|
||||
|
||||
function goGoodsDetail(skuId, goodsId) { // 跳转商品详情
|
||||
let routerUrl = router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: {skuId, goodsId}
|
||||
})
|
||||
window.open(routerUrl.href, '_blank')
|
||||
}
|
||||
|
||||
function handleView(name) { // 预览图片
|
||||
previewImage.value = name;
|
||||
visible.value = true;
|
||||
}
|
||||
|
||||
function handleRemove(index) { // 移除图片
|
||||
orderGoods.value.uploadList.splice(index, 1)
|
||||
instance.proxy.$forceUpdate()
|
||||
}
|
||||
|
||||
function handleSuccess(res, file) { // 上传成功回调
|
||||
orderGoods.value.uploadList.push(res.result)
|
||||
instance.proxy.$forceUpdate()
|
||||
}
|
||||
|
||||
function handleBeforeUpload() { // 上传之前钩子函数
|
||||
const check = orderGoods.value.uploadList.length < 6;
|
||||
if (!check) {
|
||||
Notice.warning({
|
||||
title: '最多可以上传五张图片'
|
||||
});
|
||||
return check;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
accessToken.accessToken = storage.getItem('accessToken');
|
||||
getOrderDetail()
|
||||
window.scrollTo(0, 0)
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.delivery-rate {
|
||||
|
||||
@@ -35,59 +35,59 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
import { Delete, Edit } from '@element-plus/icons-vue';
|
||||
import { memberAddress, delMemberAddress } from '@/api/address.js';
|
||||
|
||||
export default {
|
||||
components: { Delete, Edit },
|
||||
name: 'MyAddress',
|
||||
defineOptions({ name: 'MyAddress' });
|
||||
|
||||
data () {
|
||||
return {
|
||||
list: [] // 地址列表
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
add () {
|
||||
this.$router.push('/home/addAddress');
|
||||
},
|
||||
edit (id) {
|
||||
// 编辑地址
|
||||
this.$router.push({ path: '/home/addAddress', query: { id: id } });
|
||||
},
|
||||
del (id) {
|
||||
// 删除地址
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '你确定删除这个收货地址',
|
||||
onOk: () => {
|
||||
delMemberAddress(id).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success('删除成功');
|
||||
this.getAddrList();
|
||||
}
|
||||
});
|
||||
},
|
||||
onCancel: () => {
|
||||
Message.info('取消删除');
|
||||
}
|
||||
});
|
||||
},
|
||||
getAddrList () {
|
||||
// 获取地址列表
|
||||
memberAddress().then((res) => {
|
||||
const router = useRouter();
|
||||
|
||||
const list = ref([]); // 地址列表
|
||||
|
||||
function add () {
|
||||
router.push('/home/addAddress');
|
||||
}
|
||||
|
||||
// 编辑地址
|
||||
function edit (id) {
|
||||
router.push({ path: '/home/addAddress', query: { id: id } });
|
||||
}
|
||||
|
||||
// 删除地址
|
||||
function del (id) {
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '你确定删除这个收货地址',
|
||||
onOk: () => {
|
||||
delMemberAddress(id).then((res) => {
|
||||
if (res.success) {
|
||||
this.list = res.result.records;
|
||||
Message.success('删除成功');
|
||||
getAddrList();
|
||||
}
|
||||
});
|
||||
},
|
||||
onCancel: () => {
|
||||
Message.info('取消删除');
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getAddrList();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// 获取地址列表
|
||||
function getAddrList () {
|
||||
memberAddress().then((res) => {
|
||||
if (res.success) {
|
||||
list.value = res.result.records;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getAddrList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -197,266 +197,264 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref, watch } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
import { getOrderList, sureReceived, cancelOrder, delOrder } from '@/api/order';
|
||||
import { getOrderList, sureReceived, cancelOrder, delOrder as deleteOrder } from '@/api/order';
|
||||
import { afterSaleReason } from '@/api/member';
|
||||
import { orderStatusList, afterSaleStatusList } from '../enumeration.js'
|
||||
export default {
|
||||
name: 'MyOrder',
|
||||
props: {
|
||||
homePage: { // 判断是否个人中心首页展示内容
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
orderList: [], // 订单列表
|
||||
params: { // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
// orderStatus: 'ALL',
|
||||
keywords: '',
|
||||
tag: 'ALL'
|
||||
},
|
||||
cancelParams: { // 取消售后参数
|
||||
orderSn: '',
|
||||
reason: ''
|
||||
},
|
||||
// 状态数组
|
||||
orderStatusList,
|
||||
afterSaleStatusList,
|
||||
changeWay: ['全部', '待付款', '待发货', '待收货/使用'],
|
||||
activeOrderTab: 0,
|
||||
total: 0, // 数据总数
|
||||
spinShow: false, // 加载状态
|
||||
afterSaleModal: false, // 选择售后商品模态框
|
||||
afterSaleArr: [], // 售后商品列表
|
||||
cancelAvail: false, // 取消订单modal控制
|
||||
cancelReason: [] // 取消订单原因
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
if (this.homePage) this.params.pageSize = 5;
|
||||
if (!this.homePage) this.applyRouteTag();
|
||||
this.getList();
|
||||
},
|
||||
watch: {
|
||||
'$route.query.tag' () {
|
||||
if (this.homePage || this.$route.name !== 'MyOrder') return;
|
||||
const next = this.$route.query.tag || 'ALL';
|
||||
if (this.params.tag === next) return;
|
||||
this.applyRouteTag();
|
||||
this.getList();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 退款状态枚举
|
||||
refundPriceList(status) {
|
||||
switch (status) {
|
||||
case 'ALL_REFUND':
|
||||
return "全部退款";
|
||||
case 'PART_REFUND':
|
||||
return "部分退款";
|
||||
case 'NO_REFUND':
|
||||
return "";
|
||||
case 'REFUNDING':
|
||||
return "退款中";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
},
|
||||
goodsDetail (skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routeUrl = this.$router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: { skuId, goodsId }
|
||||
});
|
||||
window.open(routeUrl.href, '_blank');
|
||||
},
|
||||
orderTags () {
|
||||
return ['ALL', 'WAIT_PAY', 'WAIT_SHIP', 'WAIT_USE'];
|
||||
},
|
||||
applyRouteTag () {
|
||||
const tags = this.orderTags();
|
||||
const tag = this.$route.query.tag;
|
||||
const index = tags.indexOf(tag);
|
||||
this.activeOrderTab = index > -1 ? index : 0;
|
||||
this.params.tag = tags[this.activeOrderTab];
|
||||
this.params.pageNumber = 1;
|
||||
},
|
||||
// 切换订单状态
|
||||
change (index) {
|
||||
this.activeOrderTab = index;
|
||||
this.params.pageNumber = 1;
|
||||
delete this.params.commentStatus;
|
||||
const tags = this.orderTags();
|
||||
this.params.tag = tags[index] || 'ALL';
|
||||
const query = { ...this.$route.query };
|
||||
if (index === 0) delete query.tag;
|
||||
else query.tag = this.params.tag;
|
||||
const current = this.$route.query.tag || 'ALL';
|
||||
if (current !== this.params.tag) {
|
||||
this.$router.replace({ name: 'MyOrder', query });
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
// 跳转店铺首页
|
||||
shopPage (id) {
|
||||
this.$router.push({
|
||||
path: '/merchant',
|
||||
query: { id: id }
|
||||
});
|
||||
},
|
||||
orderDetail (sn) {
|
||||
this.$router.push({ name: 'OrderDetail', query: {sn} });
|
||||
},
|
||||
goAfterSaleDetail (sn) {
|
||||
this.$router.push({ name: 'AfterSaleDetail', query: { sn } });
|
||||
},
|
||||
received (sn) { // 确认收货
|
||||
sureReceived(sn).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('确认收货成功')
|
||||
this.getList()
|
||||
}
|
||||
})
|
||||
},
|
||||
goPay (sn) { // 去支付
|
||||
this.$router.push({path: '/payment', query: {orderType: 'ORDER', sn}});
|
||||
},
|
||||
applyAfterSale (goodsItem) { // 申请售后
|
||||
let arr = []
|
||||
goodsItem.forEach(e => {
|
||||
if (e.afterSaleStatus === 'NOT_APPLIED'|| e.afterSaleStatus === 'PART_AFTER_SALE') {
|
||||
arr.push(e)
|
||||
}
|
||||
});
|
||||
if (arr.length === 1) {
|
||||
this.$router.push({name: 'ApplyAfterSale', query: {sn: arr[0].sn}})
|
||||
} else {
|
||||
this.afterSaleArr = arr;
|
||||
this.afterSaleModal = true
|
||||
}
|
||||
},
|
||||
// 申请售后
|
||||
afterSaleSelect (item) {
|
||||
this.$router.push({name: 'ApplyAfterSale', query: {sn: item.sn}})
|
||||
},
|
||||
complain (sn, goodsIndex) { // 投诉
|
||||
this.$router.push({name: 'Complain', query: {sn, index: goodsIndex}})
|
||||
},
|
||||
delOrder (sn) { // 删除订单
|
||||
Modal.confirm({
|
||||
title: '删除订单',
|
||||
content: '<p>确认删除当前订单吗?</p>',
|
||||
onOk: () => {
|
||||
delOrder(sn).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('删除成功');
|
||||
this.getList()
|
||||
}
|
||||
})
|
||||
},
|
||||
onCancel: () => {}
|
||||
});
|
||||
},
|
||||
getList () {
|
||||
this.spinShow = true;
|
||||
let params = JSON.parse(JSON.stringify(this.params))
|
||||
if (params.orderStatus === 'ALL') {
|
||||
delete params.orderStatus
|
||||
}
|
||||
getOrderList(params).then(res => {
|
||||
this.spinShow = false
|
||||
if (res.success) {
|
||||
this.orderList = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
mapAfterSaleOrder (item) {
|
||||
return {
|
||||
...item,
|
||||
isAfterSale: true,
|
||||
serviceSn: item.sn,
|
||||
sn: item.orderSn,
|
||||
orderStatus: item.serviceStatus,
|
||||
flowPrice: item.applyRefundPrice,
|
||||
orderItems: [
|
||||
{
|
||||
image: item.goodsImage,
|
||||
name: item.goodsName,
|
||||
skuId: item.skuId,
|
||||
goodsId: item.goodsId,
|
||||
goodsPrice: item.flowPrice,
|
||||
num: item.num,
|
||||
},
|
||||
],
|
||||
allowOperationVO: {},
|
||||
}
|
||||
},
|
||||
changePageNum (val) { // 修改页码
|
||||
this.params.pageNumber = val;
|
||||
this.getList()
|
||||
},
|
||||
changePageSize (val) { // 修改页数
|
||||
this.params.pageNumber = 1;
|
||||
this.params.pageSize = val;
|
||||
this.getList()
|
||||
},
|
||||
handleCancelOrder (sn) {
|
||||
// 取消订单
|
||||
this.cancelParams.orderSn = sn;
|
||||
afterSaleReason('CANCEL').then(res => {
|
||||
if (res.success) {
|
||||
this.cancelReason = res.result;
|
||||
this.cancelAvail = true
|
||||
this.cancelParams.reason = this.cancelReason[0].reason
|
||||
}
|
||||
})
|
||||
},
|
||||
sureCancel () { // 确定取消
|
||||
cancelOrder(this.cancelParams).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('取消订单成功')
|
||||
this.getList()
|
||||
this.cancelAvail = false
|
||||
}
|
||||
})
|
||||
},
|
||||
filterOrderStatus (status) { // 获取订单状态中文
|
||||
const ob = this.orderStatusList.filter(e => { return e.status === status });
|
||||
return ob && ob[0] ? ob[0].name : status
|
||||
},
|
||||
filterAfterSaleStatus (status) {
|
||||
const ob = this.afterSaleStatusList.filter(e => e.status === status);
|
||||
return ob && ob[0] ? ob[0].name : status
|
||||
},
|
||||
canAfterSale (order) {
|
||||
if (order.isAfterSale || order.orderType === 'E_COUPON' || !order.groupAfterSaleStatus) {
|
||||
return false
|
||||
}
|
||||
return order.groupAfterSaleStatus.includes('NOT_APPLIED') || order.groupAfterSaleStatus.includes('PART_AFTER_SALE')
|
||||
},
|
||||
paymentLabel (order) {
|
||||
const map = {
|
||||
WECHAT: '微信支付',
|
||||
ALIPAY: '支付宝',
|
||||
WALLET: '余额支付',
|
||||
BANK_TRANSFER: '线下转账'
|
||||
}
|
||||
if (order.paymentMethod && map[order.paymentMethod]) {
|
||||
return map[order.paymentMethod]
|
||||
}
|
||||
if (order.payStatus === 'UNPAID' || order.orderStatus === 'UNPAID') {
|
||||
return '待支付'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
defineOptions({ name: 'MyOrder' });
|
||||
|
||||
const props = defineProps({
|
||||
homePage: { // 判断是否个人中心首页展示内容
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const orderList = ref([]); // 订单列表
|
||||
const params = reactive({ // 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
// orderStatus: 'ALL',
|
||||
keywords: '',
|
||||
tag: 'ALL'
|
||||
});
|
||||
const cancelParams = reactive({ // 取消售后参数
|
||||
orderSn: '',
|
||||
reason: ''
|
||||
});
|
||||
const changeWay = ref(['全部', '待付款', '待发货', '待收货/使用']);
|
||||
const activeOrderTab = ref(0);
|
||||
const total = ref(0); // 数据总数
|
||||
const spinShow = ref(false); // 加载状态
|
||||
const afterSaleModal = ref(false); // 选择售后商品模态框
|
||||
const afterSaleArr = ref([]); // 售后商品列表
|
||||
const cancelAvail = ref(false); // 取消订单modal控制
|
||||
const cancelReason = ref([]); // 取消订单原因
|
||||
|
||||
// 退款状态枚举
|
||||
function refundPriceList(status) {
|
||||
switch (status) {
|
||||
case 'ALL_REFUND':
|
||||
return "全部退款";
|
||||
case 'PART_REFUND':
|
||||
return "部分退款";
|
||||
case 'NO_REFUND':
|
||||
return "";
|
||||
case 'REFUNDING':
|
||||
return "退款中";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
function goodsDetail (skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routeUrl = router.resolve({
|
||||
path: '/goodsDetail',
|
||||
query: { skuId, goodsId }
|
||||
});
|
||||
window.open(routeUrl.href, '_blank');
|
||||
}
|
||||
function orderTags () {
|
||||
return ['ALL', 'WAIT_PAY', 'WAIT_SHIP', 'WAIT_USE'];
|
||||
}
|
||||
function applyRouteTag () {
|
||||
const tags = orderTags();
|
||||
const tag = route.query.tag;
|
||||
const index = tags.indexOf(tag);
|
||||
activeOrderTab.value = index > -1 ? index : 0;
|
||||
params.tag = tags[activeOrderTab.value];
|
||||
params.pageNumber = 1;
|
||||
}
|
||||
// 切换订单状态
|
||||
function change (index) {
|
||||
activeOrderTab.value = index;
|
||||
params.pageNumber = 1;
|
||||
delete params.commentStatus;
|
||||
const tags = orderTags();
|
||||
params.tag = tags[index] || 'ALL';
|
||||
const query = { ...route.query };
|
||||
if (index === 0) delete query.tag;
|
||||
else query.tag = params.tag;
|
||||
const current = route.query.tag || 'ALL';
|
||||
if (current !== params.tag) {
|
||||
router.replace({ name: 'MyOrder', query });
|
||||
}
|
||||
getList()
|
||||
}
|
||||
// 跳转店铺首页
|
||||
function shopPage (id) {
|
||||
router.push({
|
||||
path: '/merchant',
|
||||
query: { id: id }
|
||||
});
|
||||
}
|
||||
function orderDetail (sn) {
|
||||
router.push({ name: 'OrderDetail', query: {sn} });
|
||||
}
|
||||
function goAfterSaleDetail (sn) {
|
||||
router.push({ name: 'AfterSaleDetail', query: { sn } });
|
||||
}
|
||||
function received (sn) { // 确认收货
|
||||
sureReceived(sn).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('确认收货成功')
|
||||
getList()
|
||||
}
|
||||
})
|
||||
}
|
||||
function goPay (sn) { // 去支付
|
||||
router.push({path: '/payment', query: {orderType: 'ORDER', sn}});
|
||||
}
|
||||
function applyAfterSale (goodsItem) { // 申请售后
|
||||
let arr = []
|
||||
goodsItem.forEach(e => {
|
||||
if (e.afterSaleStatus === 'NOT_APPLIED'|| e.afterSaleStatus === 'PART_AFTER_SALE') {
|
||||
arr.push(e)
|
||||
}
|
||||
});
|
||||
if (arr.length === 1) {
|
||||
router.push({name: 'ApplyAfterSale', query: {sn: arr[0].sn}})
|
||||
} else {
|
||||
afterSaleArr.value = arr;
|
||||
afterSaleModal.value = true
|
||||
}
|
||||
}
|
||||
// 申请售后
|
||||
function afterSaleSelect (item) {
|
||||
router.push({name: 'ApplyAfterSale', query: {sn: item.sn}})
|
||||
}
|
||||
function complain (sn, goodsIndex) { // 投诉
|
||||
router.push({name: 'Complain', query: {sn, index: goodsIndex}})
|
||||
}
|
||||
function delOrder (sn) { // 删除订单
|
||||
Modal.confirm({
|
||||
title: '删除订单',
|
||||
content: '<p>确认删除当前订单吗?</p>',
|
||||
onOk: () => {
|
||||
deleteOrder(sn).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('删除成功');
|
||||
getList()
|
||||
}
|
||||
})
|
||||
},
|
||||
onCancel: () => {}
|
||||
});
|
||||
}
|
||||
function getList () {
|
||||
spinShow.value = true;
|
||||
let _params = JSON.parse(JSON.stringify(params))
|
||||
if (_params.orderStatus === 'ALL') {
|
||||
delete _params.orderStatus
|
||||
}
|
||||
getOrderList(_params).then(res => {
|
||||
spinShow.value = false
|
||||
if (res.success) {
|
||||
orderList.value = res.result.records;
|
||||
total.value = res.result.total;
|
||||
}
|
||||
});
|
||||
}
|
||||
function mapAfterSaleOrder (item) {
|
||||
return {
|
||||
...item,
|
||||
isAfterSale: true,
|
||||
serviceSn: item.sn,
|
||||
sn: item.orderSn,
|
||||
orderStatus: item.serviceStatus,
|
||||
flowPrice: item.applyRefundPrice,
|
||||
orderItems: [
|
||||
{
|
||||
image: item.goodsImage,
|
||||
name: item.goodsName,
|
||||
skuId: item.skuId,
|
||||
goodsId: item.goodsId,
|
||||
goodsPrice: item.flowPrice,
|
||||
num: item.num,
|
||||
},
|
||||
],
|
||||
allowOperationVO: {},
|
||||
}
|
||||
}
|
||||
function changePageNum (val) { // 修改页码
|
||||
params.pageNumber = val;
|
||||
getList()
|
||||
}
|
||||
function changePageSize (val) { // 修改页数
|
||||
params.pageNumber = 1;
|
||||
params.pageSize = val;
|
||||
getList()
|
||||
}
|
||||
function handleCancelOrder (sn) {
|
||||
// 取消订单
|
||||
cancelParams.orderSn = sn;
|
||||
afterSaleReason('CANCEL').then(res => {
|
||||
if (res.success) {
|
||||
cancelReason.value = res.result;
|
||||
cancelAvail.value = true
|
||||
cancelParams.reason = cancelReason.value[0].reason
|
||||
}
|
||||
})
|
||||
}
|
||||
function sureCancel () { // 确定取消
|
||||
cancelOrder(cancelParams).then(res => {
|
||||
if (res.success) {
|
||||
Message.success('取消订单成功')
|
||||
getList()
|
||||
cancelAvail.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
function filterOrderStatus (status) { // 获取订单状态中文
|
||||
const ob = orderStatusList.filter(e => { return e.status === status });
|
||||
return ob && ob[0] ? ob[0].name : status
|
||||
}
|
||||
function filterAfterSaleStatus (status) {
|
||||
const ob = afterSaleStatusList.filter(e => e.status === status);
|
||||
return ob && ob[0] ? ob[0].name : status
|
||||
}
|
||||
function canAfterSale (order) {
|
||||
if (order.isAfterSale || order.orderType === 'E_COUPON' || !order.groupAfterSaleStatus) {
|
||||
return false
|
||||
}
|
||||
return order.groupAfterSaleStatus.includes('NOT_APPLIED') || order.groupAfterSaleStatus.includes('PART_AFTER_SALE')
|
||||
}
|
||||
function paymentLabel (order) {
|
||||
const map = {
|
||||
WECHAT: '微信支付',
|
||||
ALIPAY: '支付宝',
|
||||
WALLET: '余额支付',
|
||||
BANK_TRANSFER: '线下转账'
|
||||
}
|
||||
if (order.paymentMethod && map[order.paymentMethod]) {
|
||||
return map[order.paymentMethod]
|
||||
}
|
||||
if (order.payStatus === 'UNPAID' || order.orderStatus === 'UNPAID') {
|
||||
return '待支付'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
watch(() => route.query.tag, () => {
|
||||
if (props.homePage || route.name !== 'MyOrder') return;
|
||||
const next = route.query.tag || 'ALL';
|
||||
if (params.tag === next) return;
|
||||
applyRouteTag();
|
||||
getList();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (props.homePage) params.pageSize = 5;
|
||||
if (!props.homePage) applyRouteTag();
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -410,7 +410,9 @@
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script setup>
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { Message } from "@/utils/message";
|
||||
import {
|
||||
orderDetail,
|
||||
@@ -438,276 +440,278 @@ import {
|
||||
* 订单详情:E_COUPON 展示 orderItems[].cardKeys,屏蔽售后/物流(FR-B-03 / FR-B-04)。
|
||||
* 移动端已完成订单用 Dialog 查看卡密(原型 P-09 / D-01)。
|
||||
*/
|
||||
export default {
|
||||
name: "order-detail",
|
||||
data() {
|
||||
return {
|
||||
order: {}, // 订单详情数据
|
||||
progressList: [], // 订单流程
|
||||
logistics: "", // 物流数据
|
||||
cardKeyDialogVisible: false,
|
||||
cancelParams: {
|
||||
// 取消售后参数
|
||||
orderSn: "",
|
||||
reason: "",
|
||||
},
|
||||
cancelAvail: false, // 取消订单modal控制
|
||||
cancelReason: [], // 取消订单原因
|
||||
orderPackage: [],
|
||||
packageTraceList: [],
|
||||
logisticsModal: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
/** 电子卡券订单:无物流/核验码,卡密数据来自 API-B-01 orderItems[].cardKeys */
|
||||
isECouponOrder() {
|
||||
return checkECouponOrder(this.order?.order?.orderType);
|
||||
},
|
||||
isVirtualOrder() {
|
||||
return this.order?.order?.orderType === "VIRTUAL";
|
||||
},
|
||||
isNonPhysicalOrder() {
|
||||
return this.isVirtualOrder || this.isECouponOrder;
|
||||
},
|
||||
/** 是否展示卡密区块(仅当前订单 orderItems) */
|
||||
hasCardKeySection() {
|
||||
return orderHasCardKeySection({
|
||||
orderItems: this.order.orderItems,
|
||||
isECouponOrder: this.isECouponOrder,
|
||||
});
|
||||
},
|
||||
cardKeyFulfillLines() {
|
||||
return collectCardKeyFulfillLines(this.order.orderItems);
|
||||
},
|
||||
ecouponCardKeyRows() {
|
||||
return flattenOrderCardKeys(this.order.orderItems, false);
|
||||
},
|
||||
/** 商家以无需配送方式发货(包裹 fulfillmentMode=NO_DELIVERY) */
|
||||
isNoDeliveryOrder() {
|
||||
return checkNoDeliveryOrder(this.orderPackage);
|
||||
},
|
||||
displayDeliveryMethodValue() {
|
||||
if (this.isNoDeliveryOrder) return "无需配送";
|
||||
return this.order?.deliveryMethodValue || "-";
|
||||
},
|
||||
noDeliveryPackages() {
|
||||
return (this.orderPackage || []).filter(isNoDeliveryPackage);
|
||||
},
|
||||
noDeliveryRemark() {
|
||||
const pkg = this.noDeliveryPackages.find((p) => p.deliveryRemark);
|
||||
return pkg?.deliveryRemark || "";
|
||||
},
|
||||
noDeliveryShipTime() {
|
||||
const pkg = this.noDeliveryPackages[0];
|
||||
return pkg?.logisticsTime || "";
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isNoDeliveryPackage,
|
||||
getFulfillmentModeLabel,
|
||||
cardKeyFulfillAlertType,
|
||||
resolveCardKeyFulfillMessage,
|
||||
lineCardKeyRows(line) {
|
||||
return line.cardKeys || [];
|
||||
},
|
||||
copyCardKey(row) {
|
||||
const text = `卡号:${row.cardNo || ""}\n卡密:${row.cardSecret || ""}`;
|
||||
this.copyText(text);
|
||||
},
|
||||
copyAllCardKeys() {
|
||||
const text = this.ecouponCardKeyRows
|
||||
.map((row, i) => `${i + 1}. 卡号:${row.cardNo || ""} 卡密:${row.cardSecret || ""}`)
|
||||
.join("\n");
|
||||
this.copyText(text || "");
|
||||
},
|
||||
copyText(text) {
|
||||
if (!text) return;
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
Message.success("已复制到剪贴板");
|
||||
});
|
||||
} else {
|
||||
const ta = document.createElement("textarea");
|
||||
ta.value = text;
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(ta);
|
||||
Message.success("已复制到剪贴板");
|
||||
defineOptions({ name: "order-detail" });
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const order = ref({}); // 订单详情数据
|
||||
const progressList = ref([]); // 订单流程
|
||||
const logistics = ref(""); // 物流数据
|
||||
const cardKeyDialogVisible = ref(false);
|
||||
const cancelParams = reactive({
|
||||
// 取消售后参数
|
||||
orderSn: "",
|
||||
reason: "",
|
||||
});
|
||||
const cancelAvail = ref(false); // 取消订单modal控制
|
||||
const cancelReason = ref([]); // 取消订单原因
|
||||
const orderPackage = ref([]);
|
||||
const packageTraceList = ref([]);
|
||||
const logisticsModal = ref(false);
|
||||
|
||||
/** 电子卡券订单:无物流/核验码,卡密数据来自 API-B-01 orderItems[].cardKeys */
|
||||
const isECouponOrder = computed(() => checkECouponOrder(order.value?.order?.orderType));
|
||||
const isVirtualOrder = computed(() => order.value?.order?.orderType === "VIRTUAL");
|
||||
const isNonPhysicalOrder = computed(() => isVirtualOrder.value || isECouponOrder.value);
|
||||
/** 是否展示卡密区块(仅当前订单 orderItems) */
|
||||
const hasCardKeySection = computed(() =>
|
||||
orderHasCardKeySection({
|
||||
orderItems: order.value.orderItems,
|
||||
isECouponOrder: isECouponOrder.value,
|
||||
})
|
||||
);
|
||||
const cardKeyFulfillLines = computed(() => collectCardKeyFulfillLines(order.value.orderItems));
|
||||
const ecouponCardKeyRows = computed(() => flattenOrderCardKeys(order.value.orderItems, false));
|
||||
/** 商家以无需配送方式发货(包裹 fulfillmentMode=NO_DELIVERY) */
|
||||
const isNoDeliveryOrder = computed(() => checkNoDeliveryOrder(orderPackage.value));
|
||||
const displayDeliveryMethodValue = computed(() => {
|
||||
if (isNoDeliveryOrder.value) return "无需配送";
|
||||
return order.value?.deliveryMethodValue || "-";
|
||||
});
|
||||
const noDeliveryPackages = computed(() => (orderPackage.value || []).filter(isNoDeliveryPackage));
|
||||
const noDeliveryRemark = computed(() => {
|
||||
const pkg = noDeliveryPackages.value.find((p) => p.deliveryRemark);
|
||||
return pkg?.deliveryRemark || "";
|
||||
});
|
||||
const noDeliveryShipTime = computed(() => {
|
||||
const pkg = noDeliveryPackages.value[0];
|
||||
return pkg?.logisticsTime || "";
|
||||
});
|
||||
|
||||
function lineCardKeyRows(line) {
|
||||
return line.cardKeys || [];
|
||||
}
|
||||
|
||||
function copyCardKey(row) {
|
||||
const text = `卡号:${row.cardNo || ""}\n卡密:${row.cardSecret || ""}`;
|
||||
copyText(text);
|
||||
}
|
||||
|
||||
function copyAllCardKeys() {
|
||||
const text = ecouponCardKeyRows.value
|
||||
.map((row, i) => `${i + 1}. 卡号:${row.cardNo || ""} 卡密:${row.cardSecret || ""}`)
|
||||
.join("\n");
|
||||
copyText(text || "");
|
||||
}
|
||||
|
||||
function copyText(text) {
|
||||
if (!text) return;
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
Message.success("已复制到剪贴板");
|
||||
});
|
||||
} else {
|
||||
const ta = document.createElement("textarea");
|
||||
ta.value = text;
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(ta);
|
||||
Message.success("已复制到剪贴板");
|
||||
}
|
||||
}
|
||||
|
||||
function isVatSpecialReceipt(receipt) {
|
||||
if (!receipt) return false;
|
||||
const rt = receipt.receiptType != null ? String(receipt.receiptType).trim() : "";
|
||||
if (rt === "2" || rt === "增值税专用发票" || receipt.invoiceKind === "VAT_SPECIAL") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isPersonalReceipt(receipt) {
|
||||
return !isVatSpecialReceipt(receipt);
|
||||
}
|
||||
|
||||
function formatReceiptType(receipt) {
|
||||
if (!receipt) return "";
|
||||
const rt = receipt.receiptType != null ? String(receipt.receiptType).trim() : "";
|
||||
if (rt === "电子普通发票" || rt === "增值税专用发票") return rt;
|
||||
return isVatSpecialReceipt(receipt) ? "增值税专用发票" : "电子普通发票";
|
||||
}
|
||||
|
||||
function formatReceiptHeaderType(receipt) {
|
||||
if (!receipt) return "";
|
||||
if (isVatSpecialReceipt(receipt)) return "单位";
|
||||
if (receipt.taxpayerId) return "单位";
|
||||
return "个人";
|
||||
}
|
||||
|
||||
function hasValidReceipt() {
|
||||
const receipt = order.value && order.value.receipt;
|
||||
if (!receipt) return false;
|
||||
const content = receipt.receiptContent ? String(receipt.receiptContent).trim() : '';
|
||||
const title = receipt.receiptTitle ? String(receipt.receiptTitle).trim() : '';
|
||||
const taxpayerId = receipt.taxpayerId ? String(receipt.taxpayerId).trim() : '';
|
||||
// 后端有时会返回占位 receipt(如 receiptContent=不开发票),这里过滤掉
|
||||
if (content === '不开发票') return false;
|
||||
return Boolean(content || title || taxpayerId);
|
||||
}
|
||||
|
||||
function getInvoiceAddress(receipt) {
|
||||
if (!receipt) return "";
|
||||
return receipt.invoiceAddress || receipt.invoiceFileUrl || "";
|
||||
}
|
||||
|
||||
function viewReceiptInvoice(receipt) {
|
||||
const invoiceAddress = getInvoiceAddress(receipt);
|
||||
if (!invoiceAddress) {
|
||||
Message.warning("暂无发票附件");
|
||||
return;
|
||||
}
|
||||
window.open(invoiceAddress, "_blank");
|
||||
}
|
||||
|
||||
function goodsDetail(skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routeUrl = router.resolve({
|
||||
path: "/goodsDetail",
|
||||
query: { skuId, goodsId },
|
||||
});
|
||||
window.open(routeUrl.href, "_blank");
|
||||
}
|
||||
|
||||
// 跳转店铺首页
|
||||
function shopPage(id) {
|
||||
router.push({
|
||||
path: "/merchant",
|
||||
query: { id: id },
|
||||
});
|
||||
}
|
||||
|
||||
async function getDetail() {
|
||||
// 获取订单详情
|
||||
orderDetail(route.query.sn).then(async (res) => {
|
||||
if (res.success) {
|
||||
order.value = res.result;
|
||||
const receiptId =
|
||||
(res.result.order && res.result.order.receiptId) ||
|
||||
res.result.receiptId ||
|
||||
(res.result.receipt && res.result.receipt.id);
|
||||
if (receiptId) {
|
||||
const receiptRes = await receiptDetail(receiptId);
|
||||
if (receiptRes && receiptRes.success && receiptRes.result) {
|
||||
order.value["receipt"] = receiptRes.result;
|
||||
}
|
||||
}
|
||||
},
|
||||
isVatSpecialReceipt (receipt) {
|
||||
if (!receipt) return false;
|
||||
const rt = receipt.receiptType != null ? String(receipt.receiptType).trim() : "";
|
||||
if (rt === "2" || rt === "增值税专用发票" || receipt.invoiceKind === "VAT_SPECIAL") {
|
||||
return true;
|
||||
progressList.value = (res.result.orderLogs || []).slice().sort((a, b) => {
|
||||
return new Date(a.createTime).getTime() - new Date(b.createTime).getTime();
|
||||
});
|
||||
if (order.value.order.deliveryMethod === 'LOGISTICS') {
|
||||
getOrderPackage(order.value.order.sn);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
isPersonalReceipt (receipt) {
|
||||
return !this.isVatSpecialReceipt(receipt);
|
||||
},
|
||||
formatReceiptType (receipt) {
|
||||
if (!receipt) return "";
|
||||
const rt = receipt.receiptType != null ? String(receipt.receiptType).trim() : "";
|
||||
if (rt === "电子普通发票" || rt === "增值税专用发票") return rt;
|
||||
return this.isVatSpecialReceipt(receipt) ? "增值税专用发票" : "电子普通发票";
|
||||
},
|
||||
formatReceiptHeaderType (receipt) {
|
||||
if (!receipt) return "";
|
||||
if (this.isVatSpecialReceipt(receipt)) return "单位";
|
||||
if (receipt.taxpayerId) return "单位";
|
||||
return "个人";
|
||||
},
|
||||
hasValidReceipt () {
|
||||
const receipt = this.order && this.order.receipt;
|
||||
if (!receipt) return false;
|
||||
const content = receipt.receiptContent ? String(receipt.receiptContent).trim() : '';
|
||||
const title = receipt.receiptTitle ? String(receipt.receiptTitle).trim() : '';
|
||||
const taxpayerId = receipt.taxpayerId ? String(receipt.taxpayerId).trim() : '';
|
||||
// 后端有时会返回占位 receipt(如 receiptContent=不开发票),这里过滤掉
|
||||
if (content === '不开发票') return false;
|
||||
return Boolean(content || title || taxpayerId);
|
||||
},
|
||||
getInvoiceAddress (receipt) {
|
||||
if (!receipt) return "";
|
||||
return receipt.invoiceAddress || receipt.invoiceFileUrl || "";
|
||||
},
|
||||
viewReceiptInvoice (receipt) {
|
||||
const invoiceAddress = this.getInvoiceAddress(receipt);
|
||||
if (!invoiceAddress) {
|
||||
Message.warning("暂无发票附件");
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getOrderPackage(sn) {
|
||||
getPackage(sn).then(res => {
|
||||
if (res.success) {
|
||||
orderPackage.value = Array.isArray(res.result) ? res.result : [];
|
||||
if (!orderPackage.value.length) {
|
||||
traces();
|
||||
}
|
||||
window.open(invoiceAddress, "_blank");
|
||||
},
|
||||
goodsDetail(skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routeUrl = this.$router.resolve({
|
||||
path: "/goodsDetail",
|
||||
query: { skuId, goodsId },
|
||||
});
|
||||
window.open(routeUrl.href, "_blank");
|
||||
},
|
||||
// 跳转店铺首页
|
||||
shopPage(id) {
|
||||
this.$router.push({
|
||||
path: "/merchant",
|
||||
query: { id: id },
|
||||
});
|
||||
},
|
||||
async getDetail() {
|
||||
// 获取订单详情
|
||||
orderDetail(this.$route.query.sn).then(async (res) => {
|
||||
if (res.success) {
|
||||
this.order = res.result;
|
||||
const receiptId =
|
||||
(res.result.order && res.result.order.receiptId) ||
|
||||
res.result.receiptId ||
|
||||
(res.result.receipt && res.result.receipt.id);
|
||||
if (receiptId) {
|
||||
const receiptRes = await receiptDetail(receiptId);
|
||||
if (receiptRes && receiptRes.success && receiptRes.result) {
|
||||
this.order["receipt"] = receiptRes.result;
|
||||
}
|
||||
}
|
||||
this.progressList = (res.result.orderLogs || []).slice().sort((a, b) => {
|
||||
return new Date(a.createTime).getTime() - new Date(b.createTime).getTime();
|
||||
});
|
||||
if (this.order.order.deliveryMethod === 'LOGISTICS') {
|
||||
this.getOrderPackage(this.order.order.sn);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getOrderPackage(sn) {
|
||||
getPackage(sn).then(res => {
|
||||
if (res.success) {
|
||||
this.orderPackage = Array.isArray(res.result) ? res.result : [];
|
||||
if (!this.orderPackage.length) {
|
||||
this.traces();
|
||||
}
|
||||
} else {
|
||||
this.traces();
|
||||
}
|
||||
}).catch(() => {
|
||||
this.traces();
|
||||
});
|
||||
},
|
||||
traces() {
|
||||
// 物流信息
|
||||
getTraces(this.$route.query.sn).then((res) => {
|
||||
if (res.success) {
|
||||
this.logistics = res.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
logisticsList() {
|
||||
this.logisticsModal = true;
|
||||
this.packageTraceList = this.orderPackage;
|
||||
// getTracesList(this.order.order.sn).then((res) => {
|
||||
// if (res.success && res.result != null) {
|
||||
// this.packageTraceList = res.result;
|
||||
// }
|
||||
// });
|
||||
},
|
||||
received(sn) {
|
||||
// 确认收货
|
||||
sureReceived(sn).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("确认收货成功");
|
||||
this.getDetail();
|
||||
}
|
||||
});
|
||||
},
|
||||
goPay(sn) {
|
||||
// 去支付
|
||||
this.$router.push({
|
||||
path: "/payment",
|
||||
query: { orderType: "ORDER", sn },
|
||||
});
|
||||
},
|
||||
applyAfterSale(sn) {
|
||||
// 申请售后
|
||||
this.$router.push({ name: "ApplyAfterSale", query: { sn: sn } });
|
||||
},
|
||||
comment(sn, goodsIndex) {
|
||||
// 评价
|
||||
this.$router.push({
|
||||
path: "/home/addEval",
|
||||
query: { sn, index: goodsIndex },
|
||||
});
|
||||
},
|
||||
complain(sn, goodsIndex) {
|
||||
// 投诉
|
||||
this.$router.push({ name: "Complain", query: { sn, index: goodsIndex } });
|
||||
},
|
||||
handleCancelOrder(sn) {
|
||||
// 取消订单
|
||||
this.cancelParams.orderSn = sn;
|
||||
afterSaleReason("CANCEL").then((res) => {
|
||||
if (res.success) {
|
||||
this.cancelReason = res.result;
|
||||
this.cancelAvail = true;
|
||||
this.cancelParams.reason = this.cancelReason[0].reason;
|
||||
}
|
||||
});
|
||||
},
|
||||
sureCancel() {
|
||||
// 确定取消
|
||||
cancelOrder(this.cancelParams).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("取消订单成功");
|
||||
this.getDetail();
|
||||
this.cancelAvail = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getDetail();
|
||||
},
|
||||
};
|
||||
} else {
|
||||
traces();
|
||||
}
|
||||
}).catch(() => {
|
||||
traces();
|
||||
});
|
||||
}
|
||||
|
||||
function traces() {
|
||||
// 物流信息
|
||||
getTraces(route.query.sn).then((res) => {
|
||||
if (res.success) {
|
||||
logistics.value = res.result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function logisticsList() {
|
||||
logisticsModal.value = true;
|
||||
packageTraceList.value = orderPackage.value;
|
||||
// getTracesList(this.order.order.sn).then((res) => {
|
||||
// if (res.success && res.result != null) {
|
||||
// this.packageTraceList = res.result;
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
function received(sn) {
|
||||
// 确认收货
|
||||
sureReceived(sn).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("确认收货成功");
|
||||
getDetail();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function goPay(sn) {
|
||||
// 去支付
|
||||
router.push({
|
||||
path: "/payment",
|
||||
query: { orderType: "ORDER", sn },
|
||||
});
|
||||
}
|
||||
|
||||
function applyAfterSale(sn) {
|
||||
// 申请售后
|
||||
router.push({ name: "ApplyAfterSale", query: { sn: sn } });
|
||||
}
|
||||
|
||||
function comment(sn, goodsIndex) {
|
||||
// 评价
|
||||
router.push({
|
||||
path: "/home/addEval",
|
||||
query: { sn, index: goodsIndex },
|
||||
});
|
||||
}
|
||||
|
||||
function complain(sn, goodsIndex) {
|
||||
// 投诉
|
||||
router.push({ name: "Complain", query: { sn, index: goodsIndex } });
|
||||
}
|
||||
|
||||
function handleCancelOrder(sn) {
|
||||
// 取消订单
|
||||
cancelParams.orderSn = sn;
|
||||
afterSaleReason("CANCEL").then((res) => {
|
||||
if (res.success) {
|
||||
cancelReason.value = res.result;
|
||||
cancelAvail.value = true;
|
||||
cancelParams.reason = cancelReason.value[0].reason;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function sureCancel() {
|
||||
// 确定取消
|
||||
cancelOrder(cancelParams).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("取消订单成功");
|
||||
getDetail();
|
||||
cancelAvail.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDetail();
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.mb_10 {
|
||||
|
||||
@@ -50,125 +50,128 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { memberCouponList } from "@/api/member.js";
|
||||
export default {
|
||||
name: "Coupons",
|
||||
data() {
|
||||
return {
|
||||
statusNameList: [
|
||||
// 优惠券状态
|
||||
"未使用",
|
||||
"已使用",
|
||||
"已过期",
|
||||
],
|
||||
statusList: ["NEW", "USED", "EXPIRE"], // 优惠券状态
|
||||
loading: false, // 列表加载状态
|
||||
params: {
|
||||
// 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
memberCouponStatus: "NEW",
|
||||
},
|
||||
total: 0, // 优惠券总数
|
||||
list: [], // 优惠券列表
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
activeStatusIndex() {
|
||||
const index = this.statusList.indexOf(this.params.memberCouponStatus);
|
||||
return index > -1 ? index : 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
// 获取优惠券列表
|
||||
this.loading = true;
|
||||
memberCouponList(this.params)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.list = res.result.records || [];
|
||||
this.total = res.result.total || 0;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
this.list = [];
|
||||
this.total = 0;
|
||||
});
|
||||
},
|
||||
// 切换优惠券状态
|
||||
change(index) {
|
||||
this.params.memberCouponStatus = this.statusList[index];
|
||||
this.params.pageNumber = 1;
|
||||
this.getList();
|
||||
},
|
||||
go(item) {
|
||||
// 根据使用条件跳转商品列表页面
|
||||
if (this.params.memberCouponStatus !== "NEW") return;
|
||||
|
||||
this.$router.push({
|
||||
path: "/goodsList",
|
||||
query: { promotionsId: item.couponId, promotionType: "COUPON" },
|
||||
});
|
||||
},
|
||||
defineOptions({ name: "Coupons" });
|
||||
|
||||
changePageNum(val) {
|
||||
// 分页改变页码
|
||||
this.params.pageNumber = val;
|
||||
this.getList();
|
||||
},
|
||||
const router = useRouter();
|
||||
|
||||
changePageSize(val) {
|
||||
// 分页改变页数
|
||||
this.params.pageNumber = 1;
|
||||
this.params.pageSize = val;
|
||||
this.getList();
|
||||
},
|
||||
const statusNameList = ref([
|
||||
// 优惠券状态
|
||||
"未使用",
|
||||
"已使用",
|
||||
"已过期",
|
||||
]);
|
||||
const statusList = ref(["NEW", "USED", "EXPIRE"]); // 优惠券状态
|
||||
const loading = ref(false); // 列表加载状态
|
||||
const params = reactive({
|
||||
// 请求参数
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
memberCouponStatus: "NEW",
|
||||
});
|
||||
const total = ref(0); // 优惠券总数
|
||||
const list = ref([]); // 优惠券列表
|
||||
|
||||
useScope(type, storeName) {
|
||||
// 根据字段返回 优惠券适用范围
|
||||
let shop = "平台";
|
||||
let goods = "全部商品";
|
||||
if (storeName !== "platform") shop = storeName;
|
||||
switch (type) {
|
||||
case "ALL":
|
||||
goods = "全部商品";
|
||||
break;
|
||||
case "PORTION_GOODS":
|
||||
goods = "部分商品";
|
||||
break;
|
||||
case "PORTION_GOODS_CATEGORY":
|
||||
goods = "部分分类商品";
|
||||
break;
|
||||
const activeStatusIndex = computed(() => {
|
||||
const index = statusList.value.indexOf(params.memberCouponStatus);
|
||||
return index > -1 ? index : 0;
|
||||
});
|
||||
|
||||
// 获取优惠券列表
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
memberCouponList(params)
|
||||
.then((res) => {
|
||||
loading.value = false;
|
||||
if (res.success) {
|
||||
list.value = res.result.records || [];
|
||||
total.value = res.result.total || 0;
|
||||
}
|
||||
return `${shop}${goods}可用`;
|
||||
},
|
||||
formatValidity(item) {
|
||||
const start = this.formatCouponTime(item && item.startTime);
|
||||
const end = this.formatCouponTime(item && item.endTime);
|
||||
if (start && end) return `${start} 至 ${end}`;
|
||||
if (end) return `至 ${end}`;
|
||||
if (start) return `${start} 起`;
|
||||
return "长期有效";
|
||||
},
|
||||
formatCouponTime(value) {
|
||||
if (!value) return "";
|
||||
const text = String(value).trim();
|
||||
if (/^\d{4}-\d{2}-\d{2}/.test(text)) {
|
||||
return text.slice(0, 16);
|
||||
}
|
||||
const date = new Date(text);
|
||||
if (Number.isNaN(date.getTime())) return text;
|
||||
const pad = (n) => String(n).padStart(2, "0");
|
||||
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
},
|
||||
};
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
list.value = [];
|
||||
total.value = 0;
|
||||
});
|
||||
}
|
||||
|
||||
// 切换优惠券状态
|
||||
function change(index) {
|
||||
params.memberCouponStatus = statusList.value[index];
|
||||
params.pageNumber = 1;
|
||||
getList();
|
||||
}
|
||||
|
||||
// 根据使用条件跳转商品列表页面
|
||||
function go(item) {
|
||||
if (params.memberCouponStatus !== "NEW") return;
|
||||
|
||||
router.push({
|
||||
path: "/goodsList",
|
||||
query: { promotionsId: item.couponId, promotionType: "COUPON" },
|
||||
});
|
||||
}
|
||||
|
||||
// 分页改变页码
|
||||
function changePageNum(val) {
|
||||
params.pageNumber = val;
|
||||
getList();
|
||||
}
|
||||
|
||||
// 分页改变页数
|
||||
function changePageSize(val) {
|
||||
params.pageNumber = 1;
|
||||
params.pageSize = val;
|
||||
getList();
|
||||
}
|
||||
|
||||
// 根据字段返回 优惠券适用范围
|
||||
function useScope(type, storeName) {
|
||||
let shop = "平台";
|
||||
let goods = "全部商品";
|
||||
if (storeName !== "platform") shop = storeName;
|
||||
switch (type) {
|
||||
case "ALL":
|
||||
goods = "全部商品";
|
||||
break;
|
||||
case "PORTION_GOODS":
|
||||
goods = "部分商品";
|
||||
break;
|
||||
case "PORTION_GOODS_CATEGORY":
|
||||
goods = "部分分类商品";
|
||||
break;
|
||||
}
|
||||
return `${shop}${goods}可用`;
|
||||
}
|
||||
|
||||
function formatValidity(item) {
|
||||
const start = formatCouponTime(item && item.startTime);
|
||||
const end = formatCouponTime(item && item.endTime);
|
||||
if (start && end) return `${start} 至 ${end}`;
|
||||
if (end) return `至 ${end}`;
|
||||
if (start) return `${start} 起`;
|
||||
return "长期有效";
|
||||
}
|
||||
|
||||
function formatCouponTime(value) {
|
||||
if (!value) return "";
|
||||
const text = String(value).trim();
|
||||
if (/^\d{4}-\d{2}-\d{2}/.test(text)) {
|
||||
return text.slice(0, 16);
|
||||
}
|
||||
const date = new Date(text);
|
||||
if (Number.isNaN(date.getTime())) return text;
|
||||
const pad = (n) => String(n).padStart(2, "0");
|
||||
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
</p></template>
|
||||
<div>
|
||||
<el-form
|
||||
ref="formData"
|
||||
ref="formDataRef"
|
||||
label-width="100px"
|
||||
:model="formData"
|
||||
:rules="formValidate"
|
||||
@@ -47,7 +47,7 @@
|
||||
</p></template>
|
||||
<div>
|
||||
<el-form
|
||||
ref="withdrawApplyFormData"
|
||||
ref="withdrawApplyFormDataRef"
|
||||
label-width="120px"
|
||||
:model="withdrawApplyFormData"
|
||||
:rules="withdrawApplyFormValidate"
|
||||
@@ -180,229 +180,230 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Message } from "@/utils/message";
|
||||
import {getDepositLog, getMembersWallet, getRecharge, getWithdrawApply, recharge, withdrawalApply} from '@/api/member';
|
||||
import {getDepositLog, getMembersWallet, getRecharge, getWithdrawApply, recharge as apiRecharge, withdrawalApply as apiWithdrawalApply} from '@/api/member';
|
||||
import {withdrawalSettingVO} from "@/api/pay";
|
||||
import { Edit } from '@element-plus/icons-vue';
|
||||
|
||||
export default {
|
||||
name: 'MoneyManagement',
|
||||
components: { Edit },
|
||||
data() {
|
||||
return {
|
||||
activeWalletTab: "log",
|
||||
frozenDeposit: 0, // 冻结余额
|
||||
memberDeposit: 0, // 余额
|
||||
defineOptions({ name: 'MoneyManagement' });
|
||||
|
||||
modal: false, // 余额充值
|
||||
withdrawApplyModal: false, // 提现申请
|
||||
formData: {
|
||||
// 充值金额
|
||||
price: 1
|
||||
},
|
||||
// 提现金额
|
||||
withdrawApplyFormData: {
|
||||
price: 1,
|
||||
minPrice: 1,
|
||||
type: '',
|
||||
realName: '',
|
||||
connectNumber: '',
|
||||
},
|
||||
// 余额日志
|
||||
walletForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
},
|
||||
// 充值记录
|
||||
rechargeForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 20 // 页面大小
|
||||
},
|
||||
// 提现记录
|
||||
withdrawApplyForm: {
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 20 // 页面大小
|
||||
},
|
||||
// 提现申请校验
|
||||
withdrawApplyFormValidate: {
|
||||
price: [
|
||||
{required: true, message: '请输入大于0小于9999的合法提现金额'},
|
||||
{
|
||||
pattern: /^[1-9]\d{0,3}(\.\d{1,2})?$/,
|
||||
message: '请输入大于0小于9999的合法提现金额',
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
realName: [
|
||||
{required: true, message: '请输入真实姓名'},
|
||||
],
|
||||
connectNumber: [
|
||||
{required: true, message: '请输入第三方登录账号'},
|
||||
],
|
||||
},
|
||||
formValidate: {
|
||||
price: [
|
||||
{required: true, message: '请输入大于等于1小于9999的合法充值金额'},
|
||||
{
|
||||
pattern: /^[1-9]\d{0,3}(\.\d{1,2})?$/,
|
||||
message: '请输入大于等于1小于9999的合法充值金额',
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
},
|
||||
logColumnsData: {},
|
||||
rechargeListData: {},
|
||||
withdrawApplyColumnsListData: {}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
// 初始化数据
|
||||
init() {
|
||||
getMembersWallet().then((res) => {
|
||||
this.frozenDeposit = res.result.memberFrozenWallet;
|
||||
this.memberDeposit = res.result.memberWallet;
|
||||
});
|
||||
getDepositLog(this.walletForm).then((res) => {
|
||||
const router = useRouter();
|
||||
|
||||
const formDataRef = ref(null);
|
||||
const withdrawApplyFormDataRef = ref(null);
|
||||
|
||||
const activeWalletTab = ref("log");
|
||||
const frozenDeposit = ref(0); // 冻结余额
|
||||
const memberDeposit = ref(0); // 余额
|
||||
|
||||
const modal = ref(false); // 余额充值
|
||||
const withdrawApplyModal = ref(false); // 提现申请
|
||||
const formData = reactive({
|
||||
// 充值金额
|
||||
price: 1
|
||||
});
|
||||
// 提现金额
|
||||
const withdrawApplyFormData = reactive({
|
||||
price: 1,
|
||||
minPrice: 1,
|
||||
type: '',
|
||||
realName: '',
|
||||
connectNumber: '',
|
||||
});
|
||||
// 余额日志
|
||||
const walletForm = reactive({
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
});
|
||||
// 充值记录
|
||||
const rechargeForm = reactive({
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 20 // 页面大小
|
||||
});
|
||||
// 提现记录
|
||||
const withdrawApplyForm = reactive({
|
||||
// 搜索框初始化对象
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 20 // 页面大小
|
||||
});
|
||||
// 提现申请校验
|
||||
const withdrawApplyFormValidate = {
|
||||
price: [
|
||||
{required: true, message: '请输入大于0小于9999的合法提现金额'},
|
||||
{
|
||||
pattern: /^[1-9]\d{0,3}(\.\d{1,2})?$/,
|
||||
message: '请输入大于0小于9999的合法提现金额',
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
realName: [
|
||||
{required: true, message: '请输入真实姓名'},
|
||||
],
|
||||
connectNumber: [
|
||||
{required: true, message: '请输入第三方登录账号'},
|
||||
],
|
||||
};
|
||||
const formValidate = {
|
||||
price: [
|
||||
{required: true, message: '请输入大于等于1小于9999的合法充值金额'},
|
||||
{
|
||||
pattern: /^[1-9]\d{0,3}(\.\d{1,2})?$/,
|
||||
message: '请输入大于等于1小于9999的合法充值金额',
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
};
|
||||
const logColumnsData = ref({});
|
||||
const rechargeListData = ref({});
|
||||
const withdrawApplyColumnsListData = ref({});
|
||||
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
|
||||
// 初始化数据
|
||||
function init() {
|
||||
getMembersWallet().then((res) => {
|
||||
frozenDeposit.value = res.result.memberFrozenWallet;
|
||||
memberDeposit.value = res.result.memberWallet;
|
||||
});
|
||||
getDepositLog(walletForm).then((res) => {
|
||||
if (res.message === 'success') {
|
||||
logColumnsData.value = res.result;
|
||||
}
|
||||
});
|
||||
}
|
||||
function tabPaneChange(v) {
|
||||
activeWalletTab.value = v;
|
||||
if (v === 'recharge') {
|
||||
getRechargeData();
|
||||
}
|
||||
if (v === 'log') {
|
||||
init();
|
||||
}
|
||||
if (v === 'withdrawApply') {
|
||||
getWithdrawApplyData();
|
||||
}
|
||||
}
|
||||
// 充值记录
|
||||
function getRechargeData() {
|
||||
getRecharge(rechargeForm).then((res) => {
|
||||
if (res.message === 'success') {
|
||||
rechargeListData.value = res.result;
|
||||
}
|
||||
});
|
||||
}
|
||||
// 提现记录
|
||||
function getWithdrawApplyData() {
|
||||
getWithdrawApply(withdrawApplyForm).then((res) => {
|
||||
if (res.message === 'success') {
|
||||
withdrawApplyColumnsListData.value = res.result;
|
||||
}
|
||||
});
|
||||
}
|
||||
function rechargeStatusText (status) {
|
||||
const map = { PAID: '已付款', UNPAID: '未付款', CANCEL: '已取消' }
|
||||
return map[status] || status || '—'
|
||||
}
|
||||
function rechargeWayText (way) {
|
||||
const map = { ALIPAY: '支付宝', WECHAT: '微信', BANK_TRANSFER: '线下转账' }
|
||||
return map[way] || way || '—'
|
||||
}
|
||||
function withdrawStatusText (status) {
|
||||
const map = {
|
||||
APPLY: '申请中',
|
||||
VIA_AUDITING: '审核通过',
|
||||
SUCCESS: '提现成功',
|
||||
ERROR: '提现失败'
|
||||
}
|
||||
return map[status] || '审核拒绝'
|
||||
}
|
||||
// 余额日志
|
||||
function changePage(v) {
|
||||
walletForm.pageNumber = v;
|
||||
init();
|
||||
}
|
||||
function changePageSize(v) {
|
||||
walletForm.pageNumber = 1;
|
||||
walletForm.pageSize = v;
|
||||
init();
|
||||
}
|
||||
// 充值记录
|
||||
function rechargeChangePage(v) {
|
||||
rechargeForm.pageNumber = v;
|
||||
getRechargeData();
|
||||
}
|
||||
function rechargeChangePageSize(v) {
|
||||
rechargeForm.pageNumber = 1;
|
||||
rechargeForm.pageSize = v;
|
||||
getRechargeData();
|
||||
}
|
||||
// 提现记录
|
||||
function withdrawChangePage(v) {
|
||||
withdrawApplyForm.pageNumber = v;
|
||||
getWithdrawApplyData();
|
||||
}
|
||||
function withdrawChangePageSize(v) {
|
||||
withdrawApplyForm.pageNumber = 1;
|
||||
withdrawApplyForm.pageSize = v;
|
||||
getWithdrawApplyData();
|
||||
}
|
||||
// 弹出在线充值框
|
||||
function recharge() {
|
||||
formData.price = 1;
|
||||
modal.value = true;
|
||||
}
|
||||
// 在线充值
|
||||
function rechargePrice() {
|
||||
formDataRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
apiRecharge(formData).then((res) => {
|
||||
if (res.message === 'success') {
|
||||
this.logColumnsData = res.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
tabPaneChange(v) {
|
||||
this.activeWalletTab = v;
|
||||
if (v === 'recharge') {
|
||||
this.getRechargeData();
|
||||
}
|
||||
if (v === 'log') {
|
||||
this.init();
|
||||
}
|
||||
if (v === 'withdrawApply') {
|
||||
this.getWithdrawApplyData();
|
||||
}
|
||||
},
|
||||
// 充值记录
|
||||
getRechargeData() {
|
||||
getRecharge(this.rechargeForm).then((res) => {
|
||||
if (res.message === 'success') {
|
||||
this.rechargeListData = res.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
// 提现记录
|
||||
getWithdrawApplyData() {
|
||||
getWithdrawApply(this.withdrawApplyForm).then((res) => {
|
||||
if (res.message === 'success') {
|
||||
this.withdrawApplyColumnsListData = res.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
rechargeStatusText (status) {
|
||||
const map = { PAID: '已付款', UNPAID: '未付款', CANCEL: '已取消' }
|
||||
return map[status] || status || '—'
|
||||
},
|
||||
rechargeWayText (way) {
|
||||
const map = { ALIPAY: '支付宝', WECHAT: '微信', BANK_TRANSFER: '线下转账' }
|
||||
return map[way] || way || '—'
|
||||
},
|
||||
withdrawStatusText (status) {
|
||||
const map = {
|
||||
APPLY: '申请中',
|
||||
VIA_AUDITING: '审核通过',
|
||||
SUCCESS: '提现成功',
|
||||
ERROR: '提现失败'
|
||||
}
|
||||
return map[status] || '审核拒绝'
|
||||
},
|
||||
// 余额日志
|
||||
changePage(v) {
|
||||
this.walletForm.pageNumber = v;
|
||||
this.init();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.walletForm.pageNumber = 1;
|
||||
this.walletForm.pageSize = v;
|
||||
this.init();
|
||||
},
|
||||
// 充值记录
|
||||
rechargeChangePage(v) {
|
||||
this.rechargeForm.pageNumber = v;
|
||||
this.getRechargeData();
|
||||
},
|
||||
rechargeChangePageSize(v) {
|
||||
this.rechargeForm.pageNumber = 1;
|
||||
this.rechargeForm.pageSize = v;
|
||||
this.getRechargeData();
|
||||
},
|
||||
// 提现记录
|
||||
withdrawChangePage(v) {
|
||||
this.withdrawApplyForm.pageNumber = v;
|
||||
this.getWithdrawApplyData();
|
||||
},
|
||||
withdrawChangePageSize(v) {
|
||||
this.withdrawApplyForm.pageNumber = 1;
|
||||
this.withdrawApplyForm.pageSize = v;
|
||||
this.getWithdrawApplyData();
|
||||
},
|
||||
// 弹出在线充值框
|
||||
recharge() {
|
||||
this.formData.price = 1;
|
||||
this.modal = true;
|
||||
},
|
||||
// 在线充值
|
||||
rechargePrice() {
|
||||
this.$refs['formData'].validate((valid) => {
|
||||
if (valid) {
|
||||
recharge(this.formData).then((res) => {
|
||||
if (res.message === 'success') {
|
||||
this.$router.push({
|
||||
path: '/payment',
|
||||
query: {orderType: 'RECHARGE', sn: res.result.rechargeSn}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// 申请提现弹出框
|
||||
withdrawalApply() {
|
||||
this.withdrawApplyModal = true;
|
||||
this.withdrawApplyFormData.minPrice = 1;
|
||||
this.withdrawApplyFormData.price = 1;
|
||||
this.withdrawApplyFormData.type = '';
|
||||
this.withdrawApplyFormData.realName = '';
|
||||
this.withdrawApplyFormData.connectNumber = '';
|
||||
withdrawalSettingVO().then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.withdrawApplyFormData.minPrice = res.result.minPrice;
|
||||
this.withdrawApplyFormData.type = res.result.type;
|
||||
this.withdrawApplyFormData.price = 1;
|
||||
}
|
||||
});
|
||||
},
|
||||
// 提现
|
||||
withdrawal() {
|
||||
this.$refs['withdrawApplyFormData'].validate((valid) => {
|
||||
if (valid) {
|
||||
withdrawalApply(this.withdrawApplyFormData).then((res) => {
|
||||
if (res && res.success) {
|
||||
Message.success('提现申请成功,关注提现状态');
|
||||
this.withdrawApplyModal = false;
|
||||
this.init(); // 余额查询
|
||||
this.getWithdrawApplyData(); // 提现记录
|
||||
}
|
||||
router.push({
|
||||
path: '/payment',
|
||||
query: {orderType: 'RECHARGE', sn: res.result.rechargeSn}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
// 申请提现弹出框
|
||||
function withdrawalApply() {
|
||||
withdrawApplyModal.value = true;
|
||||
withdrawApplyFormData.minPrice = 1;
|
||||
withdrawApplyFormData.price = 1;
|
||||
withdrawApplyFormData.type = '';
|
||||
withdrawApplyFormData.realName = '';
|
||||
withdrawApplyFormData.connectNumber = '';
|
||||
withdrawalSettingVO().then((res) => {
|
||||
if (res.code === 200) {
|
||||
withdrawApplyFormData.minPrice = res.result.minPrice;
|
||||
withdrawApplyFormData.type = res.result.type;
|
||||
withdrawApplyFormData.price = 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
// 提现
|
||||
function withdrawal() {
|
||||
withdrawApplyFormDataRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
apiWithdrawalApply(withdrawApplyFormData).then((res) => {
|
||||
if (res && res.success) {
|
||||
Message.success('提现申请成功,关注提现状态');
|
||||
withdrawApplyModal.value = false;
|
||||
init(); // 余额查询
|
||||
getWithdrawApplyData(); // 提现记录
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<div class="bind-section mb_20">
|
||||
<div class="section-title">兑换礼品卡</div>
|
||||
<el-form ref="bindForm" :model="bindForm" :rules="bindRules" inline class="bind-form">
|
||||
<el-form ref="bindFormRef" :model="bindForm" :rules="bindRules" inline class="bind-form">
|
||||
<el-form-item label="卡号" prop="cardNo" label-width="60px">
|
||||
<el-input v-model="bindForm.cardNo" placeholder="请输入卡号" maxlength="64" style="width: 220px" />
|
||||
</el-form-item>
|
||||
@@ -92,7 +92,9 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { computed, nextTick, onMounted, reactive, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Message } from "@/utils/message";
|
||||
import {
|
||||
getGiftCardCashMemberCardPage,
|
||||
@@ -100,194 +102,201 @@ import {
|
||||
activateGiftCardCashMemberCard,
|
||||
} from "@/api/promotion.js";
|
||||
|
||||
export default {
|
||||
name: "MyGiftCards",
|
||||
data() {
|
||||
return {
|
||||
statusTab: "AVAILABLE",
|
||||
loading: false,
|
||||
total: 0,
|
||||
list: [],
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
sort: "createTime",
|
||||
order: "desc",
|
||||
memberCardStatus: "AVAILABLE",
|
||||
},
|
||||
bindSubmitting: false,
|
||||
bindForm: {
|
||||
cardNo: "",
|
||||
cardSecret: "",
|
||||
},
|
||||
bindRules: {
|
||||
cardNo: [{ required: true, message: "请输入卡号", trigger: "blur" }],
|
||||
cardSecret: [{ required: true, message: "请输入兑换码", trigger: "blur" }],
|
||||
},
|
||||
noticeModal: false,
|
||||
serviceHotline: "12221111",
|
||||
activatingId: "",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
primaryActionLabel() {
|
||||
if (this.statusTab === "PENDING_ACTIVATION") {
|
||||
return "激活自用";
|
||||
}
|
||||
if (this.statusTab === "AVAILABLE") {
|
||||
return "去使用";
|
||||
}
|
||||
return "不可用";
|
||||
},
|
||||
primaryActionDisabled() {
|
||||
return this.statusTab === "UNAVAILABLE";
|
||||
},
|
||||
pendingActivateLocked() {
|
||||
return this.statusTab === "PENDING_ACTIVATION" && !!this.activatingId;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
formatYuan(val) {
|
||||
if (val == null || val === "") {
|
||||
return "—";
|
||||
}
|
||||
const n = Number(val);
|
||||
if (Number.isNaN(n)) {
|
||||
return String(val);
|
||||
}
|
||||
return Number.isInteger(n) ? String(n) : n.toFixed(2).replace(/\.?0+$/, "");
|
||||
},
|
||||
formatValidity(row) {
|
||||
const t = row && row.expireTime;
|
||||
if (!t) {
|
||||
return "长期有效";
|
||||
}
|
||||
const d = new Date(t);
|
||||
if (Number.isNaN(d.getTime())) {
|
||||
return "长期有效";
|
||||
}
|
||||
if (d.getFullYear() >= 2099) {
|
||||
return "长期有效";
|
||||
}
|
||||
const y = d.getFullYear();
|
||||
const m = String(d.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(d.getDate()).padStart(2, "0");
|
||||
return `${y}-${m}-${day} 到期`;
|
||||
},
|
||||
onStatusTab(name) {
|
||||
this.statusTab = name;
|
||||
this.params.memberCardStatus = name;
|
||||
this.params.pageNumber = 1;
|
||||
this.getList();
|
||||
},
|
||||
getList() {
|
||||
this.loading = true;
|
||||
const p = { ...this.params };
|
||||
if (p.memberCardStatus) {
|
||||
p.memberCardStatus = String(p.memberCardStatus);
|
||||
}
|
||||
getGiftCardCashMemberCardPage(p)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success && res.result) {
|
||||
this.list = res.result.records || [];
|
||||
this.total = res.result.total || 0;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
changePage(val) {
|
||||
this.params.pageNumber = val;
|
||||
this.getList();
|
||||
},
|
||||
changePageSize(val) {
|
||||
this.params.pageNumber = 1;
|
||||
this.params.pageSize = val;
|
||||
this.getList();
|
||||
},
|
||||
resetBindForm() {
|
||||
this.bindForm = { cardNo: "", cardSecret: "" };
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.bindForm) {
|
||||
this.$refs.bindForm.resetFields();
|
||||
}
|
||||
});
|
||||
},
|
||||
submitBind() {
|
||||
this.$refs.bindForm.validate((valid) => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
this.bindSubmitting = true;
|
||||
bindGiftCardCashMemberCard({
|
||||
cardNo: String(this.bindForm.cardNo).trim(),
|
||||
cardSecret: String(this.bindForm.cardSecret).trim(),
|
||||
})
|
||||
.then((res) => {
|
||||
this.bindSubmitting = false;
|
||||
if (res.success) {
|
||||
Message.success(res.message || "兑换成功");
|
||||
this.resetBindForm();
|
||||
this.params.pageNumber = 1;
|
||||
this.getList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.bindSubmitting = false;
|
||||
});
|
||||
});
|
||||
},
|
||||
onCardPrimaryAction(item) {
|
||||
if (this.primaryActionDisabled) {
|
||||
return;
|
||||
}
|
||||
if (this.statusTab === "PENDING_ACTIVATION") {
|
||||
const memberCardId = this.resolveMemberCardId(item);
|
||||
if (!memberCardId) {
|
||||
Message.error("卡片信息异常,无法激活");
|
||||
return;
|
||||
}
|
||||
this.activatingId = memberCardId;
|
||||
activateGiftCardCashMemberCard(memberCardId)
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
Message.success(res.message || "激活成功");
|
||||
this.getList();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.warn('激活礼品卡失败', err);
|
||||
})
|
||||
.finally(() => {
|
||||
this.activatingId = "";
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.statusTab === "AVAILABLE") {
|
||||
this.$router.push({ path: "/goodsList" });
|
||||
}
|
||||
},
|
||||
resolveMemberCardId(row) {
|
||||
if (!row) {
|
||||
return "";
|
||||
}
|
||||
return row.memberCardId != null && row.memberCardId !== ""
|
||||
? String(row.memberCardId)
|
||||
: row.id != null && row.id !== ""
|
||||
? String(row.id)
|
||||
: "";
|
||||
},
|
||||
isActivating(item) {
|
||||
const id = this.resolveMemberCardId(item);
|
||||
return !!this.activatingId && this.activatingId === id;
|
||||
},
|
||||
},
|
||||
defineOptions({ name: "MyGiftCards" });
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const statusTab = ref("AVAILABLE");
|
||||
const loading = ref(false);
|
||||
const total = ref(0);
|
||||
const list = ref([]);
|
||||
const params = reactive({
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
sort: "createTime",
|
||||
order: "desc",
|
||||
memberCardStatus: "AVAILABLE",
|
||||
});
|
||||
const bindSubmitting = ref(false);
|
||||
const bindForm = ref({
|
||||
cardNo: "",
|
||||
cardSecret: "",
|
||||
});
|
||||
const bindRules = {
|
||||
cardNo: [{ required: true, message: "请输入卡号", trigger: "blur" }],
|
||||
cardSecret: [{ required: true, message: "请输入兑换码", trigger: "blur" }],
|
||||
};
|
||||
const noticeModal = ref(false);
|
||||
const serviceHotline = ref("12221111");
|
||||
const activatingId = ref("");
|
||||
const bindFormRef = ref(null);
|
||||
|
||||
const primaryActionLabel = computed(() => {
|
||||
if (statusTab.value === "PENDING_ACTIVATION") {
|
||||
return "激活自用";
|
||||
}
|
||||
if (statusTab.value === "AVAILABLE") {
|
||||
return "去使用";
|
||||
}
|
||||
return "不可用";
|
||||
});
|
||||
const primaryActionDisabled = computed(() => {
|
||||
return statusTab.value === "UNAVAILABLE";
|
||||
});
|
||||
const pendingActivateLocked = computed(() => {
|
||||
return statusTab.value === "PENDING_ACTIVATION" && !!activatingId.value;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
|
||||
function formatYuan(val) {
|
||||
if (val == null || val === "") {
|
||||
return "—";
|
||||
}
|
||||
const n = Number(val);
|
||||
if (Number.isNaN(n)) {
|
||||
return String(val);
|
||||
}
|
||||
return Number.isInteger(n) ? String(n) : n.toFixed(2).replace(/\.?0+$/, "");
|
||||
}
|
||||
|
||||
function formatValidity(row) {
|
||||
const t = row && row.expireTime;
|
||||
if (!t) {
|
||||
return "长期有效";
|
||||
}
|
||||
const d = new Date(t);
|
||||
if (Number.isNaN(d.getTime())) {
|
||||
return "长期有效";
|
||||
}
|
||||
if (d.getFullYear() >= 2099) {
|
||||
return "长期有效";
|
||||
}
|
||||
const y = d.getFullYear();
|
||||
const m = String(d.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(d.getDate()).padStart(2, "0");
|
||||
return `${y}-${m}-${day} 到期`;
|
||||
}
|
||||
|
||||
function onStatusTab(name) {
|
||||
statusTab.value = name;
|
||||
params.memberCardStatus = name;
|
||||
params.pageNumber = 1;
|
||||
getList();
|
||||
}
|
||||
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
const p = { ...params };
|
||||
if (p.memberCardStatus) {
|
||||
p.memberCardStatus = String(p.memberCardStatus);
|
||||
}
|
||||
getGiftCardCashMemberCardPage(p)
|
||||
.then((res) => {
|
||||
loading.value = false;
|
||||
if (res.success && res.result) {
|
||||
list.value = res.result.records || [];
|
||||
total.value = res.result.total || 0;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
function changePage(val) {
|
||||
params.pageNumber = val;
|
||||
getList();
|
||||
}
|
||||
|
||||
function changePageSize(val) {
|
||||
params.pageNumber = 1;
|
||||
params.pageSize = val;
|
||||
getList();
|
||||
}
|
||||
|
||||
function resetBindForm() {
|
||||
bindForm.value = { cardNo: "", cardSecret: "" };
|
||||
nextTick(() => {
|
||||
if (bindFormRef.value) {
|
||||
bindFormRef.value.resetFields();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function submitBind() {
|
||||
bindFormRef.value.validate((valid) => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
bindSubmitting.value = true;
|
||||
bindGiftCardCashMemberCard({
|
||||
cardNo: String(bindForm.value.cardNo).trim(),
|
||||
cardSecret: String(bindForm.value.cardSecret).trim(),
|
||||
})
|
||||
.then((res) => {
|
||||
bindSubmitting.value = false;
|
||||
if (res.success) {
|
||||
Message.success(res.message || "兑换成功");
|
||||
resetBindForm();
|
||||
params.pageNumber = 1;
|
||||
getList();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
bindSubmitting.value = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onCardPrimaryAction(item) {
|
||||
if (primaryActionDisabled.value) {
|
||||
return;
|
||||
}
|
||||
if (statusTab.value === "PENDING_ACTIVATION") {
|
||||
const memberCardId = resolveMemberCardId(item);
|
||||
if (!memberCardId) {
|
||||
Message.error("卡片信息异常,无法激活");
|
||||
return;
|
||||
}
|
||||
activatingId.value = memberCardId;
|
||||
activateGiftCardCashMemberCard(memberCardId)
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
Message.success(res.message || "激活成功");
|
||||
getList();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.warn('激活礼品卡失败', err);
|
||||
})
|
||||
.finally(() => {
|
||||
activatingId.value = "";
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (statusTab.value === "AVAILABLE") {
|
||||
router.push({ path: "/goodsList" });
|
||||
}
|
||||
}
|
||||
|
||||
function resolveMemberCardId(row) {
|
||||
if (!row) {
|
||||
return "";
|
||||
}
|
||||
return row.memberCardId != null && row.memberCardId !== ""
|
||||
? String(row.memberCardId)
|
||||
: row.id != null && row.id !== ""
|
||||
? String(row.id)
|
||||
: "";
|
||||
}
|
||||
|
||||
function isActivating(item) {
|
||||
const id = resolveMemberCardId(item);
|
||||
return !!activatingId.value && activatingId.value === id;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -38,98 +38,103 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
import { Delete } from '@element-plus/icons-vue';
|
||||
import { tracksList, clearTracks, clearTracksById } from "@/api/member";
|
||||
export default {
|
||||
components: { Delete },
|
||||
name: "MyTrack",
|
||||
data() {
|
||||
return {
|
||||
list: [], // 我的足迹,商品列表
|
||||
spinShow: false, // 控制loading是否加载
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
order: "desc",
|
||||
sort: "updateTime",
|
||||
},
|
||||
total: 0,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
goodsDetail(skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routeUrl = this.$router.resolve({
|
||||
path: "/goodsDetail",
|
||||
query: { skuId, goodsId },
|
||||
});
|
||||
window.open(routeUrl.href, "_blank");
|
||||
},
|
||||
// 跳转店铺首页
|
||||
shopPage(id) {
|
||||
this.$router.push({
|
||||
path: "/merchant",
|
||||
query: { id: id },
|
||||
});
|
||||
},
|
||||
clearAll() {
|
||||
// 清除全部足迹
|
||||
Modal.confirm({
|
||||
title: "删除",
|
||||
content: "<p>确定要删除全部足迹吗?</p>",
|
||||
onOk: () => {
|
||||
clearTracks().then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("删除成功");
|
||||
this.getList();
|
||||
}
|
||||
});
|
||||
},
|
||||
onCancel: () => {},
|
||||
});
|
||||
},
|
||||
clearById(id) {
|
||||
// 清除全部足迹
|
||||
clearTracksById(id).then((res) => {
|
||||
|
||||
defineOptions({ name: "MyTrack" });
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const list = ref([]); // 我的足迹,商品列表
|
||||
const spinShow = ref(false); // 控制loading是否加载
|
||||
const params = reactive({
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
order: "desc",
|
||||
sort: "updateTime",
|
||||
});
|
||||
const total = ref(0);
|
||||
|
||||
function goodsDetail(skuId, goodsId) {
|
||||
// 跳转商品详情
|
||||
let routeUrl = router.resolve({
|
||||
path: "/goodsDetail",
|
||||
query: { skuId, goodsId },
|
||||
});
|
||||
window.open(routeUrl.href, "_blank");
|
||||
}
|
||||
|
||||
// 跳转店铺首页
|
||||
function shopPage(id) {
|
||||
router.push({
|
||||
path: "/merchant",
|
||||
query: { id: id },
|
||||
});
|
||||
}
|
||||
|
||||
function clearAll() {
|
||||
// 清除全部足迹
|
||||
Modal.confirm({
|
||||
title: "删除",
|
||||
content: "<p>确定要删除全部足迹吗?</p>",
|
||||
onOk: () => {
|
||||
clearTracks().then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("删除成功");
|
||||
this.getList();
|
||||
getList();
|
||||
}
|
||||
});
|
||||
},
|
||||
changePageNum(val) {
|
||||
// 修改页码
|
||||
this.params.pageNumber = val;
|
||||
this.getList();
|
||||
},
|
||||
changePageSize(val) {
|
||||
// 修改页数
|
||||
this.params.pageNumber = 1;
|
||||
this.params.pageSize = val;
|
||||
this.getList();
|
||||
},
|
||||
getList() {
|
||||
// 获取足迹列表
|
||||
this.spinShow = true;
|
||||
tracksList(this.params).then((res) => {
|
||||
this.spinShow = false;
|
||||
if (res.success && res.result.records.length) {
|
||||
this.list = res.result.records.filter(item =>{
|
||||
return item != null
|
||||
});
|
||||
this.total = res.result.total
|
||||
} else {
|
||||
this.list = [];
|
||||
}
|
||||
onCancel: () => {},
|
||||
});
|
||||
}
|
||||
|
||||
function clearById(id) {
|
||||
// 清除全部足迹
|
||||
clearTracksById(id).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("删除成功");
|
||||
getList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function changePageNum(val) {
|
||||
// 修改页码
|
||||
params.pageNumber = val;
|
||||
getList();
|
||||
}
|
||||
|
||||
function changePageSize(val) {
|
||||
// 修改页数
|
||||
params.pageNumber = 1;
|
||||
params.pageSize = val;
|
||||
getList();
|
||||
}
|
||||
|
||||
function getList() {
|
||||
// 获取足迹列表
|
||||
spinShow.value = true;
|
||||
tracksList(params).then((res) => {
|
||||
spinShow.value = false;
|
||||
if (res.success && res.result.records.length) {
|
||||
list.value = res.result.records.filter(item =>{
|
||||
return item != null
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
total.value = res.result.total
|
||||
} else {
|
||||
list.value = [];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.wrapper {
|
||||
|
||||
Reference in New Issue
Block a user