使用routify路由
This commit is contained in:
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
68
.routify/components/[...404].svelte
Normal file
68
.routify/components/[...404].svelte
Normal file
@@ -0,0 +1,68 @@
|
||||
<script context="module">
|
||||
export const load = ({ route }) => ({
|
||||
status: 404,
|
||||
error: '[Routify] Page could not be found.',
|
||||
props: { url: route.url },
|
||||
})
|
||||
|
||||
const isDev = import.meta.env?.DEV
|
||||
</script>
|
||||
|
||||
<script>
|
||||
export let url
|
||||
</script>
|
||||
|
||||
<!-- routify:meta inline=false -->
|
||||
|
||||
<!-- This file was created by Routify.
|
||||
To customize the error page, create a catchall page
|
||||
in the root of your project. Eg. [...404].svelte -->
|
||||
<div class="four04">
|
||||
<h1>404 - Page Not Found</h1>
|
||||
<p>
|
||||
The page <code>{url}</code> could not be found. Please check the URL or go back to
|
||||
the <a href="/">homepage</a>.
|
||||
</p>
|
||||
{#if isDev}
|
||||
<div>
|
||||
<h5>Dev note:</h5>
|
||||
<ul>
|
||||
<li>
|
||||
To customize this page, create a
|
||||
<code>[...404].svelte</code> file in the root of your project.
|
||||
</li>
|
||||
<li>
|
||||
You can copy this file from <code
|
||||
>.routify/components/[...404].svelte</code
|
||||
>.
|
||||
</li>
|
||||
<li>
|
||||
Custom 404 files can be created at any level of your project. For
|
||||
example, in <code>src/pages/blog/[...404].svelte</code>.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
div.four04 > * {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
}
|
||||
ul li {
|
||||
opacity: 75%;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
7
.routify/instance.default.js
Normal file
7
.routify/instance.default.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Router, createRouter } from '@roxi/routify'
|
||||
import routes from './routes.default.js'
|
||||
|
||||
// remove previous routers to avoid bumping router names (/path => /1/path)
|
||||
globalThis.__routify.reset()
|
||||
export const router = createRouter({routes})
|
||||
export { Router, routes }
|
6
.routify/render.js
Normal file
6
.routify/render.js
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
import * as module from '../src/App.svelte'
|
||||
import { renderModule } from '@roxi/routify/tools/ssr5.js'
|
||||
import { map } from './route-map.js'
|
||||
|
||||
export const render = url => renderModule(module, { url, routesMap: map })
|
4
.routify/route-map.js
Normal file
4
.routify/route-map.js
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
export const map = {
|
||||
'default': () => import('./routes.default.js').then(m => m.default)
|
||||
}
|
144
.routify/routes.default.js
Normal file
144
.routify/routes.default.js
Normal file
@@ -0,0 +1,144 @@
|
||||
// @ts-nocheck
|
||||
|
||||
|
||||
export const routes = {
|
||||
"meta": {},
|
||||
"id": "_default",
|
||||
"name": "",
|
||||
"file": {
|
||||
"path": "src/routes/_module.svelte",
|
||||
"dir": "src/routes",
|
||||
"base": "_module.svelte",
|
||||
"ext": ".svelte",
|
||||
"name": "_module"
|
||||
},
|
||||
"asyncModule": () => import('../src/routes/_module.svelte'),
|
||||
"rootName": "default",
|
||||
"routifyDir": import.meta.url,
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"dynamic": true,
|
||||
"order": false,
|
||||
"dynamicSpread": true,
|
||||
"hideInMenu": true
|
||||
},
|
||||
"id": "_default_____404__svelte",
|
||||
"name": "[...404]",
|
||||
"file": {
|
||||
"path": "src/routes/[...404].svelte",
|
||||
"dir": "src/routes",
|
||||
"base": "[...404].svelte",
|
||||
"ext": ".svelte",
|
||||
"name": "[...404]"
|
||||
},
|
||||
"asyncModule": () => import('../src/routes/[...404].svelte'),
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"isDefault": true,
|
||||
"title": "主页",
|
||||
"redirect": "/login"
|
||||
},
|
||||
"id": "_default_index_svelte",
|
||||
"name": "index",
|
||||
"file": {
|
||||
"path": "src/routes/index.svelte",
|
||||
"dir": "src/routes",
|
||||
"base": "index.svelte",
|
||||
"ext": ".svelte",
|
||||
"name": "index"
|
||||
},
|
||||
"asyncModule": () => import('../src/routes/index.svelte'),
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"meta": {},
|
||||
"id": "_default_login",
|
||||
"name": "login",
|
||||
"module": false,
|
||||
"file": {
|
||||
"path": "src/routes/login",
|
||||
"dir": "src/routes",
|
||||
"base": "login",
|
||||
"ext": "",
|
||||
"name": "login"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"isDefault": true,
|
||||
"title": "登录页面",
|
||||
"hideInMenu": true,
|
||||
"reset": true
|
||||
},
|
||||
"id": "_default_login_index_svelte",
|
||||
"name": "index",
|
||||
"file": {
|
||||
"path": "src/routes/login/index.svelte",
|
||||
"dir": "src/routes/login",
|
||||
"base": "index.svelte",
|
||||
"ext": ".svelte",
|
||||
"name": "index"
|
||||
},
|
||||
"asyncModule": () => import('../src/routes/login/index.svelte'),
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"title": "订单管理"
|
||||
},
|
||||
"id": "_default_orders",
|
||||
"name": "orders",
|
||||
"file": {
|
||||
"path": "src/routes/orders/_module.svelte",
|
||||
"dir": "src/routes/orders",
|
||||
"base": "_module.svelte",
|
||||
"ext": ".svelte",
|
||||
"name": "_module"
|
||||
},
|
||||
"asyncModule": () => import('../src/routes/orders/_module.svelte'),
|
||||
"children": [
|
||||
{
|
||||
"meta": {
|
||||
"isDefault": true,
|
||||
"title": "订单管理",
|
||||
"auth": "SF_XXX_2"
|
||||
},
|
||||
"id": "_default_orders_index_svelte",
|
||||
"name": "index",
|
||||
"file": {
|
||||
"path": "src/routes/orders/index.svelte",
|
||||
"dir": "src/routes/orders",
|
||||
"base": "index.svelte",
|
||||
"ext": ".svelte",
|
||||
"name": "index"
|
||||
},
|
||||
"asyncModule": () => import('../src/routes/orders/index.svelte'),
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"meta": {
|
||||
"title": "销售订单",
|
||||
"auth": "SF_XXX_SAle"
|
||||
},
|
||||
"id": "_default_orders_sale_svelte",
|
||||
"name": "sale",
|
||||
"file": {
|
||||
"path": "src/routes/orders/sale.svelte",
|
||||
"dir": "src/routes/orders",
|
||||
"base": "sale.svelte",
|
||||
"ext": ".svelte",
|
||||
"name": "sale"
|
||||
},
|
||||
"asyncModule": () => import('../src/routes/orders/sale.svelte'),
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
export default routes
|
18
.routify/routify-init.js
Normal file
18
.routify/routify-init.js
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
import { appInstance, preloadUrl } from '@roxi/routify'
|
||||
import { map } from './route-map.js'
|
||||
|
||||
appInstance.routeMaps = map
|
||||
|
||||
// We need to import the App module since a router is likely declared here. This saves us pre-creating the router in the preload step below.
|
||||
import * as module from '../src/App.svelte'
|
||||
|
||||
const preloadPromise = Promise.all([
|
||||
module.load?.(),
|
||||
// PreloadUrl parses the url and preloads each url chunk in a router that matches its name. So for '/hello;widget=/world',
|
||||
// it will preload '/hello' in the default router and '/world' in the 'widget' router.
|
||||
// If the respective routers don't exist, preloadUrl will use routesMap to pre-create a router and match it with the url chunk.
|
||||
preloadUrl({ routesMap: map })
|
||||
])
|
||||
|
||||
export const app = preloadPromise.then(() => import('../src/main.js'))
|
3
.vscode/extensions.json
vendored
Normal file
3
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["svelte.svelte-vscode"]
|
||||
}
|
47
README.md
Normal file
47
README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Svelte + Vite
|
||||
|
||||
This template should help get you started developing with Svelte in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
|
||||
|
||||
## Need an official Svelte framework?
|
||||
|
||||
Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
|
||||
|
||||
## Technical considerations
|
||||
|
||||
**Why use this over SvelteKit?**
|
||||
|
||||
- It brings its own routing solution which might not be preferable for some users.
|
||||
- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
|
||||
|
||||
This template contains as little as possible to get started with Vite + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
|
||||
|
||||
Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
|
||||
|
||||
**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**
|
||||
|
||||
Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.
|
||||
|
||||
**Why include `.vscode/extensions.json`?**
|
||||
|
||||
Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
|
||||
|
||||
**Why enable `checkJs` in the JS template?**
|
||||
|
||||
It is likely that most cases of changing variable types in runtime are likely to be accidental, rather than deliberate. This provides advanced typechecking out of the box. Should you like to take advantage of the dynamically-typed nature of JavaScript, it is trivial to change the configuration.
|
||||
|
||||
**Why is HMR not preserving my local component state?**
|
||||
|
||||
HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/sveltejs/svelte-hmr/tree/master/packages/svelte-hmr#preservation-of-local-state).
|
||||
|
||||
If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
|
||||
|
||||
```js
|
||||
// store.js
|
||||
// An extremely simple external store
|
||||
import { writable } from 'svelte/store'
|
||||
export default writable(0)
|
||||
```
|
13
index.html
Normal file
13
index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + Svelte</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
36
jsconfig.json
Normal file
36
jsconfig.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "bundler",
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
/**
|
||||
* svelte-preprocess cannot figure out whether you have
|
||||
* a value or a type, so tell TypeScript to enforce using
|
||||
* `import type` instead of `import` for Types.
|
||||
*/
|
||||
"verbatimModuleSyntax": true,
|
||||
"isolatedModules": true,
|
||||
"resolveJsonModule": true,
|
||||
/**
|
||||
* To have warnings / errors of the Svelte compiler at the
|
||||
* correct position, enable source maps by default.
|
||||
*/
|
||||
"sourceMap": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
/**
|
||||
* Typecheck JS in `.svelte` and `.js` files by default.
|
||||
* Disable this if you'd like to use dynamic types.
|
||||
*/
|
||||
"checkJs": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Use global.d.ts instead of compilerOptions.types
|
||||
* to avoid limiting type declarations.
|
||||
*/
|
||||
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"]
|
||||
}
|
36
package.json
Normal file
36
package.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "free_erp_admin",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^6.1.4",
|
||||
"@tailwindcss/forms": "^0.5.10",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@tailwindcss/vite": "^4.1.12",
|
||||
"@types/node": "^24.3.0",
|
||||
"flowbite": "^3.1.2",
|
||||
"flowbite-svelte": "^1.13.7",
|
||||
"flowbite-svelte-icons": "^3.0.0",
|
||||
"svelte": "^5.38.6",
|
||||
"svelte-hot-french-toast": "^4.0.0",
|
||||
"tailwindcss": "^4.1.12",
|
||||
"vite": "^6.3.5"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"esbuild"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@hvniel/svelte-router": "^0.0.2",
|
||||
"@roxi/routify": "3.0.0-next.293",
|
||||
"axios": "^1.11.0",
|
||||
"qs": "^6.14.0"
|
||||
}
|
||||
}
|
2210
pnpm-lock.yaml
generated
Normal file
2210
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
1
public/vite.svg
Normal file
1
public/vite.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
73
src/App.svelte
Normal file
73
src/App.svelte
Normal file
@@ -0,0 +1,73 @@
|
||||
<!-- <script lang="ts">
|
||||
import "./app.css";
|
||||
import Error from "./layouts/Error.svelte";
|
||||
import About from "./pages/About.svelte";
|
||||
import Home from "./pages/Home.svelte";
|
||||
|
||||
import { createHashRouter, RouterProvider } from "@hvniel/svelte-router";
|
||||
import AppLayout from "./layouts/AppLayout.svelte";
|
||||
import User, { userLoader } from "./pages/User.svelte";
|
||||
|
||||
const router = createHashRouter([
|
||||
{
|
||||
// path: "/home",
|
||||
Component: AppLayout,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
Component: Home,
|
||||
},
|
||||
// {
|
||||
// path: "/home",
|
||||
// index: true,
|
||||
// Component: Home,
|
||||
// },
|
||||
{
|
||||
path: "/user",
|
||||
index: true,
|
||||
Component: User,
|
||||
loader: userLoader,
|
||||
},
|
||||
{
|
||||
path: "/about",
|
||||
index: true,
|
||||
Component: About,
|
||||
},
|
||||
{
|
||||
path: "*",
|
||||
Component: Error,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "*",
|
||||
Component: Error,
|
||||
},
|
||||
]);
|
||||
</script>
|
||||
|
||||
<RouterProvider {router} /> -->
|
||||
|
||||
<script context="module">
|
||||
import { Router, createRouter } from "@roxi/routify";
|
||||
import { Toaster } from "svelte-hot-french-toast";
|
||||
import routes from "../.routify/routes.default.js";
|
||||
|
||||
export const router = createRouter({
|
||||
routes,
|
||||
urlRewrite: {
|
||||
toExternal: (url) => `#${url}`, // prepend URLs with #
|
||||
toInternal: (url) => url.replace(/^.+#/, ""), // remove leading #
|
||||
},
|
||||
beforeUrlChange({ route }) {
|
||||
// console.log(route);
|
||||
const { meta } = route;
|
||||
// console.log(meta);
|
||||
document.title = meta["title"] || "";
|
||||
return true;
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<Router {router} />
|
||||
<Toaster position={"top-end"} />
|
43
src/app.css
Normal file
43
src/app.css
Normal file
@@ -0,0 +1,43 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@plugin 'flowbite/plugin';
|
||||
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
|
||||
@theme {
|
||||
--color-primary-50: #fff5f2;
|
||||
--color-primary-100: #fff1ee;
|
||||
--color-primary-200: #ffe4de;
|
||||
--color-primary-300: #ffd5cc;
|
||||
--color-primary-400: #ffbcad;
|
||||
--color-primary-500: #fe795d;
|
||||
--color-primary-600: #ef562f;
|
||||
--color-primary-700: #eb4f27;
|
||||
--color-primary-800: #cc4522;
|
||||
--color-primary-900: #a5371b;
|
||||
|
||||
--color-secondary-50: #f0f9ff;
|
||||
--color-secondary-100: #e0f2fe;
|
||||
--color-secondary-200: #bae6fd;
|
||||
--color-secondary-300: #7dd3fc;
|
||||
--color-secondary-400: #38bdf8;
|
||||
--color-secondary-500: #0ea5e9;
|
||||
--color-secondary-600: #0284c7;
|
||||
--color-secondary-700: #0369a1;
|
||||
--color-secondary-800: #075985;
|
||||
--color-secondary-900: #0c4a6e;
|
||||
}
|
||||
|
||||
@source "../node_modules/flowbite-svelte/dist";
|
||||
@source "../node_modules/flowbite-svelte-icons/dist";
|
||||
|
||||
a {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
/* disable chrome cancel button */
|
||||
input[type="search"]::-webkit-search-cancel-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
1
src/assets/svelte.svg
Normal file
1
src/assets/svelte.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="26.6" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 308"><path fill="#FF3E00" d="M239.682 40.707C211.113-.182 154.69-12.301 113.895 13.69L42.247 59.356a82.198 82.198 0 0 0-37.135 55.056a86.566 86.566 0 0 0 8.536 55.576a82.425 82.425 0 0 0-12.296 30.719a87.596 87.596 0 0 0 14.964 66.244c28.574 40.893 84.997 53.007 125.787 27.016l71.648-45.664a82.182 82.182 0 0 0 37.135-55.057a86.601 86.601 0 0 0-8.53-55.577a82.409 82.409 0 0 0 12.29-30.718a87.573 87.573 0 0 0-14.963-66.244"></path><path fill="#FFF" d="M106.889 270.841c-23.102 6.007-47.497-3.036-61.103-22.648a52.685 52.685 0 0 1-9.003-39.85a49.978 49.978 0 0 1 1.713-6.693l1.35-4.115l3.671 2.697a92.447 92.447 0 0 0 28.036 14.007l2.663.808l-.245 2.659a16.067 16.067 0 0 0 2.89 10.656a17.143 17.143 0 0 0 18.397 6.828a15.786 15.786 0 0 0 4.403-1.935l71.67-45.672a14.922 14.922 0 0 0 6.734-9.977a15.923 15.923 0 0 0-2.713-12.011a17.156 17.156 0 0 0-18.404-6.832a15.78 15.78 0 0 0-4.396 1.933l-27.35 17.434a52.298 52.298 0 0 1-14.553 6.391c-23.101 6.007-47.497-3.036-61.101-22.649a52.681 52.681 0 0 1-9.004-39.849a49.428 49.428 0 0 1 22.34-33.114l71.664-45.677a52.218 52.218 0 0 1 14.563-6.398c23.101-6.007 47.497 3.036 61.101 22.648a52.685 52.685 0 0 1 9.004 39.85a50.559 50.559 0 0 1-1.713 6.692l-1.35 4.116l-3.67-2.693a92.373 92.373 0 0 0-28.037-14.013l-2.664-.809l.246-2.658a16.099 16.099 0 0 0-2.89-10.656a17.143 17.143 0 0 0-18.398-6.828a15.786 15.786 0 0 0-4.402 1.935l-71.67 45.674a14.898 14.898 0 0 0-6.73 9.975a15.9 15.9 0 0 0 2.709 12.012a17.156 17.156 0 0 0 18.404 6.832a15.841 15.841 0 0 0 4.402-1.935l27.345-17.427a52.147 52.147 0 0 1 14.552-6.397c23.101-6.006 47.497 3.037 61.102 22.65a52.681 52.681 0 0 1 9.003 39.848a49.453 49.453 0 0 1-22.34 33.12l-71.664 45.673a52.218 52.218 0 0 1-14.563 6.398"></path></svg>
|
After Width: | Height: | Size: 1.9 KiB |
17
src/layouts/AppLayout.svelte
Normal file
17
src/layouts/AppLayout.svelte
Normal file
@@ -0,0 +1,17 @@
|
||||
<script lang="ts">
|
||||
import { Outlet, useNavigate } from "@hvniel/svelte-router";
|
||||
import { Button } from "flowbite-svelte";
|
||||
const navigate = useNavigate();
|
||||
</script>
|
||||
|
||||
<div class="layout">
|
||||
<header>header</header>
|
||||
<main>
|
||||
<!-- <Link to="/home">Home</Link>
|
||||
<Link to="/about">About</Link> -->
|
||||
<Button onclick={() => navigate("/user")}>User</Button>
|
||||
<Button onclick={() => navigate("/about")}>About</Button>
|
||||
<Outlet />
|
||||
</main>
|
||||
<footer>© 2024</footer>
|
||||
</div>
|
1
src/layouts/Error.svelte
Normal file
1
src/layouts/Error.svelte
Normal file
@@ -0,0 +1 @@
|
||||
<main>Error</main>
|
34
src/lib/Counter.svelte
Normal file
34
src/lib/Counter.svelte
Normal file
@@ -0,0 +1,34 @@
|
||||
<script>
|
||||
import { Button, Modal, P } from "flowbite-svelte";
|
||||
let count = $state(0);
|
||||
let open = $state(false);
|
||||
const increment = () => {
|
||||
count += 1;
|
||||
open = !open;
|
||||
};
|
||||
</script>
|
||||
|
||||
<Button onclick={increment} color="blue" size="xs">Default {count}</Button>
|
||||
<Modal
|
||||
title="Terms of Service"
|
||||
form
|
||||
bind:open
|
||||
onaction={({ action }) => alert(`Handle "${action}"`)}
|
||||
>
|
||||
<P
|
||||
>With less than a month to go before the European Union enacts new consumer
|
||||
privacy laws for its citizens, companies around the world are updating their
|
||||
terms of service agreements to comply.</P
|
||||
>
|
||||
<P
|
||||
>The European Union’s General Data Protection Regulation (G.D.P.R.) goes
|
||||
into effect on May 25 and is meant to ensure a common set of data rights in
|
||||
the European Union. It requires organizations to notify users as soon as
|
||||
possible of high-risk data breaches that could personally affect them.</P
|
||||
>
|
||||
|
||||
{#snippet footer()}
|
||||
<Button type="submit" value="success">I accept</Button>
|
||||
<Button type="submit" value="decline" color="alternative">Decline</Button>
|
||||
{/snippet}
|
||||
</Modal>
|
9
src/main.js
Normal file
9
src/main.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import { mount } from "svelte";
|
||||
import "./app.css";
|
||||
import App from "./App.svelte";
|
||||
|
||||
const app = mount(App, {
|
||||
target: document.getElementById("app"),
|
||||
});
|
||||
|
||||
export default app;
|
7
src/pages/About.svelte
Normal file
7
src/pages/About.svelte
Normal file
@@ -0,0 +1,7 @@
|
||||
<script>
|
||||
import { Link } from "@hvniel/svelte-router";
|
||||
console.log("About");
|
||||
</script>
|
||||
|
||||
<main>About Page</main>
|
||||
<Link to="/home/index">to Home</Link>
|
39
src/pages/Home.svelte
Normal file
39
src/pages/Home.svelte
Normal file
@@ -0,0 +1,39 @@
|
||||
<script lang="ts">
|
||||
import { Link } from "@hvniel/svelte-router";
|
||||
|
||||
let count = $state(0);
|
||||
let open = $state(false);
|
||||
const increment = () => {
|
||||
count += 1;
|
||||
open = !open;
|
||||
};
|
||||
console.log("Home");
|
||||
</script>
|
||||
|
||||
<main>Home Page</main>
|
||||
<Link to="/home/about">to About</Link>
|
||||
<!-- <Button onclick={increment} color="blue" size="xs">Default {count}</Button>
|
||||
|
||||
<Modal
|
||||
title="Terms of Service"
|
||||
form
|
||||
bind:open
|
||||
onaction={({ action }) => alert(`Handle "${action}"`)}
|
||||
>
|
||||
<P
|
||||
>With less than a month to go before the European Union enacts new consumer
|
||||
privacy laws for its citizens, companies around the world are updating their
|
||||
terms of service agreements to comply.</P
|
||||
>
|
||||
<P
|
||||
>The European Union’s General Data Protection Regulation (G.D.P.R.) goes
|
||||
into effect on May 25 and is meant to ensure a common set of data rights in
|
||||
the European Union. It requires organizations to notify users as soon as
|
||||
possible of high-risk data breaches that could personally affect them.</P
|
||||
>
|
||||
|
||||
{#snippet footer()}
|
||||
<Button type="submit" value="success">I accept</Button>
|
||||
<Button type="submit" value="decline" color="alternative">Decline</Button>
|
||||
{/snippet}
|
||||
</Modal> -->
|
19
src/pages/User.svelte
Normal file
19
src/pages/User.svelte
Normal file
@@ -0,0 +1,19 @@
|
||||
<script module>
|
||||
export const userLoader = async () => {
|
||||
return {
|
||||
name: "data.name",
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { useLoaderData, useSearchParams } from "@hvniel/svelte-router";
|
||||
let a = $state(0);
|
||||
const params = useSearchParams();
|
||||
console.log(JSON.stringify(params));
|
||||
|
||||
const data = useLoaderData<typeof userLoader>();
|
||||
console.log("data", data);
|
||||
</script>
|
||||
|
||||
<p>User {a} {data?.name}</p>
|
5
src/routes/[...404].meta.js
Normal file
5
src/routes/[...404].meta.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export default (ctx) => {
|
||||
return {
|
||||
hideInMenu: true,
|
||||
};
|
||||
};
|
1
src/routes/[...404].svelte
Normal file
1
src/routes/[...404].svelte
Normal file
@@ -0,0 +1 @@
|
||||
<main>找不到页面</main>
|
167
src/routes/_module.svelte
Normal file
167
src/routes/_module.svelte
Normal file
@@ -0,0 +1,167 @@
|
||||
<!-- 布局 -->
|
||||
<script lang="ts">
|
||||
import { afterUrlChange } from "@roxi/routify";
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarDropdownWrapper,
|
||||
SidebarGroup,
|
||||
SidebarItem,
|
||||
} from "flowbite-svelte";
|
||||
import { ShoppingBagSolid } from "flowbite-svelte-icons";
|
||||
import routes from "../../.routify/routes.default.js";
|
||||
|
||||
const menu = [];
|
||||
|
||||
/** 选择菜单 */
|
||||
let activeHref = "";
|
||||
// 展开菜单
|
||||
let openTitle = "";
|
||||
export let context;
|
||||
const { route } = context;
|
||||
|
||||
menu.length = 0;
|
||||
routes.children.forEach((el) => {
|
||||
const menu2: any[] = [];
|
||||
if (!el.meta.hideInMenu && el.children.length) {
|
||||
el.children.forEach((ell) => {
|
||||
if (!ell.meta.hideInMenu) {
|
||||
const href =
|
||||
ell.file.dir.replace("src/routes", "") + "/" + ell.file.name;
|
||||
menu2.push({
|
||||
...ell,
|
||||
href: href,
|
||||
});
|
||||
|
||||
if (href == route.url || href == `${route.url}/index`) {
|
||||
activeHref = href;
|
||||
openTitle = el.meta?.title;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (menu2.length) {
|
||||
menu.push({ ...el, children: menu2 });
|
||||
}
|
||||
});
|
||||
|
||||
$afterUrlChange;
|
||||
$afterUrlChange((route) => {
|
||||
activeHref = "";
|
||||
const url = route.route.url;
|
||||
a: for (const element of menu) {
|
||||
for (const ell of element.children) {
|
||||
if (ell.href == url || ell.href == `${url}/index`) {
|
||||
activeHref = ell.href;
|
||||
openTitle = element.meta?.title;
|
||||
break a;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<header>
|
||||
<a href="/">Home</a>
|
||||
<a href="/user">user</a>
|
||||
<a href="/about">About</a>
|
||||
<a href="/orders/sale">orders/sale</a>
|
||||
<a href="/login">Login</a>
|
||||
</header>
|
||||
<section>
|
||||
<aside>
|
||||
<Sidebar
|
||||
isSingle={false}
|
||||
backdrop={false}
|
||||
params={{ x: -50, duration: 50 }}
|
||||
position="absolute"
|
||||
classes={{ nonactive: "p-2", active: "p-2" }}
|
||||
class="z-50 h-full aside"
|
||||
style="width: 100%;"
|
||||
>
|
||||
<SidebarGroup>
|
||||
{#each menu as el}
|
||||
<SidebarDropdownWrapper
|
||||
isOpen={openTitle == el.meta?.title}
|
||||
label={el.meta?.title}
|
||||
classes={{ btn: "p-2" }}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<ShoppingBagSolid
|
||||
class="h-5 w-5 text-gray-500 transition duration-75 group-hover:text-gray-900 dark:text-gray-400 dark:group-hover:text-white"
|
||||
/>
|
||||
{/snippet}
|
||||
{#each el.children as ell}
|
||||
<SidebarItem
|
||||
label={ell?.meta?.title}
|
||||
href={ell.href}
|
||||
active={activeHref == ell.href}
|
||||
/>
|
||||
{/each}
|
||||
</SidebarDropdownWrapper>
|
||||
{/each}
|
||||
</SidebarGroup>
|
||||
</Sidebar>
|
||||
</aside>
|
||||
<main>
|
||||
<div class="main-content">
|
||||
<!-- {@render children?.()} -->
|
||||
<slot />
|
||||
</div>
|
||||
<footer>footer</footer>
|
||||
</main>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--header-height: 40px;
|
||||
--footer-height: 34px;
|
||||
}
|
||||
|
||||
header {
|
||||
height: var(--header-height);
|
||||
border-bottom: 1px solid #ddd;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
section {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
aside {
|
||||
width: 200px;
|
||||
background: rgb(255, 255, 255);
|
||||
overflow: auto;
|
||||
height: calc(100vh - var(--header-height));
|
||||
position: sticky;
|
||||
left: 0px;
|
||||
top: var(--header-height);
|
||||
}
|
||||
|
||||
main {
|
||||
overflow: inherit;
|
||||
background: rgb(244, 244, 244);
|
||||
box-sizing: border-box;
|
||||
min-width: 0px;
|
||||
flex: 1;
|
||||
padding: 12px 12px 0px;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
min-height: calc(
|
||||
100vh - var(--header-height) - var(--footer-height) - 12px
|
||||
);
|
||||
padding: 12px 12px 0px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
footer {
|
||||
display: flex;
|
||||
height: 34px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
6
src/routes/index.meta.js
Normal file
6
src/routes/index.meta.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default ctx => {
|
||||
return {
|
||||
title: "主页",
|
||||
redirect: '/login'
|
||||
}
|
||||
}
|
48
src/routes/index.svelte
Normal file
48
src/routes/index.svelte
Normal file
@@ -0,0 +1,48 @@
|
||||
<script context="module">
|
||||
// 重定向页面
|
||||
export const load = (ctx) => {
|
||||
return {
|
||||
redirect: "/orders",
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { goto } from "@roxi/routify";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
$goto;
|
||||
|
||||
onMount(() => {
|
||||
// console.log('"xxxxxxxxxxxxxxxx');
|
||||
// $goto("/orders");
|
||||
});
|
||||
</script>
|
||||
|
||||
<main>Home Page</main>
|
||||
<!-- <Link to="/home/about">to About</Link> -->
|
||||
<!-- <Button onclick={increment} color="blue" size="xs">Default {count}</Button>
|
||||
|
||||
<Modal
|
||||
title="Terms of Service"
|
||||
form
|
||||
bind:open
|
||||
onaction={({ action }) => alert(`Handle "${action}"`)}
|
||||
>
|
||||
<P
|
||||
>With less than a month to go before the European Union enacts new consumer
|
||||
privacy laws for its citizens, companies around the world are updating their
|
||||
terms of service agreements to comply.</P
|
||||
>
|
||||
<P
|
||||
>The European Union’s General Data Protection Regulation (G.D.P.R.) goes
|
||||
into effect on May 25 and is meant to ensure a common set of data rights in
|
||||
the European Union. It requires organizations to notify users as soon as
|
||||
possible of high-risk data breaches that could personally affect them.</P
|
||||
>
|
||||
|
||||
{#snippet footer()}
|
||||
<Button type="submit" value="success">I accept</Button>
|
||||
<Button type="submit" value="decline" color="alternative">Decline</Button>
|
||||
{/snippet}
|
||||
</Modal> -->
|
6
src/routes/login/index.meta.js
Normal file
6
src/routes/login/index.meta.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default ctx => {
|
||||
return {
|
||||
title: "登录页面",
|
||||
hideInMenu: true
|
||||
}
|
||||
}
|
74
src/routes/login/index.svelte
Normal file
74
src/routes/login/index.svelte
Normal file
@@ -0,0 +1,74 @@
|
||||
<script lang="ts">
|
||||
import { post } from "@/utils/http";
|
||||
import { goto } from "@roxi/routify";
|
||||
import { Button, Input } from "flowbite-svelte";
|
||||
import toast from "svelte-hot-french-toast";
|
||||
|
||||
$goto; // manually initialize the helper
|
||||
|
||||
const userInfo = $state({
|
||||
login_name: "zhengw",
|
||||
password: "123456",
|
||||
login_type: 1,
|
||||
});
|
||||
|
||||
const login = () => {
|
||||
post("/Users/login", userInfo).then((res) => {
|
||||
if (res.err_code == 0) {
|
||||
toast.success("登录成功");
|
||||
$goto("/");
|
||||
} else {
|
||||
toast.error(`${res.err_code}: ${res.err_code}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- 禁用父模块 -->
|
||||
<!-- routify:meta reset -->
|
||||
|
||||
<main class="login-container">
|
||||
<div class="login-box">
|
||||
<div>后台登录</div>
|
||||
<div>
|
||||
<Input
|
||||
size="lg"
|
||||
placeholder="Large input"
|
||||
bind:value={userInfo.login_name}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Input
|
||||
size="lg"
|
||||
type="password"
|
||||
placeholder="Large input"
|
||||
bind:value={userInfo.password}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Button size="lg" style="display: block;width: 100%;" onclick={login}
|
||||
>登录</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
.login-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
height: 100dvh;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.login-box {
|
||||
width: 400px;
|
||||
border: 1px solid #ddd;
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 12px;
|
||||
}
|
||||
</style>
|
5
src/routes/orders/_module.meta.js
Normal file
5
src/routes/orders/_module.meta.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export default ctx => {
|
||||
return {
|
||||
title: "订单管理",
|
||||
}
|
||||
}
|
11
src/routes/orders/_module.svelte
Normal file
11
src/routes/orders/_module.svelte
Normal file
@@ -0,0 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { goto } from "@roxi/routify";
|
||||
|
||||
$goto;
|
||||
|
||||
// onMount(() => {
|
||||
// $goto("/orders");
|
||||
// });
|
||||
</script>
|
||||
|
||||
<slot />
|
6
src/routes/orders/index.meta.js
Normal file
6
src/routes/orders/index.meta.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default ctx => {
|
||||
return {
|
||||
title: "订单管理",
|
||||
auth: "SF_XXX_2"
|
||||
}
|
||||
}
|
1
src/routes/orders/index.svelte
Normal file
1
src/routes/orders/index.svelte
Normal file
@@ -0,0 +1 @@
|
||||
<main>Orders - index</main>
|
6
src/routes/orders/sale.meta.js
Normal file
6
src/routes/orders/sale.meta.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default ctx => {
|
||||
return {
|
||||
title: '销售订单',
|
||||
auth: "SF_XXX_SAle"
|
||||
}
|
||||
}
|
1
src/routes/orders/sale.svelte
Normal file
1
src/routes/orders/sale.svelte
Normal file
@@ -0,0 +1 @@
|
||||
<main>Orders - sale</main>
|
25
src/utils/common.ts
Normal file
25
src/utils/common.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/** 路径前面添加 api */
|
||||
export const pathAddApiString = (path: any): string => {
|
||||
/** 生产环境不加 api */
|
||||
// if (import.meta.env.PROD) {
|
||||
// return path;
|
||||
// }
|
||||
if (typeof path == 'string') {
|
||||
if (`${path}`.startsWith('http') || `${path}`.startsWith('blob:http')) {
|
||||
return path;
|
||||
}
|
||||
if (`${path}`.startsWith('/')) {
|
||||
return `/api${path}`;
|
||||
}
|
||||
return `/api/${path}`;
|
||||
}
|
||||
return path;
|
||||
};
|
||||
|
||||
/** ajax返回的基础类型 */
|
||||
export type IAjaxDataBase = {
|
||||
count: number | undefined;
|
||||
err_msg?: string;
|
||||
err_code?: number;
|
||||
[key: string]: any;
|
||||
};
|
62
src/utils/http.ts
Normal file
62
src/utils/http.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import axios, { type AxiosRequestConfig } from "axios";
|
||||
import { type IAjaxDataBase, pathAddApiString } from "./common";
|
||||
|
||||
// 添加请求拦截器
|
||||
axios.interceptors.request.use(
|
||||
(config) => {
|
||||
// 在发送请求之前做些什么
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
// 对请求错误做些什么
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// 添加响应拦截器
|
||||
axios.interceptors.response.use(
|
||||
(response) => {
|
||||
// 2xx 范围内的状态码都会触发该函数。
|
||||
// 对响应数据做点什么
|
||||
return response.data;
|
||||
},
|
||||
(error) => {
|
||||
// 超出 2xx 范围的状态码都会触发该函数。
|
||||
// 对响应错误做点什么
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
const ajax = (
|
||||
method: string,
|
||||
url: string,
|
||||
data: any,
|
||||
config?: AxiosRequestConfig<any>
|
||||
) => {
|
||||
return axios.request<any, IAjaxDataBase>({
|
||||
headers: {
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
},
|
||||
method: method,
|
||||
url: pathAddApiString(url),
|
||||
data: data,
|
||||
...config,
|
||||
});
|
||||
};
|
||||
|
||||
export const post = (
|
||||
url: string,
|
||||
data?: any,
|
||||
config?: AxiosRequestConfig<any>
|
||||
) => {
|
||||
return ajax("POST", url, data, config);
|
||||
};
|
||||
|
||||
export const get = (
|
||||
url: string,
|
||||
data: any,
|
||||
config?: AxiosRequestConfig<any>
|
||||
) => {
|
||||
return ajax("GET", url, data, config);
|
||||
};
|
2
src/vite-env.d.ts
vendored
Normal file
2
src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/// <reference types="svelte" />
|
||||
/// <reference types="vite/client" />
|
8
svelte.config.js
Normal file
8
svelte.config.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
|
||||
|
||||
/** @type {import("@sveltejs/vite-plugin-svelte").SvelteConfig} */
|
||||
export default {
|
||||
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
|
||||
// for more information about preprocessors
|
||||
preprocess: vitePreprocess()
|
||||
};
|
40
vite.config.js
Normal file
40
vite.config.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import routify from "@roxi/routify/vite-plugin";
|
||||
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
import path from "node:path";
|
||||
import { defineConfig } from "vite";
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
tailwindcss(),
|
||||
svelte(),
|
||||
routify({
|
||||
singlePage: true,
|
||||
render: {
|
||||
csr: true,
|
||||
ssg: false,
|
||||
ssr: false,
|
||||
},
|
||||
}),
|
||||
],
|
||||
base: "./",
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
},
|
||||
},
|
||||
server: {
|
||||
hmr: true,
|
||||
port: 4010,
|
||||
host: "0.0.0.0",
|
||||
proxy: {
|
||||
"/api/": {
|
||||
target: "http://192.168.1.138:93",
|
||||
// target: 'http://192.168.1.148:8089',
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/api/, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
Reference in New Issue
Block a user