@duxweb/dvha-template 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 DuxWeb
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -86,4 +86,4 @@ npm publish --access=public
86
86
 
87
87
  ## 许可证
88
88
 
89
- LGPL-3.0
89
+ MIT
package/bin/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import fs from 'fs-extra'
4
- import path from 'path'
5
- import { fileURLToPath } from 'url'
6
- import { input, select, confirm } from '@inquirer/prompts'
7
- import { cyan, green, red, yellow, blue, bold } from 'kolorist'
3
+ import path from 'node:path'
4
+ import { fileURLToPath } from 'node:url'
5
+ import { confirm, input, select } from '@inquirer/prompts'
8
6
  import { Command } from 'commander'
7
+ import fs from 'fs-extra'
8
+ import { bold, cyan, green, red, yellow } from 'kolorist'
9
9
 
10
10
  const __dirname = path.dirname(fileURLToPath(import.meta.url))
11
11
 
@@ -29,7 +29,7 @@ async function createProject(projectName) {
29
29
  if (!targetDir) {
30
30
  targetDir = await input({
31
31
  message: '请输入项目名称 / Enter project name:',
32
- default: 'my-dvha-app'
32
+ default: 'my-dvha-app',
33
33
  })
34
34
  }
35
35
 
@@ -43,7 +43,7 @@ async function createProject(projectName) {
43
43
  if (fs.existsSync(root)) {
44
44
  const overwrite = await confirm({
45
45
  message: `目录 ${targetDir} 已存在,是否覆盖? / Directory ${targetDir} already exists, overwrite?`,
46
- default: false
46
+ default: false,
47
47
  })
48
48
 
49
49
  if (!overwrite) {
@@ -58,15 +58,15 @@ async function createProject(projectName) {
58
58
  const uiConfigsDir = path.resolve(__dirname, '..', 'template', 'ui-configs')
59
59
  const availableUIs = fs.readdirSync(uiConfigsDir)
60
60
  .filter(dir => fs.statSync(path.join(uiConfigsDir, dir)).isDirectory())
61
- .map(dir => {
62
- const configPath = path.join(uiConfigsDir, dir + '.json')
61
+ .map((dir) => {
62
+ const configPath = path.join(uiConfigsDir, `${dir}.json`)
63
63
  if (fs.existsSync(configPath)) {
64
64
  const config = fs.readJsonSync(configPath)
65
65
  return {
66
66
  name: config.name,
67
67
  display: config.display,
68
68
  description: config.description,
69
- value: config.name
69
+ value: config.name,
70
70
  }
71
71
  }
72
72
  return null
@@ -78,8 +78,8 @@ async function createProject(projectName) {
78
78
  choices: availableUIs.map(ui => ({
79
79
  name: `${ui.display} - ${ui.description}`,
80
80
  value: ui.value,
81
- description: ui.description
82
- }))
81
+ description: ui.description,
82
+ })),
83
83
  })
84
84
 
85
85
  if (!template) {
@@ -117,19 +117,19 @@ async function createProject(projectName) {
117
117
  const fileName = path.basename(src)
118
118
 
119
119
  // 过滤掉不需要的目录和文件
120
- const shouldExclude =
121
- relativePath.includes('node_modules') ||
122
- relativePath.includes('.git') ||
123
- relativePath.includes('dist') ||
124
- relativePath.includes('.vite') ||
125
- fileName === '.DS_Store' ||
126
- fileName.endsWith('.log') ||
127
- fileName === 'bun.lockb' ||
128
- fileName === 'package-lock.json' ||
129
- fileName === 'yarn.lock'
120
+ const shouldExclude
121
+ = relativePath.includes('node_modules')
122
+ || relativePath.includes('.git')
123
+ || relativePath.includes('dist')
124
+ || relativePath.includes('.vite')
125
+ || fileName === '.DS_Store'
126
+ || fileName.endsWith('.log')
127
+ || fileName === 'bun.lockb'
128
+ || fileName === 'package-lock.json'
129
+ || fileName === 'yarn.lock'
130
130
 
131
131
  return !shouldExclude
132
- }
132
+ },
133
133
  })
134
134
 
135
135
  // 2. 复制UI特定的pages文件
@@ -150,13 +150,13 @@ async function createProject(projectName) {
150
150
  // 更新依赖
151
151
  pkg.dependencies = {
152
152
  ...pkg.dependencies,
153
- ...uiConfig.dependencies
153
+ ...uiConfig.dependencies,
154
154
  }
155
155
 
156
156
  if (uiConfig.devDependencies && Object.keys(uiConfig.devDependencies).length > 0) {
157
157
  pkg.devDependencies = {
158
158
  ...pkg.devDependencies,
159
- ...uiConfig.devDependencies
159
+ ...uiConfig.devDependencies,
160
160
  }
161
161
  }
162
162
 
@@ -173,7 +173,7 @@ async function createProject(projectName) {
173
173
  const appUseStatements = uiConfig.appUse || []
174
174
 
175
175
  // 找到现有导入的位置
176
- const appImportIndex = mainTsContent.indexOf("import App from './App.vue'")
176
+ const appImportIndex = mainTsContent.indexOf('import App from \'./App.vue\'')
177
177
  if (appImportIndex !== -1) {
178
178
  const insertPosition = mainTsContent.indexOf('\n', appImportIndex) + 1
179
179
  const additionalImports = importStatements.join('\n') + (importStatements.length > 0 ? '\n' : '')
@@ -184,7 +184,7 @@ async function createProject(projectName) {
184
184
  if (appUseStatements.length > 0) {
185
185
  const appUseIndex = mainTsContent.indexOf('app.use(createDux(config))')
186
186
  if (appUseIndex !== -1) {
187
- const additionalUse = appUseStatements.join('\n') + '\n'
187
+ const additionalUse = `${appUseStatements.join('\n')}\n`
188
188
  mainTsContent = mainTsContent.slice(0, appUseIndex) + additionalUse + mainTsContent.slice(appUseIndex)
189
189
  }
190
190
  }
@@ -223,7 +223,8 @@ program
223
223
  .action(async (projectName) => {
224
224
  try {
225
225
  await createProject(projectName)
226
- } catch (error) {
226
+ }
227
+ catch (error) {
227
228
  if (error.name === 'ExitPromptError') {
228
229
  console.log(yellow('\n👋 操作已取消 / Operation cancelled'))
229
230
  process.exit(0)
@@ -247,4 +248,4 @@ program
247
248
  console.log()
248
249
  })
249
250
 
250
- program.parse()
251
+ program.parse()
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@duxweb/dvha-template",
3
3
  "type": "module",
4
- "version": "1.0.7",
4
+ "version": "1.0.9",
5
5
  "description": "Create DVHA project from template",
6
6
  "author": "DuxWeb",
7
- "license": "LGPL-3.0",
7
+ "license": "MIT",
8
8
  "homepage": "https://github.com/your-username/dux-vue#readme",
9
9
  "repository": {
10
10
  "type": "git",
@@ -36,15 +36,17 @@
36
36
  "engines": {
37
37
  "node": ">=20.0.0"
38
38
  },
39
- "scripts": {
40
- "test": "./scripts/test.sh",
41
- "push": "./scripts/publish.sh",
42
- "dev": "bun run bin/index.js"
43
- },
44
39
  "dependencies": {
45
40
  "@inquirer/prompts": "^7.5.1",
46
41
  "commander": "^14.0.0",
47
42
  "fs-extra": "^11.2.0",
48
43
  "kolorist": "^1.8.0"
44
+ },
45
+ "scripts": {
46
+ "test": "./scripts/test.sh",
47
+ "push": "./scripts/publish.sh",
48
+ "dev": "node bin/index.js",
49
+ "changeset": "changeset",
50
+ "changeset:version": "changeset version"
49
51
  }
50
- }
52
+ }
@@ -3,7 +3,7 @@
3
3
  "type": "module",
4
4
  "version": "0.0.0",
5
5
  "author": "DuxWeb",
6
- "license": "LGPL-3.0",
6
+ "license": "MIT",
7
7
  "files": [
8
8
  "README.md",
9
9
  "dist",
@@ -1,11 +1,11 @@
1
- import { defineConfig, presetIcons, presetWind3 } from 'unocss'
2
1
  import icons from '@iconify-json/tabler/icons.json'
2
+ import { defineConfig, presetIcons, presetWind3 } from 'unocss'
3
3
 
4
- const generateSafeList = () => {
4
+ function generateSafeList() {
5
5
  return Object.keys(icons.icons).flatMap((item) => {
6
6
  return `i-tabler:${item}`
7
7
  })
8
- };
8
+ }
9
9
 
10
10
  const safeList = generateSafeList()
11
11
 
@@ -1,30 +1,62 @@
1
+ <script setup lang="ts">
2
+ import { useGetAuth, useLogout, useManage } from '@duxweb/dvha-core'
3
+ import { onMounted, onUnmounted, ref } from 'vue'
4
+ import Sidebar from './menu.vue'
5
+
6
+ const manage = useManage()
7
+ const user = useGetAuth()
8
+
9
+ const { mutate: logout } = useLogout({
10
+ onSuccess: () => console.log('退出成功'),
11
+ onError: error => console.error('退出失败:', error),
12
+ })
13
+
14
+ const sidebarOpen = ref(false)
15
+ const showUserMenu = ref(false)
16
+
17
+ const getUserName = () => user?.info?.name || user?.info?.username || 'Admin'
18
+ const toggleSidebar = () => sidebarOpen.value = !sidebarOpen.value
19
+ const handleLogout = () => logout()
20
+
21
+ function closeDropdowns(event: Event) {
22
+ if (!(event.target as HTMLElement).closest('.relative')) {
23
+ showUserMenu.value = false
24
+ }
25
+ }
26
+
27
+ onMounted(() => document.addEventListener('click', closeDropdowns))
28
+ onUnmounted(() => document.removeEventListener('click', closeDropdowns))
29
+ </script>
30
+
1
31
  <template>
2
32
  <div class="min-h-screen bg-gray-50 flex flex-col">
3
33
  <!-- 头部 -->
4
34
  <header class="bg-white shadow-sm border-b fixed w-full top-0 z-50">
5
35
  <div class="flex items-center justify-between h-16 px-4">
6
36
  <div class="flex items-center">
7
- <button @click="toggleSidebar" class="p-2 rounded hover:bg-gray-100 lg:hidden">
8
- <div class="i-tabler:menu-2 text-xl"></div>
37
+ <button class="p-2 rounded hover:bg-gray-100 lg:hidden" @click="toggleSidebar">
38
+ <div class="i-tabler:menu-2 text-xl" />
9
39
  </button>
10
40
  <div class="flex items-center ml-4 lg:ml-0">
11
- <div class="i-tabler:brand-vue text-2xl text-blue-600 mr-3"></div>
12
- <h1 class="text-xl font-bold">{{ manage.config?.title || 'Dux Admin' }}</h1>
41
+ <div class="i-tabler:brand-vue text-2xl text-blue-600 mr-3" />
42
+ <h1 class="text-xl font-bold">
43
+ {{ manage.config?.title || 'Dux Admin' }}
44
+ </h1>
13
45
  </div>
14
46
  </div>
15
47
 
16
48
  <!-- 用户菜单 -->
17
49
  <div class="relative">
18
- <button @click="showUserMenu = !showUserMenu" class="flex items-center p-2 rounded hover:bg-gray-100">
19
- <div class="i-tabler:user-circle text-xl mr-2"></div>
50
+ <button class="flex items-center p-2 rounded hover:bg-gray-100" @click="showUserMenu = !showUserMenu">
51
+ <div class="i-tabler:user-circle text-xl mr-2" />
20
52
  <span class="hidden md:block text-sm font-medium">{{ getUserName() }}</span>
21
- <div class="i-tabler:chevron-down text-sm ml-1 hidden md:block"></div>
53
+ <div class="i-tabler:chevron-down text-sm ml-1 hidden md:block" />
22
54
  </button>
23
55
 
24
56
  <div v-if="showUserMenu" class="absolute right-0 mt-2 w-40 bg-white rounded-md shadow-lg border z-50">
25
57
  <div class="py-1">
26
- <button @click="handleLogout" class="flex items-center w-full px-4 py-2 text-sm hover:bg-gray-100">
27
- <div class="i-tabler:logout mr-3"></div>
58
+ <button class="flex items-center w-full px-4 py-2 text-sm hover:bg-gray-100" @click="handleLogout">
59
+ <div class="i-tabler:logout mr-3" />
28
60
  退出登录
29
61
  </button>
30
62
  </div>
@@ -38,7 +70,7 @@
38
70
  <Sidebar :sidebar-open="sidebarOpen" />
39
71
 
40
72
  <!-- 遮罩层 -->
41
- <div v-if="sidebarOpen" @click="toggleSidebar" class="fixed inset-0 z-30 bg-black bg-opacity-50 lg:hidden"></div>
73
+ <div v-if="sidebarOpen" class="fixed inset-0 z-30 bg-black bg-opacity-50 lg:hidden" @click="toggleSidebar" />
42
74
 
43
75
  <!-- 主内容 -->
44
76
  <main class="flex-1">
@@ -47,33 +79,3 @@
47
79
  </div>
48
80
  </div>
49
81
  </template>
50
-
51
- <script setup lang="ts">
52
- import { ref, onMounted, onUnmounted } from 'vue'
53
- import { useManage, useGetAuth, useLogout } from '@duxweb/dvha-core'
54
- import Sidebar from './menu.vue'
55
-
56
- const manage = useManage()
57
- const user = useGetAuth()
58
-
59
- const { mutate: logout } = useLogout({
60
- onSuccess: () => console.log('退出成功'),
61
- onError: (error) => console.error('退出失败:', error)
62
- })
63
-
64
- const sidebarOpen = ref(false)
65
- const showUserMenu = ref(false)
66
-
67
- const getUserName = () => user?.info?.name || user?.info?.username || 'Admin'
68
- const toggleSidebar = () => sidebarOpen.value = !sidebarOpen.value
69
- const handleLogout = () => logout()
70
-
71
- const closeDropdowns = (event: Event) => {
72
- if (!(event.target as HTMLElement).closest('.relative')) {
73
- showUserMenu.value = false
74
- }
75
- }
76
-
77
- onMounted(() => document.addEventListener('click', closeDropdowns))
78
- onUnmounted(() => document.removeEventListener('click', closeDropdowns))
79
- </script>
@@ -1,10 +1,10 @@
1
1
  <script setup lang="ts">
2
- import { ref, reactive } from 'vue'
2
+ import type { FormInstance } from 'element-plus'
3
+ import { useLogin } from '@duxweb/dvha-core'
4
+ import { Lock, User } from '@element-plus/icons-vue'
3
5
  import { ElMessage } from 'element-plus'
6
+ import { reactive, ref } from 'vue'
4
7
  import { useRouter } from 'vue-router'
5
- import { useLogin } from '@duxweb/dvha-core'
6
- import type { FormInstance } from 'element-plus'
7
- import { User, Lock } from '@element-plus/icons-vue'
8
8
  import 'element-plus/dist/index.css'
9
9
 
10
10
  const router = useRouter()
@@ -14,16 +14,16 @@ const formRef = ref<FormInstance>()
14
14
  const formModel = reactive({
15
15
  username: '',
16
16
  password: '',
17
- remember: false
17
+ remember: false,
18
18
  })
19
19
 
20
20
  const rules = reactive({
21
21
  username: [
22
- { required: true, message: '请输入用户名', trigger: 'blur' }
22
+ { required: true, message: '请输入用户名', trigger: 'blur' },
23
23
  ],
24
24
  password: [
25
- { required: true, message: '请输入密码', trigger: 'blur' }
26
- ]
25
+ { required: true, message: '请输入密码', trigger: 'blur' },
26
+ ],
27
27
  })
28
28
 
29
29
  const { mutate, isLoading } = useLogin({
@@ -33,18 +33,19 @@ const { mutate, isLoading } = useLogin({
33
33
  onError: (error) => {
34
34
  console.log(error)
35
35
  ElMessage.error(error?.message || '登录失败,请检查用户名和密码')
36
- }
36
+ },
37
37
  })
38
38
 
39
- const handleSubmit = () => {
40
- if (!formRef.value) return
39
+ function handleSubmit() {
40
+ if (!formRef.value)
41
+ return
41
42
 
42
43
  formRef.value.validate((valid) => {
43
44
  if (valid) {
44
45
  mutate({
45
46
  username: formModel.username,
46
47
  password: formModel.password,
47
- code: "0000"
48
+ code: '0000',
48
49
  })
49
50
  }
50
51
  })
@@ -55,8 +56,12 @@ const handleSubmit = () => {
55
56
  <div class="flex justify-center items-center min-h-screen bg-gray-100">
56
57
  <div class="w-400px p-40px rounded-8px bg-white shadow-sm">
57
58
  <div class="text-center mb-40px">
58
- <h1 class="m-0 mb-8px text-24px font-600 text-gray-800">系统登录</h1>
59
- <p class="m-0 text-gray-500 text-14px">欢迎使用管理系统,请登录</p>
59
+ <h1 class="m-0 mb-8px text-24px font-600 text-gray-800">
60
+ 系统登录
61
+ </h1>
62
+ <p class="m-0 text-gray-500 text-14px">
63
+ 欢迎使用管理系统,请登录
64
+ </p>
60
65
  </div>
61
66
 
62
67
  <el-form