mirror of
https://github.com/fantastic-admin/basic.git
synced 2026-10-07 07:13:55 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e057f01edb | ||
|
|
b4b68d78ea | ||
|
|
1b0dc3b947 | ||
|
|
244e6cb4fa | ||
|
|
ded93e90b7 | ||
|
|
70b29edb6e | ||
|
|
fc2c89fa2d | ||
|
|
5ba6d08df3 | ||
|
|
c0bc31f7f4 | ||
|
|
871dd5c56f | ||
|
|
caedad8e72 | ||
|
|
bb3bd479b8 | ||
|
|
931b10c1f3 | ||
|
|
5e2558ac05 | ||
|
|
81beda6e56 | ||
|
|
1d86ef87d3 | ||
|
|
d0dc9275b3 | ||
|
|
1ccbd6402b | ||
|
|
84eb9b7a39 | ||
|
|
5e023d9055 | ||
|
|
cf4a7eae7d | ||
|
|
42b7ab33c6 | ||
|
|
85eefe75bb | ||
|
|
0bcea9d3c8 | ||
|
|
38e6abab21 | ||
|
|
1c81115605 | ||
|
|
e55e94743f | ||
|
|
efb0886e10 |
+4
-55
@@ -1,5 +1,5 @@
|
||||
[中文](./readme.md) | **English**
|
||||
<img src="https://fantastic-admin.hurui.me/logo.svg" align="right" width="80" height="80" alt="logo" />
|
||||
<a href="https://fantastic-admin.hurui.me" target="_blank"><img src="https://fantastic-admin.hurui.me/logo.svg" align="right" height="80" alt="logo" /></a>
|
||||
|
||||
# Fantastic-admin
|
||||
|
||||
@@ -56,57 +56,6 @@ If you find Fantastic-admin useful, or you are already using it, please consider
|
||||
|
||||
## Ecosystem
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th colspan="3" align="center">
|
||||
<a href="https://hooray.github.io/fantastic-startkit/" target="_blank">Fantastic-startkit</a>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="3" align="center">
|
||||
A simple and easy-to-use Vue 3 project starter kit
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th colspan="3" align="center">
|
||||
<a href="https://one-step-admin.hurui.me" target="_blank">One-step-admin</a>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="3" align="center">
|
||||
A Vue admin framework built to help you move faster than the rest
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://one-step-admin.hurui.me/preview1.png" alt="" /></td>
|
||||
<td><img src="https://one-step-admin.hurui.me/preview2.png" alt="" /></td>
|
||||
<td><img src="https://one-step-admin.hurui.me/preview3.png" alt="" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://one-step-admin.hurui.me/preview4.png" alt="" /></td>
|
||||
<td><img src="https://one-step-admin.hurui.me/preview5.png" alt="" /></td>
|
||||
<td><img src="https://one-step-admin.hurui.me/preview6.png" alt="" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th colspan="4" align="center">
|
||||
<a href="https://fantastic-mobile.hurui.me" target="_blank">Fantastic-mobile</a>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="4" align="center">
|
||||
A distinctive mobile H5 framework
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://fantastic-mobile.hurui.me/preview1.png" alt="" /></td>
|
||||
<td><img src="https://fantastic-mobile.hurui.me/preview2.png" alt="" /></td>
|
||||
<td><img src="https://fantastic-mobile.hurui.me/preview3.png" alt="" /></td>
|
||||
<td><img src="https://fantastic-mobile.hurui.me/preview4.png" alt="" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
- [`Fantastic-startkit`](https://hooray.github.io/fantastic-startkit/) - A simple and easy-to-use Vue 3 project starter kit
|
||||
- [`Fantastic-mobile`](https://fantastic-mobile.hurui.me/) - Let your H5 project have a solid engineering base
|
||||
- [`One-step-admin`](https://one-step-admin.hurui.me) - A Vue admin framework built to help you move faster than the rest
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
**中文** | [English](./README.EN.md)
|
||||
<img src="https://fantastic-admin.hurui.me/logo.svg" align="right" width="80" height="80" alt="logo" />
|
||||
<a href="https://fantastic-admin.hurui.me" target="_blank"><img src="https://fantastic-admin.hurui.me/logo.svg" align="right" height="80" alt="logo" /></a>
|
||||
|
||||
# Fantastic-admin
|
||||
|
||||
|
||||
@@ -9,11 +9,12 @@
|
||||
"serve": "http-server ./dist -o",
|
||||
"serve:test": "http-server ./dist-test -o",
|
||||
"svgo": "svgo -f src/assets/icons",
|
||||
"generate:icons": "tsx ./scripts/generate.icons.ts",
|
||||
"generate:icons": "fa-iconify-tools",
|
||||
"lint": "vue-tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fantastic-admin/components": "workspace:*",
|
||||
"@fantastic-admin/composables": "workspace:*",
|
||||
"@fantastic-admin/settings": "workspace:*",
|
||||
"@fantastic-admin/types": "workspace:*",
|
||||
"@vee-validate/zod": "catalog:",
|
||||
@@ -49,9 +50,9 @@
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@clack/prompts": "catalog:",
|
||||
"@faker-js/faker": "catalog:",
|
||||
"@fantastic-admin/copyright": "workspace:*",
|
||||
"@fantastic-admin/iconify-tools": "workspace:*",
|
||||
"@iconify/vue": "catalog:",
|
||||
"@spiriit/vite-plugin-svg-spritemap": "catalog:",
|
||||
"@types/nprogress": "catalog:",
|
||||
@@ -66,7 +67,6 @@
|
||||
"postcss-nested": "catalog:",
|
||||
"sass-embedded": "catalog:",
|
||||
"svgo": "catalog:",
|
||||
"tsx": "catalog:",
|
||||
"unplugin-auto-import": "catalog:",
|
||||
"unplugin-turbo-console": "catalog:",
|
||||
"unplugin-vue-components": "catalog:",
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import { spawn } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import * as p from '@clack/prompts'
|
||||
import { lookupCollection, lookupCollections } from '@iconify/json'
|
||||
|
||||
// 拿到全部图标集的原始数据
|
||||
const raw = await lookupCollections()
|
||||
|
||||
let lastChoose = fs.readFileSync(path.resolve(process.cwd(), 'src/iconify/index.json'), 'utf-8')
|
||||
lastChoose = JSON.parse(lastChoose)
|
||||
|
||||
// 取出可使用的图标集数据用于选择,并按名称排序
|
||||
const collections = Object.entries(raw).map(([id, item]) => ({
|
||||
...item,
|
||||
id,
|
||||
})).sort((a, b) => a.name.localeCompare(b.name))
|
||||
|
||||
p.intro('图标集生成工具')
|
||||
|
||||
/**
|
||||
* 分别会在对应目录下生成以下文件,其中(1)(3)用于离线下载并安装图标,(2)用于图标选择器使用
|
||||
* (1) src/iconify/index.json 记录用户交互信息
|
||||
* (2) src/iconify/data.json 包含多个图标集数据,仅记录图标名
|
||||
* (3) public/icons/*-raw.json 多个图标集的原始数据,独立存放,用于离线使用
|
||||
*/
|
||||
const answers = await p.group(
|
||||
{
|
||||
collections: () =>
|
||||
p.multiselect({
|
||||
message: '请选择需要生成的图标集',
|
||||
options: collections.map(item => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
hint: `${item.total} 个图标`,
|
||||
})),
|
||||
initialValues: lastChoose.collections,
|
||||
}),
|
||||
isOfflineUse: () =>
|
||||
p.confirm({
|
||||
message: '是否需要离线使用',
|
||||
initialValue: false,
|
||||
}),
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
p.cancel('操作已取消')
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const spinner = p.spinner()
|
||||
spinner.start('正在生成图标集...')
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/index.json'),
|
||||
{
|
||||
collections: answers.collections,
|
||||
isOfflineUse: answers.isOfflineUse,
|
||||
},
|
||||
)
|
||||
|
||||
const outputDir = path.resolve(process.cwd(), 'public/icons')
|
||||
await fs.ensureDir(outputDir)
|
||||
await fs.emptyDir(outputDir)
|
||||
|
||||
const collectionsMeta: object[] = []
|
||||
for (const info of answers.collections) {
|
||||
const setData = await lookupCollection(info)
|
||||
|
||||
collectionsMeta.push({
|
||||
prefix: setData.prefix,
|
||||
info: setData.info,
|
||||
icons: Object.keys(setData.icons),
|
||||
})
|
||||
|
||||
const offlineFilePath = path.join(outputDir, `${info}-raw.json`)
|
||||
|
||||
if (answers.isOfflineUse) {
|
||||
await fs.writeJSON(offlineFilePath, setData)
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/data.json'),
|
||||
collectionsMeta,
|
||||
)
|
||||
|
||||
// 使用 spawn 运行 eslint
|
||||
const eslint = spawn('eslint', ['src/iconify/data.json', 'src/iconify/index.json', '--cache', '--fix'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
})
|
||||
|
||||
eslint.on('error', (err) => {
|
||||
p.log.error(`ESLint 执行失败: ${err.message}`)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
eslint.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
p.log.error(`ESLint 执行失败,退出码: ${code}`)
|
||||
process.exit(code)
|
||||
}
|
||||
spinner.stop('图标集生成完成!')
|
||||
})
|
||||
@@ -113,7 +113,7 @@ function testAccount(account: string) {
|
||||
<FormField v-slot="{ componentField }" type="checkbox" name="remember">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<FaCheckbox v-bind="componentField">
|
||||
<FaCheckbox :model-value="componentField.modelValue" @update:model-value="componentField['onUpdate:modelValue']?.($event)">
|
||||
记住我
|
||||
</FaCheckbox>
|
||||
</FormControl>
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
export function usePagination() {
|
||||
const pagination = ref({
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
sort: null as string | null,
|
||||
order: null as string | null,
|
||||
})
|
||||
|
||||
function getParams() {
|
||||
return {
|
||||
// page,size 和 from,limit 是分页的两种方式,方便兼容两种接口
|
||||
page: pagination.value.page,
|
||||
size: pagination.value.size,
|
||||
from: (pagination.value.page - 1) * pagination.value.size,
|
||||
limit: pagination.value.size,
|
||||
...(
|
||||
pagination.value.sort && pagination.value.order && {
|
||||
sort: pagination.value.sort,
|
||||
order: pagination.value.order,
|
||||
}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async function onSizeChange(size: number) {
|
||||
pagination.value.size = size
|
||||
}
|
||||
|
||||
async function onCurrentChange(page: number) {
|
||||
pagination.value.page = page
|
||||
}
|
||||
|
||||
async function onSortChange(prop: string, order: string) {
|
||||
pagination.value.sort = prop
|
||||
pagination.value.order = order === 'ascending' ? 'asc' : 'desc'
|
||||
}
|
||||
|
||||
return {
|
||||
pagination,
|
||||
getParams,
|
||||
onSizeChange,
|
||||
onCurrentChange,
|
||||
onSortChange,
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -53,7 +53,7 @@ function handleCopy() {
|
||||
'columns-2': appSettingsStore.mode === 'pc',
|
||||
}"
|
||||
>
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
颜色方案
|
||||
@@ -83,7 +83,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.theme.colorAmblyopia" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="menu-mode">
|
||||
<FaTooltip text="侧边栏模式 (有主导航菜单)" :delay="500">
|
||||
<FaButton variant="outline" class="mode mode-side" :class="{ active: appSettingsStore.settings.menu.mode === 'side' }" @click="appSettingsStore.settings.menu.mode = 'side'">
|
||||
@@ -145,7 +145,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.menu.hotkeys" :disabled="appSettingsStore.settings.menu.mode === 'single'" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
标签栏
|
||||
@@ -175,7 +175,7 @@ function handleCopy() {
|
||||
</FaButtonGroup>
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
显示图标
|
||||
@@ -189,7 +189,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.tabbar.hotkeys" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div v-if="appSettingsStore.mode === 'pc'" class="setting-item">
|
||||
<div class="label">
|
||||
<FaIcon name="i-ic:twotone-double-arrow" />
|
||||
@@ -237,7 +237,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.toolbar.colorScheme" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
载入进度条
|
||||
@@ -248,7 +248,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.page.progress" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="p-4 pb-4 pt-14 border rounded-lg relative space-y-4">
|
||||
<div class="font-bold px-4 py-2 border-b border-e rounded-rb-lg inset-s-0 inset-t-0 absolute">
|
||||
账号
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ declare global {
|
||||
const useId: typeof import('vue').useId
|
||||
const useLink: typeof import('vue-router').useLink
|
||||
const useModel: typeof import('vue').useModel
|
||||
const usePagination: typeof import('../composables/pagination').usePagination
|
||||
const usePagination: typeof import('@fantastic-admin/composables').usePagination
|
||||
const useRoute: typeof import('vue-router').useRoute
|
||||
const useRouter: typeof import('vue-router').useRouter
|
||||
const useSlots: typeof import('vue').useSlots
|
||||
|
||||
@@ -24,6 +24,7 @@ declare module 'vue' {
|
||||
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -48,6 +49,7 @@ declare module 'vue' {
|
||||
FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
@@ -75,6 +77,7 @@ declare global {
|
||||
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
const FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
const FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
const FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
const FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
const FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
const FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -99,6 +102,7 @@ declare global {
|
||||
const FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
const FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
const FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
const FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
const FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
const FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { PluginOption } from 'vite'
|
||||
import process from 'node:process'
|
||||
import { FantasticAutoImports, FantasticComponentsResolver, FantasticComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import { ComponentsAutoImports as FantasticAdminComponentsAutoImports, ComponentsResolver as FantasticAdminComponentsResolver, ComponentsType as FantasticAdminComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { ComposablesAutoImports as FantasticAdminComposablesAutoImports } from '@fantastic-admin/composables/resolver'
|
||||
import { createCopyrightPlugins as createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import VitePluginSvgSpritemap from '@spiriit/vite-plugin-svg-spritemap'
|
||||
import vueLegacy from '@vitejs/plugin-legacy'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
@@ -37,6 +38,7 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
launchEditor: viteEnv.VITE_LAUNCH_EDITOR,
|
||||
}),
|
||||
|
||||
// https://github.com/yue1123/vite-plugin-env-parse
|
||||
envParse({
|
||||
dtsPath: 'src/types/env.d.ts',
|
||||
}),
|
||||
@@ -47,7 +49,8 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
'vue',
|
||||
'vue-router',
|
||||
'pinia',
|
||||
FantasticAutoImports,
|
||||
FantasticAdminComponentsAutoImports,
|
||||
FantasticAdminComposablesAutoImports,
|
||||
],
|
||||
dts: './src/types/auto-imports.d.ts',
|
||||
dirs: [
|
||||
@@ -63,10 +66,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
],
|
||||
dts: './src/types/components.d.ts',
|
||||
resolvers: [
|
||||
FantasticComponentsResolver(),
|
||||
FantasticAdminComponentsResolver(),
|
||||
],
|
||||
types: [
|
||||
FantasticComponentsType,
|
||||
FantasticAdminComponentsType,
|
||||
],
|
||||
}),
|
||||
|
||||
@@ -78,9 +81,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
// https://github.com/condorheroblog/vite-plugin-fake-server
|
||||
vitePluginFakeServer({
|
||||
logger: !isBuild,
|
||||
include: 'src/api/modules',
|
||||
include: 'src/api/fake_modules',
|
||||
enableProd: isBuild && viteEnv.VITE_BUILD_FAKE,
|
||||
}),
|
||||
|
||||
// https://github.com/nonzzz/vite-plugin-compression
|
||||
viteEnv.VITE_BUILD_COMPRESS && compression({
|
||||
exclude: [/\.(br)$/, /\.(gz)$/],
|
||||
@@ -105,7 +109,6 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
(() => {
|
||||
const moduleId = 'virtual:fantastic-admin/turbo-console'
|
||||
const resolvedModuleId = `\0${moduleId}`
|
||||
|
||||
return {
|
||||
name: 'vite-plugin-turbo-console-bridge',
|
||||
resolveId(id) {
|
||||
|
||||
@@ -9,11 +9,12 @@
|
||||
"serve": "http-server ./dist -o",
|
||||
"serve:test": "http-server ./dist-test -o",
|
||||
"svgo": "svgo -f src/assets/icons",
|
||||
"generate:icons": "tsx ./scripts/generate.icons.ts",
|
||||
"generate:icons": "fa-iconify-tools",
|
||||
"lint": "vue-tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fantastic-admin/components": "workspace:*",
|
||||
"@fantastic-admin/composables": "workspace:*",
|
||||
"@fantastic-admin/settings": "workspace:*",
|
||||
"@fantastic-admin/types": "workspace:*",
|
||||
"@vee-validate/zod": "catalog:",
|
||||
@@ -49,9 +50,9 @@
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@clack/prompts": "catalog:",
|
||||
"@faker-js/faker": "catalog:",
|
||||
"@fantastic-admin/copyright": "workspace:*",
|
||||
"@fantastic-admin/iconify-tools": "workspace:*",
|
||||
"@iconify/vue": "catalog:",
|
||||
"@spiriit/vite-plugin-svg-spritemap": "catalog:",
|
||||
"@types/nprogress": "catalog:",
|
||||
@@ -66,7 +67,6 @@
|
||||
"postcss-nested": "catalog:",
|
||||
"sass-embedded": "catalog:",
|
||||
"svgo": "catalog:",
|
||||
"tsx": "catalog:",
|
||||
"unplugin-auto-import": "catalog:",
|
||||
"unplugin-turbo-console": "catalog:",
|
||||
"unplugin-vue-components": "catalog:",
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import { spawn } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import * as p from '@clack/prompts'
|
||||
import { lookupCollection, lookupCollections } from '@iconify/json'
|
||||
|
||||
// 拿到全部图标集的原始数据
|
||||
const raw = await lookupCollections()
|
||||
|
||||
let lastChoose = fs.readFileSync(path.resolve(process.cwd(), 'src/iconify/index.json'), 'utf-8')
|
||||
lastChoose = JSON.parse(lastChoose)
|
||||
|
||||
// 取出可使用的图标集数据用于选择,并按名称排序
|
||||
const collections = Object.entries(raw).map(([id, item]) => ({
|
||||
...item,
|
||||
id,
|
||||
})).sort((a, b) => a.name.localeCompare(b.name))
|
||||
|
||||
p.intro('图标集生成工具')
|
||||
|
||||
/**
|
||||
* 分别会在对应目录下生成以下文件,其中(1)(3)用于离线下载并安装图标,(2)用于图标选择器使用
|
||||
* (1) src/iconify/index.json 记录用户交互信息
|
||||
* (2) src/iconify/data.json 包含多个图标集数据,仅记录图标名
|
||||
* (3) public/icons/*-raw.json 多个图标集的原始数据,独立存放,用于离线使用
|
||||
*/
|
||||
const answers = await p.group(
|
||||
{
|
||||
collections: () =>
|
||||
p.multiselect({
|
||||
message: '请选择需要生成的图标集',
|
||||
options: collections.map(item => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
hint: `${item.total} 个图标`,
|
||||
})),
|
||||
initialValues: lastChoose.collections,
|
||||
}),
|
||||
isOfflineUse: () =>
|
||||
p.confirm({
|
||||
message: '是否需要离线使用',
|
||||
initialValue: false,
|
||||
}),
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
p.cancel('操作已取消')
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const spinner = p.spinner()
|
||||
spinner.start('正在生成图标集...')
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/index.json'),
|
||||
{
|
||||
collections: answers.collections,
|
||||
isOfflineUse: answers.isOfflineUse,
|
||||
},
|
||||
)
|
||||
|
||||
const outputDir = path.resolve(process.cwd(), 'public/icons')
|
||||
await fs.ensureDir(outputDir)
|
||||
await fs.emptyDir(outputDir)
|
||||
|
||||
const collectionsMeta: object[] = []
|
||||
for (const info of answers.collections) {
|
||||
const setData = await lookupCollection(info)
|
||||
|
||||
collectionsMeta.push({
|
||||
prefix: setData.prefix,
|
||||
info: setData.info,
|
||||
icons: Object.keys(setData.icons),
|
||||
})
|
||||
|
||||
const offlineFilePath = path.join(outputDir, `${info}-raw.json`)
|
||||
|
||||
if (answers.isOfflineUse) {
|
||||
await fs.writeJSON(offlineFilePath, setData)
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/data.json'),
|
||||
collectionsMeta,
|
||||
)
|
||||
|
||||
// 使用 spawn 运行 eslint
|
||||
const eslint = spawn('eslint', ['src/iconify/data.json', 'src/iconify/index.json', '--cache', '--fix'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
})
|
||||
|
||||
eslint.on('error', (err) => {
|
||||
p.log.error(`ESLint 执行失败: ${err.message}`)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
eslint.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
p.log.error(`ESLint 执行失败,退出码: ${code}`)
|
||||
process.exit(code)
|
||||
}
|
||||
spinner.stop('图标集生成完成!')
|
||||
})
|
||||
@@ -113,7 +113,7 @@ function testAccount(account: string) {
|
||||
<FormField v-slot="{ componentField }" type="checkbox" name="remember">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<FaCheckbox v-bind="componentField">
|
||||
<FaCheckbox :model-value="componentField.modelValue" @update:model-value="componentField['onUpdate:modelValue']?.($event)">
|
||||
记住我
|
||||
</FaCheckbox>
|
||||
</FormControl>
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
export function usePagination() {
|
||||
const pagination = ref({
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
sort: null as string | null,
|
||||
order: null as string | null,
|
||||
})
|
||||
|
||||
function getParams() {
|
||||
return {
|
||||
// page,size 和 from,limit 是分页的两种方式,方便兼容两种接口
|
||||
page: pagination.value.page,
|
||||
size: pagination.value.size,
|
||||
from: (pagination.value.page - 1) * pagination.value.size,
|
||||
limit: pagination.value.size,
|
||||
...(
|
||||
pagination.value.sort && pagination.value.order && {
|
||||
sort: pagination.value.sort,
|
||||
order: pagination.value.order,
|
||||
}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async function onSizeChange(size: number) {
|
||||
pagination.value.size = size
|
||||
}
|
||||
|
||||
async function onCurrentChange(page: number) {
|
||||
pagination.value.page = page
|
||||
}
|
||||
|
||||
async function onSortChange(prop: string, order: string) {
|
||||
pagination.value.sort = prop
|
||||
pagination.value.order = order === 'ascending' ? 'asc' : 'desc'
|
||||
}
|
||||
|
||||
return {
|
||||
pagination,
|
||||
getParams,
|
||||
onSizeChange,
|
||||
onCurrentChange,
|
||||
onSortChange,
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -53,7 +53,7 @@ function handleCopy() {
|
||||
'columns-2': appSettingsStore.mode === 'pc',
|
||||
}"
|
||||
>
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
颜色方案
|
||||
@@ -83,7 +83,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.theme.colorAmblyopia" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="menu-mode">
|
||||
<FaTooltip text="侧边栏模式 (有主导航菜单)" :delay="500">
|
||||
<FaButton variant="outline" class="mode mode-side" :class="{ active: appSettingsStore.settings.menu.mode === 'side' }" @click="appSettingsStore.settings.menu.mode = 'side'">
|
||||
@@ -145,7 +145,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.menu.hotkeys" :disabled="appSettingsStore.settings.menu.mode === 'single'" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
标签栏
|
||||
@@ -175,7 +175,7 @@ function handleCopy() {
|
||||
</FaButtonGroup>
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
显示图标
|
||||
@@ -189,7 +189,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.tabbar.hotkeys" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div v-if="appSettingsStore.mode === 'pc'" class="setting-item">
|
||||
<div class="label">
|
||||
<FaIcon name="i-ic:twotone-double-arrow" />
|
||||
@@ -237,7 +237,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.toolbar.colorScheme" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
载入进度条
|
||||
@@ -248,7 +248,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.page.progress" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="p-4 pb-4 pt-14 border rounded-lg relative space-y-4">
|
||||
<div class="font-bold px-4 py-2 border-b border-e rounded-rb-lg inset-s-0 inset-t-0 absolute">
|
||||
账号
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ declare global {
|
||||
const useId: typeof import('vue').useId
|
||||
const useLink: typeof import('vue-router').useLink
|
||||
const useModel: typeof import('vue').useModel
|
||||
const usePagination: typeof import('../composables/pagination').usePagination
|
||||
const usePagination: typeof import('@fantastic-admin/composables').usePagination
|
||||
const useRoute: typeof import('vue-router').useRoute
|
||||
const useRouter: typeof import('vue-router').useRouter
|
||||
const useSlots: typeof import('vue').useSlots
|
||||
|
||||
@@ -24,6 +24,7 @@ declare module 'vue' {
|
||||
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -48,6 +49,7 @@ declare module 'vue' {
|
||||
FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
@@ -75,6 +77,7 @@ declare global {
|
||||
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
const FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
const FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
const FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
const FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
const FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
const FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -99,6 +102,7 @@ declare global {
|
||||
const FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
const FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
const FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
const FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
const FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
const FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { PluginOption } from 'vite'
|
||||
import process from 'node:process'
|
||||
import { FantasticAutoImports, FantasticComponentsResolver, FantasticComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import { ComponentsAutoImports as FantasticAdminComponentsAutoImports, ComponentsResolver as FantasticAdminComponentsResolver, ComponentsType as FantasticAdminComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { ComposablesAutoImports as FantasticAdminComposablesAutoImports } from '@fantastic-admin/composables/resolver'
|
||||
import { createCopyrightPlugins as createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import VitePluginSvgSpritemap from '@spiriit/vite-plugin-svg-spritemap'
|
||||
import vueLegacy from '@vitejs/plugin-legacy'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
@@ -37,6 +38,7 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
launchEditor: viteEnv.VITE_LAUNCH_EDITOR,
|
||||
}),
|
||||
|
||||
// https://github.com/yue1123/vite-plugin-env-parse
|
||||
envParse({
|
||||
dtsPath: 'src/types/env.d.ts',
|
||||
}),
|
||||
@@ -47,7 +49,8 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
'vue',
|
||||
'vue-router',
|
||||
'pinia',
|
||||
FantasticAutoImports,
|
||||
FantasticAdminComponentsAutoImports,
|
||||
FantasticAdminComposablesAutoImports,
|
||||
],
|
||||
dts: './src/types/auto-imports.d.ts',
|
||||
dirs: [
|
||||
@@ -63,10 +66,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
],
|
||||
dts: './src/types/components.d.ts',
|
||||
resolvers: [
|
||||
FantasticComponentsResolver(),
|
||||
FantasticAdminComponentsResolver(),
|
||||
],
|
||||
types: [
|
||||
FantasticComponentsType,
|
||||
FantasticAdminComponentsType,
|
||||
],
|
||||
}),
|
||||
|
||||
@@ -78,9 +81,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
// https://github.com/condorheroblog/vite-plugin-fake-server
|
||||
vitePluginFakeServer({
|
||||
logger: !isBuild,
|
||||
include: 'src/api/modules',
|
||||
include: 'src/api/fake_modules',
|
||||
enableProd: isBuild && viteEnv.VITE_BUILD_FAKE,
|
||||
}),
|
||||
|
||||
// https://github.com/nonzzz/vite-plugin-compression
|
||||
viteEnv.VITE_BUILD_COMPRESS && compression({
|
||||
exclude: [/\.(br)$/, /\.(gz)$/],
|
||||
@@ -105,7 +109,6 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
(() => {
|
||||
const moduleId = 'virtual:fantastic-admin/turbo-console'
|
||||
const resolvedModuleId = `\0${moduleId}`
|
||||
|
||||
return {
|
||||
name: 'vite-plugin-turbo-console-bridge',
|
||||
resolveId(id) {
|
||||
|
||||
@@ -9,11 +9,12 @@
|
||||
"serve": "http-server ./dist -o",
|
||||
"serve:test": "http-server ./dist-test -o",
|
||||
"svgo": "svgo -f src/assets/icons",
|
||||
"generate:icons": "tsx ./scripts/generate.icons.ts",
|
||||
"generate:icons": "fa-iconify-tools",
|
||||
"lint": "vue-tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fantastic-admin/components": "workspace:*",
|
||||
"@fantastic-admin/composables": "workspace:*",
|
||||
"@fantastic-admin/settings": "workspace:*",
|
||||
"@fantastic-admin/types": "workspace:*",
|
||||
"@vee-validate/zod": "catalog:",
|
||||
@@ -49,9 +50,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@arco-design/web-vue": "catalog:arco-design-vue",
|
||||
"@clack/prompts": "catalog:",
|
||||
"@faker-js/faker": "catalog:",
|
||||
"@fantastic-admin/copyright": "workspace:*",
|
||||
"@fantastic-admin/iconify-tools": "workspace:*",
|
||||
"@iconify/vue": "catalog:",
|
||||
"@spiriit/vite-plugin-svg-spritemap": "catalog:",
|
||||
"@types/nprogress": "catalog:",
|
||||
@@ -66,7 +67,6 @@
|
||||
"postcss-nested": "catalog:",
|
||||
"sass-embedded": "catalog:",
|
||||
"svgo": "catalog:",
|
||||
"tsx": "catalog:",
|
||||
"unplugin-auto-import": "catalog:",
|
||||
"unplugin-turbo-console": "catalog:",
|
||||
"unplugin-vue-components": "catalog:",
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import { spawn } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import * as p from '@clack/prompts'
|
||||
import { lookupCollection, lookupCollections } from '@iconify/json'
|
||||
|
||||
// 拿到全部图标集的原始数据
|
||||
const raw = await lookupCollections()
|
||||
|
||||
let lastChoose = fs.readFileSync(path.resolve(process.cwd(), 'src/iconify/index.json'), 'utf-8')
|
||||
lastChoose = JSON.parse(lastChoose)
|
||||
|
||||
// 取出可使用的图标集数据用于选择,并按名称排序
|
||||
const collections = Object.entries(raw).map(([id, item]) => ({
|
||||
...item,
|
||||
id,
|
||||
})).sort((a, b) => a.name.localeCompare(b.name))
|
||||
|
||||
p.intro('图标集生成工具')
|
||||
|
||||
/**
|
||||
* 分别会在对应目录下生成以下文件,其中(1)(3)用于离线下载并安装图标,(2)用于图标选择器使用
|
||||
* (1) src/iconify/index.json 记录用户交互信息
|
||||
* (2) src/iconify/data.json 包含多个图标集数据,仅记录图标名
|
||||
* (3) public/icons/*-raw.json 多个图标集的原始数据,独立存放,用于离线使用
|
||||
*/
|
||||
const answers = await p.group(
|
||||
{
|
||||
collections: () =>
|
||||
p.multiselect({
|
||||
message: '请选择需要生成的图标集',
|
||||
options: collections.map(item => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
hint: `${item.total} 个图标`,
|
||||
})),
|
||||
initialValues: lastChoose.collections,
|
||||
}),
|
||||
isOfflineUse: () =>
|
||||
p.confirm({
|
||||
message: '是否需要离线使用',
|
||||
initialValue: false,
|
||||
}),
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
p.cancel('操作已取消')
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const spinner = p.spinner()
|
||||
spinner.start('正在生成图标集...')
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/index.json'),
|
||||
{
|
||||
collections: answers.collections,
|
||||
isOfflineUse: answers.isOfflineUse,
|
||||
},
|
||||
)
|
||||
|
||||
const outputDir = path.resolve(process.cwd(), 'public/icons')
|
||||
await fs.ensureDir(outputDir)
|
||||
await fs.emptyDir(outputDir)
|
||||
|
||||
const collectionsMeta: object[] = []
|
||||
for (const info of answers.collections) {
|
||||
const setData = await lookupCollection(info)
|
||||
|
||||
collectionsMeta.push({
|
||||
prefix: setData.prefix,
|
||||
info: setData.info,
|
||||
icons: Object.keys(setData.icons),
|
||||
})
|
||||
|
||||
const offlineFilePath = path.join(outputDir, `${info}-raw.json`)
|
||||
|
||||
if (answers.isOfflineUse) {
|
||||
await fs.writeJSON(offlineFilePath, setData)
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/data.json'),
|
||||
collectionsMeta,
|
||||
)
|
||||
|
||||
// 使用 spawn 运行 eslint
|
||||
const eslint = spawn('eslint', ['src/iconify/data.json', 'src/iconify/index.json', '--cache', '--fix'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
})
|
||||
|
||||
eslint.on('error', (err) => {
|
||||
p.log.error(`ESLint 执行失败: ${err.message}`)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
eslint.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
p.log.error(`ESLint 执行失败,退出码: ${code}`)
|
||||
process.exit(code)
|
||||
}
|
||||
spinner.stop('图标集生成完成!')
|
||||
})
|
||||
@@ -113,7 +113,7 @@ function testAccount(account: string) {
|
||||
<FormField v-slot="{ componentField }" type="checkbox" name="remember">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<FaCheckbox v-bind="componentField">
|
||||
<FaCheckbox :model-value="componentField.modelValue" @update:model-value="componentField['onUpdate:modelValue']?.($event)">
|
||||
记住我
|
||||
</FaCheckbox>
|
||||
</FormControl>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -53,7 +53,7 @@ function handleCopy() {
|
||||
'columns-2': appSettingsStore.mode === 'pc',
|
||||
}"
|
||||
>
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
颜色方案
|
||||
@@ -83,7 +83,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.theme.colorAmblyopia" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="menu-mode">
|
||||
<FaTooltip text="侧边栏模式 (有主导航菜单)" :delay="500">
|
||||
<FaButton variant="outline" class="mode mode-side" :class="{ active: appSettingsStore.settings.menu.mode === 'side' }" @click="appSettingsStore.settings.menu.mode = 'side'">
|
||||
@@ -145,7 +145,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.menu.hotkeys" :disabled="appSettingsStore.settings.menu.mode === 'single'" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
标签栏
|
||||
@@ -175,7 +175,7 @@ function handleCopy() {
|
||||
</FaButtonGroup>
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
显示图标
|
||||
@@ -189,7 +189,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.tabbar.hotkeys" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div v-if="appSettingsStore.mode === 'pc'" class="setting-item">
|
||||
<div class="label">
|
||||
<FaIcon name="i-ic:twotone-double-arrow" />
|
||||
@@ -237,7 +237,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.toolbar.colorScheme" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
载入进度条
|
||||
@@ -248,7 +248,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.page.progress" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="p-4 pb-4 pt-14 border rounded-lg relative space-y-4">
|
||||
<div class="font-bold px-4 py-2 border-b border-e rounded-rb-lg inset-s-0 inset-t-0 absolute">
|
||||
账号
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ declare global {
|
||||
const useId: typeof import('vue').useId
|
||||
const useLink: typeof import('vue-router').useLink
|
||||
const useModel: typeof import('vue').useModel
|
||||
const usePagination: typeof import('../composables/pagination').usePagination
|
||||
const usePagination: typeof import('@fantastic-admin/composables').usePagination
|
||||
const useRoute: typeof import('vue-router').useRoute
|
||||
const useRouter: typeof import('vue-router').useRouter
|
||||
const useSlots: typeof import('vue').useSlots
|
||||
|
||||
@@ -24,6 +24,7 @@ declare module 'vue' {
|
||||
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -48,6 +49,7 @@ declare module 'vue' {
|
||||
FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
@@ -75,6 +77,7 @@ declare global {
|
||||
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
const FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
const FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
const FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
const FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
const FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
const FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -99,6 +102,7 @@ declare global {
|
||||
const FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
const FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
const FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
const FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
const FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
const FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { PluginOption } from 'vite'
|
||||
import process from 'node:process'
|
||||
import { FantasticAutoImports, FantasticComponentsResolver, FantasticComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import { ComponentsAutoImports as FantasticAdminComponentsAutoImports, ComponentsResolver as FantasticAdminComponentsResolver, ComponentsType as FantasticAdminComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { ComposablesAutoImports as FantasticAdminComposablesAutoImports } from '@fantastic-admin/composables/resolver'
|
||||
import { createCopyrightPlugins as createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import VitePluginSvgSpritemap from '@spiriit/vite-plugin-svg-spritemap'
|
||||
import vueLegacy from '@vitejs/plugin-legacy'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
@@ -37,6 +38,7 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
launchEditor: viteEnv.VITE_LAUNCH_EDITOR,
|
||||
}),
|
||||
|
||||
// https://github.com/yue1123/vite-plugin-env-parse
|
||||
envParse({
|
||||
dtsPath: 'src/types/env.d.ts',
|
||||
}),
|
||||
@@ -47,7 +49,8 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
'vue',
|
||||
'vue-router',
|
||||
'pinia',
|
||||
FantasticAutoImports,
|
||||
FantasticAdminComponentsAutoImports,
|
||||
FantasticAdminComposablesAutoImports,
|
||||
],
|
||||
dts: './src/types/auto-imports.d.ts',
|
||||
dirs: [
|
||||
@@ -63,10 +66,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
],
|
||||
dts: './src/types/components.d.ts',
|
||||
resolvers: [
|
||||
FantasticComponentsResolver(),
|
||||
FantasticAdminComponentsResolver(),
|
||||
],
|
||||
types: [
|
||||
FantasticComponentsType,
|
||||
FantasticAdminComponentsType,
|
||||
],
|
||||
}),
|
||||
|
||||
@@ -78,9 +81,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
// https://github.com/condorheroblog/vite-plugin-fake-server
|
||||
vitePluginFakeServer({
|
||||
logger: !isBuild,
|
||||
include: 'src/api/modules',
|
||||
include: 'src/api/fake_modules',
|
||||
enableProd: isBuild && viteEnv.VITE_BUILD_FAKE,
|
||||
}),
|
||||
|
||||
// https://github.com/nonzzz/vite-plugin-compression
|
||||
viteEnv.VITE_BUILD_COMPRESS && compression({
|
||||
exclude: [/\.(br)$/, /\.(gz)$/],
|
||||
@@ -105,7 +109,6 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
(() => {
|
||||
const moduleId = 'virtual:fantastic-admin/turbo-console'
|
||||
const resolvedModuleId = `\0${moduleId}`
|
||||
|
||||
return {
|
||||
name: 'vite-plugin-turbo-console-bridge',
|
||||
resolveId(id) {
|
||||
|
||||
@@ -9,11 +9,12 @@
|
||||
"serve": "http-server ./dist -o",
|
||||
"serve:test": "http-server ./dist-test -o",
|
||||
"svgo": "svgo -f src/assets/icons",
|
||||
"generate:icons": "tsx ./scripts/generate.icons.ts",
|
||||
"generate:icons": "fa-iconify-tools",
|
||||
"lint": "vue-tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fantastic-admin/components": "workspace:*",
|
||||
"@fantastic-admin/composables": "workspace:*",
|
||||
"@fantastic-admin/settings": "workspace:*",
|
||||
"@fantastic-admin/types": "workspace:*",
|
||||
"@vee-validate/zod": "catalog:",
|
||||
@@ -48,9 +49,9 @@
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@clack/prompts": "catalog:",
|
||||
"@faker-js/faker": "catalog:",
|
||||
"@fantastic-admin/copyright": "workspace:*",
|
||||
"@fantastic-admin/iconify-tools": "workspace:*",
|
||||
"@iconify/vue": "catalog:",
|
||||
"@spiriit/vite-plugin-svg-spritemap": "catalog:",
|
||||
"@types/nprogress": "catalog:",
|
||||
@@ -66,7 +67,6 @@
|
||||
"postcss-nested": "catalog:",
|
||||
"sass-embedded": "catalog:",
|
||||
"svgo": "catalog:",
|
||||
"tsx": "catalog:",
|
||||
"unplugin-auto-import": "catalog:",
|
||||
"unplugin-turbo-console": "catalog:",
|
||||
"unplugin-vue-components": "catalog:",
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import { spawn } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import * as p from '@clack/prompts'
|
||||
import { lookupCollection, lookupCollections } from '@iconify/json'
|
||||
|
||||
// 拿到全部图标集的原始数据
|
||||
const raw = await lookupCollections()
|
||||
|
||||
let lastChoose = fs.readFileSync(path.resolve(process.cwd(), 'src/iconify/index.json'), 'utf-8')
|
||||
lastChoose = JSON.parse(lastChoose)
|
||||
|
||||
// 取出可使用的图标集数据用于选择,并按名称排序
|
||||
const collections = Object.entries(raw).map(([id, item]) => ({
|
||||
...item,
|
||||
id,
|
||||
})).sort((a, b) => a.name.localeCompare(b.name))
|
||||
|
||||
p.intro('图标集生成工具')
|
||||
|
||||
/**
|
||||
* 分别会在对应目录下生成以下文件,其中(1)(3)用于离线下载并安装图标,(2)用于图标选择器使用
|
||||
* (1) src/iconify/index.json 记录用户交互信息
|
||||
* (2) src/iconify/data.json 包含多个图标集数据,仅记录图标名
|
||||
* (3) public/icons/*-raw.json 多个图标集的原始数据,独立存放,用于离线使用
|
||||
*/
|
||||
const answers = await p.group(
|
||||
{
|
||||
collections: () =>
|
||||
p.multiselect({
|
||||
message: '请选择需要生成的图标集',
|
||||
options: collections.map(item => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
hint: `${item.total} 个图标`,
|
||||
})),
|
||||
initialValues: lastChoose.collections,
|
||||
}),
|
||||
isOfflineUse: () =>
|
||||
p.confirm({
|
||||
message: '是否需要离线使用',
|
||||
initialValue: false,
|
||||
}),
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
p.cancel('操作已取消')
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const spinner = p.spinner()
|
||||
spinner.start('正在生成图标集...')
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/index.json'),
|
||||
{
|
||||
collections: answers.collections,
|
||||
isOfflineUse: answers.isOfflineUse,
|
||||
},
|
||||
)
|
||||
|
||||
const outputDir = path.resolve(process.cwd(), 'public/icons')
|
||||
await fs.ensureDir(outputDir)
|
||||
await fs.emptyDir(outputDir)
|
||||
|
||||
const collectionsMeta: object[] = []
|
||||
for (const info of answers.collections) {
|
||||
const setData = await lookupCollection(info)
|
||||
|
||||
collectionsMeta.push({
|
||||
prefix: setData.prefix,
|
||||
info: setData.info,
|
||||
icons: Object.keys(setData.icons),
|
||||
})
|
||||
|
||||
const offlineFilePath = path.join(outputDir, `${info}-raw.json`)
|
||||
|
||||
if (answers.isOfflineUse) {
|
||||
await fs.writeJSON(offlineFilePath, setData)
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/data.json'),
|
||||
collectionsMeta,
|
||||
)
|
||||
|
||||
// 使用 spawn 运行 eslint
|
||||
const eslint = spawn('eslint', ['src/iconify/data.json', 'src/iconify/index.json', '--cache', '--fix'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
})
|
||||
|
||||
eslint.on('error', (err) => {
|
||||
p.log.error(`ESLint 执行失败: ${err.message}`)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
eslint.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
p.log.error(`ESLint 执行失败,退出码: ${code}`)
|
||||
process.exit(code)
|
||||
}
|
||||
spinner.stop('图标集生成完成!')
|
||||
})
|
||||
@@ -113,7 +113,7 @@ function testAccount(account: string) {
|
||||
<FormField v-slot="{ componentField }" type="checkbox" name="remember">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<FaCheckbox v-bind="componentField">
|
||||
<FaCheckbox :model-value="componentField.modelValue" @update:model-value="componentField['onUpdate:modelValue']?.($event)">
|
||||
记住我
|
||||
</FaCheckbox>
|
||||
</FormControl>
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
export function usePagination() {
|
||||
const pagination = ref({
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
sort: null as string | null,
|
||||
order: null as string | null,
|
||||
})
|
||||
|
||||
function getParams() {
|
||||
return {
|
||||
// page,size 和 from,limit 是分页的两种方式,方便兼容两种接口
|
||||
page: pagination.value.page,
|
||||
size: pagination.value.size,
|
||||
from: (pagination.value.page - 1) * pagination.value.size,
|
||||
limit: pagination.value.size,
|
||||
...(
|
||||
pagination.value.sort && pagination.value.order && {
|
||||
sort: pagination.value.sort,
|
||||
order: pagination.value.order,
|
||||
}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async function onSizeChange(size: number) {
|
||||
pagination.value.size = size
|
||||
}
|
||||
|
||||
async function onCurrentChange(page: number) {
|
||||
pagination.value.page = page
|
||||
}
|
||||
|
||||
async function onSortChange(prop: string, order: string) {
|
||||
pagination.value.sort = prop
|
||||
pagination.value.order = order === 'ascending' ? 'asc' : 'desc'
|
||||
}
|
||||
|
||||
return {
|
||||
pagination,
|
||||
getParams,
|
||||
onSizeChange,
|
||||
onCurrentChange,
|
||||
onSortChange,
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -53,7 +53,7 @@ function handleCopy() {
|
||||
'columns-2': appSettingsStore.mode === 'pc',
|
||||
}"
|
||||
>
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
颜色方案
|
||||
@@ -83,7 +83,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.theme.colorAmblyopia" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="menu-mode">
|
||||
<FaTooltip text="侧边栏模式 (有主导航菜单)" :delay="500">
|
||||
<FaButton variant="outline" class="mode mode-side" :class="{ active: appSettingsStore.settings.menu.mode === 'side' }" @click="appSettingsStore.settings.menu.mode = 'side'">
|
||||
@@ -145,7 +145,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.menu.hotkeys" :disabled="appSettingsStore.settings.menu.mode === 'single'" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
标签栏
|
||||
@@ -175,7 +175,7 @@ function handleCopy() {
|
||||
</FaButtonGroup>
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
显示图标
|
||||
@@ -189,7 +189,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.tabbar.hotkeys" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div v-if="appSettingsStore.mode === 'pc'" class="setting-item">
|
||||
<div class="label">
|
||||
<FaIcon name="i-ic:twotone-double-arrow" />
|
||||
@@ -237,7 +237,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.toolbar.colorScheme" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
载入进度条
|
||||
@@ -248,7 +248,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.page.progress" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="p-4 pb-4 pt-14 border rounded-lg relative space-y-4">
|
||||
<div class="font-bold px-4 py-2 border-b border-e rounded-rb-lg inset-s-0 inset-t-0 absolute">
|
||||
账号
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ declare global {
|
||||
const useId: typeof import('vue').useId
|
||||
const useLink: typeof import('vue-router').useLink
|
||||
const useModel: typeof import('vue').useModel
|
||||
const usePagination: typeof import('../composables/pagination').usePagination
|
||||
const usePagination: typeof import('@fantastic-admin/composables').usePagination
|
||||
const useRoute: typeof import('vue-router').useRoute
|
||||
const useRouter: typeof import('vue-router').useRouter
|
||||
const useSlots: typeof import('vue').useSlots
|
||||
|
||||
@@ -24,6 +24,7 @@ declare module 'vue' {
|
||||
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -48,6 +49,7 @@ declare module 'vue' {
|
||||
FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
@@ -75,6 +77,7 @@ declare global {
|
||||
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
const FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
const FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
const FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
const FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
const FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
const FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -99,6 +102,7 @@ declare global {
|
||||
const FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
const FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
const FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
const FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
const FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
const FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { PluginOption } from 'vite'
|
||||
import process from 'node:process'
|
||||
import { FantasticAutoImports, FantasticComponentsResolver, FantasticComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import { ComponentsAutoImports as FantasticAdminComponentsAutoImports, ComponentsResolver as FantasticAdminComponentsResolver, ComponentsType as FantasticAdminComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { ComposablesAutoImports as FantasticAdminComposablesAutoImports } from '@fantastic-admin/composables/resolver'
|
||||
import { createCopyrightPlugins as createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import VitePluginSvgSpritemap from '@spiriit/vite-plugin-svg-spritemap'
|
||||
import vueLegacy from '@vitejs/plugin-legacy'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
@@ -37,6 +38,7 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
launchEditor: viteEnv.VITE_LAUNCH_EDITOR,
|
||||
}),
|
||||
|
||||
// https://github.com/yue1123/vite-plugin-env-parse
|
||||
envParse({
|
||||
dtsPath: 'src/types/env.d.ts',
|
||||
}),
|
||||
@@ -47,7 +49,8 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
'vue',
|
||||
'vue-router',
|
||||
'pinia',
|
||||
FantasticAutoImports,
|
||||
FantasticAdminComponentsAutoImports,
|
||||
FantasticAdminComposablesAutoImports,
|
||||
],
|
||||
dts: './src/types/auto-imports.d.ts',
|
||||
dirs: [
|
||||
@@ -63,10 +66,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
],
|
||||
dts: './src/types/components.d.ts',
|
||||
resolvers: [
|
||||
FantasticComponentsResolver(),
|
||||
FantasticAdminComponentsResolver(),
|
||||
],
|
||||
types: [
|
||||
FantasticComponentsType,
|
||||
FantasticAdminComponentsType,
|
||||
],
|
||||
}),
|
||||
|
||||
@@ -78,9 +81,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
// https://github.com/condorheroblog/vite-plugin-fake-server
|
||||
vitePluginFakeServer({
|
||||
logger: !isBuild,
|
||||
include: 'src/api/modules',
|
||||
include: 'src/api/fake_modules',
|
||||
enableProd: isBuild && viteEnv.VITE_BUILD_FAKE,
|
||||
}),
|
||||
|
||||
// https://github.com/nonzzz/vite-plugin-compression
|
||||
viteEnv.VITE_BUILD_COMPRESS && compression({
|
||||
exclude: [/\.(br)$/, /\.(gz)$/],
|
||||
@@ -105,7 +109,6 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
(() => {
|
||||
const moduleId = 'virtual:fantastic-admin/turbo-console'
|
||||
const resolvedModuleId = `\0${moduleId}`
|
||||
|
||||
return {
|
||||
name: 'vite-plugin-turbo-console-bridge',
|
||||
resolveId(id) {
|
||||
|
||||
@@ -9,11 +9,12 @@
|
||||
"serve": "http-server ./dist -o",
|
||||
"serve:test": "http-server ./dist-test -o",
|
||||
"svgo": "svgo -f src/assets/icons",
|
||||
"generate:icons": "tsx ./scripts/generate.icons.ts",
|
||||
"generate:icons": "fa-iconify-tools",
|
||||
"lint": "vue-tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fantastic-admin/components": "workspace:*",
|
||||
"@fantastic-admin/composables": "workspace:*",
|
||||
"@fantastic-admin/settings": "workspace:*",
|
||||
"@fantastic-admin/types": "workspace:*",
|
||||
"@vee-validate/zod": "catalog:",
|
||||
@@ -49,9 +50,9 @@
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@clack/prompts": "catalog:",
|
||||
"@faker-js/faker": "catalog:",
|
||||
"@fantastic-admin/copyright": "workspace:*",
|
||||
"@fantastic-admin/iconify-tools": "workspace:*",
|
||||
"@iconify/vue": "catalog:",
|
||||
"@spiriit/vite-plugin-svg-spritemap": "catalog:",
|
||||
"@types/nprogress": "catalog:",
|
||||
@@ -66,7 +67,6 @@
|
||||
"postcss-nested": "catalog:",
|
||||
"sass-embedded": "catalog:",
|
||||
"svgo": "catalog:",
|
||||
"tsx": "catalog:",
|
||||
"unplugin-auto-import": "catalog:",
|
||||
"unplugin-turbo-console": "catalog:",
|
||||
"unplugin-vue-components": "catalog:",
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import { spawn } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import * as p from '@clack/prompts'
|
||||
import { lookupCollection, lookupCollections } from '@iconify/json'
|
||||
|
||||
// 拿到全部图标集的原始数据
|
||||
const raw = await lookupCollections()
|
||||
|
||||
let lastChoose = fs.readFileSync(path.resolve(process.cwd(), 'src/iconify/index.json'), 'utf-8')
|
||||
lastChoose = JSON.parse(lastChoose)
|
||||
|
||||
// 取出可使用的图标集数据用于选择,并按名称排序
|
||||
const collections = Object.entries(raw).map(([id, item]) => ({
|
||||
...item,
|
||||
id,
|
||||
})).sort((a, b) => a.name.localeCompare(b.name))
|
||||
|
||||
p.intro('图标集生成工具')
|
||||
|
||||
/**
|
||||
* 分别会在对应目录下生成以下文件,其中(1)(3)用于离线下载并安装图标,(2)用于图标选择器使用
|
||||
* (1) src/iconify/index.json 记录用户交互信息
|
||||
* (2) src/iconify/data.json 包含多个图标集数据,仅记录图标名
|
||||
* (3) public/icons/*-raw.json 多个图标集的原始数据,独立存放,用于离线使用
|
||||
*/
|
||||
const answers = await p.group(
|
||||
{
|
||||
collections: () =>
|
||||
p.multiselect({
|
||||
message: '请选择需要生成的图标集',
|
||||
options: collections.map(item => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
hint: `${item.total} 个图标`,
|
||||
})),
|
||||
initialValues: lastChoose.collections,
|
||||
}),
|
||||
isOfflineUse: () =>
|
||||
p.confirm({
|
||||
message: '是否需要离线使用',
|
||||
initialValue: false,
|
||||
}),
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
p.cancel('操作已取消')
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const spinner = p.spinner()
|
||||
spinner.start('正在生成图标集...')
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/index.json'),
|
||||
{
|
||||
collections: answers.collections,
|
||||
isOfflineUse: answers.isOfflineUse,
|
||||
},
|
||||
)
|
||||
|
||||
const outputDir = path.resolve(process.cwd(), 'public/icons')
|
||||
await fs.ensureDir(outputDir)
|
||||
await fs.emptyDir(outputDir)
|
||||
|
||||
const collectionsMeta: object[] = []
|
||||
for (const info of answers.collections) {
|
||||
const setData = await lookupCollection(info)
|
||||
|
||||
collectionsMeta.push({
|
||||
prefix: setData.prefix,
|
||||
info: setData.info,
|
||||
icons: Object.keys(setData.icons),
|
||||
})
|
||||
|
||||
const offlineFilePath = path.join(outputDir, `${info}-raw.json`)
|
||||
|
||||
if (answers.isOfflineUse) {
|
||||
await fs.writeJSON(offlineFilePath, setData)
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/data.json'),
|
||||
collectionsMeta,
|
||||
)
|
||||
|
||||
// 使用 spawn 运行 eslint
|
||||
const eslint = spawn('eslint', ['src/iconify/data.json', 'src/iconify/index.json', '--cache', '--fix'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
})
|
||||
|
||||
eslint.on('error', (err) => {
|
||||
p.log.error(`ESLint 执行失败: ${err.message}`)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
eslint.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
p.log.error(`ESLint 执行失败,退出码: ${code}`)
|
||||
process.exit(code)
|
||||
}
|
||||
spinner.stop('图标集生成完成!')
|
||||
})
|
||||
@@ -113,7 +113,7 @@ function testAccount(account: string) {
|
||||
<FormField v-slot="{ componentField }" type="checkbox" name="remember">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<FaCheckbox v-bind="componentField">
|
||||
<FaCheckbox :model-value="componentField.modelValue" @update:model-value="componentField['onUpdate:modelValue']?.($event)">
|
||||
记住我
|
||||
</FaCheckbox>
|
||||
</FormControl>
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
export function usePagination() {
|
||||
const pagination = ref({
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
sort: null as string | null,
|
||||
order: null as string | null,
|
||||
})
|
||||
|
||||
function getParams() {
|
||||
return {
|
||||
// page,size 和 from,limit 是分页的两种方式,方便兼容两种接口
|
||||
page: pagination.value.page,
|
||||
size: pagination.value.size,
|
||||
from: (pagination.value.page - 1) * pagination.value.size,
|
||||
limit: pagination.value.size,
|
||||
...(
|
||||
pagination.value.sort && pagination.value.order && {
|
||||
sort: pagination.value.sort,
|
||||
order: pagination.value.order,
|
||||
}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async function onSizeChange(size: number) {
|
||||
pagination.value.size = size
|
||||
}
|
||||
|
||||
async function onCurrentChange(page: number) {
|
||||
pagination.value.page = page
|
||||
}
|
||||
|
||||
async function onSortChange(prop: string, order: string) {
|
||||
pagination.value.sort = prop
|
||||
pagination.value.order = order === 'ascending' ? 'asc' : 'desc'
|
||||
}
|
||||
|
||||
return {
|
||||
pagination,
|
||||
getParams,
|
||||
onSizeChange,
|
||||
onCurrentChange,
|
||||
onSortChange,
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -53,7 +53,7 @@ function handleCopy() {
|
||||
'columns-2': appSettingsStore.mode === 'pc',
|
||||
}"
|
||||
>
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
颜色方案
|
||||
@@ -83,7 +83,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.theme.colorAmblyopia" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="menu-mode">
|
||||
<FaTooltip text="侧边栏模式 (有主导航菜单)" :delay="500">
|
||||
<FaButton variant="outline" class="mode mode-side" :class="{ active: appSettingsStore.settings.menu.mode === 'side' }" @click="appSettingsStore.settings.menu.mode = 'side'">
|
||||
@@ -145,7 +145,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.menu.hotkeys" :disabled="appSettingsStore.settings.menu.mode === 'single'" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
标签栏
|
||||
@@ -175,7 +175,7 @@ function handleCopy() {
|
||||
</FaButtonGroup>
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
显示图标
|
||||
@@ -189,7 +189,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.tabbar.hotkeys" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div v-if="appSettingsStore.mode === 'pc'" class="setting-item">
|
||||
<div class="label">
|
||||
<FaIcon name="i-ic:twotone-double-arrow" />
|
||||
@@ -237,7 +237,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.toolbar.colorScheme" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
载入进度条
|
||||
@@ -248,7 +248,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.page.progress" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="p-4 pb-4 pt-14 border rounded-lg relative space-y-4">
|
||||
<div class="font-bold px-4 py-2 border-b border-e rounded-rb-lg inset-s-0 inset-t-0 absolute">
|
||||
账号
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ declare global {
|
||||
const useId: typeof import('vue').useId
|
||||
const useLink: typeof import('vue-router').useLink
|
||||
const useModel: typeof import('vue').useModel
|
||||
const usePagination: typeof import('../composables/pagination').usePagination
|
||||
const usePagination: typeof import('@fantastic-admin/composables').usePagination
|
||||
const useRoute: typeof import('vue-router').useRoute
|
||||
const useRouter: typeof import('vue-router').useRouter
|
||||
const useSlots: typeof import('vue').useSlots
|
||||
|
||||
+4
@@ -24,6 +24,7 @@ declare module 'vue' {
|
||||
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -48,6 +49,7 @@ declare module 'vue' {
|
||||
FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
@@ -75,6 +77,7 @@ declare global {
|
||||
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
const FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
const FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
const FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
const FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
const FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
const FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -99,6 +102,7 @@ declare global {
|
||||
const FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
const FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
const FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
const FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
const FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
const FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { PluginOption } from 'vite'
|
||||
import process from 'node:process'
|
||||
import { FantasticAutoImports, FantasticComponentsResolver, FantasticComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import { ComponentsAutoImports as FantasticAdminComponentsAutoImports, ComponentsResolver as FantasticAdminComponentsResolver, ComponentsType as FantasticAdminComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { ComposablesAutoImports as FantasticAdminComposablesAutoImports } from '@fantastic-admin/composables/resolver'
|
||||
import { createCopyrightPlugins as createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import VitePluginSvgSpritemap from '@spiriit/vite-plugin-svg-spritemap'
|
||||
import vueLegacy from '@vitejs/plugin-legacy'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
@@ -37,6 +38,7 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
launchEditor: viteEnv.VITE_LAUNCH_EDITOR,
|
||||
}),
|
||||
|
||||
// https://github.com/yue1123/vite-plugin-env-parse
|
||||
envParse({
|
||||
dtsPath: 'src/types/env.d.ts',
|
||||
}),
|
||||
@@ -47,7 +49,8 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
'vue',
|
||||
'vue-router',
|
||||
'pinia',
|
||||
FantasticAutoImports,
|
||||
FantasticAdminComponentsAutoImports,
|
||||
FantasticAdminComposablesAutoImports,
|
||||
],
|
||||
dts: './src/types/auto-imports.d.ts',
|
||||
dirs: [
|
||||
@@ -63,10 +66,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
],
|
||||
dts: './src/types/components.d.ts',
|
||||
resolvers: [
|
||||
FantasticComponentsResolver(),
|
||||
FantasticAdminComponentsResolver(),
|
||||
],
|
||||
types: [
|
||||
FantasticComponentsType,
|
||||
FantasticAdminComponentsType,
|
||||
],
|
||||
}),
|
||||
|
||||
@@ -78,9 +81,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
// https://github.com/condorheroblog/vite-plugin-fake-server
|
||||
vitePluginFakeServer({
|
||||
logger: !isBuild,
|
||||
include: 'src/api/modules',
|
||||
include: 'src/api/fake_modules',
|
||||
enableProd: isBuild && viteEnv.VITE_BUILD_FAKE,
|
||||
}),
|
||||
|
||||
// https://github.com/nonzzz/vite-plugin-compression
|
||||
viteEnv.VITE_BUILD_COMPRESS && compression({
|
||||
exclude: [/\.(br)$/, /\.(gz)$/],
|
||||
@@ -105,7 +109,6 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
(() => {
|
||||
const moduleId = 'virtual:fantastic-admin/turbo-console'
|
||||
const resolvedModuleId = `\0${moduleId}`
|
||||
|
||||
return {
|
||||
name: 'vite-plugin-turbo-console-bridge',
|
||||
resolveId(id) {
|
||||
|
||||
@@ -9,11 +9,12 @@
|
||||
"serve": "http-server ./dist -o",
|
||||
"serve:test": "http-server ./dist-test -o",
|
||||
"svgo": "svgo -f src/assets/icons",
|
||||
"generate:icons": "tsx ./scripts/generate.icons.ts",
|
||||
"generate:icons": "fa-iconify-tools",
|
||||
"lint": "vue-tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fantastic-admin/components": "workspace:*",
|
||||
"@fantastic-admin/composables": "workspace:*",
|
||||
"@fantastic-admin/settings": "workspace:*",
|
||||
"@fantastic-admin/types": "workspace:*",
|
||||
"@vee-validate/zod": "catalog:",
|
||||
@@ -49,9 +50,9 @@
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@clack/prompts": "catalog:",
|
||||
"@faker-js/faker": "catalog:",
|
||||
"@fantastic-admin/copyright": "workspace:*",
|
||||
"@fantastic-admin/iconify-tools": "workspace:*",
|
||||
"@iconify/vue": "catalog:",
|
||||
"@spiriit/vite-plugin-svg-spritemap": "catalog:",
|
||||
"@types/nprogress": "catalog:",
|
||||
@@ -66,7 +67,6 @@
|
||||
"postcss-nested": "catalog:",
|
||||
"sass-embedded": "catalog:",
|
||||
"svgo": "catalog:",
|
||||
"tsx": "catalog:",
|
||||
"unplugin-auto-import": "catalog:",
|
||||
"unplugin-turbo-console": "catalog:",
|
||||
"unplugin-vue-components": "catalog:",
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import { spawn } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import * as p from '@clack/prompts'
|
||||
import { lookupCollection, lookupCollections } from '@iconify/json'
|
||||
|
||||
// 拿到全部图标集的原始数据
|
||||
const raw = await lookupCollections()
|
||||
|
||||
let lastChoose = fs.readFileSync(path.resolve(process.cwd(), 'src/iconify/index.json'), 'utf-8')
|
||||
lastChoose = JSON.parse(lastChoose)
|
||||
|
||||
// 取出可使用的图标集数据用于选择,并按名称排序
|
||||
const collections = Object.entries(raw).map(([id, item]) => ({
|
||||
...item,
|
||||
id,
|
||||
})).sort((a, b) => a.name.localeCompare(b.name))
|
||||
|
||||
p.intro('图标集生成工具')
|
||||
|
||||
/**
|
||||
* 分别会在对应目录下生成以下文件,其中(1)(3)用于离线下载并安装图标,(2)用于图标选择器使用
|
||||
* (1) src/iconify/index.json 记录用户交互信息
|
||||
* (2) src/iconify/data.json 包含多个图标集数据,仅记录图标名
|
||||
* (3) public/icons/*-raw.json 多个图标集的原始数据,独立存放,用于离线使用
|
||||
*/
|
||||
const answers = await p.group(
|
||||
{
|
||||
collections: () =>
|
||||
p.multiselect({
|
||||
message: '请选择需要生成的图标集',
|
||||
options: collections.map(item => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
hint: `${item.total} 个图标`,
|
||||
})),
|
||||
initialValues: lastChoose.collections,
|
||||
}),
|
||||
isOfflineUse: () =>
|
||||
p.confirm({
|
||||
message: '是否需要离线使用',
|
||||
initialValue: false,
|
||||
}),
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
p.cancel('操作已取消')
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const spinner = p.spinner()
|
||||
spinner.start('正在生成图标集...')
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/index.json'),
|
||||
{
|
||||
collections: answers.collections,
|
||||
isOfflineUse: answers.isOfflineUse,
|
||||
},
|
||||
)
|
||||
|
||||
const outputDir = path.resolve(process.cwd(), 'public/icons')
|
||||
await fs.ensureDir(outputDir)
|
||||
await fs.emptyDir(outputDir)
|
||||
|
||||
const collectionsMeta: object[] = []
|
||||
for (const info of answers.collections) {
|
||||
const setData = await lookupCollection(info)
|
||||
|
||||
collectionsMeta.push({
|
||||
prefix: setData.prefix,
|
||||
info: setData.info,
|
||||
icons: Object.keys(setData.icons),
|
||||
})
|
||||
|
||||
const offlineFilePath = path.join(outputDir, `${info}-raw.json`)
|
||||
|
||||
if (answers.isOfflineUse) {
|
||||
await fs.writeJSON(offlineFilePath, setData)
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/data.json'),
|
||||
collectionsMeta,
|
||||
)
|
||||
|
||||
// 使用 spawn 运行 eslint
|
||||
const eslint = spawn('eslint', ['src/iconify/data.json', 'src/iconify/index.json', '--cache', '--fix'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
})
|
||||
|
||||
eslint.on('error', (err) => {
|
||||
p.log.error(`ESLint 执行失败: ${err.message}`)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
eslint.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
p.log.error(`ESLint 执行失败,退出码: ${code}`)
|
||||
process.exit(code)
|
||||
}
|
||||
spinner.stop('图标集生成完成!')
|
||||
})
|
||||
@@ -113,7 +113,7 @@ function testAccount(account: string) {
|
||||
<FormField v-slot="{ componentField }" type="checkbox" name="remember">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<FaCheckbox v-bind="componentField">
|
||||
<FaCheckbox :model-value="componentField.modelValue" @update:model-value="componentField['onUpdate:modelValue']?.($event)">
|
||||
记住我
|
||||
</FaCheckbox>
|
||||
</FormControl>
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
export function usePagination() {
|
||||
const pagination = ref({
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
sort: null as string | null,
|
||||
order: null as string | null,
|
||||
})
|
||||
|
||||
function getParams() {
|
||||
return {
|
||||
// page,size 和 from,limit 是分页的两种方式,方便兼容两种接口
|
||||
page: pagination.value.page,
|
||||
size: pagination.value.size,
|
||||
from: (pagination.value.page - 1) * pagination.value.size,
|
||||
limit: pagination.value.size,
|
||||
...(
|
||||
pagination.value.sort && pagination.value.order && {
|
||||
sort: pagination.value.sort,
|
||||
order: pagination.value.order,
|
||||
}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async function onSizeChange(size: number) {
|
||||
pagination.value.size = size
|
||||
}
|
||||
|
||||
async function onCurrentChange(page: number) {
|
||||
pagination.value.page = page
|
||||
}
|
||||
|
||||
async function onSortChange(prop: string, order: string) {
|
||||
pagination.value.sort = prop
|
||||
pagination.value.order = order === 'ascending' ? 'asc' : 'desc'
|
||||
}
|
||||
|
||||
return {
|
||||
pagination,
|
||||
getParams,
|
||||
onSizeChange,
|
||||
onCurrentChange,
|
||||
onSortChange,
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -53,7 +53,7 @@ function handleCopy() {
|
||||
'columns-2': appSettingsStore.mode === 'pc',
|
||||
}"
|
||||
>
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
颜色方案
|
||||
@@ -83,7 +83,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.theme.colorAmblyopia" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="menu-mode">
|
||||
<FaTooltip text="侧边栏模式 (有主导航菜单)" :delay="500">
|
||||
<FaButton variant="outline" class="mode mode-side" :class="{ active: appSettingsStore.settings.menu.mode === 'side' }" @click="appSettingsStore.settings.menu.mode = 'side'">
|
||||
@@ -145,7 +145,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.menu.hotkeys" :disabled="appSettingsStore.settings.menu.mode === 'single'" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
标签栏
|
||||
@@ -175,7 +175,7 @@ function handleCopy() {
|
||||
</FaButtonGroup>
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
显示图标
|
||||
@@ -189,7 +189,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.tabbar.hotkeys" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div v-if="appSettingsStore.mode === 'pc'" class="setting-item">
|
||||
<div class="label">
|
||||
<FaIcon name="i-ic:twotone-double-arrow" />
|
||||
@@ -237,7 +237,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.toolbar.colorScheme" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
载入进度条
|
||||
@@ -248,7 +248,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.page.progress" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="p-4 pb-4 pt-14 border rounded-lg relative space-y-4">
|
||||
<div class="font-bold px-4 py-2 border-b border-e rounded-rb-lg inset-s-0 inset-t-0 absolute">
|
||||
账号
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ declare global {
|
||||
const useId: typeof import('vue').useId
|
||||
const useLink: typeof import('vue-router').useLink
|
||||
const useModel: typeof import('vue').useModel
|
||||
const usePagination: typeof import('../composables/pagination').usePagination
|
||||
const usePagination: typeof import('@fantastic-admin/composables').usePagination
|
||||
const useRoute: typeof import('vue-router').useRoute
|
||||
const useRouter: typeof import('vue-router').useRouter
|
||||
const useSlots: typeof import('vue').useSlots
|
||||
|
||||
@@ -24,6 +24,7 @@ declare module 'vue' {
|
||||
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -48,6 +49,7 @@ declare module 'vue' {
|
||||
FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
@@ -75,6 +77,7 @@ declare global {
|
||||
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
const FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
const FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
const FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
const FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
const FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
const FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -99,6 +102,7 @@ declare global {
|
||||
const FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
const FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
const FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
const FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
const FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
const FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { PluginOption } from 'vite'
|
||||
import process from 'node:process'
|
||||
import { FantasticAutoImports, FantasticComponentsResolver, FantasticComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import { ComponentsAutoImports as FantasticAdminComponentsAutoImports, ComponentsResolver as FantasticAdminComponentsResolver, ComponentsType as FantasticAdminComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { ComposablesAutoImports as FantasticAdminComposablesAutoImports } from '@fantastic-admin/composables/resolver'
|
||||
import { createCopyrightPlugins as createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import VitePluginSvgSpritemap from '@spiriit/vite-plugin-svg-spritemap'
|
||||
import vueLegacy from '@vitejs/plugin-legacy'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
@@ -37,6 +38,7 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
launchEditor: viteEnv.VITE_LAUNCH_EDITOR,
|
||||
}),
|
||||
|
||||
// https://github.com/yue1123/vite-plugin-env-parse
|
||||
envParse({
|
||||
dtsPath: 'src/types/env.d.ts',
|
||||
}),
|
||||
@@ -47,7 +49,8 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
'vue',
|
||||
'vue-router',
|
||||
'pinia',
|
||||
FantasticAutoImports,
|
||||
FantasticAdminComponentsAutoImports,
|
||||
FantasticAdminComposablesAutoImports,
|
||||
],
|
||||
dts: './src/types/auto-imports.d.ts',
|
||||
dirs: [
|
||||
@@ -63,10 +66,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
],
|
||||
dts: './src/types/components.d.ts',
|
||||
resolvers: [
|
||||
FantasticComponentsResolver(),
|
||||
FantasticAdminComponentsResolver(),
|
||||
],
|
||||
types: [
|
||||
FantasticComponentsType,
|
||||
FantasticAdminComponentsType,
|
||||
],
|
||||
}),
|
||||
|
||||
@@ -78,9 +81,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
// https://github.com/condorheroblog/vite-plugin-fake-server
|
||||
vitePluginFakeServer({
|
||||
logger: !isBuild,
|
||||
include: 'src/api/modules',
|
||||
include: 'src/api/fake_modules',
|
||||
enableProd: isBuild && viteEnv.VITE_BUILD_FAKE,
|
||||
}),
|
||||
|
||||
// https://github.com/nonzzz/vite-plugin-compression
|
||||
viteEnv.VITE_BUILD_COMPRESS && compression({
|
||||
exclude: [/\.(br)$/, /\.(gz)$/],
|
||||
@@ -105,7 +109,6 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
(() => {
|
||||
const moduleId = 'virtual:fantastic-admin/turbo-console'
|
||||
const resolvedModuleId = `\0${moduleId}`
|
||||
|
||||
return {
|
||||
name: 'vite-plugin-turbo-console-bridge',
|
||||
resolveId(id) {
|
||||
|
||||
@@ -9,11 +9,12 @@
|
||||
"serve": "http-server ./dist -o",
|
||||
"serve:test": "http-server ./dist-test -o",
|
||||
"svgo": "svgo -f src/assets/icons",
|
||||
"generate:icons": "tsx ./scripts/generate.icons.ts",
|
||||
"generate:icons": "fa-iconify-tools",
|
||||
"lint": "vue-tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fantastic-admin/components": "workspace:*",
|
||||
"@fantastic-admin/composables": "workspace:*",
|
||||
"@fantastic-admin/settings": "workspace:*",
|
||||
"@fantastic-admin/types": "workspace:*",
|
||||
"@vee-validate/zod": "catalog:",
|
||||
@@ -49,9 +50,9 @@
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@clack/prompts": "catalog:",
|
||||
"@faker-js/faker": "catalog:",
|
||||
"@fantastic-admin/copyright": "workspace:*",
|
||||
"@fantastic-admin/iconify-tools": "workspace:*",
|
||||
"@iconify/vue": "catalog:",
|
||||
"@spiriit/vite-plugin-svg-spritemap": "catalog:",
|
||||
"@types/nprogress": "catalog:",
|
||||
@@ -66,7 +67,6 @@
|
||||
"postcss-nested": "catalog:",
|
||||
"sass-embedded": "catalog:",
|
||||
"svgo": "catalog:",
|
||||
"tsx": "catalog:",
|
||||
"unplugin-auto-import": "catalog:",
|
||||
"unplugin-turbo-console": "catalog:",
|
||||
"unplugin-vue-components": "catalog:",
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import { spawn } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import * as p from '@clack/prompts'
|
||||
import { lookupCollection, lookupCollections } from '@iconify/json'
|
||||
|
||||
// 拿到全部图标集的原始数据
|
||||
const raw = await lookupCollections()
|
||||
|
||||
let lastChoose = fs.readFileSync(path.resolve(process.cwd(), 'src/iconify/index.json'), 'utf-8')
|
||||
lastChoose = JSON.parse(lastChoose)
|
||||
|
||||
// 取出可使用的图标集数据用于选择,并按名称排序
|
||||
const collections = Object.entries(raw).map(([id, item]) => ({
|
||||
...item,
|
||||
id,
|
||||
})).sort((a, b) => a.name.localeCompare(b.name))
|
||||
|
||||
p.intro('图标集生成工具')
|
||||
|
||||
/**
|
||||
* 分别会在对应目录下生成以下文件,其中(1)(3)用于离线下载并安装图标,(2)用于图标选择器使用
|
||||
* (1) src/iconify/index.json 记录用户交互信息
|
||||
* (2) src/iconify/data.json 包含多个图标集数据,仅记录图标名
|
||||
* (3) public/icons/*-raw.json 多个图标集的原始数据,独立存放,用于离线使用
|
||||
*/
|
||||
const answers = await p.group(
|
||||
{
|
||||
collections: () =>
|
||||
p.multiselect({
|
||||
message: '请选择需要生成的图标集',
|
||||
options: collections.map(item => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
hint: `${item.total} 个图标`,
|
||||
})),
|
||||
initialValues: lastChoose.collections,
|
||||
}),
|
||||
isOfflineUse: () =>
|
||||
p.confirm({
|
||||
message: '是否需要离线使用',
|
||||
initialValue: false,
|
||||
}),
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
p.cancel('操作已取消')
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const spinner = p.spinner()
|
||||
spinner.start('正在生成图标集...')
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/index.json'),
|
||||
{
|
||||
collections: answers.collections,
|
||||
isOfflineUse: answers.isOfflineUse,
|
||||
},
|
||||
)
|
||||
|
||||
const outputDir = path.resolve(process.cwd(), 'public/icons')
|
||||
await fs.ensureDir(outputDir)
|
||||
await fs.emptyDir(outputDir)
|
||||
|
||||
const collectionsMeta: object[] = []
|
||||
for (const info of answers.collections) {
|
||||
const setData = await lookupCollection(info)
|
||||
|
||||
collectionsMeta.push({
|
||||
prefix: setData.prefix,
|
||||
info: setData.info,
|
||||
icons: Object.keys(setData.icons),
|
||||
})
|
||||
|
||||
const offlineFilePath = path.join(outputDir, `${info}-raw.json`)
|
||||
|
||||
if (answers.isOfflineUse) {
|
||||
await fs.writeJSON(offlineFilePath, setData)
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/data.json'),
|
||||
collectionsMeta,
|
||||
)
|
||||
|
||||
// 使用 spawn 运行 eslint
|
||||
const eslint = spawn('eslint', ['src/iconify/data.json', 'src/iconify/index.json', '--cache', '--fix'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
})
|
||||
|
||||
eslint.on('error', (err) => {
|
||||
p.log.error(`ESLint 执行失败: ${err.message}`)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
eslint.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
p.log.error(`ESLint 执行失败,退出码: ${code}`)
|
||||
process.exit(code)
|
||||
}
|
||||
spinner.stop('图标集生成完成!')
|
||||
})
|
||||
@@ -113,7 +113,7 @@ function testAccount(account: string) {
|
||||
<FormField v-slot="{ componentField }" type="checkbox" name="remember">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<FaCheckbox v-bind="componentField">
|
||||
<FaCheckbox :model-value="componentField.modelValue" @update:model-value="componentField['onUpdate:modelValue']?.($event)">
|
||||
记住我
|
||||
</FaCheckbox>
|
||||
</FormControl>
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
export function usePagination() {
|
||||
const pagination = ref({
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
sort: null as string | null,
|
||||
order: null as string | null,
|
||||
})
|
||||
|
||||
function getParams() {
|
||||
return {
|
||||
// page,size 和 from,limit 是分页的两种方式,方便兼容两种接口
|
||||
page: pagination.value.page,
|
||||
size: pagination.value.size,
|
||||
from: (pagination.value.page - 1) * pagination.value.size,
|
||||
limit: pagination.value.size,
|
||||
...(
|
||||
pagination.value.sort && pagination.value.order && {
|
||||
sort: pagination.value.sort,
|
||||
order: pagination.value.order,
|
||||
}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async function onSizeChange(size: number) {
|
||||
pagination.value.size = size
|
||||
}
|
||||
|
||||
async function onCurrentChange(page: number) {
|
||||
pagination.value.page = page
|
||||
}
|
||||
|
||||
async function onSortChange(prop: string, order: string) {
|
||||
pagination.value.sort = prop
|
||||
pagination.value.order = order === 'ascending' ? 'asc' : 'desc'
|
||||
}
|
||||
|
||||
return {
|
||||
pagination,
|
||||
getParams,
|
||||
onSizeChange,
|
||||
onCurrentChange,
|
||||
onSortChange,
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -53,7 +53,7 @@ function handleCopy() {
|
||||
'columns-2': appSettingsStore.mode === 'pc',
|
||||
}"
|
||||
>
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
颜色方案
|
||||
@@ -83,7 +83,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.theme.colorAmblyopia" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="menu-mode">
|
||||
<FaTooltip text="侧边栏模式 (有主导航菜单)" :delay="500">
|
||||
<FaButton variant="outline" class="mode mode-side" :class="{ active: appSettingsStore.settings.menu.mode === 'side' }" @click="appSettingsStore.settings.menu.mode = 'side'">
|
||||
@@ -145,7 +145,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.menu.hotkeys" :disabled="appSettingsStore.settings.menu.mode === 'single'" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
标签栏
|
||||
@@ -175,7 +175,7 @@ function handleCopy() {
|
||||
</FaButtonGroup>
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
显示图标
|
||||
@@ -189,7 +189,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.tabbar.hotkeys" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div v-if="appSettingsStore.mode === 'pc'" class="setting-item">
|
||||
<div class="label">
|
||||
<FaIcon name="i-ic:twotone-double-arrow" />
|
||||
@@ -237,7 +237,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.toolbar.colorScheme" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
载入进度条
|
||||
@@ -248,7 +248,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.page.progress" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="p-4 pb-4 pt-14 border rounded-lg relative space-y-4">
|
||||
<div class="font-bold px-4 py-2 border-b border-e rounded-rb-lg inset-s-0 inset-t-0 absolute">
|
||||
账号
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ declare global {
|
||||
const useId: typeof import('vue').useId
|
||||
const useLink: typeof import('vue-router').useLink
|
||||
const useModel: typeof import('vue').useModel
|
||||
const usePagination: typeof import('../composables/pagination').usePagination
|
||||
const usePagination: typeof import('@fantastic-admin/composables').usePagination
|
||||
const useRoute: typeof import('vue-router').useRoute
|
||||
const useRouter: typeof import('vue-router').useRouter
|
||||
const useSlots: typeof import('vue').useSlots
|
||||
|
||||
Vendored
+4
@@ -24,6 +24,7 @@ declare module 'vue' {
|
||||
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -48,6 +49,7 @@ declare module 'vue' {
|
||||
FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
@@ -75,6 +77,7 @@ declare global {
|
||||
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
const FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
const FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
const FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
const FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
const FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
const FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
@@ -99,6 +102,7 @@ declare global {
|
||||
const FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
const FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
const FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
const FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
const FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
const FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { PluginOption } from 'vite'
|
||||
import process from 'node:process'
|
||||
import { FantasticAutoImports, FantasticComponentsResolver, FantasticComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import { ComponentsAutoImports as FantasticAdminComponentsAutoImports, ComponentsResolver as FantasticAdminComponentsResolver, ComponentsType as FantasticAdminComponentsType } from '@fantastic-admin/components/resolver'
|
||||
import { ComposablesAutoImports as FantasticAdminComposablesAutoImports } from '@fantastic-admin/composables/resolver'
|
||||
import { createCopyrightPlugins as createFantasticAdminCopyrightPlugins } from '@fantastic-admin/copyright'
|
||||
import VitePluginSvgSpritemap from '@spiriit/vite-plugin-svg-spritemap'
|
||||
import vueLegacy from '@vitejs/plugin-legacy'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
@@ -37,6 +38,7 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
launchEditor: viteEnv.VITE_LAUNCH_EDITOR,
|
||||
}),
|
||||
|
||||
// https://github.com/yue1123/vite-plugin-env-parse
|
||||
envParse({
|
||||
dtsPath: 'src/types/env.d.ts',
|
||||
}),
|
||||
@@ -47,7 +49,8 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
'vue',
|
||||
'vue-router',
|
||||
'pinia',
|
||||
FantasticAutoImports,
|
||||
FantasticAdminComponentsAutoImports,
|
||||
FantasticAdminComposablesAutoImports,
|
||||
],
|
||||
dts: './src/types/auto-imports.d.ts',
|
||||
dirs: [
|
||||
@@ -63,10 +66,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
],
|
||||
dts: './src/types/components.d.ts',
|
||||
resolvers: [
|
||||
FantasticComponentsResolver(),
|
||||
FantasticAdminComponentsResolver(),
|
||||
],
|
||||
types: [
|
||||
FantasticComponentsType,
|
||||
FantasticAdminComponentsType,
|
||||
],
|
||||
}),
|
||||
|
||||
@@ -78,9 +81,10 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
// https://github.com/condorheroblog/vite-plugin-fake-server
|
||||
vitePluginFakeServer({
|
||||
logger: !isBuild,
|
||||
include: 'src/api/modules',
|
||||
include: 'src/api/fake_modules',
|
||||
enableProd: isBuild && viteEnv.VITE_BUILD_FAKE,
|
||||
}),
|
||||
|
||||
// https://github.com/nonzzz/vite-plugin-compression
|
||||
viteEnv.VITE_BUILD_COMPRESS && compression({
|
||||
exclude: [/\.(br)$/, /\.(gz)$/],
|
||||
@@ -105,7 +109,6 @@ export default function createVitePlugins(mode: string, isBuild = false) {
|
||||
(() => {
|
||||
const moduleId = 'virtual:fantastic-admin/turbo-console'
|
||||
const resolvedModuleId = `\0${moduleId}`
|
||||
|
||||
return {
|
||||
name: 'vite-plugin-turbo-console-bridge',
|
||||
resolveId(id) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"serve": "http-server ./dist -o",
|
||||
"serve:test": "http-server ./dist-test -o",
|
||||
"svgo": "svgo -f src/assets/icons",
|
||||
"generate:icons": "tsx ./scripts/generate.icons.ts",
|
||||
"generate:icons": "fa-iconify-tools",
|
||||
"lint": "vue-tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -17,6 +17,7 @@
|
||||
"@bytemd/plugin-gfm": "catalog:",
|
||||
"@bytemd/vue-next": "catalog:",
|
||||
"@fantastic-admin/components": "workspace:*",
|
||||
"@fantastic-admin/composables": "workspace:*",
|
||||
"@fantastic-admin/settings": "workspace:*",
|
||||
"@fantastic-admin/types": "workspace:*",
|
||||
"@tinymce/tinymce-vue": "catalog:",
|
||||
@@ -69,9 +70,9 @@
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@clack/prompts": "catalog:",
|
||||
"@faker-js/faker": "catalog:",
|
||||
"@fantastic-admin/copyright": "workspace:*",
|
||||
"@fantastic-admin/iconify-tools": "workspace:*",
|
||||
"@iconify/vue": "catalog:",
|
||||
"@spiriit/vite-plugin-svg-spritemap": "catalog:",
|
||||
"@types/nprogress": "catalog:",
|
||||
@@ -87,7 +88,6 @@
|
||||
"postcss-nested": "catalog:",
|
||||
"sass-embedded": "catalog:",
|
||||
"svgo": "catalog:",
|
||||
"tsx": "catalog:",
|
||||
"unplugin-auto-import": "catalog:",
|
||||
"unplugin-turbo-console": "catalog:",
|
||||
"unplugin-vue-components": "catalog:",
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import { spawn } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import * as p from '@clack/prompts'
|
||||
import { lookupCollection, lookupCollections } from '@iconify/json'
|
||||
|
||||
// 拿到全部图标集的原始数据
|
||||
const raw = await lookupCollections()
|
||||
|
||||
let lastChoose = fs.readFileSync(path.resolve(process.cwd(), 'src/iconify/index.json'), 'utf-8')
|
||||
lastChoose = JSON.parse(lastChoose)
|
||||
|
||||
// 取出可使用的图标集数据用于选择,并按名称排序
|
||||
const collections = Object.entries(raw).map(([id, item]) => ({
|
||||
...item,
|
||||
id,
|
||||
})).sort((a, b) => a.name.localeCompare(b.name))
|
||||
|
||||
p.intro('图标集生成工具')
|
||||
|
||||
/**
|
||||
* 分别会在对应目录下生成以下文件,其中(1)(3)用于离线下载并安装图标,(2)用于图标选择器使用
|
||||
* (1) src/iconify/index.json 记录用户交互信息
|
||||
* (2) src/iconify/data.json 包含多个图标集数据,仅记录图标名
|
||||
* (3) public/icons/*-raw.json 多个图标集的原始数据,独立存放,用于离线使用
|
||||
*/
|
||||
const answers = await p.group(
|
||||
{
|
||||
collections: () =>
|
||||
p.multiselect({
|
||||
message: '请选择需要生成的图标集',
|
||||
options: collections.map(item => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
hint: `${item.total} 个图标`,
|
||||
})),
|
||||
initialValues: lastChoose.collections,
|
||||
}),
|
||||
isOfflineUse: () =>
|
||||
p.confirm({
|
||||
message: '是否需要离线使用',
|
||||
initialValue: false,
|
||||
}),
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
p.cancel('操作已取消')
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const spinner = p.spinner()
|
||||
spinner.start('正在生成图标集...')
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/index.json'),
|
||||
{
|
||||
collections: answers.collections,
|
||||
isOfflineUse: answers.isOfflineUse,
|
||||
},
|
||||
)
|
||||
|
||||
const outputDir = path.resolve(process.cwd(), 'public/icons')
|
||||
await fs.ensureDir(outputDir)
|
||||
await fs.emptyDir(outputDir)
|
||||
|
||||
const collectionsMeta: object[] = []
|
||||
for (const info of answers.collections) {
|
||||
const setData = await lookupCollection(info)
|
||||
|
||||
collectionsMeta.push({
|
||||
prefix: setData.prefix,
|
||||
info: setData.info,
|
||||
icons: Object.keys(setData.icons),
|
||||
})
|
||||
|
||||
const offlineFilePath = path.join(outputDir, `${info}-raw.json`)
|
||||
|
||||
if (answers.isOfflineUse) {
|
||||
await fs.writeJSON(offlineFilePath, setData)
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeJSON(
|
||||
path.resolve(process.cwd(), 'src/iconify/data.json'),
|
||||
collectionsMeta,
|
||||
)
|
||||
|
||||
// 使用 spawn 运行 eslint
|
||||
const eslint = spawn('eslint', ['src/iconify/data.json', 'src/iconify/index.json', '--cache', '--fix'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
})
|
||||
|
||||
eslint.on('error', (err) => {
|
||||
p.log.error(`ESLint 执行失败: ${err.message}`)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
eslint.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
p.log.error(`ESLint 执行失败,退出码: ${code}`)
|
||||
process.exit(code)
|
||||
}
|
||||
spinner.stop('图标集生成完成!')
|
||||
})
|
||||
@@ -113,7 +113,7 @@ function testAccount(account: string) {
|
||||
<FormField v-slot="{ componentField }" type="checkbox" name="remember">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<FaCheckbox v-bind="componentField">
|
||||
<FaCheckbox :model-value="componentField.modelValue" @update:model-value="componentField['onUpdate:modelValue']?.($event)">
|
||||
记住我
|
||||
</FaCheckbox>
|
||||
</FormControl>
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
export function usePagination() {
|
||||
const pagination = ref({
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
sort: null as string | null,
|
||||
order: null as string | null,
|
||||
})
|
||||
|
||||
function getParams() {
|
||||
return {
|
||||
// page,size 和 from,limit 是分页的两种方式,方便兼容两种接口
|
||||
page: pagination.value.page,
|
||||
size: pagination.value.size,
|
||||
from: (pagination.value.page - 1) * pagination.value.size,
|
||||
limit: pagination.value.size,
|
||||
...(
|
||||
pagination.value.sort && pagination.value.order && {
|
||||
sort: pagination.value.sort,
|
||||
order: pagination.value.order,
|
||||
}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async function onSizeChange(size: number) {
|
||||
pagination.value.size = size
|
||||
}
|
||||
|
||||
async function onCurrentChange(page: number) {
|
||||
pagination.value.page = page
|
||||
}
|
||||
|
||||
async function onSortChange(prop: string, order: string) {
|
||||
pagination.value.sort = prop
|
||||
pagination.value.order = order === 'ascending' ? 'asc' : 'desc'
|
||||
}
|
||||
|
||||
return {
|
||||
pagination,
|
||||
getParams,
|
||||
onSizeChange,
|
||||
onCurrentChange,
|
||||
onSortChange,
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -53,7 +53,7 @@ function handleCopy() {
|
||||
'columns-2': appSettingsStore.mode === 'pc',
|
||||
}"
|
||||
>
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="主题" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
颜色方案
|
||||
@@ -83,7 +83,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.theme.colorAmblyopia" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain v-if="appSettingsStore.mode === 'pc'" title="导航菜单" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="menu-mode">
|
||||
<FaTooltip text="侧边栏模式 (有主导航菜单)" :delay="500">
|
||||
<FaButton variant="outline" class="mode mode-side" :class="{ active: appSettingsStore.settings.menu.mode === 'side' }" @click="appSettingsStore.settings.menu.mode = 'side'">
|
||||
@@ -145,7 +145,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.menu.hotkeys" :disabled="appSettingsStore.settings.menu.mode === 'single'" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="顶栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
标签栏
|
||||
@@ -175,7 +175,7 @@ function handleCopy() {
|
||||
</FaButtonGroup>
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="标签栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
显示图标
|
||||
@@ -189,7 +189,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.tabbar.hotkeys" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="工具栏" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div v-if="appSettingsStore.mode === 'pc'" class="setting-item">
|
||||
<div class="label">
|
||||
<FaIcon name="i-ic:twotone-double-arrow" />
|
||||
@@ -237,7 +237,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.toolbar.colorScheme" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="页面" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
载入进度条
|
||||
@@ -248,7 +248,7 @@ function handleCopy() {
|
||||
<FaSwitch v-model="appSettingsStore.settings.page.progress" />
|
||||
</div>
|
||||
</FaPageMain>
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="pb-0 border-none font-bold" main-class="space-y-4">
|
||||
<FaPageMain title="应用" class="m-0 mb-4 break-inside-avoid light:border-none" title-class="font-bold" main-class="space-y-4">
|
||||
<div class="p-4 pb-4 pt-14 border rounded-lg relative space-y-4">
|
||||
<div class="font-bold px-4 py-2 border-b border-e rounded-rb-lg inset-s-0 inset-t-0 absolute">
|
||||
账号
|
||||
|
||||
@@ -53,6 +53,14 @@ const routes: RouteRecordRaw = {
|
||||
title: '复选框',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'checkbox_group',
|
||||
name: 'componentExampleCheckboxGroup',
|
||||
component: () => import('@/views/component_example/checkbox_group/index.vue'),
|
||||
meta: {
|
||||
title: '复选框组',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'collapsible',
|
||||
name: 'componentExampleCollapsible',
|
||||
@@ -222,6 +230,14 @@ const routes: RouteRecordRaw = {
|
||||
title: '进度条',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'radio_group',
|
||||
name: 'componentExampleRadioGroup',
|
||||
component: () => import('@/views/component_example/radio_group/index.vue'),
|
||||
meta: {
|
||||
title: '单选组',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'scroll_area',
|
||||
name: 'componentExampleScrollArea',
|
||||
|
||||
@@ -95,6 +95,16 @@ const routes: RouteRecordRaw[] = [
|
||||
link: 'https://github.com/mineadmin/mineadmin',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'antdv-next',
|
||||
redirect: '',
|
||||
name: 'recommandAntdvNext',
|
||||
meta: {
|
||||
title: 'Antdv Next 组件库',
|
||||
icon: 'https://www.antdv-next.com/antdv-next.svg',
|
||||
link: 'https://www.antdv-next.com/',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ declare global {
|
||||
const useId: typeof import('vue').useId
|
||||
const useLink: typeof import('vue-router').useLink
|
||||
const useModel: typeof import('vue').useModel
|
||||
const usePagination: typeof import('../composables/pagination').usePagination
|
||||
const usePagination: typeof import('@fantastic-admin/composables').usePagination
|
||||
const useRoute: typeof import('vue-router').useRoute
|
||||
const useRouter: typeof import('vue-router').useRouter
|
||||
const useSlots: typeof import('vue').useSlots
|
||||
|
||||
+5
-77
@@ -19,82 +19,46 @@ declare module 'vue' {
|
||||
AppNotAllowed: typeof import('./../components/AppNotAllowed/index.vue')['default']
|
||||
AppNotSupportedMobile: typeof import('./../components/AppNotSupportedMobile/index.vue')['default']
|
||||
AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
|
||||
FaAnimatedBeam: typeof import('@fantastic-admin/components')['FaAnimatedBeam']
|
||||
FaAnimatedCountTo: typeof import('@fantastic-admin/components')['FaAnimatedCountTo']
|
||||
FaAnimatedCountToGroup: typeof import('@fantastic-admin/components')['FaAnimatedCountToGroup']
|
||||
FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
|
||||
FaBlurReveal: typeof import('@fantastic-admin/components')['FaBlurReveal']
|
||||
FaBorderBeam: typeof import('@fantastic-admin/components')['FaBorderBeam']
|
||||
FaButton: typeof import('@fantastic-admin/components')['FaButton']
|
||||
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
FaCarousel: typeof import('@fantastic-admin/components')['FaCarousel']
|
||||
FaCascader: typeof import('@fantastic-admin/components')['FaCascader']
|
||||
FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
FaCode: typeof import('@fantastic-admin/components')['FaCode']
|
||||
FaCodePreview: typeof import('@fantastic-admin/components')['FaCodePreview']
|
||||
FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
FaCountTo: typeof import('@fantastic-admin/components')['FaCountTo']
|
||||
FaDigitalCard: typeof import('@fantastic-admin/components')['FaDigitalCard']
|
||||
FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
FaDrawer: typeof import('@fantastic-admin/components')['FaDrawer']
|
||||
FaDropdown: typeof import('@fantastic-admin/components')['FaDropdown']
|
||||
FaEmpty: typeof import('@fantastic-admin/components')['FaEmpty']
|
||||
FaFileUpload: typeof import('@fantastic-admin/components')['FaFileUpload']
|
||||
FaFixedBar: typeof import('@fantastic-admin/components')['FaFixedBar']
|
||||
FaFlipCard: typeof import('@fantastic-admin/components')['FaFlipCard']
|
||||
FaFlipWords: typeof import('@fantastic-admin/components')['FaFlipWords']
|
||||
FaGlowyCard: typeof import('@fantastic-admin/components')['FaGlowyCard']
|
||||
FaGlowyCardWrapper: typeof import('@fantastic-admin/components')['FaGlowyCardWrapper']
|
||||
FaGradientButton: typeof import('@fantastic-admin/components')['FaGradientButton']
|
||||
FaHoverCard: typeof import('@fantastic-admin/components')['FaHoverCard']
|
||||
FaIcon: typeof import('@fantastic-admin/components')['FaIcon']
|
||||
FaIconPicker: typeof import('@fantastic-admin/components')['FaIconPicker']
|
||||
FaImagePreview: typeof import('@fantastic-admin/components')['FaImagePreview']
|
||||
FaImageUpload: typeof import('@fantastic-admin/components')['FaImageUpload']
|
||||
FaInput: typeof import('@fantastic-admin/components')['FaInput']
|
||||
FaInputOTP: typeof import('@fantastic-admin/components')['FaInputOTP']
|
||||
FaInteractiveButton: typeof import('@fantastic-admin/components')['FaInteractiveButton']
|
||||
FaKbd: typeof import('@fantastic-admin/components')['FaKbd']
|
||||
FaKbdGroup: typeof import('@fantastic-admin/components')['FaKbdGroup']
|
||||
FaLabel: typeof import('@fantastic-admin/components')['FaLabel']
|
||||
FaLayoutContainer: typeof import('@fantastic-admin/components')['FaLayoutContainer']
|
||||
FaLinkPreview: typeof import('@fantastic-admin/components')['FaLinkPreview']
|
||||
FaLoading: typeof import('@fantastic-admin/components')['FaLoading']
|
||||
FaMarquee: typeof import('@fantastic-admin/components')['FaMarquee']
|
||||
FaModal: typeof import('@fantastic-admin/components')['FaModal']
|
||||
FaMultiStepLoader: typeof import('@fantastic-admin/components')['FaMultiStepLoader']
|
||||
FaNumberField: typeof import('@fantastic-admin/components')['FaNumberField']
|
||||
FaPageHeader: typeof import('@fantastic-admin/components')['FaPageHeader']
|
||||
FaPageMain: typeof import('@fantastic-admin/components')['FaPageMain']
|
||||
FaPagination: typeof import('@fantastic-admin/components')['FaPagination']
|
||||
FaParticlesBg: typeof import('@fantastic-admin/components')['FaParticlesBg']
|
||||
FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
FaPatternBg: typeof import('@fantastic-admin/components')['FaPatternBg']
|
||||
FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
FaQrcode: typeof import('@fantastic-admin/components')['FaQrcode']
|
||||
FaScratchOff: typeof import('@fantastic-admin/components')['FaScratchOff']
|
||||
FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
FaScrollingText: typeof import('@fantastic-admin/components')['FaScrollingText']
|
||||
FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
|
||||
FaSmoothSwipe: typeof import('@fantastic-admin/components')['FaSmoothSwipe']
|
||||
FaSparklesText: typeof import('@fantastic-admin/components')['FaSparklesText']
|
||||
FaSparkline: typeof import('@fantastic-admin/components')['FaSparkline']
|
||||
FaSpotlightCard: typeof import('@fantastic-admin/components')['FaSpotlightCard']
|
||||
FaStorageBox: typeof import('@fantastic-admin/components')['FaStorageBox']
|
||||
FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
|
||||
FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
|
||||
FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
|
||||
FaTextHighlight: typeof import('@fantastic-admin/components')['FaTextHighlight']
|
||||
FaTimeAgo: typeof import('@fantastic-admin/components')['FaTimeAgo']
|
||||
FaTimeline: typeof import('@fantastic-admin/components')['FaTimeline']
|
||||
FaToast: typeof import('@fantastic-admin/components')['FaToast']
|
||||
FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
|
||||
FaTree: typeof import('@fantastic-admin/components')['FaTree']
|
||||
FaTrend: typeof import('@fantastic-admin/components')['FaTrend']
|
||||
}
|
||||
}
|
||||
@@ -108,81 +72,45 @@ declare global {
|
||||
const AppNotAllowed: typeof import('./../components/AppNotAllowed/index.vue')['default']
|
||||
const AppNotSupportedMobile: typeof import('./../components/AppNotSupportedMobile/index.vue')['default']
|
||||
const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
|
||||
const FaAnimatedBeam: typeof import('@fantastic-admin/components')['FaAnimatedBeam']
|
||||
const FaAnimatedCountTo: typeof import('@fantastic-admin/components')['FaAnimatedCountTo']
|
||||
const FaAnimatedCountToGroup: typeof import('@fantastic-admin/components')['FaAnimatedCountToGroup']
|
||||
const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
|
||||
const FaBlurReveal: typeof import('@fantastic-admin/components')['FaBlurReveal']
|
||||
const FaBorderBeam: typeof import('@fantastic-admin/components')['FaBorderBeam']
|
||||
const FaButton: typeof import('@fantastic-admin/components')['FaButton']
|
||||
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
|
||||
const FaCard: typeof import('@fantastic-admin/components')['FaCard']
|
||||
const FaCarousel: typeof import('@fantastic-admin/components')['FaCarousel']
|
||||
const FaCascader: typeof import('@fantastic-admin/components')['FaCascader']
|
||||
const FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
|
||||
const FaCode: typeof import('@fantastic-admin/components')['FaCode']
|
||||
const FaCodePreview: typeof import('@fantastic-admin/components')['FaCodePreview']
|
||||
const FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
|
||||
const FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
|
||||
const FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
|
||||
const FaCountTo: typeof import('@fantastic-admin/components')['FaCountTo']
|
||||
const FaDigitalCard: typeof import('@fantastic-admin/components')['FaDigitalCard']
|
||||
const FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
|
||||
const FaDrawer: typeof import('@fantastic-admin/components')['FaDrawer']
|
||||
const FaDropdown: typeof import('@fantastic-admin/components')['FaDropdown']
|
||||
const FaEmpty: typeof import('@fantastic-admin/components')['FaEmpty']
|
||||
const FaFileUpload: typeof import('@fantastic-admin/components')['FaFileUpload']
|
||||
const FaFixedBar: typeof import('@fantastic-admin/components')['FaFixedBar']
|
||||
const FaFlipCard: typeof import('@fantastic-admin/components')['FaFlipCard']
|
||||
const FaFlipWords: typeof import('@fantastic-admin/components')['FaFlipWords']
|
||||
const FaGlowyCard: typeof import('@fantastic-admin/components')['FaGlowyCard']
|
||||
const FaGlowyCardWrapper: typeof import('@fantastic-admin/components')['FaGlowyCardWrapper']
|
||||
const FaGradientButton: typeof import('@fantastic-admin/components')['FaGradientButton']
|
||||
const FaHoverCard: typeof import('@fantastic-admin/components')['FaHoverCard']
|
||||
const FaIcon: typeof import('@fantastic-admin/components')['FaIcon']
|
||||
const FaIconPicker: typeof import('@fantastic-admin/components')['FaIconPicker']
|
||||
const FaImagePreview: typeof import('@fantastic-admin/components')['FaImagePreview']
|
||||
const FaImageUpload: typeof import('@fantastic-admin/components')['FaImageUpload']
|
||||
const FaInput: typeof import('@fantastic-admin/components')['FaInput']
|
||||
const FaInputOTP: typeof import('@fantastic-admin/components')['FaInputOTP']
|
||||
const FaInteractiveButton: typeof import('@fantastic-admin/components')['FaInteractiveButton']
|
||||
const FaKbd: typeof import('@fantastic-admin/components')['FaKbd']
|
||||
const FaKbdGroup: typeof import('@fantastic-admin/components')['FaKbdGroup']
|
||||
const FaLabel: typeof import('@fantastic-admin/components')['FaLabel']
|
||||
const FaLayoutContainer: typeof import('@fantastic-admin/components')['FaLayoutContainer']
|
||||
const FaLinkPreview: typeof import('@fantastic-admin/components')['FaLinkPreview']
|
||||
const FaLoading: typeof import('@fantastic-admin/components')['FaLoading']
|
||||
const FaMarquee: typeof import('@fantastic-admin/components')['FaMarquee']
|
||||
const FaModal: typeof import('@fantastic-admin/components')['FaModal']
|
||||
const FaMultiStepLoader: typeof import('@fantastic-admin/components')['FaMultiStepLoader']
|
||||
const FaNumberField: typeof import('@fantastic-admin/components')['FaNumberField']
|
||||
const FaPageHeader: typeof import('@fantastic-admin/components')['FaPageHeader']
|
||||
const FaPageMain: typeof import('@fantastic-admin/components')['FaPageMain']
|
||||
const FaPagination: typeof import('@fantastic-admin/components')['FaPagination']
|
||||
const FaParticlesBg: typeof import('@fantastic-admin/components')['FaParticlesBg']
|
||||
const FaPasswordStrength: typeof import('@fantastic-admin/components')['FaPasswordStrength']
|
||||
const FaPatternBg: typeof import('@fantastic-admin/components')['FaPatternBg']
|
||||
const FaPopover: typeof import('@fantastic-admin/components')['FaPopover']
|
||||
const FaProgress: typeof import('@fantastic-admin/components')['FaProgress']
|
||||
const FaQrcode: typeof import('@fantastic-admin/components')['FaQrcode']
|
||||
const FaScratchOff: typeof import('@fantastic-admin/components')['FaScratchOff']
|
||||
const FaRadioGroup: typeof import('@fantastic-admin/components')['FaRadioGroup']
|
||||
const FaScrollArea: typeof import('@fantastic-admin/components')['FaScrollArea']
|
||||
const FaScrollingText: typeof import('@fantastic-admin/components')['FaScrollingText']
|
||||
const FaSearchBar: typeof import('@fantastic-admin/components')['FaSearchBar']
|
||||
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
|
||||
const FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
|
||||
const FaSmoothSwipe: typeof import('@fantastic-admin/components')['FaSmoothSwipe']
|
||||
const FaSparklesText: typeof import('@fantastic-admin/components')['FaSparklesText']
|
||||
const FaSparkline: typeof import('@fantastic-admin/components')['FaSparkline']
|
||||
const FaSpotlightCard: typeof import('@fantastic-admin/components')['FaSpotlightCard']
|
||||
const FaStorageBox: typeof import('@fantastic-admin/components')['FaStorageBox']
|
||||
const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
|
||||
const FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
|
||||
const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
|
||||
const FaTextHighlight: typeof import('@fantastic-admin/components')['FaTextHighlight']
|
||||
const FaTimeAgo: typeof import('@fantastic-admin/components')['FaTimeAgo']
|
||||
const FaTimeline: typeof import('@fantastic-admin/components')['FaTimeline']
|
||||
const FaToast: typeof import('@fantastic-admin/components')['FaToast']
|
||||
const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
|
||||
const FaTree: typeof import('@fantastic-admin/components')['FaTree']
|
||||
const FaTrend: typeof import('@fantastic-admin/components')['FaTrend']
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,8 @@ import Demo1 from './_demo1.vue'
|
||||
<template>
|
||||
<div>
|
||||
<FaPageHeader title="头像" description="FaAvatar" />
|
||||
<FaPageMain main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo1 />
|
||||
</div>
|
||||
<FaPageMain main-class="p-4">
|
||||
<Demo1 />
|
||||
</FaPageMain>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -5,10 +5,8 @@ import Demo1 from './_demo1.vue'
|
||||
<template>
|
||||
<div>
|
||||
<FaPageHeader title="按钮" description="FaButton" />
|
||||
<FaPageMain main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo1 />
|
||||
</div>
|
||||
<FaPageMain main-class="p-4">
|
||||
<Demo1 />
|
||||
</FaPageMain>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -9,30 +9,20 @@ import Demo5 from './_demo5.vue'
|
||||
<template>
|
||||
<div>
|
||||
<FaPageHeader title="按钮组" description="FaButtonGroup" />
|
||||
<FaPageMain main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo1 />
|
||||
</div>
|
||||
<FaPageMain main-class="p-4">
|
||||
<Demo1 />
|
||||
</FaPageMain>
|
||||
<FaPageMain title="垂直" main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo2 />
|
||||
</div>
|
||||
<FaPageMain title="垂直" main-class="p-4">
|
||||
<Demo2 />
|
||||
</FaPageMain>
|
||||
<FaPageMain title="分割线" main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo3 />
|
||||
</div>
|
||||
<FaPageMain title="分割线" main-class="p-4">
|
||||
<Demo3 />
|
||||
</FaPageMain>
|
||||
<FaPageMain title="嵌套" main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo4 />
|
||||
</div>
|
||||
<FaPageMain title="嵌套" main-class="p-4">
|
||||
<Demo4 />
|
||||
</FaPageMain>
|
||||
<FaPageMain title="与其他组件组合" main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo5 />
|
||||
</div>
|
||||
<FaPageMain title="与其他组件组合" main-class="p-4">
|
||||
<Demo5 />
|
||||
</FaPageMain>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -5,10 +5,8 @@ import Demo1 from './_demo1.vue'
|
||||
<template>
|
||||
<div>
|
||||
<FaPageHeader title="卡片" description="FaCard" />
|
||||
<FaPageMain main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo1 />
|
||||
</div>
|
||||
<FaPageMain main-class="p-4">
|
||||
<Demo1 />
|
||||
</FaPageMain>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Executable → Regular
+1
-1
@@ -5,7 +5,7 @@ const checked = ref(false)
|
||||
<template>
|
||||
<div class="flex gap-4">
|
||||
<FaCheckbox v-model="checked">
|
||||
Checkbox
|
||||
同意协议
|
||||
</FaCheckbox>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Executable → Regular
+1
-1
@@ -4,6 +4,6 @@ const checked = ref<'indeterminate' | boolean>('indeterminate')
|
||||
|
||||
<template>
|
||||
<FaCheckbox v-model="checked">
|
||||
Checkbox
|
||||
部分选中
|
||||
</FaCheckbox>
|
||||
</template>
|
||||
|
||||
Executable → Regular
+4
-8
@@ -6,15 +6,11 @@ import Demo2 from './_demo2.vue'
|
||||
<template>
|
||||
<div>
|
||||
<FaPageHeader title="复选框" description="FaCheckbox" />
|
||||
<FaPageMain main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo1 />
|
||||
</div>
|
||||
<FaPageMain main-class="p-4">
|
||||
<Demo1 />
|
||||
</FaPageMain>
|
||||
<FaPageMain title="半选状态" main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo2 />
|
||||
</div>
|
||||
<FaPageMain title="半选状态" main-class="p-4">
|
||||
<Demo2 />
|
||||
</FaPageMain>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
const value = ref(['music'])
|
||||
|
||||
const options = [
|
||||
{ label: '阅读', value: 'reading' },
|
||||
{ label: '音乐', value: 'music' },
|
||||
{ label: '运动', value: 'sports' },
|
||||
]
|
||||
|
||||
const currentText = computed(() =>
|
||||
options
|
||||
.filter(option => value.value.includes(option.value))
|
||||
.map(option => option.label)
|
||||
.join('、'),
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="gap-4 grid">
|
||||
<FaCheckboxGroup v-model="value" :options="options" />
|
||||
<FaCheckboxGroup v-model="value" :options="options" class="flex" />
|
||||
<div class="text-sm text-muted-foreground">
|
||||
当前值:{{ currentText }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
const value = ref(['dashboard', 'report'])
|
||||
|
||||
const options = [
|
||||
{
|
||||
label: '看板订阅',
|
||||
value: 'dashboard',
|
||||
description: '每天 8:00 推送核心经营指标。',
|
||||
},
|
||||
{
|
||||
label: '周报摘要',
|
||||
value: 'report',
|
||||
description: '每周一汇总关键数据变化。',
|
||||
},
|
||||
{
|
||||
label: '系统告警',
|
||||
value: 'alarm',
|
||||
description: '异常波动时立即通知处理人。',
|
||||
disabled: true,
|
||||
},
|
||||
]
|
||||
|
||||
const currentText = computed(() =>
|
||||
options
|
||||
.filter(option => value.value.includes(option.value))
|
||||
.map(option => option.label)
|
||||
.join('、'),
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="gap-4 grid">
|
||||
<FaCheckboxGroup v-model="value" :options="options" />
|
||||
<div class="text-sm text-muted-foreground">
|
||||
当前值:{{ currentText }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,68 @@
|
||||
<script setup lang="ts">
|
||||
const value = ref(['focus', 'balanced'])
|
||||
|
||||
const options = [
|
||||
{
|
||||
label: '专注模式',
|
||||
value: 'focus',
|
||||
description: '突出主任务,弱化辅助信息,适合录入和审批场景。',
|
||||
},
|
||||
{
|
||||
label: '平衡模式',
|
||||
value: 'balanced',
|
||||
description: '信息密度与可读性保持平衡,适合作为默认配置。',
|
||||
},
|
||||
{
|
||||
label: '高密度模式',
|
||||
value: 'dense',
|
||||
description: '在大屏中同时承载更多信息,适合运营与监控看板。',
|
||||
},
|
||||
]
|
||||
|
||||
const currentText = computed(() =>
|
||||
options
|
||||
.filter(option => value.value.includes(option.value))
|
||||
.map(option => option.label)
|
||||
.join('、'),
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FaCheckboxGroup
|
||||
v-model="value"
|
||||
:options="options"
|
||||
class="gap-2 md:grid-cols-3"
|
||||
option-class="rounded-xl border border-transparent px-1 py-1"
|
||||
>
|
||||
<template #option="{ option, checked, disabled }">
|
||||
<div
|
||||
class="px-4 py-3 border rounded-xl flex gap-3 w-full transition-colors items-start justify-between" :class="[
|
||||
checked ? 'border-primary bg-primary/5' : 'border-border hover:border-primary/40',
|
||||
disabled && 'opacity-60',
|
||||
]"
|
||||
>
|
||||
<div class="gap-1 grid min-w-0">
|
||||
<div class="text-sm font-medium truncate">
|
||||
{{ option.label }}
|
||||
</div>
|
||||
<div
|
||||
v-if="option.description"
|
||||
class="text-xs text-muted-foreground leading-5"
|
||||
>
|
||||
{{ option.description }}
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="text-xs font-medium shrink-0" :class="[
|
||||
checked ? 'text-primary' : 'text-muted-foreground',
|
||||
]"
|
||||
>
|
||||
{{ checked ? '已选中' : '可选择' }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</FaCheckboxGroup>
|
||||
<div class="text-sm text-muted-foreground">
|
||||
当前模式:{{ currentText }}
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
const value = ref(['dashboard'])
|
||||
|
||||
const options = [
|
||||
{ label: '看板订阅', value: 'dashboard' },
|
||||
{ label: '周报摘要', value: 'report' },
|
||||
{ label: '系统告警', value: 'alarm' },
|
||||
]
|
||||
|
||||
const currentText = computed(() =>
|
||||
options
|
||||
.filter(option => value.value.includes(option.value))
|
||||
.map(option => option.label)
|
||||
.join('、'),
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="gap-4 grid">
|
||||
<FaCheckboxGroup
|
||||
v-model="value"
|
||||
:options="options"
|
||||
:min="1"
|
||||
:max="2"
|
||||
/>
|
||||
<div class="text-sm text-muted-foreground">
|
||||
当前值:{{ currentText }}
|
||||
</div>
|
||||
<div class="text-xs text-muted-foreground leading-5">
|
||||
已选数量小于等于 1 时,已选项会被禁用;已选数量大于等于 2 时,未选项会被禁用。
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
import Demo1 from './_demo1.vue'
|
||||
import Demo2 from './_demo2.vue'
|
||||
import Demo3 from './_demo3.vue'
|
||||
import Demo4 from './_demo4.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<FaPageHeader title="复选框组" description="FaCheckboxGroup" />
|
||||
<FaPageMain main-class="p-4">
|
||||
<Demo1 />
|
||||
</FaPageMain>
|
||||
<FaPageMain title="带描述和禁用态" main-class="p-4">
|
||||
<Demo2 />
|
||||
</FaPageMain>
|
||||
<FaPageMain title="自定义选项内容" main-class="p-4">
|
||||
<Demo3 />
|
||||
</FaPageMain>
|
||||
<FaPageMain title="最少 / 最多选择" main-class="p-4">
|
||||
<Demo4 />
|
||||
</FaPageMain>
|
||||
</div>
|
||||
</template>
|
||||
@@ -6,15 +6,11 @@ import Demo2 from './_demo2.vue'
|
||||
<template>
|
||||
<div>
|
||||
<FaPageHeader title="折叠面板" description="FaCollapsible" />
|
||||
<FaPageMain main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo1 />
|
||||
</div>
|
||||
<FaPageMain main-class="p-4">
|
||||
<Demo1 />
|
||||
</FaPageMain>
|
||||
<FaPageMain title="手动控制" main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo2 />
|
||||
</div>
|
||||
<FaPageMain title="手动控制" main-class="p-4">
|
||||
<Demo2 />
|
||||
</FaPageMain>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -6,15 +6,11 @@ import Demo2 from './_demo2.vue'
|
||||
<template>
|
||||
<div>
|
||||
<FaPageHeader title="右键菜单" description="FaContextMenu" />
|
||||
<FaPageMain main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo1 />
|
||||
</div>
|
||||
<FaPageMain main-class="p-4">
|
||||
<Demo1 />
|
||||
</FaPageMain>
|
||||
<FaPageMain title="嵌套" main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo2 />
|
||||
</div>
|
||||
<FaPageMain title="嵌套" main-class="p-4">
|
||||
<Demo2 />
|
||||
</FaPageMain>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -5,10 +5,8 @@ import Demo1 from './_demo1.vue'
|
||||
<template>
|
||||
<div>
|
||||
<FaPageHeader title="分割线" description="FaDivider" />
|
||||
<FaPageMain main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo1 />
|
||||
</div>
|
||||
<FaPageMain main-class="p-4">
|
||||
<Demo1 />
|
||||
</FaPageMain>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -6,15 +6,11 @@ import Demo2 from './_demo2.vue'
|
||||
<template>
|
||||
<div>
|
||||
<FaPageHeader title="抽屉" description="FaDrawer" />
|
||||
<FaPageMain main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo1 />
|
||||
</div>
|
||||
<FaPageMain main-class="p-4">
|
||||
<Demo1 />
|
||||
</FaPageMain>
|
||||
<FaPageMain title="函数式调用" main-class="p-0">
|
||||
<div class="p-4">
|
||||
<Demo2 />
|
||||
</div>
|
||||
<FaPageMain title="函数式调用" main-class="p-4">
|
||||
<Demo2 />
|
||||
</FaPageMain>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user