低代码可视化-uniapp进销存销售表单-代码生成器
将低代码理念与Uni-App框架结合,应用到进销存销售表单的开发中,可以显著提升开发效率和代码质量。以下是对低代码可视化-UniApp进销存销售表单-代码生成器的详细分析:
客户信息
选择客户信息,选择客户信息后显示在表单开头信息。
开单人、开单日期输入组件
开单人为文本输入组件、开单日期为日期选择组件。一进来初始化数据。我们在API获取产品数据加载前执行,判断是否是修改,如果不是修改,初始化开单人为登录用户显示名、开单日期为当前日期。
如果为用户编辑信息,在加载完成后进行数据处理,把数据库返回的字符串json转为JSON结构类型的数据,构建客户信息表显示在界面上。
这个API生成的代码如下。
// 订单数据 API请求方法
async dataApi(param) {
let thiz = this;
param = param || {};
//请求地址及请求数据,可以在加载前执行上面增加自己的代码逻辑
let http_url = '/sell/orders/get';
let http_data = {
pageNum: this.dataNum,
pageSize: 10,
id: param.id || this.globalOption.id || '15'
};
let http_header = {};
//这个判断意思是表示新增而不是编辑,不用请求API
if (!this.globalOption.id) {
this.$nextTick(() => {
this.form.kaidan = this.userInfo.nickname;
this.form.kaidanDate = this.$tools.getCurrentDate();
});
return;
}
let data = await this.$http.post(http_url, http_data, http_header, 'json');
this.data = data;
//把数据库返回来的数据转为JSON
data.data.costs = JSON.parse(data.data.costs);
data.data.products = JSON.parse(data.data.products);
//重新构造客户表单显示数据
let customer = {
title: data.data.customerTitle,
address: data.data.customerAddress,
phone: data.data.customerPhone,
username: data.data.customerUsername
};
data.data.kaidanDate = this.$tools.formatDateTime(data.data.kaidanDate, 'YYYY-mm-dd');
let productsItemDatas = [];
data.data.products.forEach((item) => {
productsItemDatas.push(JSON.parse(JSON.stringify(this.productsItemData)));
});
this.formData.productsItemDatas = productsItemDatas;
let costsItemDatas = [];
data.data.costs.forEach((item) => {
costsItemDatas.push(JSON.parse(JSON.stringify(this.costsItemData)));
});
this.formData.costsItemDatas = costsItemDatas;
this.userInfo.customer = customer;
this.form = data.data;
},
商品清单
商品清单信息来源于库存商品,快速选择商品信息。采用点击商品清单弹出选择框。弹窗组件里使用选项卡来显示产品分类、使用flex布局来显示产品信息。
产品数量不为0时增加进选择产品信息里 自定义一个方法来加入数量不为0的产品。
自动计算商品总价
自定义一个方法来显示商品总价,页面模板调用此方法显示总价。
其他费用
其他费用循环子表单输入,可以随意收入费用项、费用金额。同样增加一个自定义方法来显示其他费用总价
这个页面设计器主要使用了表单组件、循环子表单、弹窗组件、选项卡组件、flex组件、文本输入、日期输入等组件来实现。
整个页面代码生成器
结合自定义API及方法的实现,整个页面代码直接生成出来。
<template>
<view class="container container333211">
<u-form :model="form" :rules="formRules" :errorType="['message', 'toast']" ref="formRef" class="flex diygw-form diygw-col-24">
<view class="flex flex-wrap diygw-col-24 flex-direction-column flex-clz">
<view class="flex flex-wrap diygw-col-0 justify-between items-center flex28-clz" @tap="navigateTo" data-type="page" data-url="/pages/customer" data-isselect="1">
<text v-if="!userInfo.customer" class="diygw-col-0 text5-clz"> 请选择客户 </text>
<view v-if="userInfo.customer" class="flex flex-wrap diygw-col-0 flex-direction-column justify-between items-center flex6-clz">
<view class="flex flex-wrap diygw-col-24 items-end">
<text class="diygw-col-0 title-clz">
{{ userInfo.customer.title }}
</text>
</view>
<view class="flex flex-wrap diygw-col-24 items-end flex22-clz">
<text class="diygw-text-line1 diygw-col-0 address-clz">
{{ userInfo.customer.username }}
</text>
<text class="diygw-col-0 text22-clz">
{{ userInfo.customer.phone }}
</text>
</view>
<text class="diygw-text-line1 diygw-col-24 text20-clz">
{{ userInfo.customer.address }}
</text>
</view>
<text class="flex icon4 diygw-col-0 icon4-clz diy-icon-right"></text>
</view>
<u-form-item labelAlign="justify" class="diygw-col-24" :required="true" label="开单人" prop="kaidan">
<u-input inputAlign="right" :focus="formData.kaidanFocus" placeholder="请输入开单人" v-model="form.kaidan"></u-input>
</u-form-item>
<u-form-item labelAlign="justify" class="diygw-col-24" label="开单日期" :required="true" prop="kaidanDate">
<u-input inputAlign="right" @click="formData.showKaidanDate = true" class="" placeholder="请选择" v-model="form.kaidanDate" type="select"></u-input>
<u-calendar maxDate="2050-12-31" v-model="formData.showKaidanDate" mode="date" @change="changeFormKaidanDate"></u-calendar>
</u-form-item>
</view>
<view class="flex flex-wrap diygw-col-24 flex-direction-column flex1-clz">
<view class="flex flex-wrap diygw-col-24 justify-between items-center flex24-clz">
<text class="diygw-col-0 text-clz"> 商品清单 </text>
<view class="flex flex-wrap diygw-col-0 items-center green flex44-clz" @tap="navigateTo" data-type="initProductNumberFunction" data-show-modal="1">
<text class="flex icon1 diygw-col-0 diy-icon-add"></text>
<text class="diygw-col-0"> 商品清单 </text>
</view>
</view>
<view class="flex flex-wrap diygw-col-24 flex2-clz">
<text class="diygw-col-0 text11-clz"> # </text>
<text class="diygw-col-0 text4-clz"> 名称 </text>
<text class="diygw-col-0 text3-clz"> 单位 </text>
<text class="diygw-col-0 text2-clz"> 数量 </text>
<text class="diygw-col-0 text1-clz"> 单价 </text>
<text class="diygw-col-0 text7-clz"> 合计 </text>
</view>
<view class="flex flex-wrap diygw-col-24">
<view class="diygw-col-24" v-for="(productsItem, productsIndex) in form.products" :key="productsIndex">
<u-form class="diygw-col-24" :model="form.products[productsIndex]" :errorType="['message', 'toast']" ref="productsRef" :rules="productsItemRules">
<view class="flex flex-wrap diygw-col-24 items-stretch">
<view class="flex flex-wrap diygw-col-0 flex-direction-column justify-center items-center flex4-clz">
<text @tap="delProductsItem" :data-index="productsIndex" class="flex icon diygw-col-0 diy-icon-roundclose"></text>
</view>
<view class="flex flex-wrap diygw-col-0 flex-direction-column justify-center items-center flex5-clz">
<u-form-item :borderBottom="false" class="diygw-col-24 diygw-form-item-small" labelPosition="top" prop="title">
<u-input :focus="formData.productsItemDatas[productsIndex].titleFocus" :disabled="productsItemData.titleDisabled" placeholder="" v-model="productsItem.title"></u-input>
</u-form-item>
</view>
<view class="flex flex-wrap diygw-col-0 flex-direction-column justify-center items-center flex11-clz">
<u-form-item :borderBottom="false" class="diygw-col-24 diygw-form-item-small" labelPosition="top" prop="unit">
<u-input :focus="formData.productsItemDatas[productsIndex].unitFocus" :disabled="productsItemData.unitDisabled" placeholder="" v-model="productsItem.unit"></u-input>
</u-form-item>
</view>
<view class="flex flex-wrap diygw-col-0 flex-direction-column justify-center items-center flex10-clz">
<u-form-item :borderBottom="false" class="diygw-col-24 diygw-form-item-small" labelPosition="top" prop="number">
<u-input inputAlign="right" :focus="formData.productsItemDatas[productsIndex].numberFocus" :disabled="productsItemData.numberDisabled" placeholder="" v-model="productsItem.number" type="digit"></u-input>
</u-form-item>
</view>
<view class="flex flex-wrap diygw-col-0 flex-direction-column justify-center items-center flex9-clz">
<u-form-item :borderBottom="false" class="diygw-col-24 diygw-form-item-small" labelPosition="top" prop="price">
<u-input inputAlign="right" :focus="formData.productsItemDatas[productsIndex].priceFocus" :disabled="productsItemData.priceDisabled" placeholder="" v-model="productsItem.price" type="digit"></u-input>
</u-form-item>
</view>
<view class="flex flex-wrap diygw-col-0 flex-direction-column justify-center flex7-clz">
<text class="diygw-col-0">
{{ calcTotal(productsItem) }}
</text>
</view>
</view>
</u-form>
</view>
</view>
<view class="flex flex-wrap diygw-col-24 justify-end items-center flex12-clz">
<text class="diygw-col-0 text9-clz"> 产品合计 </text>
<view class="flex flex-wrap diygw-col-0 flex-direction-column">
<text class="diygw-col-0 text14-clz">
{{ productsTotalFunction() }}
</text>
</view>
</view>
</view>
<view class="flex flex-wrap diygw-col-24 flex-direction-column flex14-clz">
<view class="flex flex-wrap diygw-col-24 justify-between items-center flex45-clz">
<text class="diygw-col-0 text35-clz"> 其他费用 </text>
<view class="flex flex-wrap diygw-col-0 items-center green flex46-clz" @tap="addCostsItem">
<text class="flex icon3 diygw-col-0 diy-icon-add"></text>
</view>
</view>
<view class="flex flex-wrap diygw-col-24 flex15-clz">
<text class="diygw-col-0 text8-clz"> # </text>
<text class="diygw-col-0 text10-clz"> 费用项 </text>
<text class="diygw-col-0 text12-clz"> 费用金额 </text>
</view>
<view class="flex flex-wrap diygw-col-24">
<view class="diygw-col-24" v-for="(costsItem, costsIndex) in form.costs" :key="costsIndex">
<u-form class="diygw-col-24" :model="form.costs[costsIndex]" :errorType="['message', 'toast']" ref="costsRef" :rules="costsItemRules">
<view class="flex flex-wrap diygw-col-24 items-stretch">
<view class="flex flex-wrap diygw-col-0 flex-direction-column justify-center items-center flex17-clz">
<text @tap="delCostsItem" :data-index="costsIndex" class="flex icon2 diygw-col-0 diy-icon-roundclose"></text>
</view>
<view class="flex flex-wrap diygw-col-0 flex-direction-column justify-center flex18-clz">
<u-form-item :borderBottom="false" class="diygw-col-24 diygw-form-item-small" labelPosition="top" prop="title">
<u-input :focus="formData.costsItemDatas[costsIndex].titleFocus" placeholder="" v-model="costsItem.title"></u-input>
</u-form-item>
</view>
<view class="flex flex-wrap diygw-col-0 flex-direction-column justify-center flex19-clz">
<u-form-item :borderBottom="false" class="diygw-col-24 diygw-form-item-small" labelPosition="top" prop="price">
<u-input inputAlign="right" :focus="formData.costsItemDatas[costsIndex].priceFocus" placeholder="" v-model="costsItem.price"></u-input>
</u-form-item>
</view>
</view>
</u-form>
</view>
</view>
<view class="flex flex-wrap diygw-col-24 justify-end items-center flex23-clz">
<text class="diygw-col-0 text15-clz"> 其他费用合计 </text>
<text class="diygw-col-0 text18-clz">
{{ costsTotalFunction() }}
</text>
</view>
</view>
<view class="flex flex-wrap diygw-col-24 flex-direction-column flex20-clz">
<u-form-item class="diygw-col-24" label="整单优惠" prop="youhui">
<u-input inputAlign="right" :focus="formData.youhuiFocus" placeholder="填定整单优惠金额" v-model="form.youhui" type="number"></u-input>
</u-form-item>
<view class="flex flex-wrap diygw-col-24 justify-end items-center flex21-clz">
<text class="diygw-col-0 text16-clz"> 费用合计 </text>
<text class="diygw-col-0 text19-clz">
{{ totalFunction() }}
</text>
</view>
</view>
<view class="flex flex-wrap diygw-col-24 flex-direction-column flex26-clz">
<u-form-item labelWidth="auto" class="diygw-col-24" label="订单备注" labelPosition="top" prop="remark">
<u-input maxlength="200" height="60px" class="" placeholder="订单备注信息" v-model="form.remark" type="textarea"></u-input>
</u-form-item>
</view>
</u-form>
<view class="flex flex-wrap diygw-col-24 flex-direction-column diygw-bottom flex27-clz">
<text @click="submitForm" class="diygw-col-24 green text17-clz"> 提交订单 </text>
</view>
<view @touchmove.stop.prevent="" v-if="modal" class="diygw-modal bottom-modal" :class="modal" style="z-index: 1000000">
<view class="diygw-dialog diygw-dialog-modal">
<view>
<view class="flex diygw-dialog-content">
<view class="flex flex-wrap diygw-col-24 justify-between items-center flex29-clz">
<text class="diygw-col-0 text21-clz"> 选择商品 </text>
<text @tap="navigateTo" data-type="closemodal" data-id="modal" class="flex icon8 diygw-col-0 diy-icon-close"></text>
</view>
<view class="flex flex-wrap diygw-col-24 justify-between items-center flex30-clz">
<u-form-item :borderBottom="false" class="diygw-col-0 input-clz diygw-form-border diygw-uform-item" labelPosition="top" prop="input">
<view class="flex flex-sub padding-top-xs padding-bottom-xs align-center solid input_clz">
<u-input :focus="inputFocus" placeholder="请输入商品名称查询" v-model="input"></u-input>
<text class="diy-icon-scan" style="color: #676767; font-size: 32rpx"></text>
</view>
</u-form-item>
<view class="flex flex-wrap diygw-col-0 items-center green flex41-clz" @tap="navigateTo" data-type="page" data-url="/pages/basic/product">
<text class="flex icon10 diygw-col-0 diy-icon-add"></text>
<text class="diygw-col-0"> 新增商品 </text>
</view>
</view>
<view class="flex tabs diygw-col-24 flex-direction-row tabs-clz">
<view class="diygw-tabs text-center tabs-title">
<view class="diygw-tab-item tabs-item-title" :class="index == tabsIndex ? 'cur bg-green ' : ''" v-for="(item, index) in cates.rows" :key="index" @click="changeTabs" :data-index="index">
{{ item.title }}
</view>
</view>
<view class="flex1">
<view class="tabs-content flex-sub">
<scroll-view scroll-y class="flex flex-wrap diygw-col-24 flex-direction-column flex40-clz">
<view class="flex scroll-y flex-nowrap">
<view v-for="(item, index) in products.rows" :key="index" class="flex flex-wrap diygw-col-24 items-stretch flex32-clz">
<view v-if="item.showimg" class="flex flex-wrap diygw-col-0 flex-direction-column flex33-clz">
<image :src="item.showimg" class="image1-size diygw-image diygw-col-0 image1-clz" mode="widthFix"></image>
</view>
<view class="flex flex-wrap diygw-col-0 flex-direction-column justify-center flex34-clz">
<view class="flex flex-wrap diygw-col-24 items-center flex35-clz">
<text class="diygw-col-0">
{{ item.title }}
</text>
</view>
<view class="flex flex-wrap diygw-col-24 justify-between items-center flex36-clz">
<view class="flex flex-wrap diygw-col-0">
<text class="diygw-col-0"> 单位: </text>
<text class="diygw-col-0">
{{ item.unit }}
</text>
</view>
<view class="flex diygw-col-0 justify-between items-baseline flex-nowrap flex38-clz">
<text class="diygw-col-0"> ¥ </text>
<text class="diygw-col-0 text28-clz">
{{ item.price }}
</text>
</view>
</view>
<view class="flex diygw-col-24 justify-between items-center flex-nowrap flex37-clz">
<view class="flex flex-wrap diygw-col-0 items-baseline flex39-clz">
<text class="diygw-col-0"> 库存: </text>
<text class="diygw-col-0 text31-clz">
{{ item.stockNumber }}
</text>
</view>
<text v-if="item.number == 0" @tap="addItemNumber(item)" class="flex icon6 diygw-col-0 green icon6-clz diy-icon-add"></text>
<u-form-item :borderBottom="false" :isHideMin="true" v-if="item.number > 0" class="diygw-col-0 diygw-form-item-small" labelPosition="top" prop="number">
<view class="flex diygw-col-24">
<u-number-box :isBtnRadius="true" :inputHeight="40" inpubBgColor="#ffffff" inputColor="#000000" @change="changeItemNumber($event, index, item)" name="number" v-model="item.number" bgColor="#07c160" color="#ffffff" :min="0" isHideMin :max="item.stockNumber" :step="1" />
</view>
</u-form-item>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
<view class="flex flex-wrap diygw-col-24 justify-between items-center flex42-clz">
<view class="flex flex-wrap diygw-col-0 items-baseline">
<text class="diygw-col-0"> 产品: </text>
<text class="diygw-col-0 text32-clz">
{{ form.products.length }}
</text>
<text class="diygw-col-0"> 金额: </text>
<text class="diygw-col-0 text37-clz">
{{ globalData.totalPrice }}
</text>
</view>
<text @tap="navigateTo" data-type="closemodal" data-id="modal" class="diygw-col-0 green text38-clz"> 确定 </text>
</view>
</view>
</view>
</view>
</view>
<view class="clearfix"></view>
</view>
</template>
<script>
export default {
data() {
return {
//用户全局信息
userInfo: {},
//页面传参
globalOption: {},
//自定义全局变量
globalData: { totalNumber: 0, totalPrice: 0, selectProducts: [] },
dataNum: 1,
data: {
code: 200,
msg: 'success',
data: {
id: 15,
products: '[{"title":"123","unit":"123","total":24,"number":"12","price":"2"}]',
costs: '[{"title":"123","price":"2"}]',
youhui: '2.000',
total: '24.000',
remark: '',
status: null,
kaidanDate: '2024-12-17 00:00:00',
customerTitle: '客户名',
customerUsername: '邓生',
customerPhone: '15913132246',
customerAddress: '联系地址联系地址',
productsTotal: '24.000',
costsTotal: '2.000',
createTime: '2024-12-17 16:05:44',
updateTime: '2024-12-17 16:05:44',
deleteTime: null
}
},
cates: {
rows: [
{
id: 0,
title: '',
remark: '',
sortnum: 0,
createTime: '',
updateTime: '',
deleteTime: null
}
],
total: 0,
code: 0,
msg: ''
},
products: {
rows: [
{
id: 0,
title: '',
remark: '',
img: '',
unit: '',
price: null,
number: '',
sortnum: null,
cateId: null,
userId: null,
createTime: '',
updateTime: '',
deleteTime: null
}
],
total: 0,
code: 0,
msg: ''
},
modal: '',
inputFocus: false,
input: '',
tabsTop: 0,
tabsHeight: 0,
tabsItemHeight: 0,
tabsIndex: 0,
costsItemRules: {},
item: {
number: 0
},
formRules: {
kaidan: [
{
trigger: ['change', 'blur'],
required: true,
message: '开单人不能为空'
}
],
kaidanDate: [
{
trigger: ['change', 'blur'],
required: true,
message: '开单日期不能为空哟'
}
]
},
form: {
kaidan: '',
kaidanDate: '',
products: [],
costs: [],
youhui: undefined,
remark: ''
},
costsItemData: {
titleFocus: false,
priceFocus: false
},
costsItem: {
title: '',
price: ''
},
productsItem: {
title: '',
unit: '',
number: undefined,
price: undefined
},
productsItemData: {
titleDisabled: true,
titleFocus: false,
unitDisabled: true,
unitFocus: false,
numberDisabled: true,
numberFocus: false,
priceDisabled: true,
priceFocus: false
},
formData: {
kaidanFocus: false,
showKaidanDate: false,
productsItemDatas: [],
costsItemDatas: [],
youhuiFocus: false
},
productsItemRules: {}
};
},
onShow() {
this.setCurrentPage(this);
this.initShow();
},
onLoad(option) {
this.setCurrentPage(this);
if (option) {
this.setData({
globalOption: this.getOption(option)
});
}
this.init();
},
onReady() {
this.$refs.formRef?.setRules(this.formRules);
},
methods: {
async init() {
await this.dataApi();
await this.initResetform();
},
async initShow() {
//强制重新刷新页面
await this.catesApi({ refresh: 1 });
//强制重新刷新页面
await this.productsApi({ refresh: 1 });
},
// 订单数据 API请求方法
async dataApi(param) {
let thiz = this;
param = param || {};
//请求地址及请求数据,可以在加载前执行上面增加自己的代码逻辑
let http_url = '/sell/orders/get';
let http_data = {
pageNum: this.dataNum,
pageSize: 10,
id: param.id || this.globalOption.id || '15'
};
let http_header = {};
//这个判断意思是表示新增而不是编辑,不用请求API
if (!this.globalOption.id) {
this.$nextTick(() => {
this.form.kaidan = this.userInfo.nickname;
this.form.kaidanDate = this.$tools.getCurrentDate();
});
return;
}
let data = await this.$http.post(http_url, http_data, http_header, 'json');
this.data = data;
//把数据库返回来的数据转为JSON
data.data.costs = JSON.parse(data.data.costs);
data.data.products = JSON.parse(data.data.products);
//重新构造客户表单显示数据
let customer = {
title: data.data.customerTitle,
address: data.data.customerAddress,
phone: data.data.customerPhone,
username: data.data.customerUsername
};
data.data.kaidanDate = this.$tools.formatDateTime(data.data.kaidanDate, 'YYYY-mm-dd');
let productsItemDatas = [];
data.data.products.forEach((item) => {
productsItemDatas.push(JSON.parse(JSON.stringify(this.productsItemData)));
});
this.formData.productsItemDatas = productsItemDatas;
let costsItemDatas = [];
data.data.costs.forEach((item) => {
costsItemDatas.push(JSON.parse(JSON.stringify(this.costsItemData)));
});
this.formData.costsItemDatas = costsItemDatas;
this.userInfo.customer = customer;
this.form = data.data;
},
// 所有分类 API请求方法
async catesApi(param) {
let thiz = this;
param = param || {};
//请求地址及请求数据,可以在加载前执行上面增加自己的代码逻辑
let http_url = '/sell/cate/all';
let http_data = {};
let http_header = {};
let cates = await this.$http.post(http_url, http_data, http_header, 'json');
cates.rows.unshift({ id: '', title: '全部' });
this.cates = cates;
},
// 产品数据 API请求方法
async productsApi(param) {
let thiz = this;
param = param || {};
//请求地址及请求数据,可以在加载前执行上面增加自己的代码逻辑
let http_url = '/sell/product/list';
let http_data = {
pageSize: param.pageSize || '50',
number_gt: param.number_gt || '0'
};
let http_header = {};
if (this.tabsIndex != 0) {
http_data.cateId = this.cates.rows[this.tabsIndex].id;
}
if (this.tabsIndex == this.globalData.tabsIndex) {
return;
}
this.globalData.tabsIndex = this.tabsIndex;
let products = await this.$http.post(http_url, http_data, http_header, 'json');
products.rows.forEach((item) => {
//初始化库存数量
item.stockNumber = parseFloat(item.number);
//设置显示图片
item.img = item.img ? item.img.split(',') : [];
item.showimg = item.img.length > 0 ? item.img[0] : '';
item.number = 0;
});
this.products = products;
await this.initProductNumberFunction({});
},
// 计算产品总金额 自定义方法
productsTotalFunction(param) {
let thiz = this;
function calculateTotal(item) {
let price = parseFloat(item.price) || 0;
let number = parseFloat(item.number) || 0;
return price * number;
}
this.form.productsTotal = this.form.products.reduce((sum, item) => sum + calculateTotal(item), 0);
return this.form.productsTotal;
},
// 计算其他金额总价 自定义方法
costsTotalFunction(param) {
let thiz = this;
function calculateTotal(item) {
let price = parseFloat(item.price) || 0;
return price;
}
this.form.costsTotal = this.form.costs.reduce((sum, item) => sum + calculateTotal(item), 0);
return this.form.costsTotal;
},
// 总价 自定义方法
totalFunction(param) {
let thiz = this;
let youhui = parseFloat(this.form.youhui) || 0;
this.form.total = this.productsTotalFunction() + this.costsTotalFunction() - youhui;
return this.form.total;
},
// 选择产品并计算 自定义方法
async selectProductAntTotalFunction(param) {
let thiz = this;
let number = 0;
let price = 0;
let products = this.products.rows;
products.forEach((childItem) => {
number = childItem.number + number;
price = childItem.number * childItem.price + price;
//判断是否已加入产品库
let index = this.form.products.findIndex((product) => {
return product.id == childItem.id;
});
//如果选择的产品数据大于0新增或修改
if (childItem.number > 0) {
if (index >= 0) {
this.form.products.splice(index, 1, JSON.parse(JSON.stringify(childItem)));
} else {
this.form.products.push(JSON.parse(JSON.stringify(childItem)));
this.formData.productsItemDatas.push(JSON.parse(JSON.stringify(this.productsItemData)));
}
} else {
//如果数据为0但产品库存在,当删除存在的产品库
if (index >= 0) {
this.form.products.splice(index, 1);
this.formData.productsItemDatas.splice(index, 1);
}
}
});
this.globalData.totalPrice = price;
},
// 初始数据 自定义方法
async initProductNumberFunction(param) {
let thiz = this;
let showModal = param && (param.showModal || param.showModal == 0) ? param.showModal : '0';
this.products.rows.forEach((childItem) => {
let find = this.form.products.find((product) => {
return product.id == childItem.id;
});
if (find) {
childItem.number = find.number;
}
});
if (showModal != '0') {
this.navigateTo({
type: 'openmodal',
id: 'modal'
});
}
},
changeFormKaidanDate(evt) {
this.form.kaidanDate = evt.result;
},
//子表单验证
initProductsValid() {
this.$nextTick(() => {
this.$refs['productsRef']?.forEach((subform) => {
subform.setRules(this.productsItemRules);
});
});
},
//上移子表单
upProductsItem(evt) {
let { index } = evt.currentTarget.dataset;
if (index == 0) {
this.navigateTo({
type: 'tip',
tip: '已经是第一个'
});
return false;
}
this.form.products[index] = this.form.products.splice(index - 1, 1, this.form.products[index])[0];
this.formData.productsItemDatas[index] = this.formData.productsItemDatas.splice(index - 1, 1, this.formData.productsItemDatas[index])[0];
this.initProductsValid();
},
//下移子表单
downProductsItem(evt) {
let { index } = evt.currentTarget.dataset;
if (index == this.form.products.length - 1) {
this.navigateTo({
type: 'tip',
tip: '已经是最后一个'
});
return false;
}
this.form.products[index] = this.form.products.splice(index + 1, 1, this.form.products[index])[0];
this.formData.productsItemDatas[index] = this.formData.productsItemDatas.splice(index + 1, 1, this.formData.productsItemDatas[index])[0];
this.initProductsValid();
},
//删除子表单
delProductsItem(evt) {
let { index } = evt.currentTarget.dataset;
this.form.products.splice(index, 1);
this.formData.productsItemDatas.splice(index, 1);
this.initProductsValid();
},
//增加子表单
addProductsItem() {
this.form.products.push(JSON.parse(JSON.stringify(this.productsItem)));
this.formData.productsItemDatas.push(JSON.parse(JSON.stringify(this.productsItemData)));
this.initProductsValid();
},
//验证所有的子表单
checkProductsValid() {
let flag = true;
this.$refs['productsRef']?.forEach((subform) => {
subform.validate((valid) => {
if (!valid) {
flag = false;
return false;
}
});
});
return flag;
},
calcTotal(item) {
let price = parseFloat(item.price) || 0;
let number = parseFloat(item.number) || 0;
let total = price * number;
item.total = total;
return total;
},
//子表单验证
initCostsValid() {
this.$nextTick(() => {
this.$refs['costsRef']?.forEach((subform) => {
subform.setRules(this.costsItemRules);
});
});
},
//上移子表单
upCostsItem(evt) {
let { index } = evt.currentTarget.dataset;
if (index == 0) {
this.navigateTo({
type: 'tip',
tip: '已经是第一个'
});
return false;
}
this.form.costs[index] = this.form.costs.splice(index - 1, 1, this.form.costs[index])[0];
this.formData.costsItemDatas[index] = this.formData.costsItemDatas.splice(index - 1, 1, this.formData.costsItemDatas[index])[0];
this.initCostsValid();
},
//下移子表单
downCostsItem(evt) {
let { index } = evt.currentTarget.dataset;
if (index == this.form.costs.length - 1) {
this.navigateTo({
type: 'tip',
tip: '已经是最后一个'
});
return false;
}
this.form.costs[index] = this.form.costs.splice(index + 1, 1, this.form.costs[index])[0];
this.formData.costsItemDatas[index] = this.formData.costsItemDatas.splice(index + 1, 1, this.formData.costsItemDatas[index])[0];
this.initCostsValid();
},
//删除子表单
delCostsItem(evt) {
let { index } = evt.currentTarget.dataset;
this.form.costs.splice(index, 1);
this.formData.costsItemDatas.splice(index, 1);
this.initCostsValid();
},
//增加子表单
addCostsItem() {
this.form.costs.push(JSON.parse(JSON.stringify(this.costsItem)));
this.formData.costsItemDatas.push(JSON.parse(JSON.stringify(this.costsItemData)));
this.initCostsValid();
},
//验证所有的子表单
checkCostsValid() {
let flag = true;
this.$refs['costsRef']?.forEach((subform) => {
subform.validate((valid) => {
if (!valid) {
flag = false;
return false;
}
});
});
return flag;
},
initResetform() {
this.initform = JSON.stringify(this.form);
//如果想给表单默认初始值,其中row为某一行数据也可能是API返回的结果集,然后给到this.form
//this.form = this.$tools.changeRowToForm(row,this.form)
},
resetForm() {
this.form = JSON.parse(this.initform);
},
async submitForm(e) {
this.$refs.formRef?.setRules(this.formRules);
this.initProductsValid();
this.initCostsValid();
this.$nextTick(async () => {
let productsvalid = await this.checkProductsValid();
let costsvalid = await this.checkCostsValid();
let valid = await this.$refs.formRef.validate();
if (valid && productsvalid && costsvalid) {
//保存数据
let param = this.form;
let header = {
'Content-Type': 'application/json'
};
let url = '/sell/orders/add';
if (this.userInfo.customer) {
param.customerTitle = this.userInfo.customer.title;
param.customerPhone = this.userInfo.customer.phone;
param.customerAddress = this.userInfo.customer.address;
param.customerUsername = this.userInfo.customer.username;
}
if (this.form.products.length == 0) {
this.showToast('产品不能为空');
return;
}
let findProducts = this.form.products.filter((item) => {
return !item.title;
});
if (findProducts.length > 0) {
this.showToast('产品不能为空');
return;
}
let res = await this.$http.post(url, param, header, 'json');
if (res.code == 200) {
if (this.form.id) {
this.showToast('更新成功');
this.navigateTo({
type: 'page',
url: 'sells'
});
} else {
//提示是否继续新增
let flag = await this.showModal('是否继续新增');
if (flag) {
//重置表单
this.resetForm();
this.form.kaidan = this.userInfo.nickname;
this.form.kaidanDate = this.$tools.getCurrentDate();
delete this.globalData.tabsIndex;
this.productsApi();
} else {
//关闭窗口
this.navigateTo({
type: 'page',
url: 'sells'
});
}
}
}
} else {
console.log('验证失败');
}
});
},
changeTabs(evt) {
let { index } = evt.currentTarget.dataset;
if (index == this.tabsIndex) return;
this.setData({
tabsIndex: index
});
this.navigateTo({ type: 'productsApi' });
},
addItemNumber(item) {
item.number = 1;
this.selectProductAntTotalFunction();
},
changeItemNumber(evt, index, item) {
this.navigateTo({ foritem: item, forindex: index, type: 'selectProductAntTotalFunction' });
}
}
};
</script>
<style lang="scss" scoped>
.flex-clz {
background-color: #ffffff;
margin-left: 20rpx;
border-bottom-left-radius: 12rpx;
overflow: hidden;
width: calc(100% - 20rpx - 20rpx) !important;
border-top-left-radius: 12rpx;
margin-top: 10rpx;
border-top-right-radius: 12rpx;
border-bottom-right-radius: 12rpx;
margin-bottom: 10rpx;
margin-right: 20rpx;
}
.flex28-clz {
padding-top: 20rpx;
flex: 1;
padding-left: 20rpx;
padding-bottom: 20rpx;
padding-right: 20rpx;
}
.text5-clz {
flex: 1;
font-weight: bold;
font-size: 28rpx !important;
}
.flex6-clz {
flex: 1;
}
.title-clz {
flex: 1;
font-weight: bold;
font-size: 28rpx !important;
}
.flex22-clz {
font-weight: bold;
font-size: 28rpx !important;
}
.address-clz {
flex: 1;
}
.text22-clz {
font-weight: bold;
font-size: 28rpx !important;
}
.text20-clz {
margin-left: 0rpx;
color: #989898;
flex: 1;
width: calc(100% - 0rpx - 0rpx) !important;
margin-top: 10rpx;
margin-bottom: 0rpx;
margin-right: 0rpx;
}
.icon4-clz {
color: #989898;
}
.icon4 {
font-size: 40rpx;
}
.flex1-clz {
background-color: #ffffff;
margin-left: 20rpx;
border-bottom-left-radius: 12rpx;
overflow: hidden;
width: calc(100% - 20rpx - 20rpx) !important;
border-top-left-radius: 12rpx;
margin-top: 10rpx;
border-top-right-radius: 12rpx;
border-bottom-right-radius: 12rpx;
margin-bottom: 10rpx;
margin-right: 20rpx;
}
.flex24-clz {
padding-top: 20rpx;
flex: 1;
padding-left: 20rpx;
padding-bottom: 20rpx;
padding-right: 20rpx;
}
.text-clz {
font-size: 28rpx !important;
}
.flex44-clz {
padding-top: 6rpx;
border-bottom-left-radius: 12rpx;
overflow: hidden;
padding-left: 10rpx;
padding-bottom: 6rpx;
border-top-left-radius: 12rpx;
border-top-right-radius: 12rpx;
border-bottom-right-radius: 12rpx;
padding-right: 10rpx;
}
.icon1 {
font-size: 28rpx;
}
.flex2-clz {
background-color: #f4f4f4;
}
.text11-clz {
flex-shrink: 0;
padding-top: 10rpx;
border-right: 2rpx solid #eee;
padding-left: 10rpx;
width: 60rpx !important;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #eee;
text-align: center;
padding-right: 10rpx;
}
.text4-clz {
flex-shrink: 0;
padding-top: 10rpx;
border-right: 2rpx solid #eee;
flex: 1;
padding-left: 10rpx;
width: 60rpx !important;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #eee;
text-align: center;
padding-right: 10rpx;
}
.text3-clz {
flex-shrink: 0;
padding-top: 10rpx;
border-right: 2rpx solid #eee;
padding-left: 10rpx;
width: 120rpx !important;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #eee;
text-align: center;
padding-right: 10rpx;
}
.text2-clz {
flex-shrink: 0;
padding-top: 10rpx;
border-right: 2rpx solid #eee;
padding-left: 10rpx;
width: 120rpx !important;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #eee;
text-align: center;
padding-right: 10rpx;
}
.text1-clz {
flex-shrink: 0;
padding-top: 10rpx;
border-right: 2rpx solid #eee;
padding-left: 10rpx;
width: 120rpx !important;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #eee;
text-align: center;
padding-right: 10rpx;
}
.text7-clz {
flex-shrink: 0;
padding-top: 10rpx;
border-right: 2rpx solid #eee;
padding-left: 10rpx;
width: 120rpx !important;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #eee;
text-align: center;
padding-right: 10rpx;
}
.flex4-clz {
flex-shrink: 0;
border-right: 2rpx solid #eee;
width: 60rpx !important;
border-bottom: 2rpx solid #eee;
text-align: center;
}
.icon {
font-size: 40rpx;
}
.flex5-clz {
flex-shrink: 0;
border-right: 2rpx solid #eee;
flex: 1;
width: 120rpx !important;
border-bottom: 2rpx solid #eee;
text-align: center;
}
.flex11-clz {
flex-shrink: 0;
border-right: 2rpx solid #eee;
width: 120rpx !important;
border-bottom: 2rpx solid #eee;
text-align: center;
}
.flex10-clz {
flex-shrink: 0;
border-right: 2rpx solid #eee;
width: 120rpx !important;
border-bottom: 2rpx solid #eee;
text-align: center;
}
.flex9-clz {
flex-shrink: 0;
border-right: 2rpx solid #eee;
width: 120rpx !important;
border-bottom: 2rpx solid #eee;
text-align: center;
}
.flex7-clz {
flex-shrink: 0;
border-right: 2rpx solid #eee;
width: 120rpx !important;
border-bottom: 2rpx solid #eee;
text-align: center;
}
.flex12-clz {
padding-top: 20rpx;
flex: 1;
padding-left: 20rpx;
padding-bottom: 20rpx;
padding-right: 0rpx;
}
.text9-clz {
margin-left: 10rpx;
font-weight: bold;
margin-top: 10rpx;
margin-bottom: 10rpx;
margin-right: 10rpx;
}
.text14-clz {
color: #f30303;
font-weight: bold;
font-size: 28rpx !important;
text-align: center;
min-width: 60px;
}
.flex14-clz {
background-color: #ffffff;
margin-left: 20rpx;
border-bottom-left-radius: 12rpx;
overflow: hidden;
width: calc(100% - 20rpx - 20rpx) !important;
border-top-left-radius: 12rpx;
margin-top: 10rpx;
border-top-right-radius: 12rpx;
border-bottom-right-radius: 12rpx;
margin-bottom: 10rpx;
margin-right: 20rpx;
}
.flex45-clz {
padding-top: 20rpx;
flex: 1;
padding-left: 20rpx;
padding-bottom: 20rpx;
padding-right: 20rpx;
}
.text35-clz {
font-size: 28rpx !important;
}
.flex46-clz {
padding-top: 6rpx;
border-bottom-left-radius: 12rpx;
overflow: hidden;
padding-left: 10rpx;
padding-bottom: 6rpx;
border-top-left-radius: 12rpx;
border-top-right-radius: 12rpx;
border-bottom-right-radius: 12rpx;
padding-right: 10rpx;
}
.icon3 {
font-size: 28rpx;
}
.flex15-clz {
background-color: #f4f4f4;
}
.text8-clz {
flex-shrink: 0;
padding-top: 10rpx;
border-right: 2rpx solid #eee;
padding-left: 10rpx;
width: 60rpx !important;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #eee;
text-align: center;
padding-right: 10rpx;
}
.text10-clz {
flex-shrink: 0;
padding-top: 10rpx;
border-right: 2rpx solid #eee;
flex: 1;
padding-left: 10rpx;
width: 60rpx !important;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #eee;
text-align: center;
padding-right: 10rpx;
}
.text12-clz {
flex-shrink: 0;
padding-top: 10rpx;
border-right: 2rpx solid #eee;
padding-left: 10rpx;
width: 160rpx !important;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #eee;
text-align: center;
padding-right: 10rpx;
}
.flex17-clz {
flex-shrink: 0;
border-right: 2rpx solid #eee;
width: 60rpx !important;
border-bottom: 2rpx solid #eee;
text-align: center;
}
.icon2 {
font-size: 40rpx;
}
.flex18-clz {
flex-shrink: 0;
border-right: 2rpx solid #eee;
flex: 1;
width: 120rpx !important;
border-bottom: 2rpx solid #eee;
text-align: center;
}
.flex19-clz {
flex-shrink: 0;
border-right: 2rpx solid #eee;
width: 160rpx !important;
border-bottom: 2rpx solid #eee;
text-align: center;
}
.flex23-clz {
padding-top: 10rpx;
flex: 1;
padding-left: 20rpx;
padding-bottom: 10rpx;
padding-right: 0rpx;
}
.text15-clz {
margin-left: 10rpx;
font-weight: bold;
margin-top: 10rpx;
margin-bottom: 10rpx;
margin-right: 10rpx;
}
.text18-clz {
color: #f30303;
font-weight: bold;
font-size: 28rpx !important;
text-align: center;
min-width: 60px;
}
.flex20-clz {
background-color: #ffffff;
margin-left: 20rpx;
border-bottom-left-radius: 12rpx;
overflow: hidden;
width: calc(100% - 20rpx - 20rpx) !important;
border-top-left-radius: 12rpx;
margin-top: 10rpx;
border-top-right-radius: 12rpx;
border-bottom-right-radius: 12rpx;
margin-bottom: 10rpx;
margin-right: 20rpx;
}
.flex21-clz {
padding-top: 20rpx;
flex: 1;
padding-left: 20rpx;
padding-bottom: 20rpx;
padding-right: 0rpx;
}
.text16-clz {
margin-left: 10rpx;
font-weight: bold;
margin-top: 10rpx;
margin-bottom: 10rpx;
margin-right: 10rpx;
}
.text19-clz {
color: #f30303;
font-weight: bold;
font-size: 28rpx !important;
text-align: center;
min-width: 60px;
}
.flex26-clz {
background-color: #ffffff;
margin-left: 20rpx;
border-bottom-left-radius: 12rpx;
overflow: hidden;
width: calc(100% - 20rpx - 20rpx) !important;
border-top-left-radius: 12rpx;
margin-top: 10rpx;
border-top-right-radius: 12rpx;
border-bottom-right-radius: 12rpx;
margin-bottom: 10rpx;
margin-right: 20rpx;
}
.flex27-clz {
background-color: #ffffff;
border-bottom-left-radius: 0rpx;
overflow: hidden;
left: 0rpx;
bottom: 0rpx;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
border-bottom-right-radius: 0rpx;
}
.text17-clz {
padding-top: 16rpx;
border-bottom-left-radius: 120rpx;
color: #ffffff;
padding-left: 20rpx;
font-size: 28rpx !important;
padding-bottom: 16rpx;
border-top-right-radius: 120rpx;
margin-right: 10rpx;
margin-left: 10rpx;
overflow: hidden;
width: calc(100% - 10rpx - 10rpx) !important;
border-top-left-radius: 120rpx;
margin-top: 10rpx;
border-bottom-right-radius: 120rpx;
margin-bottom: 10rpx;
text-align: center;
padding-right: 20rpx;
}
.modal-clz {
border-bottom-left-radius: 0rpx;
z-index: 1000000;
overflow: hidden;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
border-bottom-right-radius: 0rpx;
}
.diygw-dialog-modal {
border-top-left-radius: 10px !important;
border-top-right-radius: 10px !important;
border-bottom-left-radius: 0px !important;
border-bottom-right-radius: 0px !important;
}
.flex29-clz {
padding-top: 20rpx;
padding-left: 20rpx;
padding-bottom: 20rpx;
padding-right: 20rpx;
}
.text21-clz {
font-size: 28rpx !important;
}
.icon8 {
font-size: 48rpx;
}
.flex30-clz {
padding-top: 0rpx;
padding-left: 0rpx;
padding-bottom: 0rpx;
padding-right: 20rpx;
}
.input-clz {
flex: 1;
}
.input_clz {
border-radius: 40rpx !important;
}
.flex41-clz {
padding-top: 16rpx;
border-bottom-left-radius: 12rpx;
overflow: hidden;
padding-left: 10rpx;
padding-bottom: 16rpx;
border-top-left-radius: 12rpx;
border-top-right-radius: 12rpx;
border-bottom-right-radius: 12rpx;
padding-right: 10rpx;
}
.icon10 {
font-size: 28rpx;
}
.tabs-clz {
border-top: 2rpx solid #eee;
}
.tabs .diygw-tab-item {
height: 80rpx;
line-height: 80rpx;
}
.tabs-content {
height: 400px;
}
.tabs-title {
width: 200rpx;
background-color: #f8f8f8 !important;
}
.tabs-item-title.cur {
background-color: #ffffff !important;
color: #000000 !important;
}
.flex40-clz {
height: 800rpx;
}
.flex32-clz {
padding-top: 10rpx;
padding-left: 10rpx;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #f3f3f3;
margin-right: 10rpx;
background-color: #ffffff;
margin-left: 10rpx;
box-shadow: 0rpx 0rpx 6rpx 1px rgba(219, 219, 219, 0.12);
overflow: hidden;
width: calc(100% - 10rpx - 10rpx) !important;
margin-top: 10rpx;
margin-bottom: 10rpx;
padding-right: 10rpx;
}
.flex33-clz {
padding-top: 10rpx;
padding-left: 0rpx;
padding-bottom: 0rpx;
padding-right: 0rpx;
}
.image1-clz {
border-bottom-left-radius: 12rpx;
overflow: hidden;
border-top-left-radius: 12rpx;
border-top-right-radius: 12rpx;
border-bottom-right-radius: 12rpx;
}
.image1-size {
height: 96rpx !important;
width: 96rpx !important;
}
.flex34-clz {
flex: 1;
}
.flex35-clz {
padding-top: 10rpx;
font-weight: bold;
padding-left: 10rpx;
font-size: 28rpx !important;
padding-bottom: 10rpx;
padding-right: 10rpx;
}
.flex36-clz {
padding-top: 0rpx;
padding-left: 10rpx;
padding-bottom: 0rpx;
padding-right: 10rpx;
}
.flex38-clz {
font-weight: bold;
}
.text28-clz {
font-size: 28rpx !important;
}
.flex37-clz {
padding-top: 0rpx;
padding-left: 10rpx;
padding-bottom: 0rpx;
padding-right: 10rpx;
}
.flex39-clz {
color: #fd0101;
}
.text31-clz {
font-weight: bold;
font-size: 28rpx !important;
}
.icon6-clz {
padding-top: 8rpx;
border-bottom-left-radius: 120rpx;
overflow: hidden;
padding-left: 8rpx;
padding-bottom: 8rpx;
border-top-left-radius: 120rpx;
border-top-right-radius: 120rpx;
border-bottom-right-radius: 120rpx;
padding-right: 8rpx;
}
.icon6 {
font-size: 28rpx;
}
.flex42-clz {
border-top: 2rpx solid #eee;
padding-top: 10rpx;
padding-left: 20rpx;
padding-bottom: 10rpx;
padding-right: 20rpx;
}
.text32-clz {
margin-left: 0rpx;
font-weight: bold;
font-size: 30rpx !important;
margin-top: 0rpx;
margin-bottom: 0rpx;
margin-right: 20rpx;
}
.text37-clz {
margin-left: 0rpx;
font-weight: bold;
font-size: 30rpx !important;
margin-top: 0rpx;
margin-bottom: 0rpx;
margin-right: 20rpx;
}
.text38-clz {
padding-top: 20rpx;
border-bottom-left-radius: 12rpx;
overflow: hidden;
padding-left: 30rpx;
padding-bottom: 20rpx;
border-top-left-radius: 12rpx;
border-top-right-radius: 12rpx;
border-bottom-right-radius: 12rpx;
padding-right: 30rpx;
}
.container333211 {
padding-bottom: 160rpx;
background-color: #f7f7f7;
}
</style>