|
|
@@ -7,14 +7,46 @@
|
|
|
</el-breadcrumb>
|
|
|
</template>
|
|
|
<el-form :model="forms" ref="forms" label-width="70px" class="search-form">
|
|
|
- <el-row>
|
|
|
- <el-form-item label="关键词" prop="keyword">
|
|
|
+ <el-row style="align-items: center">
|
|
|
+ <el-form-item label="关键词" prop="keyword" style="margin: 0 10px">
|
|
|
<el-col>
|
|
|
- <el-input v-model="forms.keyword" prefix-icon="Search"></el-input>
|
|
|
+ <el-input v-model="forms.keyword" clearable prefix-icon="Search"></el-input>
|
|
|
</el-col>
|
|
|
</el-form-item>
|
|
|
+ <el-form-item label="订单状态" prop="status" style="margin: 0 10px">
|
|
|
+ <el-select v-model="forms.status" :empty-values="[null, undefined]" :value-on-clear="null" clearable
|
|
|
+ style="width: 100px">
|
|
|
+ <el-option label="全部" value=""></el-option>
|
|
|
+ <el-option label="草稿" value="Draft"></el-option>
|
|
|
+ <el-option label="已提交" value="Submitted"></el-option>
|
|
|
+ <el-option label="已审核" value="Approved"></el-option>
|
|
|
+ <el-option label="已支付" value="Paid"></el-option>
|
|
|
+ <el-option label="已确认" value="Confirmed"></el-option>
|
|
|
+ <el-option label="处理中" value="Processing"></el-option>
|
|
|
+ <el-option label="已完成" value="Completed"></el-option>
|
|
|
+ <el-option label="已取消" value="Cancelled"></el-option>
|
|
|
+ <el-option label="已驳回" value="Rejected"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="审核状态" prop="status" style="margin: 0 10px">
|
|
|
+ <el-select v-model="forms.auditStatus" :empty-values="[null, undefined]" :value-on-clear="null" clearable
|
|
|
+ style="width: 100px">
|
|
|
+ <el-option label="全部" value=""></el-option>
|
|
|
+ <el-option label="待审核" value="Pending"></el-option>
|
|
|
+ <el-option label="审核通过" value="Approved"></el-option>
|
|
|
+ <el-option label="审核驳回" value="Rejected"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="支付状态" prop="paymentStatus" style="margin: 0 10px">
|
|
|
+ <el-select v-model="forms.paymentStatus" :empty-values="[null, undefined]" :value-on-clear="null" clearable
|
|
|
+ style="width: 100px">
|
|
|
+ <el-option label="全部" value=""></el-option>
|
|
|
+ <el-option label="待支付" value="Pending"></el-option>
|
|
|
+ <el-option label="已支付" value="Paid"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
<el-form-item label="" label-width="20px">
|
|
|
- <el-button type="primary" icon="search" @click="submit('forms')">
|
|
|
+ <el-button type="primary" icon="search" @click="searchOrderList">
|
|
|
搜索
|
|
|
</el-button>
|
|
|
</el-form-item>
|
|
|
@@ -40,7 +72,7 @@
|
|
|
<template #default="scope">
|
|
|
<div>开始日期: {{ scope.row.travelStartDate }}</div>
|
|
|
<div>结束日期: {{ scope.row.travelEndDate }}</div>
|
|
|
- <div>共: <el-tag size="small">{{ scope.row.travelDays }}天</el-tag></div>
|
|
|
+ <div>共: <el-tag size="small">{{ scope.row.travelDays + 1 }}天</el-tag></div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column prop="touristCount" label="人数" width="80" align="center"></el-table-column>
|
|
|
@@ -83,10 +115,13 @@
|
|
|
<template #default="scope">
|
|
|
<!-- <el-button type="primary" link size="small" @click="edit(scope.row)">编辑</el-button> -->
|
|
|
<!-- <el-button type="success" link size="small" @click="audit(scope.row)">审核</el-button> -->
|
|
|
- <el-button type="warning" link size="small" @click="payment(scope.row)">收款</el-button>
|
|
|
+ <el-button type="info" link size="small" @click="attachment(scope.row)">附件</el-button>
|
|
|
+ <el-button type="warning" v-if="userAccountId === 'testuser'" link size="small"
|
|
|
+ @click="payment(scope.row)">收款</el-button>
|
|
|
<el-button type="info" link size="small" @click="editSchedule(scope.row)">行程</el-button>
|
|
|
<el-button type="primary" link size="small" @click="editTourists(scope.row)">游客</el-button>
|
|
|
- <el-button type="danger" link size="small" @click="del(scope.row)">删除</el-button>
|
|
|
+ <el-button v-if="scope.row.status === 'Submitted'" type="danger" link size="small"
|
|
|
+ @click="del(scope.row)">删除</el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
@@ -104,7 +139,8 @@
|
|
|
<el-row :gutter="10">
|
|
|
<el-col :span="24">
|
|
|
<el-form-item label="旅行社" prop="agencyID">
|
|
|
- <el-select v-model="formData.agencyID" filterable @change="handleAgencyChange">
|
|
|
+ <el-select v-model="formData.agencyID" :disabled="!!userAgencyId" filterable
|
|
|
+ @change="handleAgencyChange">
|
|
|
<el-option v-for="item in agencyOptions" :key="item.id" :label="item.agencyName" :value="item.id">
|
|
|
</el-option>
|
|
|
</el-select>
|
|
|
@@ -215,7 +251,7 @@
|
|
|
</el-table-column>
|
|
|
<el-table-column label="操作" width="100" align="center">
|
|
|
<template #default="scope">
|
|
|
- <el-button type="primary" link size="small" @click="editProductItem(scope.row)">编辑</el-button>
|
|
|
+ <!-- <el-button type="primary" link size="small" @click="editProductItem(scope.row)">编辑</el-button> -->
|
|
|
<el-button type="danger" link size="small" @click="delProductItem(scope.$index)">删除</el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
@@ -241,16 +277,19 @@
|
|
|
</div>
|
|
|
</el-collapse-item>
|
|
|
|
|
|
- <el-collapse-item title="游客信息" name="tourists">
|
|
|
+ <el-collapse-item title="领队/游客信息" name="tourists">
|
|
|
<div>
|
|
|
<div class="product-toolbar" style="margin-bottom:10px;">
|
|
|
- <el-button type="primary" size="small" @click="addTouristInfo">
|
|
|
+ <el-button type="primary" size="small" @click="addTouristItem(true)">
|
|
|
+ 新增领队
|
|
|
+ </el-button>
|
|
|
+ <el-button type="primary" size="small" @click="addTouristItem(false)">
|
|
|
新增游客
|
|
|
</el-button>
|
|
|
- <el-button type="danger" size="small" v-if="formData.tourists && formData.tourists.length"
|
|
|
+ <!-- <el-button type="danger" size="small" v-if="formData.tourists && formData.tourists.length"
|
|
|
@click="formData.tourists = []">
|
|
|
清空游客
|
|
|
- </el-button>
|
|
|
+ </el-button> -->
|
|
|
</div>
|
|
|
|
|
|
<el-table :data="formData.tourists || []" border size="small" style="width:100%">
|
|
|
@@ -401,6 +440,43 @@
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
</el-collapse-item>
|
|
|
+ <el-collapse-item title="附件" name="attachments">
|
|
|
+ <el-row :gutter="10" style="margin-bottom: 10px">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-button type="primary" size="small" @click="downloadTemplate">下载模板</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="10">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-upload ref="orderUploadRef" action="/api/BaseUploader/Basic" :show-file-list="false"
|
|
|
+ :data="uploadParams" :headers="headers" accept=".xls,.xlsx" :limit="10" :on-success="uploadSuccess"
|
|
|
+ :file-list="fileList" :on-error="uploadError" :on-remove="removeFile" :before-upload="beforeUpload"
|
|
|
+ @on-preview="downloadFile">
|
|
|
+ <el-button type="primary" size="small">上传<i class="el-icon-plus"></i></el-button>
|
|
|
+ </el-upload>
|
|
|
+
|
|
|
+ <div class="file-list">
|
|
|
+ <el-row v-if="fileList && fileList.length" :gutter="10" style="align-items:center;">
|
|
|
+ <el-col v-for="file in fileList" :key="file.id || file.raw?.uid" :span="24"
|
|
|
+ style="display:flex;align-items:center;justify-content:space-between;margin-bottom:6px;">
|
|
|
+ <div style="flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;">
|
|
|
+ <a href="javascript:;" @click.prevent="downloadFile(file)" style="color:#409EFF;">
|
|
|
+ {{ file.name }}
|
|
|
+ </a>
|
|
|
+ <span style="color:#999;margin-left:8px;">{{ file.url ? '' : '(本地文件)' }}</span>
|
|
|
+ </div>
|
|
|
+ <div style="margin-left:12px;white-space:nowrap;">
|
|
|
+ <el-button type="text" size="small" @click="downloadFile(file)">下载</el-button>
|
|
|
+ <el-button type="danger" size="small" @click="removeFile(file)">删除</el-button>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <div v-else style="text-align:center;color:#999;padding:12px;">暂无附件</div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-collapse-item>
|
|
|
</el-collapse>
|
|
|
</el-scrollbar>
|
|
|
</el-form>
|
|
|
@@ -414,10 +490,11 @@
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
|
|
|
- <el-dialog title="行程信息维护" width="700px" v-model="scheduleDialogVisible" destroy-on-close :before-close="currentOrderId = ''">
|
|
|
- <div class="schedule-toolbar" style="margin-bottom: 10px">
|
|
|
+ <el-dialog title="行程信息" width="700px" v-model="scheduleDialogVisible" destroy-on-close
|
|
|
+ :before-close="currentOrderId = ''">
|
|
|
+ <!-- <div class="schedule-toolbar" style="margin-bottom: 10px">
|
|
|
<el-button type="primary" size="small" @click="addSchedule">新增行程</el-button>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
|
|
|
<el-table :data="scheduleList" border style="width: 100%" size="small">
|
|
|
<el-table-column type="index" label="序号" width="50" align="center" />
|
|
|
@@ -428,12 +505,12 @@
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column prop="title" label="标题" />
|
|
|
- <el-table-column label="操作" width="120" align="center">
|
|
|
+ <!-- <el-table-column label="操作" width="120" align="center">
|
|
|
<template #default="scope">
|
|
|
<el-button type="primary" link size="small" @click="editScheduleItem(scope.row)">编辑</el-button>
|
|
|
<el-button type="danger" link size="small" @click="delScheduleItem(scope.$index)">删除</el-button>
|
|
|
</template>
|
|
|
- </el-table-column>
|
|
|
+ </el-table-column> -->
|
|
|
</el-table>
|
|
|
</el-dialog>
|
|
|
|
|
|
@@ -460,10 +537,11 @@
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
|
|
|
- <el-dialog title="游客信息维护" width="900px" v-model="touristsDialogVisible" destroy-on-close :before-close="currentOrderId = ''">
|
|
|
- <div class="tourists-toolbar" style="margin-bottom: 10px;">
|
|
|
- <el-button type="primary" size="small" @click="addTouristInfo">新增游客</el-button>
|
|
|
- </div>
|
|
|
+ <el-dialog title="游客信息" width="900px" v-model="touristsDialogVisible" destroy-on-close
|
|
|
+ :before-close="currentOrderId = ''">
|
|
|
+ <!-- <div class="tourists-toolbar" style="margin-bottom: 10px;">
|
|
|
+ <el-button type="primary" size="small" @click="addTouristItem">新增游客</el-button>
|
|
|
+ </div> -->
|
|
|
|
|
|
<el-table :data="touristsList" border style="width: 100%" size="small">
|
|
|
<el-table-column type="index" label="序号" width="50" align="center" />
|
|
|
@@ -489,12 +567,12 @@
|
|
|
<el-tag v-else type="info">否</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="操作" width="120" align="center">
|
|
|
+ <!-- <el-table-column label="操作" width="120" align="center">
|
|
|
<template #default="scope">
|
|
|
<el-button type="primary" link size="small" @click="editTouristItem(scope.row)">编辑</el-button>
|
|
|
<el-button type="danger" link size="small" @click="delTouristItem(scope.$index)">删除</el-button>
|
|
|
</template>
|
|
|
- </el-table-column>
|
|
|
+ </el-table-column> -->
|
|
|
</el-table>
|
|
|
</el-dialog>
|
|
|
|
|
|
@@ -557,11 +635,11 @@
|
|
|
<el-input v-model="touristForm.email" />
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
- <el-col :span="24">
|
|
|
+ <!-- <el-col :span="24">
|
|
|
<el-form-item label="是否领队">
|
|
|
- <el-switch v-model="touristForm.isLeader" />
|
|
|
+ <el-switch v-model="touristForm.isLeader" disabled />
|
|
|
</el-form-item>
|
|
|
- </el-col>
|
|
|
+ </el-col> -->
|
|
|
<el-col :span="12">
|
|
|
<el-form-item label="紧急联系人" prop="emergencyContact">
|
|
|
<el-input v-model="touristForm.emergencyContact" />
|
|
|
@@ -669,7 +747,8 @@
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
|
|
|
- <el-dialog title="产品详情" width="1000px" v-model="productItemDialogVisible" append-to-body>
|
|
|
+ <el-dialog title="产品详情" width="1000px" v-model="productItemDialogVisible" append-to-body
|
|
|
+ @close="closeProductItemDialog">
|
|
|
<el-form :model="productForm" :rules="productRules" ref="productFormRef" label-width="120px">
|
|
|
<div style="margin: 10px 30px;">
|
|
|
<div style="margin-bottom:8px;">
|
|
|
@@ -692,7 +771,17 @@
|
|
|
</el-input>
|
|
|
<el-button size="small" @click="productFormParams.keyword = ''; searchProductList()">清空</el-button>
|
|
|
</div>
|
|
|
- <el-table :data="productList" border size="small" max-height="220px" stripe>
|
|
|
+ <div style="margin: 10px" v-if="tempSelectedProducts.length">
|
|
|
+ 已选择产品:
|
|
|
+ <el-tag v-for="(item, idx) in tempSelectedProducts" :key="`pt-${idx}`" closable
|
|
|
+ @close="removeProductSelection(item)">{{ item.productName }}</el-tag>
|
|
|
+ </div>
|
|
|
+ <el-table ref="productSelectTableRef" :row-key="(row) => row.id" :data="productList" border size="small"
|
|
|
+ max-height="300px" stripe @selection-change="handlePtSelectionChange" @select="handelPtSelect"
|
|
|
+ @select-all="handlePtSelectAll">
|
|
|
+ <el-table-column type="selection" width="55" />
|
|
|
+ <el-table-column type="index" width="50" />
|
|
|
+
|
|
|
<el-table-column prop="productName" label="产品名称" min-width="200" />
|
|
|
<el-table-column prop="productCode" label="产品编码" width="140" />
|
|
|
<el-table-column prop="type" label="类型" width="120">
|
|
|
@@ -702,55 +791,94 @@
|
|
|
<template #default="scope">¥{{ (Number(scope.row.price) || Number(scope.row.unitPrice) || 0).toFixed(2)
|
|
|
}}</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="操作" width="120" align="center">
|
|
|
+ <!-- <el-table-column label="操作" width="120" align="center">
|
|
|
<template #default="scope">
|
|
|
<el-button type="primary" size="mini" @click="itemSelectProduct(scope.row.id)">选择</el-button>
|
|
|
</template>
|
|
|
- </el-table-column>
|
|
|
+ </el-table-column> -->
|
|
|
</el-table>
|
|
|
<el-pagination class="pagination" style="margin: 10px;" background layout="total, prev, pager, next"
|
|
|
- :page-size="forms.rows" :total="total" @current-change="getProductList">
|
|
|
+ :page-size="forms.rows" :total="productTotal" @current-change="handelProductPageChange">
|
|
|
</el-pagination>
|
|
|
</div>
|
|
|
+ </el-form>
|
|
|
|
|
|
- <el-form-item label="选择产品" prop="productID">
|
|
|
- <span v-if="productForm.productID">{{ productForm.productName }}-{{ productForm.productCode }}</span>
|
|
|
- <span v-else style="color:#999;">请选择产品</span>
|
|
|
- </el-form-item>
|
|
|
+ <template #footer>
|
|
|
+ <span class="dialog-footer">
|
|
|
+ <el-button @click="productItemDialogVisible = false">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="submitProductItem">确 定</el-button>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
|
|
|
- <el-form-item label="使用日期" prop="useDate">
|
|
|
- <el-date-picker v-model="productForm.useDate" disabled type="date" placeholder="选择日期" />
|
|
|
- </el-form-item>
|
|
|
+ <el-dialog title="上传附件" v-model="attachDialogVisible" width="700px" append-to-body @close="currentOrderId = ''">
|
|
|
+ <div style="margin-bottom:12px;">
|
|
|
+ <el-button type="primary" size="small" @click="downloadTemplate">下载模板</el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-upload ref="orderUploadRef" action="/api/BaseUploader/Basic" :show-file-list="false" :data="uploadParams"
|
|
|
+ :headers="headers" accept=".xls,.xlsx" :limit="10" :on-success="uploadSuccess" :file-list="fileList"
|
|
|
+ :on-error="uploadError" :on-remove="removeFile" :before-upload="beforeUpload" @on-preview="downloadFile">
|
|
|
+ <el-button type="primary" size="small">上传<i class="el-icon-plus"></i></el-button>
|
|
|
+ </el-upload>
|
|
|
+
|
|
|
+ <div class="file-list" style="margin: 10px 0">
|
|
|
+ <el-row v-if="fileList && fileList.length" :gutter="10" style="align-items:center;">
|
|
|
+ <el-col v-for="file in fileList" :key="file.id || file.raw?.uid" :span="24"
|
|
|
+ style="display:flex;align-items:center;justify-content:space-between;margin-bottom:6px;">
|
|
|
+ <div style="flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;">
|
|
|
+ <a href="javascript:;" @click.prevent="downloadFile(file)" style="color:#409EFF;">
|
|
|
+ {{ file.name }}
|
|
|
+ </a>
|
|
|
+ <span style="color:#999;margin-left:8px;">{{ file.url ? '' : '(本地文件)' }}</span>
|
|
|
+ </div>
|
|
|
+ <div style="margin-left:12px;white-space:nowrap;">
|
|
|
+ <el-button type="text" size="small" @click="downloadFile(file)">下载</el-button>
|
|
|
+ <el-button type="danger" size="small" @click="removeFile(file)">删除</el-button>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <div v-else style="text-align:center;color:#999;padding:12px;">暂无附件</div>
|
|
|
+ </div>
|
|
|
|
|
|
- <el-form-item label="数量" prop="quantity">
|
|
|
- <el-input v-model.number="productForm.quantity" disabled style="width:100px" />
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog :title="`收款`" v-model="paymentDialogVisible" width="500px" append-to-body @close="cancelPayment">
|
|
|
+ <el-form :model="paymentForm" ref="paymentFormRef" label-width="100px">
|
|
|
+ <el-form-item label="收款方式" prop="method">
|
|
|
+ <el-radio-group v-model="paymentForm.method">
|
|
|
+ <el-radio-button label="Online">在线支付</el-radio-button>
|
|
|
+ <el-radio-button label="Balance">余额扣款</el-radio-button>
|
|
|
+ <el-radio-button label="Offline">线下支付</el-radio-button>
|
|
|
+ </el-radio-group>
|
|
|
</el-form-item>
|
|
|
|
|
|
- <!-- <el-col :span="12">
|
|
|
- <el-form-item label="单价" prop="price">
|
|
|
- <el-input-number v-model.number="productForm.price" :min="0" :precision="2" style="width:160px" />
|
|
|
- </el-form-item>
|
|
|
- </el-col> -->
|
|
|
+ <el-form-item label="收款金额" prop="amount">
|
|
|
+ <el-input-number v-model.number="paymentForm.amount" disabled :min="0" :precision="2" style="width:200px" />
|
|
|
+ </el-form-item>
|
|
|
|
|
|
- <el-form-item label="描述" prop="remark">
|
|
|
- <el-input type="textarea" v-model="productForm.remark" :rows="4" />
|
|
|
+ <el-form-item label="订单号" prop="orderNo">
|
|
|
+ <el-input v-model="paymentForm.orderNo" disabled placeholder="可选(线上/线下支付时填写)" />
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
|
|
|
<template #footer>
|
|
|
<span class="dialog-footer">
|
|
|
- <el-button @click="productItemDialogVisible = false">取 消</el-button>
|
|
|
- <el-button type="primary" @click="submitProductItem">确 定</el-button>
|
|
|
+ <el-button @click="paymentDialogVisible = false">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="submitPayment">确 定</el-button>
|
|
|
</span>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
- </el-card>
|
|
|
|
|
|
+ </el-card>
|
|
|
</template>
|
|
|
<script>
|
|
|
import request from '@/utils/request'
|
|
|
+import store from "@/store";
|
|
|
import {
|
|
|
getOrders,
|
|
|
+ getOrderNo,
|
|
|
delOrder,
|
|
|
createOrder,
|
|
|
updateOrder,
|
|
|
@@ -763,23 +891,35 @@ import {
|
|
|
updateTouristInfo,
|
|
|
deleteTouristInfo,
|
|
|
} from '@/api/order';
|
|
|
+import { getPayParams } from '@/api/pay';
|
|
|
+import { delFile, fetchFileList } from '@/api/basic';
|
|
|
import { getProducts } from '@/api/product';
|
|
|
import { getProductCategories } from '@/api/productCategory';
|
|
|
-import { cloneDeep } from 'lodash-es';
|
|
|
+import { before, cloneDeep, map, uniqBy } from 'lodash-es';
|
|
|
import { getTravelAgencies } from '@/api/travelAgency';
|
|
|
import moment from 'moment/moment';
|
|
|
-import { ProductTypes } from '@/constant';
|
|
|
+import { ProductTypes, FileTypeMap } from '@/constant';
|
|
|
import utils from '@/utils/util';
|
|
|
|
|
|
export default {
|
|
|
name: "OrderManage",
|
|
|
components: {},
|
|
|
data() {
|
|
|
+ const access_token = sessionStorage.getItem('access_token') || '';
|
|
|
+ const token_type = sessionStorage.getItem('token_type') || '';
|
|
|
+ console.log(this.$store.getters.getUserInfo, '----userInfo---');
|
|
|
return {
|
|
|
+ headers: {
|
|
|
+ Authorization: token_type + ' ' + access_token,
|
|
|
+ },
|
|
|
+ uploadParams: {},
|
|
|
ProductTypes,
|
|
|
productTypeArr: Object.keys(ProductTypes).map((key) => ({ label: ProductTypes[key], value: key })),
|
|
|
forms: {
|
|
|
keyword: "",
|
|
|
+ status: "",
|
|
|
+ auditStatus: "",
|
|
|
+ paymentStatus: "",
|
|
|
columns: [
|
|
|
{ label: "订单号", prop: "orderNo" },
|
|
|
{ label: "旅行社名称", prop: "agencyName" },
|
|
|
@@ -810,10 +950,11 @@ export default {
|
|
|
formData: {},
|
|
|
isAdd: true,
|
|
|
formLabelWidth: "120px",
|
|
|
- activeTab: ['basic', 'details', 'tourists'],
|
|
|
+ activeTab: ['basic', 'details', 'tourists', 'attachments'],
|
|
|
currUseDate: '',
|
|
|
useDateList: [],
|
|
|
currentOrderId: '',
|
|
|
+ currentOrderNo: '',
|
|
|
categoryOptions: [],
|
|
|
agencyOptions: [],
|
|
|
formRules: {
|
|
|
@@ -899,6 +1040,7 @@ export default {
|
|
|
},
|
|
|
productDialogVisible: false,
|
|
|
productItemDialogVisible: false,
|
|
|
+ tempSelectedProducts: [],
|
|
|
productForm: {},
|
|
|
productFormParams: {
|
|
|
keyword: "",
|
|
|
@@ -931,6 +1073,14 @@ export default {
|
|
|
{ max: 500, message: '长度不能超过500个字符', trigger: 'blur' }
|
|
|
]
|
|
|
},
|
|
|
+ attachDialogVisible: false,
|
|
|
+ fileList: [],
|
|
|
+ paymentDialogVisible: false,
|
|
|
+ paymentForm: {
|
|
|
+ amount: null,
|
|
|
+ method: 'Online',
|
|
|
+ orderNo: '',
|
|
|
+ },
|
|
|
};
|
|
|
},
|
|
|
methods: {
|
|
|
@@ -954,7 +1104,14 @@ export default {
|
|
|
this.productFormParams.page = 1;
|
|
|
this.getProductList();
|
|
|
},
|
|
|
- getProductList() {
|
|
|
+ async handelProductPageChange(page) {
|
|
|
+ this.productFormParams.page = page;
|
|
|
+ await this.getProductList();
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.updatePtCheckStatus();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ async getProductList() {
|
|
|
this.productFormParams.filters = [];
|
|
|
if (this.productType) {
|
|
|
this.productFormParams.filters = [
|
|
|
@@ -965,10 +1122,9 @@ export default {
|
|
|
}
|
|
|
]
|
|
|
}
|
|
|
- getProducts(this.productFormParams).then((res) => {
|
|
|
- this.productList = res.data?.data || [];
|
|
|
- this.productTotal = res.data?.records || 0;
|
|
|
- });
|
|
|
+ const res = await getProducts(this.productFormParams)
|
|
|
+ this.productList = res.data?.data || [];
|
|
|
+ this.productTotal = res.data?.records || 0;
|
|
|
},
|
|
|
getTravelAgencies() {
|
|
|
getTravelAgencies({
|
|
|
@@ -986,6 +1142,10 @@ export default {
|
|
|
this.agencyOptions = res.data?.data || [];
|
|
|
});
|
|
|
},
|
|
|
+ searchOrderList() {
|
|
|
+ this.forms.page = 1;
|
|
|
+ this.getOrderList();
|
|
|
+ },
|
|
|
sizeHandler(val) {
|
|
|
this.forms.rows = val;
|
|
|
this.getOrderList();
|
|
|
@@ -998,21 +1158,61 @@ export default {
|
|
|
this.isAdd = false;
|
|
|
this.searchProductList();
|
|
|
this.getTravelAgencies();
|
|
|
+ this.currentOrderId = row.id;
|
|
|
const res = await getOrderDetailById(row.id);
|
|
|
this.formData = cloneDeep(res.data);
|
|
|
this.formDialogVisible = true;
|
|
|
},
|
|
|
- add(row) {
|
|
|
+ async add(row) {
|
|
|
+ const res = await getOrderNo();
|
|
|
+ if (res?.code === 200) {
|
|
|
+ this.currentOrderNo = res.data;
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.data?.message);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.fileList = [];
|
|
|
this.isAdd = true;
|
|
|
this.searchProductList();
|
|
|
this.getTravelAgencies();
|
|
|
this.formDialogVisible = true;
|
|
|
- this.formData = {};
|
|
|
+ this.formData = {
|
|
|
+ agencyID: this.userAgencyId,
|
|
|
+ tourists: [],
|
|
|
+ details: [],
|
|
|
+ };
|
|
|
},
|
|
|
close() {
|
|
|
+ this.currentOrderId = '';
|
|
|
+ this.currentOrderNo = '';
|
|
|
this.$refs.formRef.resetFields();
|
|
|
},
|
|
|
getOrderList() {
|
|
|
+ this.forms.filters = [];
|
|
|
+ if (this.forms.status) {
|
|
|
+ this.forms.filters = [
|
|
|
+ {
|
|
|
+ name: 'status',
|
|
|
+ operate: 0,
|
|
|
+ value: this.forms.status
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ if (this.forms.auditStatus) {
|
|
|
+ this.forms.filters.push({
|
|
|
+ name: 'auditStatus',
|
|
|
+ operate: 0,
|
|
|
+ value: this.forms.auditStatus
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (this.forms.paymentStatus) {
|
|
|
+ this.forms.filters.push({
|
|
|
+ name: 'paymentStatus',
|
|
|
+ operate: 0,
|
|
|
+ value: this.forms.paymentStatus
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
getOrders(this.forms || {}).then((res) => {
|
|
|
this.tableData = res.data?.data || []
|
|
|
this.total = res.data?.records || 0
|
|
|
@@ -1025,12 +1225,16 @@ export default {
|
|
|
this.$message.error('请至少添加一个产品');
|
|
|
return;
|
|
|
}
|
|
|
- if (!this.formData.tourists?.length) {
|
|
|
- this.$message.error('请至少添加一个游客');
|
|
|
+ const hasLeader = this.formData.tourists?.some(item => item.isLeader);
|
|
|
+ if (!hasLeader) {
|
|
|
+ this.$message.error('请至少添加一个领队');
|
|
|
return;
|
|
|
}
|
|
|
this.formData.touristCount = this.formData.tourists.length;
|
|
|
const opt = this.isAdd ? createOrder : updateOrder;
|
|
|
+ if (this.currentOrderNo) {
|
|
|
+ this.formData.orderNo = this.currentOrderNo;
|
|
|
+ }
|
|
|
opt(this.formData).then((res) => {
|
|
|
if (res.code === 200) {
|
|
|
this.$message({
|
|
|
@@ -1050,7 +1254,20 @@ export default {
|
|
|
that.$refs.table.toggleRowExpansion(row);
|
|
|
});
|
|
|
},
|
|
|
-
|
|
|
+ async payment(row) {
|
|
|
+ const res = await getPayParams(row.id);
|
|
|
+ console.log('---pay params---', res);
|
|
|
+ this.paymentForm.orderNo = row.orderNo;
|
|
|
+ this.paymentForm.amount = row.totalAmount;
|
|
|
+ this.paymentDialogVisible = true;
|
|
|
+ },
|
|
|
+ cancelPayment() {
|
|
|
+ this.paymentForm = {
|
|
|
+ amount: null,
|
|
|
+ method: 'Online',
|
|
|
+ orderNo: '',
|
|
|
+ };
|
|
|
+ },
|
|
|
del(row) {
|
|
|
this.$confirm("此操作将删除选择数据, 是否继续?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning", })
|
|
|
.then(() => {
|
|
|
@@ -1104,6 +1321,9 @@ export default {
|
|
|
this.formData.details.splice(index, 1);
|
|
|
this.formData.totalAmount = (this.formData.details || []).reduce((s, p) => s + (Number(p.unitPrice) || 0) * (Number(p.quantity) || 0), 0)
|
|
|
},
|
|
|
+ removeProductSelection(item) {
|
|
|
+ this.$refs.productSelectTableRef?.toggleRowSelection(item, false);
|
|
|
+ },
|
|
|
itemSelectProduct(value, row) {
|
|
|
const product = this.productList.find(item => item.id === value);
|
|
|
if (!product) return;
|
|
|
@@ -1121,20 +1341,73 @@ export default {
|
|
|
this.productForm.productType = ProductTypes[product.type] || product.type;
|
|
|
}
|
|
|
},
|
|
|
+ closeProductItemDialog() {
|
|
|
+ this.$refs.productSelectTableRef?.clearSelection();
|
|
|
+ this.tempSelectedProducts = [];
|
|
|
+ },
|
|
|
+ handlePtSelectionChange(rows) {
|
|
|
+ },
|
|
|
+ setPtSelection() { },
|
|
|
+ handelPtSelect(selectedRows, row) {
|
|
|
+ this.productList.forEach((product) => {
|
|
|
+ if (selectedRows.find((sr) => sr.id === product.id)) {
|
|
|
+ this.tempSelectedProducts.push(({ id: product.id, productName: product.productName }))
|
|
|
+ } else {
|
|
|
+ this.tempSelectedProducts = this.tempSelectedProducts.filter((item) => item.id !== product.id);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ this.tempSelectedProducts = uniqBy(this.tempSelectedProducts, 'id');
|
|
|
+ },
|
|
|
+ handlePtSelectAll(selectedRows) {
|
|
|
+ this.productList.forEach((product) => {
|
|
|
+ if (selectedRows.find((sr) => sr.id === product.id)) {
|
|
|
+ this.tempSelectedProducts.push(({ id: product.id, productName: product.productName }))
|
|
|
+ } else {
|
|
|
+ this.tempSelectedProducts = this.tempSelectedProducts.filter((item) => item.id !== product.id);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ this.tempSelectedProducts = uniqBy(this.tempSelectedProducts, 'id');
|
|
|
+ },
|
|
|
+ updatePtCheckStatus() {
|
|
|
+ debugger;
|
|
|
+ this.$refs.productSelectTableRef?.clearSelection();
|
|
|
+ this.productList.forEach((product) => {
|
|
|
+ this.$refs.productSelectTableRef?.toggleRowSelection(product, !!this.tempSelectedProducts.find((item) => item.id === product.id));
|
|
|
+ });
|
|
|
+ },
|
|
|
submitProductItem() {
|
|
|
- this.$refs.productFormRef.validate(valid => {
|
|
|
- if (valid) {
|
|
|
- this.productItemDialogVisible = false;
|
|
|
- this.formData.totalAmount = (this.formData.details || []).reduce((s, p) => s + (Number(p.unitPrice) || 0) * (Number(p.quantity) || 0), 0)
|
|
|
- if (!this.formData.details.find((d) => d.uid === this.productForm.uid)) {
|
|
|
- this.formData.details.push(this.productForm)
|
|
|
- }
|
|
|
- this.productForm = {};
|
|
|
+ if (!this.tempSelectedProducts.length) {
|
|
|
+ this.$message.error('请选择产品');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.tempSelectedProducts.forEach((item) => {
|
|
|
+ if (!this.formData.details.find((d) => d.productID === item.id)) {
|
|
|
+ this.formData.details.push({
|
|
|
+ productID: item.id,
|
|
|
+ productName: item.productName,
|
|
|
+ productCode: item.productCode,
|
|
|
+ productType: ProductTypes[item.type] || item.type,
|
|
|
+ unitPrice: item.price,
|
|
|
+ useDate: this.currUseDate,
|
|
|
+ quantity: 1,
|
|
|
+ remark: ''
|
|
|
+ });
|
|
|
}
|
|
|
});
|
|
|
+
|
|
|
+ this.productItemDialogVisible = false;
|
|
|
+ this.formData.totalAmount = (this.formData.details || []).reduce((s, p) => s + (Number(p.unitPrice) || 0) * (Number(p.quantity) || 0), 0)
|
|
|
},
|
|
|
- addTouristInfo() {
|
|
|
+ addTouristItem(isLeader = false) {
|
|
|
this.formData.tourists = this.formData.tourists || []
|
|
|
+ if (isLeader) {
|
|
|
+ const hasLeader = this.formData.tourists.find(t => t.isLeader);
|
|
|
+ if (hasLeader) {
|
|
|
+ this.$message.error('已存在领队游客,不能重复添加');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
this.touristForm = {
|
|
|
uid: `tourist-item-${utils.getUUID(8, 16)}`,
|
|
|
touristName: '',
|
|
|
@@ -1143,7 +1416,7 @@ export default {
|
|
|
idNumber: '',
|
|
|
phone: '',
|
|
|
passengerType: 'Adult',
|
|
|
- isLeader: !this.formData.tourists.length,
|
|
|
+ isLeader: !!isLeader,
|
|
|
emergencyContact: '',
|
|
|
emergencyPhone: '',
|
|
|
specialRequirements: '',
|
|
|
@@ -1301,7 +1574,74 @@ export default {
|
|
|
'Student': '学生'
|
|
|
};
|
|
|
return types[type] || type;
|
|
|
- }
|
|
|
+ },
|
|
|
+ async attachment(row) {
|
|
|
+ this.currentOrderNo = row.orderNo;
|
|
|
+ const res = await fetchFileList('', this.currentOrderNo)
|
|
|
+
|
|
|
+ this.fileList = (res?.data || []).map(file => ({
|
|
|
+ id: file.id,
|
|
|
+ name: file.name,
|
|
|
+ url: file.url,
|
|
|
+ status: 'success',
|
|
|
+ raw: {
|
|
|
+ uid: `upload-file-${file.id}`,
|
|
|
+ }
|
|
|
+ }));
|
|
|
+ this.attachDialogVisible = true;
|
|
|
+ },
|
|
|
+ downloadTemplate() {
|
|
|
+ const link = document.createElement('a');
|
|
|
+ link.href = '/证件号导入模板.xlsx';
|
|
|
+ link.download = '证件号导入模板.xlsx';
|
|
|
+ document.body.appendChild(link);
|
|
|
+ link.click();
|
|
|
+ document.body.removeChild(link);
|
|
|
+ },
|
|
|
+ uploadSuccess(res, file, fileList) {
|
|
|
+ console.log(res, file, fileList, 'uploadSuccess');
|
|
|
+ if (res.code === 200) {
|
|
|
+ const fileInfo = res.data[0];
|
|
|
+ file.id = fileInfo.id;
|
|
|
+ file.url = fileInfo.path;
|
|
|
+ this.$message.success(file.name + ' 上传成功');
|
|
|
+ } else {
|
|
|
+ this.$message.error(file.name + ' 上传失败: ' + res.content);
|
|
|
+ this.fileList = this.fileList.filter(f => f.raw.uid !== file.raw.uid);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ uploadError(err, file) {
|
|
|
+ console.log(err, file);
|
|
|
+ this.$message.error(file.name + ' 上传失败');
|
|
|
+ this.fileList = this.fileList.filter(f => f.raw.uid !== file.raw.uid);
|
|
|
+ },
|
|
|
+ beforeUpload(file) {
|
|
|
+ this.uploadParams = {
|
|
|
+ fileCode: this.currentOrderNo,
|
|
|
+ // fileCode: utils.getUUID(8, 16),
|
|
|
+ fileType: FileTypeMap[file.type] || 'Other',
|
|
|
+ // folderID: 'OrderAttachments',
|
|
|
+ dataType: 'OrderTourist'
|
|
|
+ };
|
|
|
+ const isLt10M = file.size / 1024 / 1024 < 10;
|
|
|
+ if (!isLt10M) { $message.error('单个文件不能超过 10MB'); }
|
|
|
+ return isLt10M;
|
|
|
+ },
|
|
|
+ downloadFile(file) {
|
|
|
+ console.log(file, 'downloadFile');
|
|
|
+ window.open(file.url);
|
|
|
+ },
|
|
|
+ removeFile(file, fileList) {
|
|
|
+ this.$confirm('确认删除该附件?')
|
|
|
+ .then(() => {
|
|
|
+ if (file.id) {
|
|
|
+ delFile(file.id).then(() => {
|
|
|
+ this.$message.success('删除成功');
|
|
|
+ });
|
|
|
+ }
|
|
|
+ this.fileList = this.fileList.filter(f => f.raw.uid !== file.raw.uid);
|
|
|
+ });
|
|
|
+ },
|
|
|
},
|
|
|
computed: {
|
|
|
travelInfo() {
|
|
|
@@ -1309,6 +1649,15 @@ export default {
|
|
|
travelStartDate: this.formData.travelStartDate,
|
|
|
travelDays: this.formData.travelDays,
|
|
|
};
|
|
|
+ },
|
|
|
+ userInfo() {
|
|
|
+ return store.getters.getUserInfo;
|
|
|
+ },
|
|
|
+ userAccountId() {
|
|
|
+ return store.getters.getUserInfo?.account || '';
|
|
|
+ },
|
|
|
+ userAgencyId() {
|
|
|
+ return store.getters.getUserInfo?.agencys[0] || '';
|
|
|
}
|
|
|
},
|
|
|
watch: {
|
|
|
@@ -1343,4 +1692,12 @@ export default {
|
|
|
this.getTravelAgencies();
|
|
|
},
|
|
|
};
|
|
|
-</script>
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="less" scoped>
|
|
|
+.search-form {
|
|
|
+ .el-form-item {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|