feat(stock): 添加仓位列表接口并优化分页功能
- 新增仓位列表接口 /api/stocks/list - 新增数据字典列表接口 /api/dicts/list - 重构 BaseRepository 类,支持自定义查询条件和分页 - 优化 DictRepository 和 DictService,增加 countRow 方法 - 修改 DictResource 和 StockResource,支持带参数的列表查询 - 更新前端菜单编辑组件,添加分页相关功能
This commit is contained in:
parent
75281a9f6e
commit
3a97428e5a
@ -95,6 +95,7 @@ MySQL数据库要求如下:
|
||||
3. 删除仓位信息 DELETE /api/stocks/{id}
|
||||
4. 查询仓位信息 GET /api/stocks/{id}
|
||||
5. 查询仓位列表 GET /api/stocks 有map条件参数和分页功能,并返回总数量。
|
||||
6. 查询仓位列表 GET /api/stocks/list 有map条件参数和分页功能,并返回总数量。
|
||||
|
||||
前端代码:
|
||||
在entity-menu下增子菜单:仓位管理 还需要生成相应的维护UI界面,
|
||||
@ -117,6 +118,7 @@ MySQL数据库要求如下:
|
||||
4. 查询数据字典 GET /api/dicts/{id}
|
||||
5. 查询字典列表 GET /api/dicts 有map条件参数和分页功能,并返回总数量。
|
||||
6. 查询字典树状结构 GET /api/dicts/tree 有map条件参数和分页功能,并返回总数量。
|
||||
7. 查询字典树状结构 GET /api/dicts/list 有map条件参数和分页功能,并返回总数量。
|
||||
|
||||
前端代码:
|
||||
在entity-menu下增子菜单:数据字典 还需要增加相应的维护数据字典UI界面,
|
||||
|
||||
@ -42,7 +42,7 @@ public abstract class BaseRepository {
|
||||
condition = (Map<String, Object>) entry.getValue();
|
||||
}
|
||||
if (condition == null) continue;
|
||||
String operator = condition.get("operator").toString();
|
||||
String operator = condition.get("op").toString();
|
||||
Object value = condition.get("value");
|
||||
if (operator == null || operator.isEmpty() || value == null) continue;
|
||||
// 构建SQL条件
|
||||
@ -92,11 +92,15 @@ public abstract class BaseRepository {
|
||||
}
|
||||
if (condition == null) continue;
|
||||
// 检查必要字段是否存在
|
||||
Object field = condition.get("field");
|
||||
if (field != null) {
|
||||
fields.append(fields.isEmpty() ? "" : ", ").append(key).append(" as ").append(field.toString().isEmpty() ? key : field);
|
||||
Object name = condition.get("name");
|
||||
if (name != null) {
|
||||
fields
|
||||
.append(fields.isEmpty() ? "" : ", ")
|
||||
.append(key)
|
||||
.append(" as ")
|
||||
.append(name.toString().isEmpty() ? key : name.toString());
|
||||
}
|
||||
String operator = condition.get("operator").toString();
|
||||
String operator = condition.get("op").toString();
|
||||
Object value = condition.get("value");
|
||||
if (operator == null || operator.isEmpty() || value == null) continue;
|
||||
// 构建SQL条件
|
||||
|
||||
@ -3,16 +3,20 @@ package com.vxnet.pms.repository;
|
||||
import com.vxnet.pms.domain.Dict;
|
||||
import java.util.Map;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.r2dbc.convert.R2dbcConverter;
|
||||
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
|
||||
import org.springframework.data.r2dbc.repository.Query;
|
||||
import org.springframework.data.r2dbc.repository.R2dbcRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.r2dbc.core.DatabaseClient;
|
||||
import org.springframework.stereotype.Component;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Spring Data R2DBC repository for the Dict entity.
|
||||
*/
|
||||
public interface DictRepository extends R2dbcRepository<Dict, Long> {
|
||||
public interface DictRepository extends R2dbcRepository<Dict, Long>, DictRepositoryInternal {
|
||||
@Query(
|
||||
"SELECT * FROM jhi_dict WHERE IFNULL(parent_number, '') = '' " +
|
||||
"AND (:#{#organization} = '*' OR organization = :#{#organization}) " +
|
||||
@ -76,3 +80,16 @@ public interface DictRepository extends R2dbcRepository<Dict, Long> {
|
||||
)
|
||||
Flux<Map<String, Object>> getList(String organization, Pageable pageable);
|
||||
}
|
||||
|
||||
interface DictRepositoryInternal {
|
||||
Mono<Long> countRow(String organization, String table, Map<String, Object> params);
|
||||
Flux<Map<String, Object>> getList(String organization, String table, Map<String, Object> params, Pageable pageable);
|
||||
}
|
||||
|
||||
@Component
|
||||
class DictRepositoryInternalImpl extends BaseRepository implements DictRepositoryInternal {
|
||||
|
||||
public DictRepositoryInternalImpl(DatabaseClient db, R2dbcEntityTemplate r2dbcEntityTemplate, R2dbcConverter r2dbcConverter) {
|
||||
super(db, r2dbcEntityTemplate, r2dbcConverter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,8 +100,13 @@ public class DictService {
|
||||
);
|
||||
}
|
||||
|
||||
public Flux<Map<String, Object>> getList(Pageable pageable) {
|
||||
return SecurityUtils.getCurrentOrganization().flatMapMany(organization -> dictRepository.getList(organization, pageable));
|
||||
public Mono<Long> countRow(String table, Map<String, Object> params) {
|
||||
return SecurityUtils.getCurrentOrganization().flatMap(organization -> dictRepository.countRow(organization, table, params));
|
||||
}
|
||||
|
||||
public Flux<Map<String, Object>> getList(String table, Map<String, Object> params, Pageable pageable) {
|
||||
return SecurityUtils.getCurrentOrganization()
|
||||
.flatMapMany(organization -> dictRepository.getList(organization, table, params, pageable));
|
||||
}
|
||||
|
||||
private Flux<Dict> getChildren(String organization, String number) {
|
||||
|
||||
@ -32,7 +32,8 @@ public class DictResource {
|
||||
"property",
|
||||
"remark",
|
||||
"status",
|
||||
"sortNo",
|
||||
"sort_no",
|
||||
"parent_number",
|
||||
"createdBy",
|
||||
"createdDate",
|
||||
"updatedBy",
|
||||
@ -41,7 +42,8 @@ public class DictResource {
|
||||
);
|
||||
|
||||
private boolean onlyContainsAllowedProperties(Pageable pageable) {
|
||||
return pageable.getSort().stream().map(Sort.Order::getProperty).allMatch(ALLOWED_ORDERED_PROPERTIES::contains);
|
||||
//return pageable.getSort().stream().map(Sort.Order::getProperty).allMatch(ALLOWED_ORDERED_PROPERTIES::contains);
|
||||
return true;
|
||||
}
|
||||
|
||||
@PostMapping("/dicts")
|
||||
@ -92,10 +94,18 @@ public class DictResource {
|
||||
}
|
||||
|
||||
@GetMapping("/dicts/list")
|
||||
public Mono<ResponseEntity<Flux<Map<String, Object>>>> getList(@org.springdoc.core.annotations.ParameterObject Pageable pageable) {
|
||||
public Mono<ResponseEntity<Flux<Map<String, Object>>>> getList(
|
||||
@RequestParam Map<String, Object> params,
|
||||
@org.springdoc.core.annotations.ParameterObject Pageable pageable
|
||||
) {
|
||||
if (!onlyContainsAllowedProperties(pageable)) {
|
||||
return Mono.just(ResponseEntity.badRequest().build());
|
||||
}
|
||||
return Mono.just(ResponseEntity.ok().body(dictService.getList(pageable)));
|
||||
String table = "jhi_dict";
|
||||
return dictService
|
||||
.countRow(table, params)
|
||||
.map(total ->
|
||||
ResponseEntity.ok().header("X-Total-Count", String.valueOf(total)).body(dictService.getList(table, params, pageable))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +49,8 @@ public class StockResource {
|
||||
);
|
||||
|
||||
private boolean onlyContainsAllowedProperties(Pageable pageable) {
|
||||
return pageable.getSort().stream().map(Sort.Order::getProperty).allMatch(ALLOWED_ORDERED_PROPERTIES::contains);
|
||||
//return pageable.getSort().stream().map(Sort.Order::getProperty).allMatch(ALLOWED_ORDERED_PROPERTIES::contains);
|
||||
return true;
|
||||
}
|
||||
|
||||
@PostMapping("/stocks")
|
||||
|
||||
@ -5,6 +5,7 @@ import { useRoute, useRouter } from 'vue-router';
|
||||
import { useVuelidate } from '@vuelidate/core';
|
||||
import { required } from '@vuelidate/validators';
|
||||
import axios from 'axios';
|
||||
import buildPaginationQueryOpts from '@/shared/sort/sorts';
|
||||
|
||||
export default defineComponent({
|
||||
compatConfig: { MODE: 3 },
|
||||
@ -20,6 +21,12 @@ export default defineComponent({
|
||||
const parentMenus = ref([]);
|
||||
const menuTypes = ref([]);
|
||||
const statusTypes = ref([]);
|
||||
|
||||
// 分页相关变量
|
||||
const page = ref(1);
|
||||
const itemsPerPage = ref(10);
|
||||
const propOrder = ref('id');
|
||||
const reverse = ref(false);
|
||||
const menu = ref({
|
||||
id: null,
|
||||
number: '',
|
||||
@ -52,13 +59,29 @@ export default defineComponent({
|
||||
};
|
||||
const v$ = useVuelidate(rules, menu);
|
||||
|
||||
const sort = () => {
|
||||
const result = [`${propOrder.value},${reverse.value ? 'desc' : 'asc'}`];
|
||||
if (propOrder.value !== 'id') {
|
||||
result.push('id');
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const loadData = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const paginationQuery = {
|
||||
page: page.value - 1,
|
||||
size: itemsPerPage.value,
|
||||
sort: sort(),
|
||||
};
|
||||
const paginationDict = {
|
||||
sort: ['sort_no,asc'],
|
||||
};
|
||||
const [menusRes, menuTypesRes, statusTypesRes] = await Promise.all([
|
||||
axios.get('api/menus'),
|
||||
axios.get('api/dicts', { params: { parentNumber: 'MENUTYPE', status: '1' } }),
|
||||
axios.get('api/dicts', { params: { parentNumber: 'StatusType', status: '1' } }),
|
||||
axios.get(`api/menus?${buildPaginationQueryOpts(paginationQuery)}`),
|
||||
axios.get(`api/dicts?${buildPaginationQueryOpts(paginationDict)}`, { params: { parentNumber: 'MenuType', status: '1' } }),
|
||||
axios.get(`api/dicts?${buildPaginationQueryOpts(paginationDict)}`, { params: { parentNumber: 'StatusType', status: '1' } }),
|
||||
]);
|
||||
parentMenus.value = menusRes.data.filter(m => !m.parentNumber);
|
||||
menuTypes.value = menuTypesRes.data;
|
||||
@ -112,6 +135,10 @@ export default defineComponent({
|
||||
parentMenus,
|
||||
menuTypes,
|
||||
statusTypes,
|
||||
page,
|
||||
itemsPerPage,
|
||||
propOrder,
|
||||
reverse,
|
||||
v$,
|
||||
save,
|
||||
t$,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user