|
|
@@ -0,0 +1,367 @@
|
|
|
+<template>
|
|
|
+ <view class="order-detail" :class="{ 'fixed-bottom-2': type == 2 }" @click="playGlobalSound">
|
|
|
+ <scroll-view class="scroller" :scroll-into-view="toView" scroll-y="true" scroll-with-animation="true">
|
|
|
+ <view class="flex flex-a-c flex-j-b bg-white bind-audit mb-16">
|
|
|
+ <text>绑定复审员</text>
|
|
|
+ <text class="text-center flex-1">{{
|
|
|
+ orderDetail.auditUserName || selectedAuditor?.userName || ""
|
|
|
+ }}</text>
|
|
|
+ <text @click="showAuditorSelector = true" class="color-primary">绑定</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <OrderInfo :detail="orderDetail" @refresh="() => getOrderDetail(true)" />
|
|
|
+
|
|
|
+ <UserInfoCard :detail="orderDetail" />
|
|
|
+
|
|
|
+ <view class="mt-16" style="padding: 0 6rpx">
|
|
|
+ <u-subsection :list="list" mode="subsection" :current="current"
|
|
|
+ @change="handleSectionChange"></u-subsection>
|
|
|
+ <ReviewBookInfo v-if="current == 0" :bookList="orderDetail.detailReviewVoList" :detail="orderDetail"
|
|
|
+ @get-all-firstLetter="onGetAllFirstLetter" />
|
|
|
+ <LogisticsTimeline v-if="current == 1" :list="orderDetail.trackingVoList" />
|
|
|
+ <FileInfo v-if="current == 2" :orderId="orderDetail.orderId" />
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+
|
|
|
+ <view class="fixed-left">
|
|
|
+ <view class="bind-code common-bg" style="margin-bottom: 30px; padding: 20rpx" @click="handleBindCode">绑码
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="common-bg flex flex-a-c flex-j-c flex-d">
|
|
|
+ <view class="book-status-item" @click="scrollToView('good')">良好</view>
|
|
|
+ <view class="book-status-item item-center" @click="scrollToView('average')">一般</view>
|
|
|
+ <view class="book-status-item" @click="scrollToView('poor')">极差</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="fixed-right">
|
|
|
+ <view class="letter-bg flex flex-a-c flex-j-c flex-d">
|
|
|
+ <view class="letter-item"><u-icon name="arrow-up-fill" size="20" color="#ffffff"
|
|
|
+ @click="scrollToTop"></u-icon></view>
|
|
|
+ <view class="letter-item" v-for="(item, index) in allLetters" :key="index" @click="scrollToView(item)">
|
|
|
+ {{ item }}</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="common-bg fixed-bottom">
|
|
|
+ <u-button type="primary" size="large" @click="handleComplete">完成</u-button>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <AuditorSelector :show="showAuditorSelector" @update:show="showAuditorSelector = $event"
|
|
|
+ @auditor-selected="handleAuditorSelected" />
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, onUnmounted } from "vue";
|
|
|
+import { onLoad, onShow } from "@dcloudio/uni-app";
|
|
|
+import AuditorSelector from "./components/AuditorSelector.vue";
|
|
|
+import OrderInfo from "./components/OrderInfo.vue";
|
|
|
+import UserInfoCard from "./components/UserInfoCard.vue";
|
|
|
+import LogisticsTimeline from "../express/components/LogisticsTimeline.vue";
|
|
|
+import ReviewBookInfo from "./components/ReviewBookInfo.vue";
|
|
|
+import FileInfo from "./components/FileInfo.vue";
|
|
|
+
|
|
|
+const showAuditorSelector = ref(false);
|
|
|
+const selectedAuditor = ref({});
|
|
|
+const handleAuditorSelected = (auditor) => {
|
|
|
+ selectedAuditor.value = auditor;
|
|
|
+ orderDetail.value.auditUserId = auditor.userId;
|
|
|
+ orderDetail.value.auditUserName = auditor.userName;
|
|
|
+
|
|
|
+ uni.setStorageSync("checkUserInfo", {
|
|
|
+ userName: auditor.userName,
|
|
|
+ userId: auditor.userId,
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+//点击全局音效
|
|
|
+function playGlobalSound() {
|
|
|
+ uni.$u.playClickSound();
|
|
|
+}
|
|
|
+
|
|
|
+//点击滚动的位置
|
|
|
+const toView = ref("");
|
|
|
+function scrollToView(to) {
|
|
|
+ toView.value = to;
|
|
|
+
|
|
|
+ uni.pageScrollTo({
|
|
|
+ selector: "#" + to,
|
|
|
+ duration: 200,
|
|
|
+ });
|
|
|
+}
|
|
|
+//回到顶部
|
|
|
+function scrollToTop() {
|
|
|
+ uni.pageScrollTo({
|
|
|
+ top: 0,
|
|
|
+ duration: 200,
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+//绑码
|
|
|
+function handleBindCode() {
|
|
|
+ uni.$u.toast("暂无开发");
|
|
|
+}
|
|
|
+
|
|
|
+const list = ref(["图书清单", "物流信息", "上传附件"]);
|
|
|
+const current = ref(0);
|
|
|
+const handleSectionChange = (index) => {
|
|
|
+ current.value = index;
|
|
|
+};
|
|
|
+
|
|
|
+//监听书籍的首字母
|
|
|
+const allLetters = ref([]);
|
|
|
+function onGetAllFirstLetter(data) {
|
|
|
+ allLetters.value = data;
|
|
|
+}
|
|
|
+
|
|
|
+//完成
|
|
|
+function handleComplete() {
|
|
|
+ let bookList = orderDetail.value.detailReviewVoList;
|
|
|
+ let bool = bookList.some((item) => !item.auditReviewComment?.sts);
|
|
|
+ if (bool) {
|
|
|
+ let text = "还有未复审的书";
|
|
|
+ uni.$u.toast(text);
|
|
|
+ uni.$u.ttsModule.speak(text);
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ uni.$u.http
|
|
|
+ .post("/app/orderreview/reviewOrderFinish", {
|
|
|
+ reviewId: orderDetail.value.reviewId,
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ if (res.code == 200) {
|
|
|
+ uni.showToast({ title: "复审完成", icon: "none" });
|
|
|
+ uni.$u.ttsModule.speak("复审完成");
|
|
|
+ uni.navigateBack();
|
|
|
+ }else{
|
|
|
+ uni.$u.ttsModule.speak(res.msg);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const orderDetail = ref({ status: 0 });
|
|
|
+//获取订单详情
|
|
|
+function getOrderDetail(forceRefresh = false) {
|
|
|
+ if (!orderId.value) return;
|
|
|
+
|
|
|
+ // 如果是强制刷新,重置标志位
|
|
|
+ if (forceRefresh) {
|
|
|
+ hasLoadedOrderDetail.value = false;
|
|
|
+ hasLoadedCheckUser.value = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ uni.showLoading({
|
|
|
+ title: "加载中...",
|
|
|
+ mask: true,
|
|
|
+ });
|
|
|
+ uni.$u.http
|
|
|
+ .get("/app/orderreview/getOrderInfoForReview", {
|
|
|
+ params: {
|
|
|
+ searchType: 1,
|
|
|
+ search: orderId.value,
|
|
|
+ },
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ if (res.code == 200) {
|
|
|
+ orderDetail.value = res.data;
|
|
|
+
|
|
|
+ // 只有在首次加载且没有复审员信息时才调用getCheckUserInfo
|
|
|
+ if (!hasLoadedCheckUser.value && !res.data.auditUserId) {
|
|
|
+ getCheckUserInfo();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (res.data.auditUserId) {
|
|
|
+ let auditUserInfo = {
|
|
|
+ userName: res.data.auditUserName,
|
|
|
+ userId: res.data.auditUserId,
|
|
|
+ };
|
|
|
+ uni.setStorageSync("checkUserInfo", auditUserInfo);
|
|
|
+ } else {
|
|
|
+ let userInfo = uni.getStorageSync("checkUserInfo");
|
|
|
+ if (userInfo && userInfo.userName) {
|
|
|
+ orderDetail.value.auditUserName = userInfo.userName;
|
|
|
+ orderDetail.value.auditUserId = userInfo.userId;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (isOnLoad.value) {
|
|
|
+ if (res.data.manageRemark.length > 0 && res.data.status < 10) {
|
|
|
+ uni.$u.ttsModule.speak("此订单有备注信息,请注意查看");
|
|
|
+ }
|
|
|
+ if (res.data.warnArea && res.data.warnArea.length > 0) {
|
|
|
+ let text = `此订单来源于${res.data.warnArea}`;
|
|
|
+ uni.$u.ttsModule.speak(text);
|
|
|
+ }
|
|
|
+ isOnLoad.value = false;
|
|
|
+ }
|
|
|
+ hasLoadedOrderDetail.value = true; // 标记订单详情已加载
|
|
|
+ } else {
|
|
|
+ uni.$u.toast(res.msg);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ uni.hideLoading();
|
|
|
+ });
|
|
|
+}
|
|
|
+//获取上一次绑定的复审员信息
|
|
|
+function getCheckUserInfo() {
|
|
|
+ uni.$u.http.get("/app/orderinfo/getCheckUser").then((res) => {
|
|
|
+ if (res.code == 200) {
|
|
|
+ let userInfo = res.data || {};
|
|
|
+ orderDetail.value.auditUserName = userInfo.userName || '';
|
|
|
+ orderDetail.value.auditUserId = userInfo.userId || '';
|
|
|
+ uni.setStorageSync("checkUserInfo", {
|
|
|
+ userName: userInfo.userName,
|
|
|
+ userId: userInfo.userId,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ hasLoadedCheckUser.value = true; // 标记复审员信息已加载
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+//isbn正则校验是否符合
|
|
|
+function checkIsbn(isbn) {
|
|
|
+ const isbn13Regex = /^(?:97[89]-?\d{1,5}-?\d{1,7}-?\d{1,6}-?\d)$/;
|
|
|
+ if (isbn13Regex.test(isbn)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+//扫码之后的逻辑
|
|
|
+function handleScan(isbn) {
|
|
|
+ if (!checkIsbn(isbn)) {
|
|
|
+ let text = `不是正确的ISBN码`;
|
|
|
+ uni.$u.ttsModule.speak(text);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (orderDetail.value.status >= 10) {
|
|
|
+ uni.$u.ttsModule.speak("订单已复审完成");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //取 isbn 的后四位字符串进行播报
|
|
|
+ let isbnStr = `${isbn.slice(-4)}`;
|
|
|
+
|
|
|
+ let isbnList = orderDetail.value.detailVoList.map((item) => item.isbn);
|
|
|
+
|
|
|
+ if (isbnList.includes(isbn)) {
|
|
|
+ let book = orderDetail.value.detailVoList.find((item) => item.isbn == isbn);
|
|
|
+
|
|
|
+ //扫描到套装书
|
|
|
+ if (book.suit == 1) {
|
|
|
+ let text = `${isbnStr}请注意套装书是否齐全`;
|
|
|
+ uni.$u.ttsModule.speak(text);
|
|
|
+ }
|
|
|
+ //扫描到需要取出的书
|
|
|
+ if (book.bookWarn == 1) {
|
|
|
+ let text = `请注意${isbnStr}需要取出`;
|
|
|
+ uni.$u.ttsModule.speak(text);
|
|
|
+ }
|
|
|
+
|
|
|
+ uni.navigateTo({
|
|
|
+ url: `/pages/index/detail/book-audit?isbn=${isbn}&orderId=${orderDetail.value.orderId}`,
|
|
|
+ });
|
|
|
+ uni.setStorageSync("auditBook", book);
|
|
|
+ uni.setStorageSync("orderDetail", orderDetail.value);
|
|
|
+ } else {
|
|
|
+ let text = `此订单中不存在${isbnStr}这本书 `;
|
|
|
+ uni.$u.ttsModule.speak(text);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//扫码
|
|
|
+function handleScanCode() {
|
|
|
+ uni.scanCode({
|
|
|
+ success: (res) => {
|
|
|
+ res.result && handleScan(res.result);
|
|
|
+ },
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+const orderId = ref("");
|
|
|
+const isOnLoad = ref(false);
|
|
|
+const hasLoadedOrderDetail = ref(false); // 添加标志位控制订单详情是否已加载
|
|
|
+const hasLoadedCheckUser = ref(false); // 添加标志位控制复审员信息是否已加载
|
|
|
+
|
|
|
+// 1 表示到货复审 2 表示查看订单
|
|
|
+const type = ref(1);
|
|
|
+onLoad((options) => {
|
|
|
+ isOnLoad.value = true;
|
|
|
+ orderId.value = options.id;
|
|
|
+ orderDetail.value = uni.getStorageSync("orderDetail") || {};
|
|
|
+ type.value = options.type || 1;
|
|
|
+
|
|
|
+ uni.removeStorageSync("scannedBooks");
|
|
|
+});
|
|
|
+
|
|
|
+
|
|
|
+onShow(() => {
|
|
|
+ // 只有在首次加载时才调用getOrderDetail,避免重复请求
|
|
|
+ getOrderDetail();
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style>
|
|
|
+page {
|
|
|
+ background-color: #f5f5f5;
|
|
|
+}
|
|
|
+</style>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.order-detail {
|
|
|
+ font-size: 30rpx;
|
|
|
+ padding-bottom: 140rpx;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &.fixed-bottom-2 {
|
|
|
+ padding-bottom: 30rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .bind-audit {
|
|
|
+ padding: 20rpx 30rpx;
|
|
|
+ border-bottom: 1px solid #e5e5e5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .fixed-left {
|
|
|
+ position: fixed;
|
|
|
+ left: 0;
|
|
|
+ top: 11%;
|
|
|
+ width: 100rpx;
|
|
|
+
|
|
|
+ .common-bg {
|
|
|
+ background-color: rgba(34, 172, 56, 0.7);
|
|
|
+ border-radius: 0 30rpx 30rpx 0;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #ffffff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .book-status-item {
|
|
|
+ padding: 20rpx;
|
|
|
+ border-top: 1rpx solid #ffffff;
|
|
|
+ border-bottom: 1rpx solid #ffffff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .fixed-right {
|
|
|
+ position: fixed;
|
|
|
+ right: 0;
|
|
|
+ top: 12%;
|
|
|
+ width: 70rpx;
|
|
|
+
|
|
|
+ .letter-bg {
|
|
|
+ background-color: rgba(34, 172, 56, 0.7);
|
|
|
+ border-radius: 10rpx 0 0 10rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #ffffff;
|
|
|
+ padding: 12rpx 0;
|
|
|
+ padding-bottom: 6rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .letter-item {
|
|
|
+ padding-bottom: 12rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|