diff --git a/README.md b/README.md index a25b88e..f925aed 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ github地址:https://github.com/vvandk/kinit 👩‍👦‍👦 - [x] 📚字典管理:对系统中经常使用的一些较为固定的数据进行维护。 -- [ ] 📁附件管理:对平台上所有文件、图片等进行统一管理,对接阿里云OSS。 +- [x] 📁文件上传:对接阿里云OSS与本地存储。 - [x] 🔒登录认证:目前支持用户使用手机号+密码方式登录。 @@ -82,7 +82,7 @@ github地址:https://github.com/vvandk/kinit 👩‍👦‍👦 网站标题,LOGO,描述,ICO,备案号,底部内容,百度统计代码,等等 -- [ ] 数据分析:根据用户的登录用户地址分析出哪个地区的人最多 +- [x] 用户分布:接入高德地图显示各地区用户分布情况 - [x] 🗓️登录日志:用户登录日志记录和查询。 @@ -94,7 +94,7 @@ github地址:https://github.com/vvandk/kinit 👩‍👦‍👦 - [x] 导入导出:灵活支持数据导入导出功能 -- [x] 手机验证码登录功能’ +- [x] 手机验证码登录功能 ## TODO @@ -123,6 +123,7 @@ github地址:https://github.com/vvandk/kinit 👩‍👦‍👦 - [vue3-json-viewer](https://gitee.com/isfive/vue3-json-viewer):简单易用的json内容展示组件,适配vue3和vite。 - [vue3-slide-verify](https://github.com/monoplasty/vue3-slide-verify):滑块验证码插件 vue3 + typescript - [SortableJS/vue.draggable.next](https://github.com/SortableJS/vue.draggable.next):Vue 组件 (Vue.js 3.0) 允许拖放和与视图模型数组同步。 +- [高德地图API (amap.com)](https://lbs.amap.com/api/jsapi-v2/guide/webcli/map-vue1):地图 JSAPI 2.0 是高德开放平台免费提供的第四代 Web 地图渲染引擎, 以 WebGL 为主要绘图手段,本着“更轻、更快、更易用”的服务原则,广泛采用了各种前沿技术,交互体验、视觉体验大幅提升,同时提供了众多新增能力和特性。 #### 后端 diff --git a/kinit-admin/package.json b/kinit-admin/package.json index 4c354f2..3e31bab 100644 --- a/kinit-admin/package.json +++ b/kinit-admin/package.json @@ -1,6 +1,6 @@ { "name": "vue-element-plus-admin", - "version": "1.8.4", + "version": "1.8.5", "description": "一套基于vue3、element-plus、typesScript、vite3的后台集成方案。", "author": "Archer <502431556@qq.com>", "private": false, @@ -24,9 +24,10 @@ "analysis": "windicss-analysis" }, "dependencies": { + "@amap/amap-jsapi-loader": "^1.0.1", "@iconify/iconify": "^3.0.0", - "@vueuse/core": "^9.4.0", - "@wangeditor/editor": "^5.1.22", + "@vueuse/core": "^9.5.0", + "@wangeditor/editor": "^5.1.23", "@wangeditor/editor-for-vue": "^5.1.10", "@zxcvbn-ts/core": "^2.1.0", "animate.css": "^4.1.1", @@ -45,7 +46,7 @@ "qrcode": "^1.5.1", "qs": "^6.11.0", "url": "^0.11.0", - "vue": "3.2.41", + "vue": "3.2.45", "vue-i18n": "9.2.2", "vue-router": "^4.1.6", "vue-types": "^4.2.1", @@ -56,7 +57,7 @@ "devDependencies": { "@commitlint/cli": "^17.2.0", "@commitlint/config-conventional": "^17.2.0", - "@iconify/json": "^2.1.134", + "@iconify/json": "^2.1.139", "@intlify/vite-plugin-vue-i18n": "^6.0.3", "@purge-icons/generated": "^0.9.0", "@types/intro.js": "^5.1.0", @@ -65,35 +66,35 @@ "@types/nprogress": "^0.2.0", "@types/qrcode": "^1.5.0", "@types/qs": "^6.9.7", - "@typescript-eslint/eslint-plugin": "^5.42.0", - "@typescript-eslint/parser": "^5.42.0", + "@typescript-eslint/eslint-plugin": "^5.43.0", + "@typescript-eslint/parser": "^5.43.0", "@vitejs/plugin-vue": "^3.2.0", - "@vitejs/plugin-vue-jsx": "^2.1.0", + "@vitejs/plugin-vue-jsx": "^2.1.1", "autoprefixer": "^10.4.13", "eslint": "^8.27.0", "eslint-config-prettier": "^8.5.0", - "eslint-define-config": "^1.11.0", + "eslint-define-config": "^1.12.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-vue": "^9.7.0", - "husky": "^8.0.1", + "husky": "^8.0.2", "less": "^4.1.3", "lint-staged": "^13.0.3", "plop": "^3.1.1", - "postcss": "^8.4.18", + "postcss": "^8.4.19", "postcss-html": "^1.5.0", "postcss-less": "^6.0.0", "prettier": "^2.7.1", "rimraf": "^3.0.2", - "rollup": "^3.2.5", - "stylelint": "^14.14.1", + "rollup": "^3.3.0", + "stylelint": "^14.15.0", "stylelint-config-html": "^1.1.0", - "stylelint-config-prettier": "^9.0.3", + "stylelint-config-prettier": "^9.0.4", "stylelint-config-recommended": "^9.0.0", "stylelint-config-standard": "^29.0.0", "stylelint-order": "^5.0.0", - "typescript": "4.8.4", - "unplugin-vue-macros": "^0.16.0", - "vite": "3.2.2", + "typescript": "4.9.3", + "unplugin-vue-macros": "^0.16.3", + "vite": "3.2.4", "vite-plugin-eslint": "^1.8.1", "vite-plugin-html": "^3.2.0", "vite-plugin-mock": "^2.9.6", diff --git a/kinit-admin/src/api/dashboard/map/index.ts b/kinit-admin/src/api/dashboard/map/index.ts new file mode 100644 index 0000000..9661d6c --- /dev/null +++ b/kinit-admin/src/api/dashboard/map/index.ts @@ -0,0 +1,5 @@ +import request from '@/config/axios' + +export const getUserLoginDistributeApi = (): Promise => { + return request.get({ url: '/vadmin/record/analysis/user/login/distribute/' }) +} diff --git a/kinit-admin/src/components/Form/src/Form.vue b/kinit-admin/src/components/Form/src/Form.vue index 8a1824a..5077924 100644 --- a/kinit-admin/src/components/Form/src/Form.vue +++ b/kinit-admin/src/components/Form/src/Form.vue @@ -245,11 +245,7 @@ export default defineComponent({ vModel={formModel.value[item.field]} {...(autoSetPlaceholder && setTextPlaceholder(item))} {...setComponentProps(item)} - style={ - item?.component === 'Input' - ? { width: '100%', ...item.componentProps?.style } - : { ...item.componentProps?.style } - } + style={item.componentProps?.style} {...(notRenderOptions.includes(item?.component as string) && item?.componentProps?.options ? { options: item?.componentProps?.options || [] } @@ -276,8 +272,8 @@ export default defineComponent({ return renderRadioOptions(item) case 'Checkbox': case 'CheckboxButton': - const { renderChcekboxOptions } = useRenderCheckbox() - return renderChcekboxOptions(item) + const { renderCheckboxOptions } = useRenderCheckbox() + return renderCheckboxOptions(item) default: break } diff --git a/kinit-admin/src/components/Form/src/components/useRenderCheckbox.tsx b/kinit-admin/src/components/Form/src/components/useRenderCheckbox.tsx index c551669..16adecf 100644 --- a/kinit-admin/src/components/Form/src/components/useRenderCheckbox.tsx +++ b/kinit-admin/src/components/Form/src/components/useRenderCheckbox.tsx @@ -3,7 +3,7 @@ import { ElCheckbox, ElCheckboxButton } from 'element-plus' import { defineComponent } from 'vue' export const useRenderCheckbox = () => { - const renderChcekboxOptions = (item: FormSchema) => { + const renderCheckboxOptions = (item: FormSchema) => { // 如果有别名,就取别名 const labelAlias = item?.componentProps?.optionsAlias?.labelField const valueAlias = item?.componentProps?.optionsAlias?.valueField @@ -11,17 +11,16 @@ export const useRenderCheckbox = () => { typeof defineComponent > return item?.componentProps?.options?.map((option) => { - return {option[valueAlias || 'label']} - // const { value, ...other } = option - // return ( - // - // {option[valueAlias || 'label']} - // - // ) + const { value, ...other } = option + return ( + + {option[labelAlias || 'label']} + + ) }) } return { - renderChcekboxOptions + renderCheckboxOptions } } diff --git a/kinit-admin/src/components/Form/src/components/useRenderRadio.tsx b/kinit-admin/src/components/Form/src/components/useRenderRadio.tsx index 307987e..45b65bf 100644 --- a/kinit-admin/src/components/Form/src/components/useRenderRadio.tsx +++ b/kinit-admin/src/components/Form/src/components/useRenderRadio.tsx @@ -11,13 +11,12 @@ export const useRenderRadio = () => { typeof defineComponent > return item?.componentProps?.options?.map((option) => { - return {option[valueAlias || 'label']} - // const { value, ...other } = option - // return ( - // - // {option[valueAlias || 'label']} - // - // ) + const { value, ...other } = option + return ( + + {option[labelAlias || 'label']} + + ) }) } diff --git a/kinit-admin/src/components/Form/src/components/useRenderSelect.tsx b/kinit-admin/src/components/Form/src/components/useRenderSelect.tsx index 7162cd4..e4b5a26 100644 --- a/kinit-admin/src/components/Form/src/components/useRenderSelect.tsx +++ b/kinit-admin/src/components/Form/src/components/useRenderSelect.tsx @@ -36,9 +36,9 @@ export const useRenderSelect = (slots: Slots) => { return ( {{ default: () => diff --git a/kinit-admin/src/components/Table/src/Table.vue b/kinit-admin/src/components/Table/src/Table.vue index d7d47f0..0a880a9 100644 --- a/kinit-admin/src/components/Table/src/Table.vue +++ b/kinit-admin/src/components/Table/src/Table.vue @@ -52,7 +52,6 @@ export default defineComponent({ }, emits: ['update:limit', 'update:page', 'register'], setup(props, { attrs, slots, emit, expose }) { - console.log('attrs', attrs) const elTableRef = ref>() // 注册 diff --git a/kinit-admin/src/components/UserInfo/src/UserInfo.vue b/kinit-admin/src/components/UserInfo/src/UserInfo.vue index d92c296..fef8329 100644 --- a/kinit-admin/src/components/UserInfo/src/UserInfo.vue +++ b/kinit-admin/src/components/UserInfo/src/UserInfo.vue @@ -32,6 +32,14 @@ const toHome = () => { push('/system/home') } +const toGitee = () => { + window.open('https://gitee.com/ktianc/kinit') +} + +const toGithub = () => { + window.open('https://github.com/vvandk/kinit') +} + const user = authStore.getUser @@ -52,6 +60,12 @@ const user = authStore.getUser 个人主页 + + Gitee + + + Github + 退出系统 diff --git a/kinit-admin/src/store/modules/auth.ts b/kinit-admin/src/store/modules/auth.ts index 96da11a..c1483a1 100644 --- a/kinit-admin/src/store/modules/auth.ts +++ b/kinit-admin/src/store/modules/auth.ts @@ -53,9 +53,8 @@ export const useAuthStore = defineStore('auth', { if (res) { wsCache.set(appStore.getToken, `${res.data.token_type} ${res.data.access_token}`) // 存储用户信息 - wsCache.set(appStore.getUserInfo, res.data.user) - this.user = res.data.user - this.isUser = true + const auth = useAuthStore() + await auth.getUserInfo() } return res }, diff --git a/kinit-admin/src/views/Dashboard/Map.vue b/kinit-admin/src/views/Dashboard/Map.vue new file mode 100644 index 0000000..ac458c9 --- /dev/null +++ b/kinit-admin/src/views/Dashboard/Map.vue @@ -0,0 +1,183 @@ + + + + + + + diff --git a/kinit-admin/src/views/Login/components/LoginForm.vue b/kinit-admin/src/views/Login/components/LoginForm.vue index f993b5d..a2233d9 100644 --- a/kinit-admin/src/views/Login/components/LoginForm.vue +++ b/kinit-admin/src/views/Login/components/LoginForm.vue @@ -129,8 +129,8 @@ const signIn = async () => { loading.value = true const { getFormData } = methods const formData = await getFormData() + const authStore = useAuthStoreWithOut() try { - const authStore = useAuthStoreWithOut() const res = await authStore.login(formData) if (res) { if (!res.data.is_reset_password) { @@ -140,8 +140,10 @@ const signIn = async () => { // 是否使用动态路由 getMenu() } + } else { + loading.value = false } - } finally { + } catch (e: any) { loading.value = false } } diff --git a/kinit-admin/src/views/Login/components/TelephoneCodeForm.vue b/kinit-admin/src/views/Login/components/TelephoneCodeForm.vue index b6387a4..d2dd592 100644 --- a/kinit-admin/src/views/Login/components/TelephoneCodeForm.vue +++ b/kinit-admin/src/views/Login/components/TelephoneCodeForm.vue @@ -97,8 +97,8 @@ const telephoneCodeLogin = async () => { loading.value = true const { getFormData } = methods const formData = await getFormData() + const authStore = useAuthStoreWithOut() try { - const authStore = useAuthStoreWithOut() const res = await authStore.login(formData) if (res) { if (!res.data.is_reset_password) { @@ -108,8 +108,10 @@ const telephoneCodeLogin = async () => { // 是否使用动态路由 getMenu() } + } else { + loading.value = false } - } finally { + } catch (e: any) { loading.value = false } } @@ -127,17 +129,21 @@ const getSMSCode = async () => { SMSCodeNumber.value = 60 const { getFormData } = methods const formData = await getFormData() - const res = await postSMSCodeApi({ telephone: formData.telephone }) - if (res?.data) { - let timer = setInterval(() => { - SMSCodeNumber.value-- - if (SMSCodeNumber.value < 1) { - SMSCodeStatus.value = true - clearInterval(timer) - } - }, 1000) - } else { - ElMessage.error('发送失败,请联系管理员') + try { + const res = await postSMSCodeApi({ telephone: formData.telephone }) + if (res?.data) { + let timer = setInterval(() => { + SMSCodeNumber.value-- + if (SMSCodeNumber.value < 1) { + SMSCodeStatus.value = true + clearInterval(timer) + } + }, 1000) + } else { + ElMessage.error('发送失败,请联系管理员') + SMSCodeStatus.value = true + } + } catch (e: any) { SMSCodeStatus.value = true } } diff --git a/kinit-admin/src/views/Reset/Reset.vue b/kinit-admin/src/views/Reset/Reset.vue index f9059ba..728848e 100644 --- a/kinit-admin/src/views/Reset/Reset.vue +++ b/kinit-admin/src/views/Reset/Reset.vue @@ -107,8 +107,10 @@ const save = async () => { if (res) { // 是否使用动态路由 getMenu() + } else { + loading.value = false } - } finally { + } catch (e: any) { loading.value = false } } diff --git a/kinit-admin/src/views/vadmin/auth/menu/components/Write.vue b/kinit-admin/src/views/vadmin/auth/menu/components/Write.vue index 68010c2..d511375 100644 --- a/kinit-admin/src/views/vadmin/auth/menu/components/Write.vue +++ b/kinit-admin/src/views/vadmin/auth/menu/components/Write.vue @@ -6,6 +6,7 @@ import { useValidator } from '@/hooks/web/useValidator' import { getMenuTreeOptionsApi } from '@/api/vadmin/auth/menu' import { ElButton, ElInput } from 'element-plus' import { schema } from './menu.data' +import { propTypes } from '@/utils/propTypes' const { required } = useValidator() @@ -13,7 +14,8 @@ const props = defineProps({ currentRow: { type: Object as PropType>, default: () => null - } + }, + parentId: propTypes.number.def(undefined) }) const rules = reactive({ @@ -53,6 +55,10 @@ const getMenuTreeOptions = async () => { value: res.data } ]) + if (props.parentId) { + const { setValue } = methods + setValue('parent_id', props.parentId) + } } } diff --git a/kinit-admin/src/views/vadmin/auth/menu/components/menu.data.ts b/kinit-admin/src/views/vadmin/auth/menu/components/menu.data.ts index 162f8f1..0626b54 100644 --- a/kinit-admin/src/views/vadmin/auth/menu/components/menu.data.ts +++ b/kinit-admin/src/views/vadmin/auth/menu/components/menu.data.ts @@ -58,7 +58,7 @@ export const columns = reactive([ }, { field: 'action', - width: '150px', + width: '200px', label: '操作', show: true } @@ -77,7 +77,9 @@ export const schema = reactive([ width: '100%' }, checkStrictly: true, - placeholder: '请选择上级菜单' + placeholder: '请选择上级菜单', + nodeKey: 'value', + defaultExpandAll: true } }, { @@ -130,6 +132,11 @@ export const schema = reactive([ component: 'InputNumber', colProps: { span: 12 + }, + componentProps: { + style: { + width: '100%' + } } }, { @@ -216,6 +223,6 @@ export const schema = reactive([ colProps: { span: 12 }, - ifshow: (values) => values.menu_type !== '0' + ifshow: (values) => values.menu_type === '2' } ]) diff --git a/kinit-admin/src/views/vadmin/auth/menu/index.vue b/kinit-admin/src/views/vadmin/auth/menu/index.vue index 7277d39..207ad56 100644 --- a/kinit-admin/src/views/vadmin/auth/menu/index.vue +++ b/kinit-admin/src/views/vadmin/auth/menu/index.vue @@ -45,9 +45,11 @@ const dialogVisible = ref(false) const dialogTitle = ref('') const delLoading = ref(false) const actionType = ref('') +const parentId = ref() // 添加事件 const AddAction = () => { + parentId.value = null dialogTitle.value = t('exampleDemo.add') tableObject.currentRow = null dialogVisible.value = true @@ -56,6 +58,7 @@ const AddAction = () => { // 编辑事件 const updateAction = (row: any) => { + parentId.value = null dialogTitle.value = '编辑' tableObject.currentRow = row dialogVisible.value = true @@ -64,6 +67,7 @@ const updateAction = (row: any) => { // 删除事件 const delData = async (row: any) => { + parentId.value = null tableObject.currentRow = row const { delListApi } = methods delLoading.value = true @@ -72,6 +76,15 @@ const delData = async (row: any) => { }) } +// 添加子菜单事件 +const addSonMenu = async (row: any) => { + parentId.value = row.id + dialogTitle.value = t('exampleDemo.add') + tableObject.currentRow = null + dialogVisible.value = true + actionType.value = 'add' +} + const loading = ref(false) const writeRef = ref>() @@ -124,7 +137,9 @@ watch(
- 新增菜单 + 新增菜单 @@ -149,10 +164,31 @@ watch(
@@ -173,7 +209,7 @@ watch( - + - + {
- + 新增用户 - + 批量导入用户 - + 导出筛选用户 - + 重置密码通知短信 - + 批量删除 @@ -212,11 +212,18 @@ const sendPasswordToSMS = async () => { @register="register" >