写商城后台管理系统时肯定会遇到商品sku配置,sku表格配置,表格的每一项几乎都要经过验证才能提交,下面是我写的一个demo(拖动排序基于vuedraggable)
功能
- 表格内所有的输入框验证
- 表格拖动排序
- 增加/删除
预览:
拖动效果预览:
安装vuedraggable
npm install vuedraggable
完整代码
<script lang="ts" setup>
import { reactive, ref } from "vue";
import type { FormInstance } from "element-plus";
import draggable from "vuedraggable/src/vuedraggable";
import { Plus, Delete } from "@element-plus/icons-vue";
const ruleFormRef = ref<FormInstance>();
const ruleForm = reactive({
tableData: [
{
key_id: 1,
title: "黑色", //规格名称
wholesale_price: 88.88, //批发价
guiding_price: 100, //市场指导价
stock: 10, //库存
warning_value: 5, //库存预警值
volume: 2.14, //体积
weight: 3.12 //重量
},
{
key_id: 2,
title: "黑444444色", //规格名称
wholesale_price: 88.88, //批发价
guiding_price: 100, //市场指导价
stock: 10, //库存
warning_value: 5, //库存预警值
volume: 2.14, //体积
weight: 3.12 //重量
}
]
});
const rules = reactive({
title: [{ required: true, message: "请输入商品规格名称", trigger: "blur" }],
wholesale_price: [
{ required: true, message: "请输入批发价", trigger: "blur" }
],
guiding_price: [
{ required: true, message: "请输入市场指导价", trigger: "blur" }
],
stock: [{ required: true, message: "请输入库存", trigger: "blur" }],
warning_value: [
{ required: true, message: "请输入库存预警值", trigger: "blur" }
],
volume: [{ required: true, message: "请输入体积", trigger: "blur" }],
weight: [{ required: true, message: "请输入重量", trigger: "blur" }]
});
// 添加
const rowAdd = () => {
console.log("添加了");
ruleForm.tableData.push({
key_id: new Date().getTime() + ruleForm.tableData.length,
title: "", //规格名称
wholesale_price: 0, //批发价
guiding_price: 0, //市场指导价
stock: 0, //库存
warning_value: 0, //库存预警值
volume: 0, //体积
weight: 0 //重量
});
};
//删除
const rowDel = index => {
ruleForm.tableData.splice(index, 1);
};
//提交验证
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid, fields) => {
if (valid) {
console.log("submit!");
} else {
console.log("error submit!", fields);
}
});
};
//重置
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
};
const update = () => {};
</script>
<template>
<el-form
ref="ruleFormRef"
:model="ruleForm"
label-width="0"
class="demo-ruleForm"
>
<div class="const_box_nav">
<div class="l">商品规格、库存SKU设置</div>
<div class="r">
<el-button type="primary" :icon="Plus" @click="rowAdd">添 加</el-button>
</div>
</div>
<el-scrollbar>
<table class="const_box">
<tbody>
<tr class="box_list_header">
<th class="item">商品规格名称</th>
<th class="item">批发价</th>
<th class="item">市场指导价</th>
<th class="item">库存</th>
<th class="item">预警值</th>
<th class="item">体积㎡</th>
<th class="item">重量kg</th>
<th class="item" style="width: 150px !important; flex: none">
操作
</th>
</tr>
<draggable
v-model="ruleForm.tableData"
class="class-container"
item-key="key_id"
animation="300"
ghostClass="ghost"
forceFallback="true"
@update="update"
>
<template #item="{ element, index }">
<tr class="box_list_row">
<td class="items">
<el-form-item
:prop="'tableData.' + index + '.title'"
:rules="rules.title"
style="width: 100%"
>
<el-input placeholder="请输入" v-model="element.title" />
</el-form-item>
</td>
<td class="items">
<el-form-item
:prop="'tableData.' + index + '.wholesale_price'"
:rules="rules.wholesale_price"
>
<el-input-number
v-model="element.wholesale_price"
:min="0"
:step="0.01"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</td>
<td class="items">
<el-form-item
:prop="'tableData.' + index + '.guiding_price'"
:rules="rules.guiding_price"
>
<el-input-number
v-model="element.guiding_price"
:min="0"
:step="0.01"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</td>
<td class="items">
<el-form-item
:prop="'tableData.' + index + '.stock'"
:rules="rules.stock"
>
<el-input-number
v-model="element.stock"
:min="0"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</td>
<td class="items">
<el-form-item
:prop="'tableData.' + index + '.warning_value'"
:rules="rules.warning_value"
>
<el-input-number
v-model="element.warning_value"
:min="0"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</td>
<td class="items">
<el-form-item
:prop="'tableData.' + index + '.volume'"
:rules="rules.volume"
>
<el-input-number
v-model="element.volume"
:min="0"
:step="0.01"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</td>
<td class="items">
<el-form-item
:prop="'tableData.' + index + '.weight'"
:rules="rules.weight"
>
<el-input-number
v-model="element.weight"
:min="0"
:step="0.01"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</td>
<td class="items" style="width: 150px !important; flex: none">
<div>
<el-button
type="danger"
:icon="Delete"
circle
@click="rowDel(index)"
/>
</div>
</td>
</tr>
</template>
</draggable>
<tr v-if="ruleForm.tableData.length <= 0">
<td class="no_list">暂无数据</td>
</tr>
</tbody>
</table>
</el-scrollbar>
<el-form-item style="margin: 15px">
<el-button type="primary" @click="submitForm(ruleFormRef)">
提交
</el-button>
<el-button @click="resetForm(ruleFormRef)">重置</el-button>
</el-form-item>
</el-form>
</template>
<style lang="scss" scoped>
.const_box_nav {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 15px;
.l {
color: #000;
font-weight: 700;
}
}
.const_box {
width: 100%;
border: 1px solid #dcdfe6;
border-bottom: none;
background-color: #fff;
.box_list_header {
display: flex;
font-weight: 700;
.item {
flex: 1;
min-width: 150px;
height: 40px;
border-bottom: 1px solid #dcdfe6;
display: flex;
align-items: center;
justify-content: center;
}
.item:not(:first-child) {
border-left: 1px solid #dcdfe6;
}
}
.box_list_row {
display: flex;
cursor: move;
background-color: #fff;
.items {
flex: 1;
min-width: 150px;
padding: 0 15px;
padding-top: 18px;
border-bottom: 1px solid #dcdfe6;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.items:not(:first-child) {
border-left: 1px solid #dcdfe6;
}
.items:last-child {
padding: 0;
}
}
.box_list_row:nth-child(odd) {
background-color: #fafafa;
}
.ghost {
box-shadow: inset 0px 0px 1px 3px #409eff;
}
.no_list {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
height: 70px;
font-size: 14px;
color: #909399;
border-bottom: 1px solid #dcdfe6;
}
}
</style>
vuedraggable配置项说明
属性:
options配置项:
事件: