|
|
@@ -0,0 +1,454 @@
|
|
|
+<!--
|
|
|
+ 自由冲销确认页(方案A)
|
|
|
+ 用途:selectCustom?forward=1 选客后进入;按客户选花材/金额提交 create(customId),不是负销售开单。
|
|
|
+-->
|
|
|
+<template>
|
|
|
+ <view class="forward-confirm">
|
|
|
+ <view class="card">
|
|
|
+ <view class="card__title">客户:{{ customName || '' }}</view>
|
|
|
+ <view class="search-row">
|
|
|
+ <input
|
|
|
+ class="search-input"
|
|
|
+ type="text"
|
|
|
+ v-model="py"
|
|
|
+ placeholder="拼音首字母搜索花材"
|
|
|
+ placeholder-style="color:#999"
|
|
|
+ @confirm="searchProduct"
|
|
|
+ />
|
|
|
+ <button class="admin-button-com middle blue search-btn" @click="searchProduct">搜索</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 搜索结果 -->
|
|
|
+ <view class="card" v-if="!$util.isEmpty(searchList)">
|
|
|
+ <view class="card__title">搜索结果</view>
|
|
|
+ <view class="search-item" v-for="(p, idx) in searchList" :key="idx" @click="addProduct(p)">
|
|
|
+ <text class="search-item__name">{{ p.name }}</text>
|
|
|
+ <text class="search-item__price">¥{{ parseFloat(p.price || p.bigPrice || 0) }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 已选冲销明细 -->
|
|
|
+ <view class="card">
|
|
|
+ <view class="card__title">冲销花材</view>
|
|
|
+ <view v-if="$util.isEmpty(items)" class="empty-tip">请搜索并添加花材</view>
|
|
|
+ <view class="item-row" v-for="(it, idx) in items" :key="idx">
|
|
|
+ <view class="item-row__head">
|
|
|
+ <text class="item-row__name">{{ it.name }}</text>
|
|
|
+ <text class="item-row__del" @click="removeItem(idx)">删除</text>
|
|
|
+ </view>
|
|
|
+ <view class="item-row__fields">
|
|
|
+ <view class="field">
|
|
|
+ <text class="field__label">数量</text>
|
|
|
+ <input class="field__input" type="digit" v-model="it.num" @input="recalcAmount(it)" />
|
|
|
+ </view>
|
|
|
+ <view class="field field--ml">
|
|
|
+ <text class="field__label">单价</text>
|
|
|
+ <input class="field__input" type="digit" v-model="it.unitPrice" @input="recalcAmount(it)" />
|
|
|
+ </view>
|
|
|
+ <view class="field field--ml">
|
|
|
+ <text class="field__label">金额</text>
|
|
|
+ <input class="field__input" type="digit" v-model="it.amount" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="total-row">
|
|
|
+ <text>合计</text>
|
|
|
+ <text class="total-row__price">¥{{ totalAmount }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 自由冲销:仅返余额 / 仅记账 -->
|
|
|
+ <view class="card">
|
|
|
+ <view class="opt-row">
|
|
|
+ <text class="opt-label">资金处理</text>
|
|
|
+ <view class="opt-btns">
|
|
|
+ <button
|
|
|
+ class="admin-button-com middle"
|
|
|
+ :class="fundType === 2 ? 'blue' : 'default'"
|
|
|
+ @click="fundType = 2"
|
|
|
+ >返余额</button>
|
|
|
+ <button
|
|
|
+ class="admin-button-com middle opt-btns__ml"
|
|
|
+ :class="fundType === 3 ? 'blue' : 'default'"
|
|
|
+ @click="fundType = 3"
|
|
|
+ >仅记账</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="opt-row">
|
|
|
+ <text class="opt-label">库存</text>
|
|
|
+ <view class="opt-btns">
|
|
|
+ <button
|
|
|
+ class="admin-button-com middle"
|
|
|
+ :class="forwardStock === 0 ? 'blue' : 'default'"
|
|
|
+ @click="forwardStock = 0"
|
|
|
+ >回库存</button>
|
|
|
+ <button
|
|
|
+ class="admin-button-com middle opt-btns__ml"
|
|
|
+ :class="forwardStock === 1 ? 'blue' : 'default'"
|
|
|
+ @click="forwardStock = 1"
|
|
|
+ >不回库存</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="opt-row">
|
|
|
+ <text class="opt-label">备注</text>
|
|
|
+ <input class="remark-input" type="text" v-model="remark" placeholder="选填" placeholder-style="color:#999" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="bottom-bar">
|
|
|
+ <button class="admin-button-com big default bottom-bar__btn" @click="goBack">取消</button>
|
|
|
+ <button class="admin-button-com big blue bottom-bar__btn bottom-bar__btn--ml" @click="submit">确认冲销</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { productList } from '@/api/product'
|
|
|
+import { createForward } from '@/api/forward'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'forwardConfirm',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ customId: 0,
|
|
|
+ customName: '',
|
|
|
+ py: '',
|
|
|
+ searchList: [],
|
|
|
+ items: [],
|
|
|
+ fundType: 2,
|
|
|
+ forwardStock: 1,
|
|
|
+ remark: '',
|
|
|
+ submitting: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ totalAmount() {
|
|
|
+ let sum = 0
|
|
|
+ this.items.forEach(it => {
|
|
|
+ sum += Number(it.amount) || 0
|
|
|
+ })
|
|
|
+ return parseFloat(sum.toFixed(2))
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLoad(option) {
|
|
|
+ this.customId = Number(option.customId || 0)
|
|
|
+ this.customName = option.customName || ''
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ goBack() {
|
|
|
+ uni.navigateBack()
|
|
|
+ },
|
|
|
+ /** 按拼音搜可冲销花材 */
|
|
|
+ searchProduct() {
|
|
|
+ if (!this.py) {
|
|
|
+ this.$msg('请输入拼音')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uni.showLoading({ mask: true })
|
|
|
+ productList({ py: this.py, page: 1, pageSize: 30 }).then(res => {
|
|
|
+ uni.hideLoading()
|
|
|
+ if (res.code == 1) {
|
|
|
+ const list = res.data.list || res.data.data || res.data || []
|
|
|
+ this.searchList = Array.isArray(list) ? list : []
|
|
|
+ if (this.$util.isEmpty(this.searchList)) {
|
|
|
+ this.$msg('未找到花材')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ uni.hideLoading()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /** 加入已选明细,默认数量 1 */
|
|
|
+ addProduct(p) {
|
|
|
+ const productId = p.id || p.productId
|
|
|
+ if (!productId) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const exist = this.items.find(it => Number(it.productId) === Number(productId))
|
|
|
+ if (exist) {
|
|
|
+ this.$msg('已添加该花材')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const unitPrice = parseFloat(p.price || p.bigPrice || 0)
|
|
|
+ this.items.push({
|
|
|
+ productId,
|
|
|
+ name: p.name || '',
|
|
|
+ num: 1,
|
|
|
+ bigNum: 1,
|
|
|
+ smallNum: 0,
|
|
|
+ unitPrice,
|
|
|
+ price: unitPrice,
|
|
|
+ amount: unitPrice
|
|
|
+ })
|
|
|
+ this.$msg('已添加')
|
|
|
+ },
|
|
|
+ removeItem(idx) {
|
|
|
+ this.items.splice(idx, 1)
|
|
|
+ },
|
|
|
+ recalcAmount(it) {
|
|
|
+ const num = Number(it.num) || 0
|
|
|
+ const price = Number(it.unitPrice) || 0
|
|
|
+ it.amount = parseFloat((num * price).toFixed(2))
|
|
|
+ it.price = price
|
|
|
+ it.bigNum = num
|
|
|
+ it.smallNum = 0
|
|
|
+ },
|
|
|
+ submit() {
|
|
|
+ if (!this.customId) {
|
|
|
+ this.$msg('缺少客户')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.$util.isEmpty(this.items)) {
|
|
|
+ this.$msg('请选择冲销花材')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.totalAmount <= 0) {
|
|
|
+ this.$msg('冲销金额必须大于0')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.forwardStock !== 0 && this.forwardStock !== 1) {
|
|
|
+ this.$msg('请选择是否回库存')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.submitting) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const payloadItems = this.items.map(it => ({
|
|
|
+ productId: it.productId,
|
|
|
+ name: it.name,
|
|
|
+ num: Number(it.num) || 0,
|
|
|
+ bigNum: Number(it.bigNum) || Number(it.num) || 0,
|
|
|
+ smallNum: Number(it.smallNum) || 0,
|
|
|
+ unitPrice: Number(it.unitPrice) || 0,
|
|
|
+ price: Number(it.price || it.unitPrice) || 0,
|
|
|
+ amount: Number(it.amount) || 0
|
|
|
+ }))
|
|
|
+ this.$util.confirmModal({ content: '确认提交冲销凭证?' }, () => {
|
|
|
+ this.submitting = true
|
|
|
+ uni.showLoading({ title: '提交中', mask: true })
|
|
|
+ createForward({
|
|
|
+ customId: this.customId,
|
|
|
+ fundType: this.fundType,
|
|
|
+ forwardStock: this.forwardStock,
|
|
|
+ amount: this.totalAmount,
|
|
|
+ remark: this.remark || '',
|
|
|
+ items: payloadItems
|
|
|
+ }).then(res => {
|
|
|
+ uni.hideLoading()
|
|
|
+ this.submitting = false
|
|
|
+ if (res.code == 1) {
|
|
|
+ const data = res.data || {}
|
|
|
+ this.$util.pageTo({
|
|
|
+ url: '/admin/billing/forwardResult',
|
|
|
+ type: 2,
|
|
|
+ query: {
|
|
|
+ fundType: data.fundType || this.fundType,
|
|
|
+ amount: data.amount || this.totalAmount,
|
|
|
+ customId: data.customId || this.customId,
|
|
|
+ customName: this.customName,
|
|
|
+ forwardSn: data.forwardSn || '',
|
|
|
+ forwardId: data.forwardId || 0
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ uni.hideLoading()
|
|
|
+ this.submitting = false
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.forward-confirm {
|
|
|
+ min-height: 100vh;
|
|
|
+ padding: 20upx 20upx 180upx;
|
|
|
+ background: #f5f7fa;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.card {
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 12upx;
|
|
|
+ padding: 24upx;
|
|
|
+ margin-bottom: 20upx;
|
|
|
+
|
|
|
+ &__title {
|
|
|
+ font-size: 30upx;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+ margin-bottom: 16upx;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.search-row {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.search-input {
|
|
|
+ flex: 1;
|
|
|
+ height: 68upx;
|
|
|
+ padding: 0 20upx;
|
|
|
+ background: #f5f7fa;
|
|
|
+ border-radius: 8upx;
|
|
|
+ font-size: 28upx;
|
|
|
+}
|
|
|
+
|
|
|
+.search-btn {
|
|
|
+ margin-left: 16upx;
|
|
|
+ min-width: 120upx;
|
|
|
+}
|
|
|
+
|
|
|
+.search-item {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 18upx 0;
|
|
|
+ border-bottom: 1upx solid #f0f2f5;
|
|
|
+
|
|
|
+ &__name {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 28upx;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__price {
|
|
|
+ font-size: 28upx;
|
|
|
+ color: #ff4757;
|
|
|
+ margin-left: 16upx;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.empty-tip {
|
|
|
+ font-size: 26upx;
|
|
|
+ color: #999;
|
|
|
+ padding: 20upx 0;
|
|
|
+}
|
|
|
+
|
|
|
+.item-row {
|
|
|
+ padding: 16upx 0;
|
|
|
+ border-bottom: 1upx solid #f0f2f5;
|
|
|
+
|
|
|
+ &__head {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__name {
|
|
|
+ font-size: 28upx;
|
|
|
+ color: #333;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__del {
|
|
|
+ font-size: 26upx;
|
|
|
+ color: #ff4757;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__fields {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ margin-top: 12upx;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.field {
|
|
|
+ flex: 1;
|
|
|
+
|
|
|
+ &--ml {
|
|
|
+ margin-left: 12upx;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__label {
|
|
|
+ display: block;
|
|
|
+ font-size: 22upx;
|
|
|
+ color: #999;
|
|
|
+ margin-bottom: 6upx;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__input {
|
|
|
+ height: 60upx;
|
|
|
+ padding: 0 12upx;
|
|
|
+ background: #f5f7fa;
|
|
|
+ border-radius: 8upx;
|
|
|
+ font-size: 26upx;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.total-row {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding-top: 20upx;
|
|
|
+ font-size: 28upx;
|
|
|
+ color: #333;
|
|
|
+
|
|
|
+ &__price {
|
|
|
+ color: #ff4757;
|
|
|
+ font-weight: bold;
|
|
|
+ font-size: 34upx;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.opt-row {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: center;
|
|
|
+ padding: 16upx 0;
|
|
|
+}
|
|
|
+
|
|
|
+.opt-label {
|
|
|
+ width: 140upx;
|
|
|
+ flex-shrink: 0;
|
|
|
+ font-size: 28upx;
|
|
|
+ color: #909399;
|
|
|
+}
|
|
|
+
|
|
|
+.opt-btns {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+
|
|
|
+ &__ml {
|
|
|
+ margin-left: 16upx;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.remark-input {
|
|
|
+ flex: 1;
|
|
|
+ height: 64upx;
|
|
|
+ padding: 0 16upx;
|
|
|
+ background: #f5f7fa;
|
|
|
+ border-radius: 8upx;
|
|
|
+ font-size: 28upx;
|
|
|
+}
|
|
|
+
|
|
|
+.bottom-bar {
|
|
|
+ position: fixed;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ padding: 20upx 24upx;
|
|
|
+ background: #fff;
|
|
|
+ box-shadow: 0 -4upx 16upx rgba(0, 0, 0, 0.06);
|
|
|
+
|
|
|
+ &__btn {
|
|
|
+ flex: 1;
|
|
|
+
|
|
|
+ &--ml {
|
|
|
+ margin-left: 20upx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|