@xizs/nuxt-antui 0.0.1

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.
@@ -0,0 +1,5 @@
1
+ // https://nuxt.com/docs/api/configuration/nuxt-config
2
+ export default defineNuxtConfig({
3
+ devtools: { enabled: true },
4
+ compatibilityDate: "2025-04-18"
5
+ })
package/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # Nuxt Minimal Starter
2
+
3
+ Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
4
+
5
+ ## Setup
6
+
7
+ Make sure to install dependencies:
8
+
9
+ ```bash
10
+ # npm
11
+ npm install
12
+
13
+ # pnpm
14
+ pnpm install
15
+
16
+ # yarn
17
+ yarn install
18
+
19
+ # bun
20
+ bun install
21
+ ```
22
+
23
+ ## Development Server
24
+
25
+ Start the development server on `http://localhost:3000`:
26
+
27
+ ```bash
28
+ # npm
29
+ npm run dev
30
+
31
+ # pnpm
32
+ pnpm dev
33
+
34
+ # yarn
35
+ yarn dev
36
+
37
+ # bun
38
+ bun run dev
39
+ ```
40
+
41
+ ## Production
42
+
43
+ Build the application for production:
44
+
45
+ ```bash
46
+ # npm
47
+ npm run build
48
+
49
+ # pnpm
50
+ pnpm build
51
+
52
+ # yarn
53
+ yarn build
54
+
55
+ # bun
56
+ bun run build
57
+ ```
58
+
59
+ Locally preview production build:
60
+
61
+ ```bash
62
+ # npm
63
+ npm run preview
64
+
65
+ # pnpm
66
+ pnpm preview
67
+
68
+ # yarn
69
+ yarn preview
70
+
71
+ # bun
72
+ bun run preview
73
+ ```
74
+
75
+ Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
@@ -0,0 +1,14 @@
1
+ export default defineAppConfig({
2
+ myLayer: {
3
+ name: 'Hello from Nuxt layer'
4
+ }
5
+ })
6
+
7
+ declare module '@nuxt/schema' {
8
+ interface AppConfigInput {
9
+ myLayer?: {
10
+ /** Project name */
11
+ name?: string
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,2 @@
1
+ @import "tailwindcss";
2
+ @source "../../"
@@ -0,0 +1,124 @@
1
+ import { AForm, AFormItem, AInput, ASelect,AInputNumber, LineOutlined, ASwitch, ATextarea } from "#components"
2
+
3
+ export type FormItemType = {
4
+ label:string,
5
+ key:string|string[],
6
+ is:string,
7
+ bind:any,
8
+ rules:any[]
9
+ }
10
+
11
+ export type FormPropsType = {
12
+ form:FormItemType[],
13
+ submit:(formData:any)=>{
14
+
15
+ },
16
+ showSubmit?:boolean
17
+ }
18
+
19
+ const FormComs = {
20
+ input:(form:any,item:FormItemType)=>{
21
+ return <AInput v-model:value={form[item.key]}></AInput>
22
+ },
23
+ textarea:(form:any,item:FormItemType)=>{
24
+ return <ATextarea v-model:value={form[item.key]}></ATextarea>
25
+ },
26
+ inputNumber:(form:any,item:FormItemType)=>{
27
+ return <AInputNumber v-model:value={form[item.key]} {...item.bind}></AInputNumber>
28
+ },
29
+ inputNumberRange:(form:any,item:FormItemType)=>{
30
+ return <div class="flex items-center gap-2">
31
+ <AInputNumber class="flex-1" v-model:value={form[item.key[0]]} {...item.bind[0]}></AInputNumber>
32
+ <LineOutlined />
33
+ <AInputNumber class="flex-1" v-model:value={form[item.key[1]]} {...item.bind[1]}></AInputNumber>
34
+ </div>
35
+ },
36
+ select:(form:any,item:FormItemType)=>{
37
+ return <ASelect v-model:value={form[item.key]} options={item.bind.options}></ASelect>
38
+ },
39
+ countrySelect:(form:any,item:FormItemType)=>{
40
+ return <ASelect v-model:value={form[item.key]} options={Const.CountrySelectList()}></ASelect>
41
+ },
42
+ switch:(form:any,item:FormItemType)=>{
43
+ return <ASwitch v-model:checked={form[item.key]} {...item.bind}></ASwitch>
44
+ }
45
+ }
46
+
47
+ export default defineComponent({
48
+ props:{
49
+ // form: Array as () => FormType[],
50
+ // action: Array as () => JSX.Element[],
51
+ // table: Object as () => FormTableProps<any>["table"],
52
+ // control: Object
53
+ form:{
54
+ type:Array as ()=>FormPropsType['form'],
55
+ required:true
56
+ },
57
+ submit:{
58
+ type:Function as FormPropsType['submit'],
59
+ required:true
60
+ },
61
+ showSubmit:{
62
+ type:Boolean,
63
+ default:true
64
+ },
65
+ },
66
+ setup(props,{expose}){
67
+
68
+ let thisRef = ref(null)
69
+ let formData = ref({})
70
+ let rules = ref({})
71
+ props.form.forEach(item=>{
72
+ if(Array.isArray(item.key)){
73
+ item.key.forEach(key=>{
74
+ formData.value[key] = item.value??''
75
+ rules.value[item.key] = item.rules??[]
76
+
77
+ })
78
+ }else{
79
+ formData.value[item.key] = item.value??''
80
+ rules.value[item.key] = item.rules??[]
81
+ }
82
+
83
+ // if(Array.isArray(item.rules)){
84
+ // item.rules.forEach(rule=>{
85
+ // rules.value
86
+ // })
87
+ // }
88
+ // rules.value[item.key] = item.rules??[]
89
+ })
90
+
91
+ let loading = ref(false)
92
+ let submit = async ()=>{
93
+ if(loading.value){
94
+ throw new Error('loading')
95
+ }
96
+ loading.value = true
97
+ try{
98
+ await thisRef.value.validate()
99
+ await props.submit(formData.value)
100
+ }finally{
101
+ loading.value = false
102
+ }
103
+ }
104
+
105
+ expose({
106
+ submit,
107
+ loading
108
+ })
109
+
110
+
111
+
112
+ return ()=><AForm ref={thisRef} model={formData.value} rules={rules.value} label-col={{ span: 6 }} wrapper-col={{ span: 16 }}>
113
+ {/* {JSON.stringify(formData.value)} */}
114
+ {
115
+ props.form.map(item=>{
116
+ return <AFormItem label={item.label} name={item.key}>
117
+ {FormComs[item.is](formData.value,item)}
118
+ </AFormItem>
119
+ })
120
+ }
121
+
122
+ </AForm>
123
+ }
124
+ })
@@ -0,0 +1,271 @@
1
+ import { defineComponent, ref } from 'vue'
2
+ import { AForm, AFormItem, AInput, AButton, ATable, ASelect, APagination, ARangePicker, RedoOutlined } from '#components'
3
+ import type { TableColumnType } from 'ant-design-vue'
4
+ import dayjs from 'dayjs'
5
+
6
+ type TableFormItemType = {
7
+ label: string
8
+ key: string
9
+ is: string
10
+ bind?: any
11
+ }
12
+
13
+ let dateRange = defineComponent({
14
+ props:{
15
+ form:{
16
+ type:Object as ()=>any,
17
+ required:true
18
+ },
19
+ item:{
20
+ type:Object as ()=>TableFormItemType,
21
+ required:true
22
+ }
23
+ },
24
+ setup(props){
25
+ let value = watchRef(ref([]),(nv,ov)=>{
26
+ if(nv?.length>0){
27
+ props.form[props.item.key[0]] = nv[0].format('YYYY-MM-DD 00:00:00')
28
+ props.form[props.item.key[1]] = nv[1].format('YYYY-MM-DD 23:59:59')
29
+ }else{
30
+ props.form[props.item.key[0]] = ''
31
+ props.form[props.item.key[1]] = ''
32
+ }
33
+ })
34
+
35
+ const rangePresets = ref([
36
+ { label: '今天', value: [dayjs(), dayjs()] },
37
+ { label: '昨天', value: [dayjs().add(-1, 'd'), dayjs().add(-1, 'd')] },
38
+ { label: '最近7天', value: [dayjs().add(-7, 'd'), dayjs()] },
39
+ { label: '最近30天', value: [dayjs().add(-30, 'd'), dayjs()] },
40
+ ]);
41
+
42
+ return ()=><ARangePicker presets={rangePresets.value} v-model:value={value.value} />
43
+ }
44
+ })
45
+
46
+
47
+ const FormItems = {
48
+ input:(form:any,item:TableFormItemType)=>{
49
+ return <AInput size="middle" v-model:value={form[item.key]} placeholder={`please input ${item.label}`}></AInput>
50
+ },
51
+ select:(form:any,item:TableFormItemType)=>{
52
+ return <ASelect allowClear class="min-w-[150px]" v-model:value={form[item.key]} options={item.bind.options} placeholder={`please select ${item.label}`}></ASelect>
53
+ },
54
+ dateRange:(form:any,item:TableFormItemType)=>{
55
+
56
+ return h(dateRange,{form,item})
57
+ }
58
+ }
59
+
60
+ export type TablePropsType = {
61
+ form: TableFormItemType[]
62
+ action?: {
63
+ search?: boolean
64
+ reset?: boolean
65
+ export?: boolean
66
+ opther: () => any
67
+ }
68
+ table: {
69
+ 'v-slots'?:any
70
+ enableSelection?: boolean
71
+ columns: TableColumnType[]
72
+ data: () => any[]
73
+ }
74
+ }
75
+
76
+ export type AttributeType = {
77
+ selectItems:any[],
78
+ selectKeys:any[],
79
+ page:number,
80
+ pageSize:number
81
+ }
82
+
83
+ export const FormTableProps = {
84
+ form: {
85
+ type: Array as () => TableFormItemType[],
86
+ required: true
87
+ },
88
+ formOptions:{
89
+ type:Object as () => {
90
+ search:boolean,
91
+ reset:boolean,
92
+ export:boolean,
93
+ opther?:()=>any
94
+ },
95
+ default:()=>({
96
+ search:true,
97
+ reset:true,
98
+ export:false,
99
+ })
100
+ },
101
+ action: {
102
+ type: Object as () => TablePropsType['action'],
103
+ default: () => ({
104
+ search: true,
105
+ reset: true,
106
+ export: true,
107
+ opther: () => null
108
+ })
109
+ },
110
+ table: {
111
+ type: Object as () => TablePropsType['table'],
112
+ default: () => ({
113
+ enableSelection: false,
114
+ columns: [],
115
+ data: () => [],
116
+ rowKey:(row:any)=>any
117
+ })
118
+ },
119
+ attribute:{
120
+ type:Object as ()=> AttributeType
121
+ },
122
+ control:{
123
+ type:Object,
124
+ required:true
125
+ }
126
+ }
127
+
128
+ export default defineComponent({
129
+ name: 'TableLayout',
130
+ props: FormTableProps,
131
+ setup(props) {
132
+
133
+ const form = ref({})
134
+ props.form.forEach((item) => {
135
+ form.value[item.key] = item.value?? ''
136
+ })
137
+ let pagination =reactive({
138
+ page:1,
139
+ pageSize:20,
140
+ total:0
141
+ })
142
+
143
+
144
+ const tableData = asyncReactive<any[]>(async ()=>{
145
+ let res = await props.table.data({...form.value,...pagination})
146
+ if(Array.isArray(res)){
147
+ res = {
148
+ list:res,
149
+ meta:{
150
+ pagination:{
151
+ total:0,
152
+ per_page:pagination.pageSize,
153
+ current_page:pagination.page
154
+ }
155
+ }
156
+ }
157
+ }
158
+ console.log(res)
159
+ pagination.total = res.meta.pagination.total
160
+ pagination.pageSize = res.meta.pagination.per_page
161
+ pagination.page = res.meta.pagination.current_page
162
+ console.log(res)
163
+ return res.list
164
+ },[])
165
+
166
+
167
+ const rowSelection = {
168
+ selectedRowKeys: props.attribute?.selectKeys,
169
+ onChange: (keys,rows)=>{
170
+ props.attribute!.selectKeys.splice(0,props.attribute!.selectKeys.length,...keys)
171
+ props.attribute!.selectItems.splice(0,props.attribute!.selectItems.length,...rows)
172
+ }
173
+ }
174
+
175
+ props.control.refresh = ()=>tableData.load()
176
+
177
+
178
+ return () => (
179
+ <div class="flex flex-col gap-2 h-full ">
180
+ {/* {JSON.stringify(form.value)} */}
181
+ {props.form&&<AForm layout="inline gap-2">
182
+ {props.form?.map((item) => {
183
+ form[item.key] = item.value?? ''
184
+ return (
185
+ <AFormItem label={item.label}>
186
+ {/* <AInput type="text" /> */}
187
+ {FormItems[item.is](form.value,item)}
188
+ </AFormItem>
189
+ )
190
+ })}
191
+ <div class="flex gap-2">
192
+ {props.formOptions.search && <AButton type="primary" onClick={()=>tableData.load()}>搜索</AButton>}
193
+ {props.formOptions.reset && <AButton>重置</AButton>}
194
+ {props.formOptions.export && <AButton type="primary">导出</AButton>}
195
+ </div>
196
+ </AForm>}
197
+
198
+ <div class="flex items-center justify-between">
199
+ <div>{props.action.other}</div>
200
+
201
+ {/* <div class="flex gap-2">
202
+ {props.action.search && <AButton type="primary" onClick={()=>tableData.load()}>搜索</AButton>}
203
+ {props.action.reset && <AButton>重置</AButton>}
204
+ {props.action.export && <AButton type="primary">导出</AButton>}
205
+ </div> */}
206
+ </div>
207
+ {/* <a-descriptions bordered size="small" column={5} layout="vertical">
208
+ <a-descriptions-item label="游玩人数">33</a-descriptions-item>
209
+ <a-descriptions-item label="游玩人次">1810000000</a-descriptions-item>
210
+ <a-descriptions-item label="转入/下注">33</a-descriptions-item>
211
+ <a-descriptions-item label="转出">12</a-descriptions-item>
212
+ <a-descriptions-item label="人均盈亏"> 11</a-descriptions-item>
213
+ </a-descriptions> */}
214
+ <div class="flex-1 mt-3 overflow-scroll flex flex-col">
215
+ <ATable
216
+ row-selection={props.table.enableSelection?rowSelection:null}
217
+ rowKey={props.table.rowKey??((row,key)=>key)}
218
+ loading={tableData.loading}
219
+ scroll={{x: true}}
220
+ columns={props.table.columns}
221
+ pagination={false}
222
+ sticky={tableData.value.length>0}
223
+ v-slots={{
224
+ headerCell: ({ title,column }: any) => (
225
+ <div style={{'white-space': 'nowrap'}}>
226
+ {title }
227
+ </div>
228
+ ),
229
+ bodyCell:(row)=>{
230
+ if(row.column?.customRender!=null){
231
+ return row.column.customRender(row)
232
+ }
233
+ return <div class="whitespace-nowrap" style={{ width:row.column.width??'100px'}}>{row.text}</div>
234
+ },
235
+ ...props.table['v-slots']
236
+
237
+ }}
238
+ dataSource={tableData.value}
239
+ />
240
+ </div>
241
+ <div class="mt-3 flex items-center justify-between">
242
+ <div>
243
+ { props.table.enableSelection && (`选中项: ${props.attribute.selectKeys.length}`)}
244
+ </div>
245
+ <div class="flex items-center gap-2">
246
+ <APagination
247
+ hideOnSinglePage={true}
248
+ v-model:current={pagination.page}
249
+ total={pagination.total}
250
+ pageSize={pagination.pageSize}
251
+ onChange={(page) => {
252
+ pagination.page = page
253
+ tableData.load()
254
+ }}
255
+ pageSizeOptions={['20','50','100']}
256
+ onShowSizeChange={(current, size) => {
257
+ pagination.pageSize = size
258
+ pagination.page = current
259
+ tableData.load()
260
+ }}
261
+ />
262
+
263
+ <AButton icon={h(RedoOutlined)} loading={tableData.loading} onClick={tableData.load} />
264
+ </div>
265
+
266
+ </div>
267
+
268
+ </div>
269
+ )
270
+ }
271
+ })
@@ -0,0 +1,15 @@
1
+ import { ACard } from "#components"
2
+ import { FormTableProps } from "./FormTable"
3
+
4
+ export default defineComponent({
5
+
6
+ props:FormTableProps,
7
+
8
+ setup(props){
9
+ const {com,params} = FormTable(props)
10
+
11
+ return ()=><ACard class="absolute top-0 left-0 right-0 bottom-0 h-full" bodyStyle="height:100%">
12
+ <com></com>
13
+ </ACard>
14
+ }
15
+ })
@@ -0,0 +1,178 @@
1
+ <template>
2
+ <a-layout class="top-0 bottom-0 left-0 right-0 absolute">
3
+ <a-layout-sider
4
+ v-model:collapsed="collapsed"
5
+ breakpoint="lg"
6
+ collapsed-width="0"
7
+ width="220px"
8
+ >
9
+ <div class="text-center text-white p-2 text-lg " >
10
+ LOGO
11
+ </div>
12
+ <LayoutMenu :items="props.menu"></LayoutMenu>
13
+ </a-layout-sider>
14
+
15
+ <a-layout>
16
+ <a-layout-header :style="{ background: '#fff', padding: 0 }">
17
+ <div class="flex h-full items-center justify-between gap-2 px-4">
18
+ <div class="flex items-center gap-2">
19
+ <menu-unfold-outlined
20
+ v-if="collapsed"
21
+ class="trigger text-[20px]"
22
+ @click="() => (collapsed = !collapsed)"
23
+ />
24
+ <menu-fold-outlined v-else class="trigger text-[20px]" @click="() => (collapsed = !collapsed)" />
25
+ <div class="leading-4 gap-1 flex flex-col justify-center h-full">
26
+ <div class="text-[12px] text-[#aaa]">{{routeInfo.names.join(' / ')}}</div>
27
+ <div class="font-bold text-[18px]">{{routeInfo.name}}</div>
28
+ </div>
29
+ </div>
30
+ <div class=" flex items-center">
31
+ <div >
32
+ <a-dropdown >
33
+ <div class="h-[30px] leading-[30px]">{{ useAdmin().value?.username }}</div>
34
+ <template #overlay>
35
+ <a-menu>
36
+ <a-menu-item @click="()=>singOut()">
37
+ <a href="javascript:;">退出</a>
38
+ </a-menu-item>
39
+ </a-menu>
40
+ </template>
41
+ </a-dropdown>
42
+ </div>
43
+
44
+ </div>
45
+ </div>
46
+ </a-layout-header>
47
+ <!-- <div class="p-4 bg-white" style="border-top:1px solid #eee">
48
+ <div class="leading-4 gap-1 flex flex-col justify-center h-full">
49
+ <div class="text-[12px] text-[#aaa]">{{routeInfo.names.join(' / ')}}</div>
50
+ <div class="font-bold text-[18px]">{{routeInfo.name}}</div>
51
+ </div>
52
+ </div> -->
53
+ <a-layout-content :style="{ }" class="relative m-4">
54
+ <div class="absolute top-0 left-0 right-0 bottom-0">
55
+ <slot ></slot>
56
+ </div>
57
+ </a-layout-content>
58
+ </a-layout>
59
+ </a-layout>
60
+ </template>
61
+ <script lang="ts" setup>
62
+ import type { MenuItemType } from './Menu.vue';
63
+
64
+ const collapsed = ref(false)
65
+
66
+ const props = defineProps<{
67
+ menu: MenuItemType[]
68
+ }>()
69
+
70
+ // const menuItems:MenuItemType = [
71
+ // {
72
+ // title:'首页',
73
+ // icon: () => h(PieChartOutlined),
74
+ // path:'/'
75
+ // },
76
+ // {
77
+ // title:'用户',
78
+ // icon: () => h(PieChartOutlined),
79
+ // path:'/user',
80
+ // children:[
81
+ // {
82
+ // title:'用户列表',
83
+ // icon:'InboxOutlined',
84
+ // path:'/user/list'
85
+ // }
86
+ // ]
87
+ // },
88
+ // {
89
+ // title:'数据报表',
90
+ // icon: () => h(PieChartOutlined),
91
+ // path:'/dataReport',
92
+ // children:[
93
+ // {
94
+ // title:'平台活跃报表',
95
+ // path:'/DataReport/platformActiveReport'
96
+ // },
97
+ // {
98
+ // title:'平台财务报表',
99
+ // path:'/DataReport/platformfinanceReport'
100
+ // },
101
+ // {
102
+ // title:'消耗报表',
103
+ // path:'/DataReport/consumptionReport'
104
+ // }
105
+ // ]
106
+ // },
107
+ // {
108
+ // title:'结算管理',
109
+ // icon: () => h(PieChartOutlined),
110
+ // path:'/settleManage',
111
+ // children:[
112
+ // {
113
+ // title:'分包游戏报表',
114
+ // path:'/settleManage/subGameReport'
115
+ // },
116
+
117
+ // ]
118
+ // },
119
+ // {
120
+ // title:'综艺直播游戏',
121
+ // icon: () => h(PieChartOutlined),
122
+ // path:'/liveGame',
123
+ // children:[
124
+ // {
125
+ // title:'综艺直播间数据',
126
+ // path:'/liveGame/liveData'
127
+ // },
128
+ // {
129
+ // title:'直播间开奖操控',
130
+ // path:'/liveGame/LotteryControl'
131
+ // },
132
+ // {
133
+ // title:'直播间实时监控',
134
+ // path:'/liveGame/liveMonitor'
135
+ // },
136
+ // {
137
+ // title:'机器人管理',
138
+ // path:'/liveGame/robotManage',
139
+ // children:[
140
+ // {
141
+ // title:'机器人列表',
142
+ // path:'/liveGame/robotManage/robotList'
143
+ // },
144
+ // {
145
+ // title:'机器人配置',
146
+ // path:'/liveGame/robotManage/robotConfig'
147
+ // },
148
+ // {
149
+ // title:'机器人资源库',
150
+ // path:'/liveGame/robotManage/robotResourceLibrary'
151
+ // },
152
+ // {
153
+ // title:'机器人类型',
154
+ // path:'/liveGame/robotManage/robotType'
155
+ // },
156
+ // {
157
+ // title:'自动弹幕文本配置',
158
+ // path:'/liveGame/robotManage/autoDanmuTextConfig'
159
+ // },
160
+ // ]
161
+ // },
162
+ // {
163
+ // title:'综艺游戏直播间配置',
164
+ // path:'/liveGame/gameLiveConfig'
165
+ // }
166
+
167
+ // ]
168
+ // }
169
+
170
+ // ]
171
+ const router = useRouter()
172
+
173
+
174
+ let routeInfo = useRouteInfo(props.menu)
175
+
176
+
177
+ </script>
178
+
@@ -0,0 +1,79 @@
1
+ <template>
2
+ <a-menu
3
+ v-model:openKeys="state.openKeys"
4
+ v-model:selectedKeys="state.openKeys"
5
+ mode="inline"
6
+ theme="dark"
7
+ :inline-collapsed="state.collapsed"
8
+ :items="items"
9
+ @select="select"
10
+ ></a-menu>
11
+ </template>
12
+ <script lang="ts" setup>
13
+
14
+ export type MenuItemType = {
15
+ icon?:string,
16
+ title:string,
17
+ path:string,
18
+ children?:MenuItemType[]
19
+ }
20
+ const props = defineProps<{
21
+ items: MenuItemType[],
22
+ }>()
23
+
24
+ const router = useRouter()
25
+ const select = ({ item, key, keyPath })=>{
26
+ router.push(key)
27
+ state.openKeys = keyPath
28
+ }
29
+
30
+ const state = reactive({
31
+ collapsed: false,
32
+ selectedKeys: [''],
33
+ openKeys: [''],
34
+ preOpenKeys: ['sub1'],
35
+ });
36
+
37
+ const items = computed(()=>{
38
+ let a = props.items.map((item) => {
39
+ const { icon, title, path, children } = item;
40
+ let newItem = {
41
+ key: path,
42
+ icon: icon,
43
+ label: title,
44
+
45
+ };
46
+ if(children){
47
+ newItem.children=children?.map((child) =>{
48
+ let c = {
49
+ key: child.path,
50
+ label: child.title,
51
+ }
52
+ if(child.children){
53
+ c.children=child.children?.map((subChild) =>{
54
+ return {
55
+ key: subChild.path,
56
+ label: subChild.title,
57
+ }
58
+ })
59
+ }
60
+ return c
61
+ })
62
+ }
63
+ return newItem
64
+ });
65
+ console.log(a)
66
+ return a
67
+ })
68
+
69
+ let routeInfo = useRouteInfo(props.items)
70
+
71
+ onMounted(()=>{
72
+ state.selectedKeys=routeInfo.value.paths
73
+ state.openKeys=routeInfo.value.paths
74
+ })
75
+
76
+
77
+ </script>
78
+
79
+
@@ -0,0 +1,26 @@
1
+ import { createVNode, render } from "vue"
2
+
3
+ export const Drawer = (el)=>{
4
+
5
+ let com = defineComponent({
6
+ setup(){
7
+ let open=ref(true)
8
+ console.log('aaaaaa')
9
+ return ()=> h(el,{
10
+ open: open.value, // 等价于 v-model:open
11
+ 'onUpdate:open': (val: boolean) => {
12
+ open.value = val
13
+ console.log(val,open.value)
14
+ },
15
+ })
16
+ }
17
+ })
18
+
19
+
20
+ let container = document.createDocumentFragment()
21
+ const vnode = h(com)
22
+ vnode.appContext = useNuxtApp().vueApp._context
23
+ render(vnode,container)
24
+ document.body.appendChild(container)
25
+
26
+ }
@@ -0,0 +1 @@
1
+ export const FormItem = {}
@@ -0,0 +1,126 @@
1
+ import { createVNode, render } from "vue"
2
+ import Form from "../components/global/Form"
3
+ import { AModal } from "#components"
4
+
5
+ export const NormalModal = (el)=>{
6
+ let control = {close:()=>{}}
7
+ let container = document.createDocumentFragment()
8
+
9
+ let com = defineComponent({
10
+ setup(){
11
+ let open=ref(true)
12
+ control.close = ()=>{
13
+ open.value = false
14
+ }
15
+ return ()=> h(el,{
16
+ open: open.value, // 等价于 v-model:open
17
+ 'onUpdate:open': (val: boolean) => {
18
+ open.value = val
19
+ if(!val){
20
+ setTimeout(() => {
21
+ render(null, container) // 卸载组件
22
+ if (container.parentNode) {
23
+ container.parentNode.removeChild(container) // 移除 DOM
24
+ }
25
+ }, 1000);
26
+ }
27
+ },
28
+ })
29
+ }
30
+ })
31
+
32
+ const vnode = h(com)
33
+ vnode.appContext = useNuxtApp().vueApp._context
34
+ render(vnode,container)
35
+ document.body.appendChild(container)
36
+
37
+ return control
38
+
39
+ }
40
+
41
+ // export Modal.Normal = NormalModal
42
+
43
+
44
+ type FormModalParamsType= {
45
+ title:string,
46
+ form:{
47
+ label:string,
48
+ key:string,
49
+ is:string
50
+ }[],
51
+ submit:()=>void
52
+ }
53
+
54
+ export const FormModal = (params:FormModalParamsType)=>{
55
+
56
+ let submit:()=>void
57
+
58
+ // let control = NormalModal(h(AModal,{
59
+ // title: params.title,
60
+ // okText: '提交'+loading?.value,
61
+ // cancelText: '取消',
62
+ // onOk: async ()=>{
63
+ // await submit()
64
+ // control.close()
65
+ // }
66
+
67
+ // },h(defineComponent({
68
+ // setup(){
69
+ // let formRef = ref(null)
70
+
71
+ // onMounted(()=>{
72
+ // submit = formRef.value.submit
73
+ // loading = formRef.value.loading
74
+ // })
75
+
76
+ // return ()=>h(Form,{
77
+ // ref: formRef,
78
+ // form: params.form,
79
+ // submit:params.submit,
80
+ // showSubmit: false
81
+ // })
82
+ // }
83
+ // }))))
84
+
85
+ let control = NormalModal(h(defineComponent({
86
+ setup(){
87
+ let formRef = ref(null)
88
+ let loading =ref(false)
89
+
90
+ onMounted(()=>{
91
+ submit = async ()=>{
92
+ loading.value = true
93
+ try{
94
+ await formRef.value.submit()
95
+ }finally{
96
+
97
+ loading.value = false
98
+ }
99
+ }
100
+ // loading = formRef.value.loading
101
+ })
102
+
103
+ return ()=>h(AModal,{
104
+ title: params.title,
105
+ okText: '提交',
106
+ cancelText: '取消',
107
+ confirmLoading: loading.value,
108
+ onOk: async ()=>{
109
+ await submit()
110
+ control.close()
111
+ }
112
+
113
+ },h(Form,{
114
+ ref: formRef,
115
+ form: params.form,
116
+ submit:params.submit,
117
+ showSubmit: false
118
+ }))
119
+ }
120
+ })))
121
+ }
122
+
123
+ export const MModal = {
124
+ Normal: NormalModal,
125
+ Form: FormModal
126
+ }
@@ -0,0 +1,63 @@
1
+ import { ACard, ADropdown, AMenu, EllipsisOutlined } from "#components";
2
+ import type { TablePropsType } from "../components/global/FormTable";
3
+ import FormTableCom from "../components/global/FormTable";
4
+
5
+
6
+ export const FormTable = (props:TablePropsType)=>{
7
+
8
+ const attribute = reactive({
9
+ selectItems:[],
10
+ selectKeys:[],
11
+ page:1,
12
+ pageSize:10
13
+ })
14
+
15
+ const control = {
16
+ refresh:()=>{}
17
+ }
18
+
19
+ return {
20
+ com:h(FormTableCom,{...props,attribute,control}),
21
+ attribute,
22
+ control
23
+ }
24
+ }
25
+
26
+ export const TablePage = (props:TablePropsType)=>{
27
+ let TableParams = FormTable(props)
28
+
29
+ return {
30
+ ...TableParams,
31
+ com: h(ACard,{class:"absolute top-0 left-0 right-0 bottom-0 h-full",bodyStyle:"height:100%"},TableParams.com)
32
+
33
+ }
34
+ }
35
+
36
+ export const TableCell = {
37
+ Dropdown:(params:{label:string,icon:string,onClick:()=>void}[])=>{
38
+ // return h(EllipsisOutlined,{class:"mr-2"},{default:()=>{
39
+ // return h()
40
+ // }})
41
+
42
+ return h('div',{style:{'min-width':'50px'}},h(ADropdown,{},{
43
+ default:()=>{
44
+ return h(EllipsisOutlined,{class:"mr-2"})
45
+ },
46
+ overlay:()=>{
47
+ return h(AMenu,{items:params.map(item=>{
48
+ return {
49
+ label:item.label,
50
+ icon:()=>item.icon,
51
+ onClick:item.onClick
52
+ }
53
+ })})
54
+ }
55
+ }))
56
+ },
57
+ Tenant:(params:{name:string,id:string})=>{
58
+ return h('div',{class:"flex flex-col"},[
59
+ h('span',{class:"mr-2"},params.name),
60
+ h('span',{class:"mr-2 whitespace-nowrap"},`ID: ${params.id}`)
61
+ ])
62
+ },
63
+ }
@@ -0,0 +1,6 @@
1
+ // @ts-check
2
+ import withNuxt from './.nuxt/eslint.config.mjs'
3
+
4
+ export default withNuxt(
5
+ // Your custom configs here
6
+ )
package/nuxt.config.ts ADDED
@@ -0,0 +1,22 @@
1
+ import tailwindcss from '@tailwindcss/vite'
2
+ import { fileURLToPath } from 'url'
3
+ import { dirname, join } from 'path'
4
+ const currentDir = dirname(fileURLToPath(import.meta.url))
5
+ console.log(currentDir)
6
+
7
+ // https://nuxt.com/docs/api/configuration/nuxt-config
8
+ export default defineNuxtConfig({
9
+ compatibilityDate: '2024-11-01',
10
+ devtools: { enabled: true },
11
+
12
+ future: {
13
+ compatibilityVersion: 4
14
+ },
15
+
16
+ modules: ['@ant-design-vue/nuxt'],
17
+ extends: ['@xizs/nuxt-base'],
18
+ css: [join(currentDir, './app/assets/css/main.css')],
19
+ vite:{
20
+ plugins: [tailwindcss()],
21
+ }
22
+ })
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@xizs/nuxt-antui",
3
+ "type": "module",
4
+ "version": "0.0.1",
5
+ "main": "./nuxt.config.ts",
6
+ "scripts": {
7
+ "dev": "nuxi dev .playground",
8
+ "build": "nuxt build .playground",
9
+ "generate": "nuxt generate .playground",
10
+ "preview": "nuxt preview .playground",
11
+ "lint": "eslint .",
12
+ "postinstall": "nuxt prepare .playground"
13
+ },
14
+ "dependencies": {
15
+ "@ant-design-vue/nuxt": "1.4.6",
16
+ "@tailwindcss/vite": "^4.1.3",
17
+ "@xizs/nuxt-base": "^0.0.4",
18
+ "ant-design-vue": ">=4",
19
+ "nuxt": "^3.16.2",
20
+ "tailwindcss": "^4.0.14",
21
+ "vue": "^3.5.13",
22
+ "vue-router": "^4.5.0"
23
+ }
24
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "../.nuxt/tsconfig.server.json"
3
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "./.playground/.nuxt/tsconfig.json",
3
+ }