feat(stock): 增加库存列表筛选和排序功能
- 为过滤参数添加操作符选择(等于、模糊匹配、大于、小于) - 实现多条件筛选功能 - 添加每页显示条数选择 - 优化排序逻辑,固定 ID 列为第二排序条件 - 修复分页显示逻辑,适应每页显示全部的场景 - 优化 SQL 查询语句生成逻辑
This commit is contained in:
parent
1abc943e01
commit
ac2f1292f0
@ -101,7 +101,7 @@ public abstract class BaseRepository {
|
||||
public Flux<Map<String, Object>> getRows(String organization, String table, Map<String, Object> params, Pageable pageable) {
|
||||
params = preprocessParams(params);
|
||||
String orderBy = pageable.getSort().isEmpty()
|
||||
? "1"
|
||||
? ""
|
||||
: pageable.getSort().stream().map(order -> order.getProperty() + " " + order.getDirection()).collect(Collectors.joining(", "));
|
||||
long page = pageable.getPageNumber();
|
||||
long size = pageable.getPageSize();
|
||||
@ -157,7 +157,8 @@ public abstract class BaseRepository {
|
||||
sql.append(fields.isEmpty() ? " * " : fields.toString());
|
||||
sql.append(String.format(" FROM %s ", table));
|
||||
sql.append(wheres.toString());
|
||||
sql.append(String.format(" ORDER BY %s", orderBy));
|
||||
// 使用与RegionRepository和DictRepository一致的排序处理方式
|
||||
if (!orderBy.isEmpty()) sql.append(" ORDER BY ").append(orderBy);
|
||||
if (size > 0) sql.append(String.format(" LIMIT %d OFFSET %d", size, page * size));
|
||||
|
||||
DatabaseClient.GenericExecuteSpec executeSpec = db.sql(sql.toString()).bind("organization", organization);
|
||||
|
||||
@ -37,9 +37,9 @@ export default defineComponent({
|
||||
|
||||
// 过滤参数
|
||||
const filterParams = ref({
|
||||
number: null,
|
||||
name: null,
|
||||
property: null,
|
||||
number: { op: '=', value: null },
|
||||
name: { op: '=', value: null },
|
||||
property: { op: '=', value: null },
|
||||
});
|
||||
|
||||
const handleFilter = () => {
|
||||
@ -50,6 +50,9 @@ export default defineComponent({
|
||||
|
||||
const sort = () => {
|
||||
const result = [`${propOrder.value},${reverse.value ? 'desc' : 'asc'}`];
|
||||
if (propOrder.value !== 'id') {
|
||||
result.push('id');
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
@ -57,9 +60,10 @@ export default defineComponent({
|
||||
isFetching.value = true;
|
||||
try {
|
||||
const processedParams = showFilter.value
|
||||
? Object.entries(filterParams.value).reduce((acc, [key, value]) => {
|
||||
// 将空字符串转换为null,确保查询条件不生效
|
||||
acc[key] = value === '' ? null : value;
|
||||
? Object.entries(filterParams.value).reduce((acc, [key, { op, value }]) => {
|
||||
if (value !== null && value !== '') {
|
||||
acc[key] = { op, value };
|
||||
}
|
||||
return acc;
|
||||
}, {})
|
||||
: {};
|
||||
@ -110,6 +114,11 @@ export default defineComponent({
|
||||
handleSyncList();
|
||||
};
|
||||
|
||||
const handlePageSizeChange = () => {
|
||||
page.value = 1; // 重置页码
|
||||
handleSyncList();
|
||||
};
|
||||
|
||||
handleSyncList();
|
||||
|
||||
return {
|
||||
@ -126,6 +135,7 @@ export default defineComponent({
|
||||
handleSyncList,
|
||||
handleFilter,
|
||||
handlePageChange,
|
||||
handlePageSizeChange,
|
||||
prepareDelete,
|
||||
deleteStock,
|
||||
changeOrder,
|
||||
|
||||
@ -28,15 +28,39 @@
|
||||
<div class="form-section">
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="filter-number">{{ $t('jewpmsApp.stock.number') }}</label>
|
||||
<input type="text" class="form-control" id="filter-number" v-model="filterParams.number" />
|
||||
<div class="d-flex">
|
||||
<select class="form-control w-auto mr-2" v-model="filterParams.number.op">
|
||||
<option value="=">=</option>
|
||||
<option value="like">like</option>
|
||||
<option value=">">></option>
|
||||
<option value="<"><</option>
|
||||
</select>
|
||||
<input type="text" class="form-control" id="filter-number" v-model="filterParams.number.value" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="filter-name">{{ $t('jewpmsApp.stock.name') }}</label>
|
||||
<input type="text" class="form-control" id="filter-name" v-model="filterParams.name" />
|
||||
<div class="d-flex">
|
||||
<select class="form-control w-auto mr-2" v-model="filterParams.name.op">
|
||||
<option value="=">=</option>
|
||||
<option value="like">like</option>
|
||||
<option value=">">></option>
|
||||
<option value="<"><</option>
|
||||
</select>
|
||||
<input type="text" class="form-control" id="filter-name" v-model="filterParams.name.value" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="filter-property">{{ $t('jewpmsApp.stock.property') }}</label>
|
||||
<input type="text" class="form-control" id="filter-property" v-model="filterParams.property" />
|
||||
<div class="d-flex">
|
||||
<select class="form-control w-auto mr-2" v-model="filterParams.property.op">
|
||||
<option value="=">=</option>
|
||||
<option value="like">like</option>
|
||||
<option value=">">></option>
|
||||
<option value="<"><</option>
|
||||
</select>
|
||||
<input type="text" class="form-control" id="filter-property" v-model="filterParams.property.value" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -98,18 +122,26 @@
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<div class="row justify-content-center" v-if="totalItems > 0">
|
||||
<div class="col-sm-4">
|
||||
<div class="col-sm-2">
|
||||
<select class="form-control" v-model="itemsPerPage" @change="handlePageSizeChange">
|
||||
<option :value="10">{{ $t('entity.action.perpage', { itemsPerPage: 10 }) }}</option>
|
||||
<option :value="20">{{ $t('entity.action.perpage', { itemsPerPage: 20 }) }}</option>
|
||||
<option :value="50">{{ $t('entity.action.perpage', { itemsPerPage: 50 }) }}</option>
|
||||
<option :value="0">{{ $t('entity.action.all') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<div class="info jhi-item-count">
|
||||
{{
|
||||
$t('global.item-count', {
|
||||
first: (page - 1) * itemsPerPage + 1,
|
||||
second: page * itemsPerPage < totalItems ? page * itemsPerPage : totalItems,
|
||||
second: itemsPerPage > 0 && page * itemsPerPage < totalItems ? page * itemsPerPage : totalItems,
|
||||
total: totalItems,
|
||||
})
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="col-sm-7">
|
||||
<b-pagination
|
||||
v-model="page"
|
||||
:total-rows="totalItems"
|
||||
|
||||
@ -35,7 +35,7 @@ export const useDateFormat = ({ entityRef }: { entityRef?: Ref<Record<string, an
|
||||
: {};
|
||||
|
||||
const i18n = useI18n();
|
||||
const formatDateI18N = (date, format = 'short') => (date ? i18n.d(Date.parse(date), format) : null);
|
||||
const formatDateI18N = (date, format = 'short') => (date ? i18n.d(dayjs(date).toDate(), format) : null);
|
||||
const i18nUtils = {
|
||||
formatDateI18N,
|
||||
formatDateLong: date => formatDateI18N(date, 'long'),
|
||||
|
||||
@ -118,10 +118,11 @@
|
||||
"ribbon": {
|
||||
"dev": "开发环境"
|
||||
},
|
||||
"item-count": "显示第 { first } - { second } 条,共 { total } 条"
|
||||
"item-count": "显示第 { first } - { second } 行,共 { total } 行"
|
||||
},
|
||||
"entity": {
|
||||
"action": {
|
||||
"all": "全部",
|
||||
"actions": "操作",
|
||||
"addblob": "增加 BLOB",
|
||||
"addimage": "增加图片",
|
||||
@ -150,6 +151,7 @@
|
||||
"upload": "上传",
|
||||
"view": "查看",
|
||||
"tree": "树形",
|
||||
"perpage": "每页{ itemsPerPage }行",
|
||||
"page": "分页",
|
||||
"show": "显示 { otherEntity }",
|
||||
"select": "(选择)",
|
||||
|
||||
@ -44,6 +44,7 @@ const config = defineConfig({
|
||||
'@': fileURLToPath(new URL('./src/main/webapp/app/', import.meta.url)),
|
||||
'@content': fileURLToPath(new URL('./src/main/webapp/content/', import.meta.url)),
|
||||
},
|
||||
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
|
||||
},
|
||||
define: {
|
||||
I18N_HASH: '"generated_hash"',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user