118 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
import { faker } from '@faker-js/faker';
 | 
						|
import { eventHandler, getQuery } from 'h3';
 | 
						|
import { verifyAccessToken } from '~/utils/jwt-utils';
 | 
						|
import {
 | 
						|
  sleep,
 | 
						|
  unAuthorizedResponse,
 | 
						|
  usePageResponseSuccess,
 | 
						|
} from '~/utils/response';
 | 
						|
 | 
						|
function generateMockDataList(count: number) {
 | 
						|
  const dataList = [];
 | 
						|
 | 
						|
  for (let i = 0; i < count; i++) {
 | 
						|
    const dataItem = {
 | 
						|
      id: faker.string.uuid(),
 | 
						|
      imageUrl: faker.image.avatar(),
 | 
						|
      imageUrl2: faker.image.avatar(),
 | 
						|
      open: faker.datatype.boolean(),
 | 
						|
      status: faker.helpers.arrayElement(['success', 'error', 'warning']),
 | 
						|
      productName: faker.commerce.productName(),
 | 
						|
      price: faker.commerce.price(),
 | 
						|
      currency: faker.finance.currencyCode(),
 | 
						|
      quantity: faker.number.int({ min: 1, max: 100 }),
 | 
						|
      available: faker.datatype.boolean(),
 | 
						|
      category: faker.commerce.department(),
 | 
						|
      releaseDate: faker.date.past(),
 | 
						|
      rating: faker.number.float({ min: 1, max: 5 }),
 | 
						|
      description: faker.commerce.productDescription(),
 | 
						|
      weight: faker.number.float({ min: 0.1, max: 10 }),
 | 
						|
      color: faker.color.human(),
 | 
						|
      inProduction: faker.datatype.boolean(),
 | 
						|
      tags: Array.from({ length: 3 }, () => faker.commerce.productAdjective()),
 | 
						|
    };
 | 
						|
 | 
						|
    dataList.push(dataItem);
 | 
						|
  }
 | 
						|
 | 
						|
  return dataList;
 | 
						|
}
 | 
						|
 | 
						|
const mockData = generateMockDataList(100);
 | 
						|
 | 
						|
export default eventHandler(async (event) => {
 | 
						|
  const userinfo = verifyAccessToken(event);
 | 
						|
  if (!userinfo) {
 | 
						|
    return unAuthorizedResponse(event);
 | 
						|
  }
 | 
						|
 | 
						|
  await sleep(600);
 | 
						|
 | 
						|
  const { page, pageSize, sortBy, sortOrder } = getQuery(event);
 | 
						|
  // 规范化分页参数,处理 string[]
 | 
						|
  const pageRaw = Array.isArray(page) ? page[0] : page;
 | 
						|
  const pageSizeRaw = Array.isArray(pageSize) ? pageSize[0] : pageSize;
 | 
						|
  const pageNumber = Math.max(
 | 
						|
    1,
 | 
						|
    Number.parseInt(String(pageRaw ?? '1'), 10) || 1,
 | 
						|
  );
 | 
						|
  const pageSizeNumber = Math.min(
 | 
						|
    100,
 | 
						|
    Math.max(1, Number.parseInt(String(pageSizeRaw ?? '10'), 10) || 10),
 | 
						|
  );
 | 
						|
  const listData = structuredClone(mockData);
 | 
						|
 | 
						|
  // 规范化 query 入参,兼容 string[]
 | 
						|
  const sortKeyRaw = Array.isArray(sortBy) ? sortBy[0] : sortBy;
 | 
						|
  const sortOrderRaw = Array.isArray(sortOrder) ? sortOrder[0] : sortOrder;
 | 
						|
  // 检查 sortBy 是否是 listData 元素的合法属性键
 | 
						|
  if (
 | 
						|
    typeof sortKeyRaw === 'string' &&
 | 
						|
    listData[0] &&
 | 
						|
    Object.prototype.hasOwnProperty.call(listData[0], sortKeyRaw)
 | 
						|
  ) {
 | 
						|
    // 定义数组元素的类型
 | 
						|
    type ItemType = (typeof listData)[0];
 | 
						|
    const sortKey = sortKeyRaw as keyof ItemType; // 将 sortBy 断言为合法键
 | 
						|
    const isDesc = sortOrderRaw === 'desc';
 | 
						|
    listData.sort((a, b) => {
 | 
						|
      const aValue = a[sortKey] as unknown;
 | 
						|
      const bValue = b[sortKey] as unknown;
 | 
						|
 | 
						|
      let result = 0;
 | 
						|
 | 
						|
      if (typeof aValue === 'number' && typeof bValue === 'number') {
 | 
						|
        result = aValue - bValue;
 | 
						|
      } else if (aValue instanceof Date && bValue instanceof Date) {
 | 
						|
        result = aValue.getTime() - bValue.getTime();
 | 
						|
      } else if (typeof aValue === 'boolean' && typeof bValue === 'boolean') {
 | 
						|
        if (aValue === bValue) {
 | 
						|
          result = 0;
 | 
						|
        } else {
 | 
						|
          result = aValue ? 1 : -1;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        const aStr = String(aValue);
 | 
						|
        const bStr = String(bValue);
 | 
						|
        const aNum = Number(aStr);
 | 
						|
        const bNum = Number(bStr);
 | 
						|
        result =
 | 
						|
          Number.isFinite(aNum) && Number.isFinite(bNum)
 | 
						|
            ? aNum - bNum
 | 
						|
            : aStr.localeCompare(bStr, undefined, {
 | 
						|
                numeric: true,
 | 
						|
                sensitivity: 'base',
 | 
						|
              });
 | 
						|
      }
 | 
						|
 | 
						|
      return isDesc ? -result : result;
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  return usePageResponseSuccess(
 | 
						|
    String(pageNumber),
 | 
						|
    String(pageSizeNumber),
 | 
						|
    listData,
 | 
						|
  );
 | 
						|
});
 |