企业入驻

This commit is contained in:
wangyilin 2024-09-03 11:28:48 +08:00
parent f88b71adf6
commit c20eb9f1be
25 changed files with 431 additions and 126 deletions

View File

@ -68,7 +68,6 @@ export const staticRouter: RouteRecordRaw[] =
}, },
component: () => import('@/views/login.vue') component: () => import('@/views/login.vue')
}, },
{ {
//登录页面 //登录页面
path: '/register-index', path: '/register-index',

View File

@ -13,19 +13,22 @@
"ant-design-vue": "^4.2.3", "ant-design-vue": "^4.2.3",
"axios": "^1.7.5", "axios": "^1.7.5",
"jsencrypt": "^3.3.2", "jsencrypt": "^3.3.2",
"lodash-es": "^4.17.21",
"pinia": "^2.2.2", "pinia": "^2.2.2",
"pinia-plugin-persistedstate": "^3.2.0", "pinia-plugin-persistedstate": "^3.2.0",
"sass": "^1.77.8", "sass": "^1.77.8",
"vue": "^3.4.37", "vue": "^3.4.37",
"vue-router": "4", "vue-router": "4",
"vue-uuid": "^3.0.0", "vue-uuid": "^3.0.0"
"lodash-es": "^4.17.21"
}, },
"devDependencies": { "devDependencies": {
"@types/lodash-es": "^4.17.8", "@types/lodash-es": "^4.17.8",
"@types/node": "^22.5.1", "@types/node": "^22.5.1",
"@vitejs/plugin-vue": "^5.1.2", "@vitejs/plugin-vue": "^5.1.2",
"@vitejs/plugin-vue-jsx": "^4.0.1", "@vitejs/plugin-vue-jsx": "^4.0.1",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.44",
"tailwindcss": "^3.4.10",
"typescript": "^5.5.3", "typescript": "^5.5.3",
"unplugin-vue-components": "^0.27.4", "unplugin-vue-components": "^0.27.4",
"vite": "^5.4.1", "vite": "^5.4.1",

View File

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@ -0,0 +1,20 @@
<template>
<i v-if="type==='class'" :class="[`iconfont ${fontClass}`]" :style="{fontSize:`${size}px`}"/>
<svg v-else-if="type === 'svg'" :style="{width:`${size}px`,height:`${size}px`}">
<use :href="`#${fontClass}`"/>
</svg>
</template>
<script setup lang="ts">
import {IconFontProps} from "@/types/components/iconfont/IconFont";
withDefaults(defineProps<IconFontProps>(), {
size: 25,
type: "svg"
});
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,47 @@
<template>
<template v-for="item in menuList">
<a-sub-menu
v-if="item.type === 'dir'"
:key="item.path"
>
<template #icon>
<icon-font :font-class="item.icon"/>
</template>
<template #title>
<span class="margin-left-xs">{{ item.title }}</span>
</template>
<menu-item :menu-list="item.children"/>
</a-sub-menu>
<a-menu-item
v-else
:key="item.path as any"
@click="()=>router.push(item.path)"
>
<template #icon>
<icon-font :font-class="item.icon"/>
</template>
<span class="margin-left-xs">{{ item.title }}</span>
</a-menu-item>
</template>
</template>
<script setup lang="ts">
import {SystemMenu} from "@/types/config";
import {useRouter} from "vue-router";
import IconFont from "@/components/iconfont/IconFont.vue";
const router = useRouter()
withDefaults(defineProps<{
menuList?: SystemMenu[]
}>(), {
menuList: (): SystemMenu[] => {
return [];
}
})
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,30 @@
<template>
<a-menu
:selectedKeys="activeMenus"
mode="inline"
:inline-collapsed="false"
class="system-menus"
>
<menu-item :menu-list="SYSTEM_MENUS"/>
</a-menu>
</template>
<script setup lang="ts">
import {computed} from "vue";
import {useRoute} from "vue-router";
import {SYSTEM_MENUS} from "@/config";
import MenuItem from "@/components/layout/MenuItem.vue";
const route = useRoute()
const activeMenus = computed(() => [route.path]);
console.log(activeMenus)
</script>
<style scoped lang="scss">
.system-menus {
height: calc(100% - 100px);
overflow-y: auto;
}
</style>

View File

@ -12,6 +12,7 @@
<div v-else class="logo flex-center"> <div v-else class="logo flex-center">
<img src="@/assets/vue.svg" title="超级后台" alt="xx"> <img src="@/assets/vue.svg" title="超级后台" alt="xx">
</div> </div>
<SystemMenus/>
</a-layout-sider> </a-layout-sider>
<a-layout> <a-layout>
<a-layout-header <a-layout-header
@ -37,6 +38,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref} from "vue"; import {ref} from "vue";
import LayoutHeader from "@/components/layout/header/LayoutHeader.vue"; import LayoutHeader from "@/components/layout/header/LayoutHeader.vue";
import SystemMenus from "@/components/layout/SystemMenus.vue";
const collapsed = ref<boolean>(false); const collapsed = ref<boolean>(false);

View File

@ -38,17 +38,22 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import {ref} from 'vue' import {onMounted, ref} from 'vue'
import {FormInstance, notification} from "ant-design-vue"; import {FormInstance, notification} from "ant-design-vue";
import {Rule} from "ant-design-vue/es/form"; import {Rule} from "ant-design-vue/es/form";
import {LoginParams} from "@/types/views/login.ts"; import {LoginParams} from "@/types/views/login.ts";
import api from "@/axios"; import api from "@/axios";
import {CLIENT_TYPE} from "@/config"; import {CLIENT_TYPE} from "@/config";
import rsaUtil from "@/utils/rsaUtil.ts";
import {TokenInfo} from "@/types/stores/userStore.ts"; import {TokenInfo} from "@/types/stores/userStore.ts";
import {useUserStore} from "@/stores/modules/userStore.ts"; import {useUserStore} from "@/stores/modules/userStore.ts";
import {useRouter} from "vue-router"; import {useRoute, useRouter} from "vue-router";
import rsaUtil from "@/utils/rsaUtil.ts";
onMounted(()=>{
const route = useRoute()
loginParams.value.telephone = <string> route.query.account
loginParams.value.password =<string> route.query.password
})
const userStore = useUserStore() const userStore = useUserStore()
const router = useRouter() const router = useRouter()
@ -56,7 +61,6 @@ const formRef = ref<FormInstance>(null!)
const loginParamsRule: Record<keyof LoginParams, Rule[]> = { const loginParamsRule: Record<keyof LoginParams, Rule[]> = {
telephone: [ telephone: [
{required: true, message: '请输入手机号', trigger: 'change'}, {required: true, message: '请输入手机号', trigger: 'change'},
{len: 11, message: "长度不够", trigger: 'blur'},
], ],
password: [ password: [
{required: true, message: '请输入密码', trigger: 'change'}, {required: true, message: '请输入密码', trigger: 'change'},
@ -64,10 +68,11 @@ const loginParamsRule: Record<keyof LoginParams, Rule[]> = {
], ],
} }
const loginParams = ref<LoginParams>({ const loginParams = ref<LoginParams>({
telephone: __APP_ENV.VITE_APP_ENV === "development" ? '15576404472' : '', telephone: __APP_ENV.VITE_APP_ENV === "development" ? '13575462314' : '',
password: __APP_ENV.VITE_APP_ENV === "development" ? '123456' : '' password: __APP_ENV.VITE_APP_ENV === "development" ? '123456' : ''
}); });
/** /**
* 登录 * 登录
*/ */
@ -78,7 +83,7 @@ const login = async () => {
const resp = await api.post<TokenInfo>('/login', { const resp = await api.post<TokenInfo>('/login', {
clientType: CLIENT_TYPE, clientType: CLIENT_TYPE,
loginParams: { loginParams: {
telephone: loginParams.value.telephone, accountOrTelephone: loginParams.value.telephone,
password: rsaUtil.encryptStr(loginParams.value.password) password: rsaUtil.encryptStr(loginParams.value.password)
} }
}) })
@ -95,6 +100,7 @@ const login = async () => {
}) })
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -0,0 +1,17 @@
import api from "@/axios";
type DictType =
'CheckStatus'
| 'DeleteFlag'
| 'IsEnable'
| 'IsOrNot'
| 'Sex'
export const initEnums = () => {
api.get<Record<DictType, SelectNodeVo<any>[]>>('/common/enums').then(resp => {
sessionStorage.setItem('dictMap', JSON.stringify(resp.data))
})
}
export const enumSelectNodes = <T>(enumType: DictType): SelectNodeVo<T>[] => JSON.parse(sessionStorage.getItem('dictMap') as string)?.[enumType] || []

View File

@ -1,2 +1,35 @@
export const CLIENT_TYPE = "MANAGEMENT_SUPER"; import {SystemMenu} from "@/types/config";
export const ROUTER_WHITE_LIST: string[] = ['/login', '/test','/enterprise']; export const ROUTER_WHITE_LIST: string[] = ['/login', '/test','/enterprise'];
export const CLIENT_TYPE:string = "MANAGEMENT_SECURITY";
export const SYSTEM_MENUS: SystemMenu[] = [
{
title: '首页',
name: 'index',
path: '/index',
type: "menu",
component: () => import('@/views/index.vue')
}, {
title: '单位管理',
name: 'userManagement',
path: '/userManagement',
type: 'dir',
children: [
{
title: '用户管理',
name: 'bgManagement',
path: '/bgManagement',
type: 'menu',
component: () => import('@/views/userManagement/bgManagement/index.vue')
}, {
title: '小程序管理',
name: 'uniManagement',
path: '/uniManagement',
type: 'menu',
component: () => import('@/views/userManagement/uniManagement/index.vue')
}
]
}
]

View File

@ -61,3 +61,19 @@ interface BaseEnum<T> {
value: T; value: T;
label: string label: string
} }
interface dataStatus {
account: string;
password: string;
remark: string;
checkStatus: {
extData: {
color: string;
};
label: string;
value: number;
};
}

View File

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@ -1,7 +1,7 @@
import {createApp} from 'vue' import {createApp} from 'vue'
import App from '@/App.vue' import App from '@/App.vue'
import '@/reset.css' import '@/reset.css'
import './index.css'
// 公共样式 // 公共样式
import '@/assets/scss/common.scss' import '@/assets/scss/common.scss'
// iconfont css // iconfont css
@ -10,9 +10,12 @@ import "@/assets/iconfont/iconfont.css";
import router from "@/router"; import router from "@/router";
// pinia stores // pinia stores
import pinia from "@/stores"; import pinia from "@/stores";
import {initEnums} from "@/config/dict.ts";
initEnums()
const vueApp = createApp(App); const vueApp = createApp(App);
vueApp vueApp
.use(router) .use(router)
.use(pinia) .use(pinia)

View File

@ -1,14 +1,35 @@
import {RouteRecordRaw} from "vue-router"; import {RouteRecordRaw} from "vue-router";
import {SYSTEM_MENUS} from "@/config";
import {SystemMenu} from "@/types/config";
/**
*
*/
const extractMenuToRouter = (): RouteRecordRaw[] => {
const result: RouteRecordRaw[] = []
const traverse = (data: SystemMenu[]) => {
data.forEach(item => {
if (item.type === 'dir' && item.children && item.children.length > 0) {
traverse(item.children)
} else {
result.push({
path: item.path,
name: item.name,
meta: {
title: item.title
},
component: item.component
} as RouteRecordRaw)
}
})
}
traverse(SYSTEM_MENUS)
return result;
}
export const staticRouter: RouteRecordRaw[] = [ export const staticRouter: RouteRecordRaw[] = [
{
path: '/enterprise',
name: 'enterprise',
meta: {
title: '企业入驻',
},
component: () => import("@/views/enterprise.vue"),
},
{ {
path: '/login', path: '/login',
name: 'login', name: 'login',
@ -19,30 +40,15 @@ export const staticRouter: RouteRecordRaw[] = [
}, { }, {
path: "/", path: "/",
redirect: '/index', redirect: '/index',
}, {
path: '/test',
name: 'test',
meta: {
title: '测试',
},
component: () => import("@/views/test.vue"),
}, { }, {
path: '/layout', path: '/layout',
name: 'layout', name: 'layout',
redirect: '/index', redirect: '/index',
component: () => import("@/components/layout/layout.vue"), component: () => import("@/components/layout/layout.vue"),
children: [ children: extractMenuToRouter()
{ }, {
path: '/index', path: '/test',
name: 'index', name: 'test',
meta: { component: () => import("@/views/test.vue"),
title: '首页',
icon: 'icon-shouye',
fixed: true,
isKeepAlive: false
},
component: () => import('@/views/index.vue')
}
]
}, },
] ]

View File

@ -5,7 +5,7 @@ export const useUserStore = defineStore({
id: 'useUserStore', id: 'useUserStore',
state: (): UserStore => { state: (): UserStore => {
return { return {
tokenInfo: undefined tokenInfo: undefined,
} }
}, },
actions: { actions: {
@ -14,7 +14,7 @@ export const useUserStore = defineStore({
}, },
async resetUserInfo() { async resetUserInfo() {
this.tokenInfo = undefined; this.tokenInfo = undefined;
} },
}, },
getters: { getters: {
getTokenInfo: (state): TokenInfo => state.tokenInfo as TokenInfo, getTokenInfo: (state): TokenInfo => state.tokenInfo as TokenInfo,

View File

@ -0,0 +1,5 @@
export interface IconFontProps {
fontClass?: string,
size?: number,
type?: 'class' | 'svg'
}

View File

@ -0,0 +1,12 @@
import {RouteComponent} from "vue-router";
export interface SystemMenu {
type: 'dir' | 'menu';
title: string;
path: string;
name: string;
icon?: string;
component?: RouteComponent;
children?: SystemMenu[];
}

View File

@ -1,8 +1,10 @@
export interface TokenInfo { export interface TokenInfo {
name: string; name: string;
value: string; value: string;
} }
export interface UserStore { export interface UserStore {
tokenInfo?: TokenInfo; tokenInfo?: TokenInfo;
} }

View File

@ -1,7 +1,12 @@
<template> <template>
<div class="enterprise"> <!-- 背景色覆盖整个页面并且能够正常滚动内容同时固定内层内容的位置 -->
<div class="enterpriseIndex"> <body style="margin: 0; padding: 0; overflow: auto">
<div class="enterpriseItem"> <!-- 背景色层 -->
<div class="bg-gray-100" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: -1"></div>
<!-- 内容层 -->
<div class="flex justify-center" style="position: relative; margin: 20px auto">
<!-- 卡片盒子 -->
<div class="w-full max-w-3xl p-6 bg-white rounded-xl shadow-md">
<a-tabs v-model:activeKey="activeKey" :tabBarGutter="300" centered > <a-tabs v-model:activeKey="activeKey" :tabBarGutter="300" centered >
<a-tab-pane key="1" tab="企业入驻"> <a-tab-pane key="1" tab="企业入驻">
<a-form <a-form
@ -14,13 +19,13 @@
@finish="onFinish" @finish="onFinish"
> >
<a-form-item label="名称" name="name"> <a-form-item label="名称" name="name">
<a-input v-model:value="formDate.name" /> <a-input :allowClear="true" v-model:value="formDate.name" />
</a-form-item> </a-form-item>
<a-form-item label="统一社会编码" name="socialCode"> <a-form-item :allowClear="true" label="统一社会编码" name="socialCode">
<a-input v-model:value="formDate.socialCode"/> <a-input v-model:value="formDate.socialCode"/>
</a-form-item> </a-form-item>
<a-form-item label="公司性质" name="nature"> <a-form-item label="公司性质" name="nature">
<a-input v-model:value="formDate.nature"/> <a-input :allowClear="true" v-model:value="formDate.nature"/>
</a-form-item> </a-form-item>
<a-form-item label="行政区划" > <a-form-item label="行政区划" >
<a-cascader v-model:value="formDate.administrativeDivisionCodes" :show-search="{ filter }" :options="administrativeDivisionTree" @change="searchAdministrativeDivisionTree" /> <a-cascader v-model:value="formDate.administrativeDivisionCodes" :show-search="{ filter }" :options="administrativeDivisionTree" @change="searchAdministrativeDivisionTree" />
@ -28,43 +33,58 @@
<a-form-item label="营业执照" name="businessLicense"> <a-form-item label="营业执照" name="businessLicense">
<SingleImageFileUpload v-model:value="formDate.businessLicense"></SingleImageFileUpload> <SingleImageFileUpload v-model:value="formDate.businessLicense"></SingleImageFileUpload>
</a-form-item> </a-form-item>
<a-form-item label="法人名"> <a-form-item label="法人名">
<a-input v-model:value="formDate.legalPersonInfo" /> <a-input :allowClear="true" v-model:value="formDate.legalPersonInfo" />
</a-form-item> </a-form-item>
<a-form-item label="法人手机号码"> <a-form-item label="法人手机号码">
<a-input v-model:value="formDate.telephone" /> <a-input :allowClear="true" v-model:value="formDate.telephone" />
</a-form-item> </a-form-item>
<a-form-item label="详细地址" > <a-form-item label="详细地址" >
<a-input v-model:value="formDate.address" /> <a-input :allowClear="true" v-model:value="formDate.address" />
</a-form-item> </a-form-item>
<a-form-item :wrapper-col="{ offset: 8, span: 16 }"> <a-form-item :wrapper-col="{ offset: 8, span: 16 }">
<a-button type="primary" html-type="submit" style="width: 100px">确认</a-button> <a-button type="primary" html-type="submit" style="width: 100px">确认</a-button>
<a-button style="width: 100px;margin-left: 10px" @click="resetForm">重置表单</a-button>
</a-form-item> </a-form-item>
</a-form> </a-form>
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="2" tab="查询企业状态" > <a-tab-pane key="2" tab="查询企业状态" >
<a-form
</a-tab-pane> :label-col="labelCol"
</a-tabs> :wrapper-col="wrapperCol"
</div> :model="statusDate"
layout="horizontal">
<a-form-item label="统一社会编码" name="onlyCode" :rules="[{ required: true, message: '请输入统一社会编码进行查询' }]">
<a-input :allowClear="true" v-model:value="statusDate.onlyCode"></a-input>
</a-form-item>
<a-form-item :wrapper-col="{ offset: 8, span: 16 }">
<a-button type="primary" html-type="submit" style="width: 100px" @click="getCheckStatus">确认</a-button>
</a-form-item>
</a-form>
</a-tab-pane></a-tabs>
</div> </div>
</div> </div>
</body>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {ref, onMounted} from 'vue'; import {ref, onMounted,createVNode,h} from 'vue';
import type { Rule } from 'ant-design-vue/es/form'; import type { Rule } from 'ant-design-vue/es/form';
import type { ShowSearchType } from 'ant-design-vue/es/cascader'; import type { ShowSearchType } from 'ant-design-vue/es/cascader';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import api from "@/axios"; import api from "@/axios";
import { message } from 'ant-design-vue'; import {message, Modal} from 'ant-design-vue';
import SingleImageFileUpload from "@/components/upload/SingleImageFileUpload.vue"; import SingleImageFileUpload from "@/components/upload/SingleImageFileUpload.vue";
import {useRouter} from "vue-router";
const activeKey = ref('1'); const activeKey = ref('1');
const labelCol = { style: { width: '120px' } }; const labelCol = { style: { width: '120px' } };
const wrapperCol = { span: 14 }; const wrapperCol = { span: 14 };
const administrativeDivisionTree = ref<TreeNodeVo<string>[]>([]) const administrativeDivisionTree = ref<TreeNodeVo<string>[]>([])
const formDateRef = ref(); const formDateRef = ref();
const router = useRouter()
interface formDatePort { interface formDatePort {
name:string, name:string,
socialCode:string, socialCode:string,
@ -76,6 +96,11 @@ interface formDatePort {
nature:string nature:string
} }
interface statusPort {
onlyCode:string,
unitOptType:string
}
const formDate = ref<formDatePort>({ const formDate = ref<formDatePort>({
name:'', name:'',
socialCode:'', socialCode:'',
@ -87,6 +112,10 @@ const formDate = ref<formDatePort>({
nature:'' nature:''
}) })
const statusDate = ref<statusPort>({
onlyCode:'',
unitOptType:'SECURITY_UNIT'
})
const rules: Record<string, Rule[]> = { const rules: Record<string, Rule[]> = {
name: [ name: [
{ required: true, message: '请输入姓名', trigger: 'change' }, { required: true, message: '请输入姓名', trigger: 'change' },
@ -105,9 +134,6 @@ const rules: Record<string, Rule[]> = {
] ]
}; };
// 1 // 1
const DivisionTree = async ()=>{ const DivisionTree = async ()=>{
const resp = await api.get<TreeNodeVo<string>[]>('/common/administrativeDivisionTree') const resp = await api.get<TreeNodeVo<string>[]>('/common/administrativeDivisionTree')
@ -116,6 +142,7 @@ const DivisionTree = async ()=>{
// 2 // 2
const filter: ShowSearchType['filter'] = (inputValue, path) => { const filter: ShowSearchType['filter'] = (inputValue, path) => {
console.log(inputValue,path)
return path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1); return path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
}; };
@ -123,8 +150,6 @@ const filter: ShowSearchType['filter'] = (inputValue, path) => {
const searchAdministrativeDivisionTree = (e:Array<string>)=>{ const searchAdministrativeDivisionTree = (e:Array<string>)=>{
formDate.value.administrativeDivisionCodes = e formDate.value.administrativeDivisionCodes = e
} }
// //
const onFinish = async ()=>{ const onFinish = async ()=>{
// //
@ -143,9 +168,7 @@ const onFinish = async ()=>{
address:formDate.value.address address:formDate.value.address
} }
const resp = await api.post('/common/securityUnitRegister',securityUnitRegisterParams) const resp = await api.post('/common/securityUnitRegister',securityUnitRegisterParams)
console.log(resp) message.success(resp.message)
await message.loading('正在注册中...')
message.success('企业入驻成功')
await formDateRef.value.resetFields() // await formDateRef.value.resetFields() //
formDate.value = { formDate.value = {
name:'', name:'',
@ -157,26 +180,56 @@ const onFinish = async ()=>{
address:'', address:'',
nature:'' nature:''
} }
} }
//
const resetForm = ()=>{
formDateRef.value.resetFields()
}
//
const getCheckStatus = async ()=>{
const indexCheckStatusParams = {
onlyCode:statusDate.value.onlyCode,
unitOptType:statusDate.value.unitOptType
}
const resp = await api.post<dataStatus>('/management/getCheckStatus',indexCheckStatusParams)
showConfirm(resp.data)
}
const showConfirm = (columnsDate:dataStatus) => {
if(columnsDate.checkStatus.value === 0){
Modal.success({
title: `审核通过`,
icon: createVNode(ExclamationCircleOutlined),
content: h('div', {}, [
h('div', `账号:${columnsDate.account}`),
h('div', `密码:${columnsDate.password}`),
h('div', `${columnsDate.remark}`)
]),
okText:'跳转',
async onOk() {
await router.push({
path:'/login',
query:{
account:columnsDate.account,
password:columnsDate.password
}
}).then(()=>{})
},
onCancel() {},
});
}else{
Modal.error({
title: `未审核`,
icon: createVNode(ExclamationCircleOutlined),
content:`${columnsDate.remark}`,
});
}
};
onMounted( async ()=>{ onMounted( async ()=>{
await DivisionTree() await DivisionTree()
}) })
</script> </script>
<style scoped lang="scss">
.enterprise{
display: flex;
justify-content: center; /* 水平居中 */
align-items: center;
text-align: center;
height: 100vh;
width: 100%;
.enterpriseIndex{
border: 1px solid #cccccc;
height: 90vh;
width: 800px;
}
}
</style>

View File

@ -0,0 +1,12 @@
<template>
<div>服务项目管理</div>
</template>
<script setup lang="ts">
</script>
<style scoped lang="scss">
</style>

View File

@ -1,13 +1,11 @@
<template> <template>
<div>
<SingleImageFileUpload v-model:value="url"></SingleImageFileUpload>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import SingleImageFileUpload from "@/components/upload/SingleImageFileUpload.vue";
import {ref} from "vue";
const url = ref<string>('')
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
</style> </style>

View File

@ -0,0 +1,12 @@
<template>
<div>用户管理</div>
</template>
<script setup lang="ts">
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,11 @@
<template>
<div>小程序管理</div>
</template>
<script setup lang="ts">
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,9 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
theme: {
extend: {},
},
plugins: [],
}