feat: 为搜索输入框添加.native.prevent修饰符并优化角色表单菜单选择

1. 在多个视图的搜索输入框上添加.native.prevent修饰符,防止表单默认提交行为
2. 重构角色表单的菜单权限选择,从树形结构改为分类复选框形式
3. 在智能柜详情页添加商品名称搜索功能
4. 在cabinet-cell接口中添加goodsName查询参数
This commit is contained in:
dzq 2025-05-26 09:59:51 +08:00
parent 9d7b502698
commit 210386a036
18 changed files with 125 additions and 78 deletions

View File

@ -4,6 +4,7 @@ export interface CabinetCellQuery extends BasePageQuery {
cabinetId?: number;
cellNo?: number;
cellType?: number;
goodsName?: string;
}
export interface CabinetCellDTO {

View File

@ -204,12 +204,12 @@ const switchCellType = (cellType: number) => {
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="柜体ID" prop="cabinetId">
<el-input @keyup.enter="onSearch" v-model.number="searchFormParams.cabinetId" placeholder="请输入柜体ID" clearable
class="!w-[200px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model.number="searchFormParams.cabinetId"
placeholder="请输入柜体ID" clearable class="!w-[200px]" />
</el-form-item>
<el-form-item label="单元格号:" prop="cellNo">
<el-input @keyup.enter="onSearch" v-model.number="searchFormParams.cellNo" placeholder="请输入单元格号" clearable
class="!w-[180px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model.number="searchFormParams.cellNo"
placeholder="请输入单元格号" clearable class="!w-[180px]" />
</el-form-item>
<el-form-item label="单元格类型:" prop="cellType">
<el-select v-model="searchFormParams.cellType" placeholder="请选择类型" clearable class="!w-[180px]">

View File

@ -122,12 +122,12 @@ getList();
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="服务地址:" prop="serverUrl">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.serverUrl" placeholder="请输入服务地址" clearable
class="!w-[200px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.serverUrl" placeholder="请输入服务地址"
clearable class="!w-[200px]" />
</el-form-item>
<el-form-item label="用户名:" prop="username">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.username" placeholder="请输入用户名" clearable
class="!w-[200px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.username" placeholder="请输入用户名"
clearable class="!w-[200px]" />
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="useRenderIcon(Search)" @click="onSearch">

View File

@ -84,8 +84,8 @@ getList();
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="格口ID" prop="cellId">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.cellId" placeholder="请输入格口ID" clearable
class="!w-[200px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.cellId" placeholder="请输入格口ID"
clearable class="!w-[200px]" />
</el-form-item>
<el-form-item label="操作类型:" prop="operationType">
<el-select v-model="searchFormParams.operationType" placeholder="请选择类型" clearable class="!w-[180px]">

View File

@ -138,8 +138,8 @@ getList();
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="商店名称:" prop="shopName">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.shopName" placeholder="请输入商店名称" clearable
class="!w-[200px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.shopName" placeholder="请输入商店名称"
clearable class="!w-[200px]" />
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="useRenderIcon(Search)" @click="onSearch">

View File

@ -2,7 +2,7 @@
import { ref, onMounted } from "vue";
import { useRoute, useRouter } from "vue-router";
import { getSmartCabinetDetailApi, type SmartCabinetDTO } from "@/api/cabinet/smart-cabinet";
import { changeGoodsCellsStock, clearGoodsCells, getCabinetCellList, type CabinetCellDTO } from "@/api/cabinet/cabinet-cell";
import { CabinetCellQuery, changeGoodsCellsStock, clearGoodsCells, getCabinetCellList, type CabinetCellDTO } from "@/api/cabinet/cabinet-cell";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { CabinetImgMap } from "@/utils/cabinetImgMap";
import GatewayConfigModal from "@/views/cabinet/smart-cabinet/GatewayConfigModal.vue";
@ -50,6 +50,9 @@ const shopConfigVisible = ref(false);
const mainCabinetConfigVisible = ref(false);
const editCabinetDrawerVisible = ref(false);
const cellList = ref<CabinetCellDTO[]>([]);
const searchCellParams = ref<CabinetCellQuery>({
goodsName: null
});
const cellPagination = ref({
pageSize: 5,
currentPage: 1,
@ -140,11 +143,17 @@ function switchCellType(cellType: number) {
}
}
function resetCellSearch() {
searchCellParams.value.cellNo = null;
fetchCellList();
}
async function fetchCellList() {
try {
loading.value = true;
const { data } = await getCabinetCellList({
cabinetId: cabinetId.value,
goodsName: searchCellParams.value.goodsName,
pageSize: cellPagination.value.pageSize,
pageNum: cellPagination.value.currentPage
});
@ -304,10 +313,26 @@ onMounted(() => {
</div>
<div class="cell-details" v-if="activeTab === 'cells'">
<div style="display: flex; justify-content: flex-end; margin-bottom: 16px;">
<el-button type="primary" :size="'small'" :icon="useRenderIcon(AddFill)" @click="cellFormVisible = true">
<div style="display: flex; justify-content: space-between; margin-bottom: 16px;">
<el-form :inline="true" :model="searchCellParams" class="search-form">
<el-form-item>
<el-input @keyup.enter.native.prevent="fetchCellList" v-model="searchCellParams.goodsName"
placeholder="请输入商品名称" clearable class="!w-[180px]" />
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="useRenderIcon(Search)" :loading="loading" @click="fetchCellList">
搜索
</el-button>
</el-form-item>
<el-form-item>
<el-button :icon="useRenderIcon(Refresh)" @click="resetCellSearch">
重置
</el-button>
</el-form-item>
</el-form>
<!-- <el-button type="primary" :size="'small'" :icon="useRenderIcon(AddFill)" @click="cellFormVisible = true">
新增格口
</el-button>
</el-button> -->
</div>
<el-table v-loading="loading" :data="cellList" border>
<el-table-column label="格口ID" prop="cellId" width="80" />
@ -346,7 +371,8 @@ onMounted(() => {
</el-table-column>
<el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }">
<el-button v-if="cabinetInfo.belongType === 0" type="success" link :icon="useRenderIcon(AddFill)" @click="handleConfigure(row)">
<el-button v-if="cabinetInfo.belongType === 0" type="success" link :icon="useRenderIcon(AddFill)"
@click="handleConfigure(row)">
配置商品
</el-button>

View File

@ -92,8 +92,8 @@ onMounted(() => {
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color flex w-[99/100] pl-[22px] pt-[12px]">
<el-form-item label="" prop="cabinetName">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.cabinetName" placeholder="请输入柜体名称" clearable
class="!w-[200px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.cabinetName" placeholder="请输入柜体名称"
clearable class="!w-[200px]" />
</el-form-item>
<el-form-item label="" prop="cabinetType">
<el-select v-model="searchFormParams.cabinetType" placeholder="请选择柜体类型" clearable class="!w-[180px]">

View File

@ -160,8 +160,8 @@ getList();
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="柜体名称:" prop="cabinetName">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.cabinetName" placeholder="请输入柜体名称" clearable
class="!w-[200px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.cabinetName" placeholder="请输入柜体名称"
clearable class="!w-[200px]" />
</el-form-item>
<el-form-item label="柜体类型:" prop="cabinetType">
<el-select v-model="searchFormParams.cabinetType" placeholder="请选择类型" clearable class="!w-[180px]">

View File

@ -86,12 +86,12 @@ getList().then(() => getTotalBalance());
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="姓名:" prop="name">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.name" placeholder="请输入姓名" clearable
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.name" placeholder="请输入姓名" clearable
class="!w-[180px]" />
</el-form-item>
<el-form-item label="手机号:" prop="mobile">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.mobile" placeholder="请输入手机号" clearable
class="!w-[180px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.mobile" placeholder="请输入手机号"
clearable class="!w-[180px]" />
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="useRenderIcon(Search)" @click="onSearch">

View File

@ -133,16 +133,16 @@ getList();
value-format="YYYY-MM-DD HH:mm:ss" class="!w-[200px]" />
</el-form-item>
<el-form-item label="审批ID" prop="approvalId">
<el-input @keyup.enter="onSearch" v-model.number="searchFormParams.approvalId" placeholder="请输入审批ID" clearable
class="!w-[180px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model.number="searchFormParams.approvalId"
placeholder="请输入审批ID" clearable class="!w-[180px]" />
</el-form-item>
<el-form-item label="订单ID" prop="orderId">
<el-input @keyup.enter="onSearch" v-model.number="searchFormParams.orderId" placeholder="请输入订单ID" clearable
class="!w-[180px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model.number="searchFormParams.orderId" placeholder="请输入订单ID"
clearable class="!w-[180px]" />
</el-form-item>
<el-form-item label="商品ID" prop="goodsId">
<el-input @keyup.enter="onSearch" v-model.number="searchFormParams.goodsId" placeholder="请输入商品ID" clearable
class="!w-[180px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model.number="searchFormParams.goodsId" placeholder="请输入商品ID"
clearable class="!w-[180px]" />
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-select v-model="searchFormParams.status" placeholder="请选择状态" clearable class="!w-[180px]">

View File

@ -231,8 +231,8 @@ const handleClearGoods = async (row: CabinetCellDTO) => {
<div class="flex-1 pl-4">
<el-form ref="formRef" :inline="true" :model="searchFormParams" class="search-form bg-bg_color w-full pt-[12px]">
<el-form-item label="单元格号:" prop="cellNo">
<el-input @keyup.enter="onSearch" v-model.number="searchFormParams.cellNo" placeholder="请输入单元格号" clearable
class="!w-[180px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model.number="searchFormParams.cellNo"
placeholder="请输入单元格号" clearable class="!w-[180px]" />
</el-form-item>
<el-form-item label="单元格类型:" prop="cellType">
<el-select v-model="searchFormParams.cellType" placeholder="请选择类型" clearable class="!w-[180px]">
@ -312,7 +312,7 @@ const handleClearGoods = async (row: CabinetCellDTO) => {
</el-table-column>
</el-table>
<el-pagination v-model:current-page="pagination.currentPage" v-model:page-size="pagination.pageSize"
:page-sizes="[5,8,10,11,12,13,14,15,16,18,20]" layout="total, sizes, prev, pager, next, jumper"
:page-sizes="[5, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20]" layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total" @size-change="onSizeChange" @current-change="onCurrentChange" class="pagination" />
</div>
<el-dialog v-model="configVisible" title="配置商品" width="80%">

View File

@ -158,11 +158,12 @@ getList();
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="分类名称:" prop="categoryName">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.categoryName" placeholder="请输入分类名称" clearable
class="!w-[200px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.categoryName" placeholder="请输入分类名称"
clearable class="!w-[200px]" />
</el-form-item>
<el-form-item label="排序:" prop="sort">
<el-input-number @keyup.enter="onSearch" v-model="searchFormParams.sort" :min="0" class="!w-[120px]" />
<el-input-number @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.sort" :min="0"
class="!w-[120px]" />
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="useRenderIcon(Search)" @click="onSearch">

View File

@ -134,8 +134,8 @@ const handleEdit = (row: GoodsDTO) => {
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="商品名称:" prop="goodsName">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.goodsName" placeholder="请输入商品名称" clearable
class="!w-[200px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.goodsName" placeholder="请输入商品名称"
clearable class="!w-[200px]" />
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-select v-model="searchFormParams.status" placeholder="请选择状态" clearable class="!w-[180px]">
@ -209,7 +209,7 @@ const handleEdit = (row: GoodsDTO) => {
删除
</el-button>
</template>
</el-popconfirm> -->
</el-popconfirm> -->
</template>
</el-table-column>
</el-table>

View File

@ -142,12 +142,12 @@ getList();
value-format="YYYY-MM-DD HH:mm:ss" class="!w-[200px]" />
</el-form-item>
<el-form-item label="订单编号:" prop="orderId">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.orderId" placeholder="请输入订单编号" clearable
class="!w-[200px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.orderId" placeholder="请输入订单编号"
clearable class="!w-[200px]" />
</el-form-item>
<el-form-item label="格口ID" prop="cellId">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.cellId" placeholder="请输入格口ID" clearable
class="!w-[200px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.cellId" placeholder="请输入格口ID"
clearable class="!w-[200px]" />
</el-form-item>
<el-form-item label="订单状态:" prop="status">
<el-select v-model="searchFormParams.status" placeholder="请选择状态" clearable class="!w-[180px]">

View File

@ -101,20 +101,42 @@ async function handleConfirm() {
loading.value = false;
}
}
const processedMenuOptions = computed(() => {
const categories = [];
const collectLeaves = (menu: MenuDTO) => {
if (!menu.children) return [];
return menu.children.filter(child => child.children?.length ? false : true);
};
const collectMenus = (menuOption: MenuDTO) => {
const leaves = collectLeaves(menuOption);
leaves.unshift(menuOption);
if (leaves.length) {
categories.push({
categoryName: menuOption.menuName,
items: leaves
});
}
if (menuOption.children?.length) {
const lastMenu = menuOption.children.filter(child => child.children?.length);
lastMenu.forEach(child => {
collectMenus(child);
});
}
};
props.menuOptions.forEach(menuOption => {
collectMenus(menuOption);
})
return categories;
});
</script>
<template>
<v-dialog
show-full-screen
fixed-body-height
use-body-scrolling
:title="type === 'add' ? '新增角色' : '更新角色'"
v-model="visible"
:loading="loading"
@confirm="handleConfirm"
@cancel="visible = false"
@opened="handleOpened"
>
<v-dialog show-full-screen fixed-body-height use-body-scrolling :title="type === 'add' ? '新增角色' : '更新角色'"
v-model="visible" :loading="loading" @confirm="handleConfirm" @cancel="visible = false" @opened="handleOpened">
<el-form :model="formData" label-width="120px" :rules="rules" ref="formRef">
<el-form-item prop="roleName" label="角色名称" required inline-message>
<el-input v-model="formData.roleName" />
@ -127,29 +149,20 @@ async function handleConfirm() {
</el-form-item>
<el-form-item prop="status" label="角色状态">
<el-radio-group v-model="formData.status">
<el-radio
v-for="item in Object.keys(statusList)"
:key="item"
:label="statusList[item].value"
>{{ statusList[item].label }}</el-radio
>
<el-radio v-for="item in Object.keys(statusList)" :key="item" :label="statusList[item].value">{{
statusList[item].label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="菜单权限" prop="menuIds">
<el-tree
ref="treeRef"
:props="{ label: 'menuName', children: 'children' }"
:data="props.menuOptions"
node-key="id"
check-strictly
show-checkbox
default-expand-all
check-on-click-node
:expand-on-click-node="false"
:default-checked-keys="formData.menuIds"
@check-change="handleCheckChange"
style="width: 100%"
/>
<el-checkbox-group v-model="formData.menuIds" class="checkbox-group">
<template v-for="menu in processedMenuOptions" :key="menu.id">
<span class="menu-category">{{ menu.categoryName }}</span>
<el-checkbox v-for="item in menu.items" :key="item.id" :label="item.id" class="menu-checkbox">
{{ item.menuName }}
</el-checkbox>
<el-divider class="divider" />
</template>
</el-checkbox-group>
</el-form-item>
<el-form-item prop="remark" label="备注" style="margin-bottom: 0">
<el-input type="textarea" v-model="formData.remark" />
@ -157,3 +170,9 @@ async function handleConfirm() {
</el-form>
</v-dialog>
</template>
<style scoped lang="scss">
.divider {
margin: 4px 0;
}
</style>

View File

@ -53,8 +53,8 @@ watch(
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="姓名:" prop="nickname">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.nickname" placeholder="请输入" clearable
class="!w-[160px]" />
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.nickname" placeholder="请输入"
clearable class="!w-[160px]" />
</el-form-item>
<!-- <el-form-item label="用户编号:" prop="userId">
<el-input

View File

@ -116,7 +116,7 @@ onMounted(() => {
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="搜索:" prop="search">
<el-input v-model="searchFormParams.search" placeholder="请输入姓名/手机号/身份证" clearable class="!w-[300px]"
@keyup.enter="onSearch" @change="handleSearchInput" />
@keyup.enter.native.prevent="onSearch" @change="handleSearchInput" />
</el-form-item>
<el-form-item label="标签:" prop="tagName">
<el-select v-model="searchFormParams.tagName" placeholder="请选择" clearable class="!w-[160px]">

View File

@ -51,7 +51,7 @@ watch(
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="姓名:" prop="name">
<el-input @keyup.enter="onSearch" v-model="searchFormParams.name" placeholder="请输入" clearable
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.name" placeholder="请输入" clearable
class="!w-[160px]" />
</el-form-item>
<el-form-item>