Skip to content

Commit

Permalink
feat(pixi): add pixi demo
Browse files Browse the repository at this point in the history
  • Loading branch information
qhanw committed Sep 12, 2024
1 parent 58c1389 commit bdf9046
Show file tree
Hide file tree
Showing 121 changed files with 10,314 additions and 1,987 deletions.
17 changes: 17 additions & 0 deletions pixi/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# http://editorconfig.org

root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[Makefile]
indent_style = tab
20 changes: 0 additions & 20 deletions pixi/.eslintrc.cjs

This file was deleted.

1 change: 1 addition & 0 deletions pixi/.husky/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx --no -- commitlint --edit $1
1 change: 1 addition & 0 deletions pixi/.husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm exec lint-staged
14 changes: 14 additions & 0 deletions pixi/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/public
/dist
/coverage

**/*.svg
*.png

.DS_Store
.eslintignore
.eslintcache

.editorconfig
.gitignore
.prettierignore
11 changes: 11 additions & 0 deletions pixi/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/** @type {import("prettier").Config} */
const config = {
singleQuote: true,
trailingComma: 'all',
printWidth: 100,
proseWrap: 'never',
endOfLine: 'lf',
overrides: [{ files: '.prettierrc.js' }],
}

export default config
1 change: 1 addition & 0 deletions pixi/commitlint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default { extends: ['@commitlint/config-conventional'] };
25 changes: 25 additions & 0 deletions pixi/config/access.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { Route } from './base';

// import { getUserInfo, getAuthKeys } from '@/utils/store';

type AuthProvider = {
canAccess: (route?: Route) => void;
[propName: string]: any;
};

export const access: AuthProvider = {
canAccess: (route) => {
// 如果是超级管理员
const isAdmin = 'root' === 'root';
if (isAdmin) return isAdmin;

const authKeys = [] as string[];

// 如果权限权限不存在
if (!authKeys?.length || !route?.path) return false;

const key = route.path.replace(/^\//, '').replace(/\//g, ':').toUpperCase().replace(/-/g, '_');

return authKeys.includes(key);
},
};
33 changes: 33 additions & 0 deletions pixi/config/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// explain: https://unocss.dev/guide/extracting#extracting-from-build-tools-pipeline
// @unocss-include

export type Route = {
path?: string;
element?: string;
name?: string;
icon?: React.ReactNode;
index?: boolean;
layout?: string;
access?: string;
children?: Route[];
redirect?: string;
hideInMenu?: boolean;
};

const routes: Route[] = [
{
path: '/',
layout: './layouts/BaseLayout',
children: [
{ path: 'lands', name: 'lands', element: './lands' },
{ path: 'ads', name: 'ads', element: './ads' },
{ path: 'recharge', name: 'recharge', element: './recharge' },

{ path: '*', element: './exception/404' },
],
},

{ path: '*', element: './exception/404' },
];

export default routes;
37 changes: 37 additions & 0 deletions pixi/config/menus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { Route } from './base';
import base from './base';
import { access } from './access';
import { getFullPath } from './utils';

const genMenus = function f(r: Route[], parent?: Route) {
return r.reduce((prev, curr) => {
const { index, children, icon, path } = curr;

if (index) curr.path = parent?.path || '/';

if (icon && typeof icon === 'string') {
curr.icon = <span className={`anticon ${icon}`} />;
}

// full path
// 补全 path 使路由变为绝对地址
const fullPath = getFullPath(curr, parent?.path);

// 权限过滤
// 如果子页面没有权限配置则继承父级权限
const realPath = path !== '*';
const acc = fullPath.access || parent?.access;
const pass = acc && realPath ? access[acc]?.(fullPath) : true;

if (pass && realPath) {
prev.push({
...fullPath,
...(children ? { children: f(children, { ...fullPath, access: acc }) } : {}),
});
}

return prev;
}, [] as Route[]);
};

export const menus = () => genMenus(base.filter((node) => node.path === '/')).at(-1);
85 changes: 85 additions & 0 deletions pixi/config/routes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React, { Suspense, lazy } from 'react';
import { Spin } from 'antd';
import { Outlet, Navigate } from 'react-router-dom';
import type { Route } from './base';
import base from './base';
import { access } from './access';
import { getFullPath } from './utils';

import ErrorBoundary from '@/pages/exception/ErrorBoundary';

const lazyLoad = (src: any) => (
<Suspense fallback={<Spin spinning />}>{React.createElement(lazy(src))}</Suspense>
);

// 动态路由配置
const pages = import.meta.glob([
'/src/{pages,layouts}/**/*.{ts,tsx,js,jsx}',
'!**/{components,utils,services,auth,modals,map}',
'!**/{utils,util,service,services,auth,modal}.{ts,tsx,js,jsx}',
'!**/*.{d.ts,json}',
]);

const exception = {
403: '/src/pages/exception/403',
404: '/src/pages/exception/404',
500: '/src/pages/exception/500',
ErrorBoundary: '/src/pages/exception/ErrorBoundary',
};

const metaPages = Object.entries(pages).reduce(
(prev, [key, val]) => ({
...prev,
[key.replace(/(\/index)?\.tsx$/, '')]: val,
}),
{} as any,
);

/**
* 根据配置文件解析路由
* @param r 路由配置
* @param allow 继承父级权限
* @returns 路由配置
*/
const genRoutes = function f(r: Route[], parent?: Route): any {
return r.map((curr) => {
const { index, path, layout, element, children, redirect, access: acc } = curr;
// 如果不存在 layout 和 页面组件,表示当前路由层为无布局容器页
const isEmptyContainer = !(layout || element);

let page;
if (!isEmptyContainer) {
const replacer = `/src/${layout ? '' : 'pages/'}`;
page = metaPages[(layout ?? element)!.replace('./', replacer)];
}

const elem = page ?? metaPages[exception[404]];

// full path
// 补全 path 使路由变为绝对地址
const fullPath = getFullPath(curr, parent?.path);

return {
loader: () => {
// 鉴权权限
// 先判断父级权限,现判断子页权限

const p = parent?.access && access[parent?.access](fullPath);
const c = acc && access[acc](fullPath);
const pass = p ?? c ?? true;

const realPath = path !== '*'; // 是否为真实路由地址
if (!pass && realPath) throw new Response('Not Authorized', { status: 403 });

return null;
},
errorElement: <ErrorBoundary />, // lazyLoad(metaPages[exception.ErrorBoundary]),
element: isEmptyContainer ? <Outlet /> : lazyLoad(elem),
...(index ? { index } : { path }),
...(redirect ? { element: <Navigate to={redirect} replace /> } : {}),
...(children ? { children: f(children, fullPath) } : {}),
};
});
};

export const routes = genRoutes(base);
16 changes: 16 additions & 0 deletions pixi/config/site.cfg.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { ProLayoutProps } from '@ant-design/pro-components';

const cfg: ProLayoutProps = {
title: 'SYS',
location: { pathname: '/' },
appList: [
{
icon: 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
title: 'Ant Design',
desc: '杭州市较知名的 UI 设计语言',
url: 'https://ant.design',
},
],
};

export default cfg;
12 changes: 12 additions & 0 deletions pixi/config/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Route } from './base';

export function getFullPath(curr: Route, parentPath?: string) {
const path = curr.path;
return {
...curr,
path: path?.startsWith('/')
? path
: '/' +
[...(parentPath?.split('/') || []), ...(path?.split('/') || [])].filter(Boolean).join('/'),
};
}
40 changes: 40 additions & 0 deletions pixi/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';

export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],

'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
args: 'all',
argsIgnorePattern: '^_',
caughtErrors: 'all',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_',
varsIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
'@typescript-eslint/consistent-type-imports': 'error',
},
},
);
4 changes: 2 additions & 2 deletions pixi/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>PixiJs Example</title>
</head>
<body>
<div id="root"></div>
Expand Down
Loading

0 comments on commit bdf9046

Please sign in to comment.