1. 修复:移动端头像剪切功能
2. 更新:升级PC端vue-element-plus-admin版本到1.9.2 3. 更新:文件上传接口 4. 新增:kinit-api 命令创建app目录
This commit is contained in:
parent
36079a5055
commit
5abaef08cc
@ -1,7 +1,66 @@
|
||||
# Changelog
|
||||
- # Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
## [1.9.2](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.9.1...v1.9.2) (2023-01-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复TS类型错误 ([1c06a27](https://github.com/kailong321200875/vue-element-plus-admin/commit/1c06a27b900a891cd0b47098062cebc984ff6505))
|
||||
|
||||
## [1.9.1](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.9.0...v1.9.1) (2023-01-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* dark mode toggle ([bbc7646](https://github.com/kailong321200875/vue-element-plus-admin/commit/bbc764601ec864c2fdbe3ad78c083c5ae80615e0))
|
||||
|
||||
## [1.9.0](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.7...v1.9.0) (2022-12-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* 添加打包进度条 ([354e87f](https://github.com/kailong321200875/vue-element-plus-admin/commit/354e87f7c533ad8e93ef484b47d0fe16f17048c9))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* husky ([6fe5b2e](https://github.com/kailong321200875/vue-element-plus-admin/commit/6fe5b2e6c781b251bff5f0ac936c04dcfe5ef95f))
|
||||
|
||||
## [1.8.7](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.6...v1.8.7) (2022-12-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 解决iframe无法正常工作 ([4fcc46f](https://github.com/kailong321200875/vue-element-plus-admin/commit/4fcc46fccf747b47909e2079c4f2abc5dbfb1a0c))
|
||||
|
||||
## [1.8.6](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.5...v1.8.6) (2022-11-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复Search组件无法默认值 ([3368fda](https://github.com/kailong321200875/vue-element-plus-admin/commit/3368fda251bd3ff5a8e0059b3b33f9c0339d236b))
|
||||
|
||||
## [1.8.5](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.4...v1.8.5) (2022-11-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复Form赋值问题 ([f37cc1b](https://github.com/kailong321200875/vue-element-plus-admin/commit/f37cc1b5801add3ada168dbbcf4cd2c340f0e30d))
|
||||
|
||||
## [1.8.4](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.3...v1.8.4) (2022-11-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复option禁用属性无效 ([0b671e9](https://github.com/kailong321200875/vue-element-plus-admin/commit/0b671e914e396c7666ad5e34768a6e29f7dfbd33))
|
||||
|
||||
|
||||
### Styling
|
||||
|
||||
* input默认宽度与select对齐 ([0b671e9](https://github.com/kailong321200875/vue-element-plus-admin/commit/0b671e914e396c7666ad5e34768a6e29f7dfbd33))
|
||||
|
||||
## [1.8.3](https://github.com/kailong321200875/vue-element-plus-admin/compare/v1.8.2...v1.8.3) (2022-10-28)
|
||||
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
# vue-element-plus-admin
|
||||
|
||||
vue-element-plus-admin 是一个基于 `element-plus` 免费开源的中后台模版。使用了最新的`vue3`,`vite3`,`TypeScript`等主流技术开发,开箱即用的中后台前端解决方案,可以用来作为项目的启动模版,也可用于学习参考。并且时刻关注着最新技术动向,尽可能的第一时间更新。
|
||||
vue-element-plus-admin 是一个基于 `element-plus` 免费开源的中后台模版。使用了最新的`vue3`,`vite4`,`TypeScript`等主流技术开发,开箱即用的中后台前端解决方案,可以用来作为项目的启动模版,也可用于学习参考。并且时刻关注着最新技术动向,尽可能的第一时间更新。
|
||||
|
||||
## 特性
|
||||
|
||||
- **最新技术栈**:使用 Vue3/vite3 等前端前沿技术开发
|
||||
- **最新技术栈**:使用 Vue3/vite4 等前端前沿技术开发
|
||||
- **TypeScript**: 应用程序级 JavaScript 的语言
|
||||
- **主题**: 可配置的主题
|
||||
- **国际化**:内置完善的国际化方案
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "vue-element-plus-admin",
|
||||
"version": "1.8.7",
|
||||
"description": "一套基于vue3、element-plus、typesScript、vite3的后台集成方案。",
|
||||
"version": "1.9.2",
|
||||
"description": "一套基于vue3、element-plus、typesScript、vite4的后台集成方案。",
|
||||
"author": "Archer <502431556@qq.com>",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
@ -25,88 +25,88 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@amap/amap-jsapi-loader": "^1.0.1",
|
||||
"@iconify/iconify": "^3.0.0",
|
||||
"@kjgl77/datav-vue3": "^1.3.3",
|
||||
"@vueuse/core": "^9.5.0",
|
||||
"@iconify/iconify": "^3.0.1",
|
||||
"@kjgl77/datav-vue3": "^1.4.2",
|
||||
"@vueuse/core": "^9.10.0",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.10",
|
||||
"@zxcvbn-ts/core": "^2.1.0",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.1.3",
|
||||
"clipboard": "^2.0.11",
|
||||
"consola": "^2.15.3",
|
||||
"echarts": "^5.4.0",
|
||||
"echarts-wordcloud": "^2.0.0",
|
||||
"element-plus": "2.2.21",
|
||||
"axios": "^1.2.2",
|
||||
"echarts": "^5.4.1",
|
||||
"echarts-wordcloud": "^2.1.0",
|
||||
"element-plus": "2.2.28",
|
||||
"intro.js": "^6.0.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mitt": "^3.0.0",
|
||||
"mockjs": "^1.1.0",
|
||||
"moment": "^2.29.4",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.0.23",
|
||||
"pinia-plugin-persist": "^1.0.0",
|
||||
"pinia": "^2.0.29",
|
||||
"qrcode": "^1.5.1",
|
||||
"qs": "^6.11.0",
|
||||
"terser": "^5.16.1",
|
||||
"url": "^0.11.0",
|
||||
"vue": "3.2.45",
|
||||
"vue-i18n": "9.2.2",
|
||||
"vue-router": "^4.1.6",
|
||||
"vue-types": "^4.2.1",
|
||||
"vue-types": "^5.0.2",
|
||||
"vue3-json-viewer": "^2.2.2",
|
||||
"vuedraggable": "4.1.0",
|
||||
"web-storage-cache": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.2.0",
|
||||
"@commitlint/config-conventional": "^17.2.0",
|
||||
"@iconify/json": "^2.1.139",
|
||||
"@intlify/vite-plugin-vue-i18n": "^6.0.3",
|
||||
"@commitlint/cli": "^17.4.2",
|
||||
"@commitlint/config-conventional": "^17.4.2",
|
||||
"@iconify/json": "^2.2.7",
|
||||
"@intlify/unplugin-vue-i18n": "^0.8.1",
|
||||
"@purge-icons/generated": "^0.9.0",
|
||||
"@types/intro.js": "^5.1.0",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/qrcode": "^1.5.0",
|
||||
"@types/qs": "^6.9.7",
|
||||
"@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.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.48.1",
|
||||
"@typescript-eslint/parser": "^5.48.1",
|
||||
"@vitejs/plugin-legacy": "^3.0.1",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"@vitejs/plugin-vue-jsx": "^3.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"eslint": "^8.27.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-define-config": "^1.12.0",
|
||||
"consola": "^2.15.3",
|
||||
"eslint": "^8.32.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-define-config": "^1.14.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-vue": "^9.7.0",
|
||||
"husky": "^8.0.2",
|
||||
"eslint-plugin-vue": "^9.9.0",
|
||||
"husky": "^8.0.3",
|
||||
"less": "^4.1.3",
|
||||
"lint-staged": "^13.0.3",
|
||||
"lint-staged": "^13.1.0",
|
||||
"plop": "^3.1.1",
|
||||
"postcss": "^8.4.19",
|
||||
"postcss": "^8.4.21",
|
||||
"postcss-html": "^1.5.0",
|
||||
"postcss-less": "^6.0.0",
|
||||
"prettier": "^2.7.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "^3.3.0",
|
||||
"stylelint": "^14.15.0",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^4.0.7",
|
||||
"rollup": "^3.10.0",
|
||||
"stylelint": "^14.16.1",
|
||||
"stylelint-config-html": "^1.1.0",
|
||||
"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.9.3",
|
||||
"unplugin-vue-macros": "^0.16.3",
|
||||
"vite": "3.2.4",
|
||||
"stylelint-order": "^6.0.1",
|
||||
"terser": "^5.16.1",
|
||||
"typescript": "4.9.4",
|
||||
"unplugin-vue-define-options": "^1.1.4",
|
||||
"vite": "4.0.4",
|
||||
"vite-plugin-ejs": "^1.6.4",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vite-plugin-purge-icons": "^0.9.1",
|
||||
"vite-plugin-progress": "^0.0.6",
|
||||
"vite-plugin-purge-icons": "^0.9.2",
|
||||
"vite-plugin-style-import": "2.0.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vite-plugin-windicss": "^1.8.8",
|
||||
"vue-tsc": "^1.0.9",
|
||||
"vite-plugin-windicss": "^1.8.10",
|
||||
"vue-tsc": "^1.0.24",
|
||||
"windicss": "^3.5.6",
|
||||
"windicss-analysis": "^0.3.5"
|
||||
},
|
||||
|
@ -47,7 +47,7 @@ const { wsCache } = useCache()
|
||||
|
||||
// 根据浏览器当前主题设置系统主题色
|
||||
const setDefaultTheme = () => {
|
||||
if (wsCache.get('isDark')) {
|
||||
if (wsCache.get('isDark') !== null) {
|
||||
appStore.setIsDark(wsCache.get('isDark'))
|
||||
return
|
||||
}
|
||||
@ -68,7 +68,7 @@ setDefaultTheme()
|
||||
@prefix-cls: ~'@{namespace}-app';
|
||||
|
||||
.size {
|
||||
width: 100%;
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ const { variables } = useDesign()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const props = defineProps({
|
||||
size: propTypes.oneOf<ElementPlusSize[]>(['default', 'small', 'large']).def('default')
|
||||
size: propTypes.oneOf<ElementPlusSize>(['default', 'small', 'large']).def('default')
|
||||
})
|
||||
|
||||
provide('configGlobal', props)
|
||||
|
@ -23,7 +23,7 @@ const props = defineProps({
|
||||
default: () => []
|
||||
},
|
||||
data: {
|
||||
type: Object as PropType<Recordable>,
|
||||
type: Object as PropType<any>,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
@ -50,6 +50,7 @@ watch(
|
||||
)
|
||||
|
||||
const dialogStyle = computed(() => {
|
||||
console.log(unref(dialogHeight))
|
||||
return {
|
||||
height: unref(dialogHeight)
|
||||
}
|
||||
@ -63,6 +64,7 @@ const dialogStyle = computed(() => {
|
||||
destroy-on-close
|
||||
lock-scroll
|
||||
draggable
|
||||
align-center
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<template #header>
|
||||
|
@ -57,6 +57,7 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<router-link
|
||||
:class="[
|
||||
prefixCls,
|
||||
@ -84,4 +85,5 @@ watch(
|
||||
{{ title }}
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -137,7 +137,7 @@ const moveToCurrentTag = async () => {
|
||||
const tagLinksRefs = useTemplateRefsList<RouterLinkProps>()
|
||||
|
||||
const moveToTarget = (currentTag: RouteLocationNormalizedLoaded) => {
|
||||
const wrap$ = unref(scrollbarRef)?.wrap$
|
||||
const wrap$ = unref(scrollbarRef)?.wrapRef
|
||||
let firstTag: Nullable<RouterLinkProps> = null
|
||||
let lastTag: Nullable<RouterLinkProps> = null
|
||||
|
||||
@ -233,7 +233,7 @@ const scroll = ({ scrollLeft }) => {
|
||||
|
||||
// 移动到某个位置
|
||||
const move = (to: number) => {
|
||||
const wrap$ = unref(scrollbarRef)?.wrap$
|
||||
const wrap$ = unref(scrollbarRef)?.wrapRef
|
||||
const { start } = useScrollTo({
|
||||
el: wrap$!,
|
||||
position: 'scrollLeft',
|
||||
|
@ -13,7 +13,7 @@ const { t } = useI18n()
|
||||
|
||||
const authStore = useAuthStoreWithOut()
|
||||
|
||||
const { replace, push } = useRouter()
|
||||
const { push } = useRouter()
|
||||
|
||||
const loginOut = () => {
|
||||
ElMessageBox.confirm(t('common.loginOutMessage'), t('common.reminder'), {
|
||||
|
@ -8,6 +8,7 @@ const TIME_AGO_MESSAGE_MAP: {
|
||||
} = {
|
||||
'zh-CN': {
|
||||
justNow: '刚刚',
|
||||
invalid: '无效时间',
|
||||
past: (n) => (n.match(/\d/) ? `${n}前` : n),
|
||||
future: (n) => (n.match(/\d/) ? `${n}后` : n),
|
||||
month: (n, past) => (n === 1 ? (past ? '上个月' : '下个月') : `${n} 个月`),
|
||||
@ -20,6 +21,7 @@ const TIME_AGO_MESSAGE_MAP: {
|
||||
},
|
||||
en: {
|
||||
justNow: '刚刚',
|
||||
invalid: 'Invalid Date',
|
||||
past: (n) => (n.match(/\d/) ? `${n} ago` : n),
|
||||
future: (n) => (n.match(/\d/) ? `in ${n}` : n),
|
||||
month: (n, past) =>
|
||||
|
@ -1,11 +1,8 @@
|
||||
import type { App } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import piniaPluginPersist from 'pinia-plugin-persist' // 持久化存储
|
||||
|
||||
const store = createPinia()
|
||||
|
||||
store.use(piniaPluginPersist)
|
||||
|
||||
export const setupStore = (app: App<Element>) => {
|
||||
app.use(store)
|
||||
}
|
||||
|
@ -35,10 +35,6 @@ export const useAuthStore = defineStore('auth', {
|
||||
isUser: false
|
||||
}
|
||||
},
|
||||
persist: {
|
||||
// 开启持久化存储
|
||||
enabled: true
|
||||
},
|
||||
getters: {
|
||||
getUser(): UserState {
|
||||
return this.user
|
||||
|
@ -10,10 +10,6 @@ export const useDictStore = defineStore('dict', {
|
||||
state: (): DictState => ({
|
||||
dictObj: {}
|
||||
}),
|
||||
persist: {
|
||||
// 开启持久化存储
|
||||
enabled: true
|
||||
},
|
||||
getters: {},
|
||||
actions: {
|
||||
async getDictObj(dictTypes: string[]) {
|
||||
|
@ -18,10 +18,6 @@ export const usePermissionStore = defineStore('permission', {
|
||||
isAddRouters: false,
|
||||
menuTabRouters: []
|
||||
}),
|
||||
persist: {
|
||||
// 开启持久化存储
|
||||
enabled: true
|
||||
},
|
||||
getters: {
|
||||
getRouters(): AppRouteRecordRaw[] {
|
||||
return this.routers
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { EChartsOption } from 'echarts'
|
||||
import { EChartsOption as EChartsWordOption } from 'echarts-wordcloud'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
export const lineOptions: EChartsOption = {
|
||||
export const lineOptions = {
|
||||
title: {
|
||||
text: t('analysis.monthlySales'),
|
||||
left: 'center'
|
||||
@ -185,7 +184,7 @@ export const radarOption: EChartsOption = {
|
||||
]
|
||||
}
|
||||
|
||||
export const wordOptions: EChartsWordOption = {
|
||||
export const wordOptions = {
|
||||
series: [
|
||||
{
|
||||
type: 'wordCloud',
|
||||
|
@ -49,13 +49,21 @@ const { setValues, setValue } = methods
|
||||
|
||||
// 上传成功的钩子函数
|
||||
const handleICOUploadSuccess: UploadProps['onSuccess'] = (response) => {
|
||||
if (response.code === 200) {
|
||||
setValue('web_ico', response.data.remote_path)
|
||||
setValue('web_ico_local_path', response.data.local_path)
|
||||
} else {
|
||||
ElMessage.error(response.message)
|
||||
}
|
||||
}
|
||||
|
||||
// 上传成功的钩子函数
|
||||
const handleLogoUploadSuccess: UploadProps['onSuccess'] = (response) => {
|
||||
if (response.code === 200) {
|
||||
setValue('web_logo', response.data.remote_path)
|
||||
} else {
|
||||
ElMessage.error(response.message)
|
||||
}
|
||||
}
|
||||
|
||||
let formData = ref({} as Recordable)
|
||||
|
@ -24,13 +24,13 @@
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
"types": [
|
||||
"@intlify/vite-plugin-vue-i18n/client",
|
||||
"@intlify/unplugin-vue-i18n/types",
|
||||
"vite/client",
|
||||
"element-plus/global",
|
||||
"@types/intro.js",
|
||||
"@types/qrcode",
|
||||
"vite-plugin-svg-icons/client",
|
||||
"unplugin-vue-macros/macros-global"
|
||||
"unplugin-vue-define-options/macros-global"
|
||||
],
|
||||
"typeRoots": ["./node_modules/@types/", "./types"]
|
||||
},
|
||||
|
@ -3,14 +3,14 @@ import { loadEnv } from 'vite'
|
||||
import type { UserConfig, ConfigEnv } from 'vite'
|
||||
import Vue from '@vitejs/plugin-vue'
|
||||
import WindiCSS from 'vite-plugin-windicss'
|
||||
import progress from 'vite-plugin-progress'
|
||||
import VueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import EslintPlugin from 'vite-plugin-eslint'
|
||||
import VueI18n from '@intlify/vite-plugin-vue-i18n'
|
||||
import { createStyleImportPlugin, ElementPlusResolve } from 'vite-plugin-style-import'
|
||||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
|
||||
import PurgeIcons from 'vite-plugin-purge-icons'
|
||||
import { viteMockServe } from 'vite-plugin-mock'
|
||||
import VueMarcos from 'unplugin-vue-macros/vite'
|
||||
import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite"
|
||||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
|
||||
import DefineOptions from "unplugin-vue-define-options/vite"
|
||||
import { createStyleImportPlugin, ElementPlusResolve } from 'vite-plugin-style-import'
|
||||
import { ViteEjsPlugin } from "vite-plugin-ejs"
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
@ -34,6 +34,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
|
||||
Vue(),
|
||||
VueJsx(),
|
||||
WindiCSS(),
|
||||
progress(),
|
||||
createStyleImportPlugin({
|
||||
resolves: [ElementPlusResolve()],
|
||||
libs: [{
|
||||
@ -48,7 +49,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
|
||||
cache: false,
|
||||
include: ['src/**/*.vue', 'src/**/*.ts', 'src/**/*.tsx'] // 检查的文件
|
||||
}),
|
||||
VueI18n({
|
||||
VueI18nPlugin({
|
||||
runtimeOnly: true,
|
||||
compositionOnly: true,
|
||||
include: [resolve(__dirname, 'src/locales/**')]
|
||||
@ -70,7 +71,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
|
||||
// setupProdMockServer()
|
||||
// `
|
||||
// }),
|
||||
VueMarcos(),
|
||||
DefineOptions(),
|
||||
ViteEjsPlugin({
|
||||
title: env.VITE_APP_TITLE
|
||||
})
|
||||
|
@ -11,7 +11,7 @@ from fastapi.security import OAuth2PasswordBearer
|
||||
"""
|
||||
系统版本
|
||||
"""
|
||||
VERSION = "1.4.2"
|
||||
VERSION = "1.4.3"
|
||||
|
||||
"""安全警告: 不要在生产中打开调试运行!"""
|
||||
DEBUG = True
|
||||
|
@ -7,7 +7,6 @@
|
||||
# @desc : 增删改查
|
||||
|
||||
from typing import List
|
||||
|
||||
from aioredis import Redis
|
||||
from fastapi import UploadFile
|
||||
from core.exception import CustomException
|
||||
@ -16,11 +15,11 @@ from sqlalchemy import select
|
||||
from core.crud import DalBase
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from core.validator import vali_telephone
|
||||
from utils.aliyun_oss import AliyunOSS, BucketConf
|
||||
from utils.file.aliyun_oss import AliyunOSS, BucketConf
|
||||
from utils.file.file_manage import FileManage
|
||||
from utils.aliyun_sms import AliyunSMS
|
||||
from utils.excel.import_manage import ImportManage, FieldType
|
||||
from utils.excel.write_xlsx import WriteXlsx
|
||||
from utils.file_manage import FileManage
|
||||
from .params import UserParams
|
||||
from utils.tools import test_password
|
||||
from . import models, schemas
|
||||
@ -214,8 +213,10 @@ class UserDal(DalBase):
|
||||
"""
|
||||
更新当前用户头像
|
||||
"""
|
||||
manage = FileManage(file, "avatar")
|
||||
result = await AliyunOSS(BucketConf(**settings.ALIYUN_OSS)).upload_image(manage.path, file)
|
||||
test = await FileManage.save_tmp_file(file)
|
||||
print(test)
|
||||
await file.seek(0)
|
||||
result = await AliyunOSS(BucketConf(**settings.ALIYUN_OSS)).upload_image("avatar", file)
|
||||
if not result:
|
||||
raise CustomException(msg="上传失败", code=status.HTTP_ERROR)
|
||||
user.avatar = result
|
||||
|
@ -11,6 +11,7 @@
|
||||
"""
|
||||
from fastapi import Depends
|
||||
from core.dependencies import Paging, QueryParams
|
||||
from typing import Union
|
||||
|
||||
|
||||
class UserParams(QueryParams):
|
||||
@ -18,7 +19,8 @@ class UserParams(QueryParams):
|
||||
列表分页
|
||||
"""
|
||||
|
||||
def __init__(self, name: str = None, telephone: str = None, is_active: bool = None, params: Paging = Depends()):
|
||||
def __init__(self, name: str = None, telephone: str = None, is_active: Union[bool, str] = None,
|
||||
params: Paging = Depends()):
|
||||
super().__init__(params)
|
||||
self.name = ("like", name)
|
||||
self.telephone = ("like", telephone)
|
||||
|
@ -13,9 +13,8 @@ import os
|
||||
from typing import List, Union
|
||||
from sqlalchemy import select, update
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from application.settings import STATIC_ROOT
|
||||
from utils.file_manage import FileManage
|
||||
from utils.file.file_manage import FileManage
|
||||
from . import models, schemas
|
||||
from core.crud import DalBase
|
||||
|
||||
|
@ -6,17 +6,17 @@
|
||||
# @desc : 主要接口文件
|
||||
|
||||
# UploadFile 库依赖:pip install python-multipart
|
||||
from typing import Optional, List
|
||||
from fastapi import APIRouter, Depends, Query, Body, UploadFile, Request, Form
|
||||
from typing import List
|
||||
from fastapi import APIRouter, Depends, Body, UploadFile, Request, Form
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from application.settings import ALIYUN_OSS
|
||||
from core.database import db_getter
|
||||
from utils.aliyun_oss import AliyunOSS, BucketConf
|
||||
from utils.file.aliyun_oss import AliyunOSS, BucketConf
|
||||
from utils.aliyun_sms import AliyunSMS
|
||||
from utils.file_manage import FileManage
|
||||
from utils.file.file_manage import FileManage
|
||||
from utils.response import SuccessResponse, ErrorResponse
|
||||
from . import schemas, crud, models
|
||||
from core.dependencies import Paging, IdList
|
||||
from . import schemas, crud
|
||||
from core.dependencies import IdList
|
||||
from apps.vadmin.auth.utils.current import login_auth, Auth
|
||||
from .params import DictTypeParams, DictDetailParams
|
||||
|
||||
@ -107,8 +107,7 @@ async def get_dict_detail(data_id: int, auth: Auth = Depends(login_auth)):
|
||||
###########################################################
|
||||
@app.post("/upload/image/to/oss/", summary="上传图片到阿里云OSS")
|
||||
async def upload_image_to_oss(file: UploadFile, path: str = Form(...)):
|
||||
manage = FileManage(file, path)
|
||||
result = await AliyunOSS(BucketConf(**ALIYUN_OSS)).upload_image(manage.path, file)
|
||||
result = await AliyunOSS(BucketConf(**ALIYUN_OSS)).upload_image(path, file)
|
||||
if not result:
|
||||
return ErrorResponse(msg="上传失败")
|
||||
return SuccessResponse(result)
|
||||
|
@ -23,12 +23,13 @@ from core.exception import register_exception
|
||||
import typer
|
||||
from scripts.initialize.initialize import InitializeData, Environment
|
||||
import asyncio
|
||||
from scripts.create_app.main import CreateApp
|
||||
|
||||
|
||||
shell_app = typer.Typer()
|
||||
|
||||
|
||||
def create_app():
|
||||
def init_app():
|
||||
"""
|
||||
启动项目
|
||||
|
||||
@ -83,7 +84,7 @@ def run():
|
||||
"""
|
||||
启动项目
|
||||
"""
|
||||
uvicorn.run(app='main:create_app', host="0.0.0.0", port=9000)
|
||||
uvicorn.run(app='main:init_app', host="0.0.0.0", port=9000)
|
||||
|
||||
|
||||
@shell_app.command()
|
||||
@ -109,5 +110,17 @@ def migrate(env: Environment = Environment.pro):
|
||||
InitializeData().migrate_model(env)
|
||||
|
||||
|
||||
@shell_app.command()
|
||||
def create_app(path: str):
|
||||
"""
|
||||
自动创建初始化 APP 结构
|
||||
|
||||
@params path: app 路径,根目录为apps,填写apps后面路径即可,例子:vadmin/auth
|
||||
"""
|
||||
print(f"开始创建并初始化 {path} APP")
|
||||
app = CreateApp(path)
|
||||
app.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
shell_app()
|
||||
|
7
kinit-api/scripts/create_app/__init__.py
Normal file
7
kinit-api/scripts/create_app/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @version : 1.0
|
||||
# @Creaet Time : 2022/12/9 15:26
|
||||
# @File : __init__.py
|
||||
# @IDE : PyCharm
|
||||
# @desc : 简要说明
|
100
kinit-api/scripts/create_app/main.py
Normal file
100
kinit-api/scripts/create_app/main.py
Normal file
@ -0,0 +1,100 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @version : 1.0
|
||||
# @Creaet Time : 2022/12/9 15:27
|
||||
# @File : main.py
|
||||
# @IDE : PyCharm
|
||||
# @desc : 简要说明
|
||||
import datetime
|
||||
import os.path
|
||||
|
||||
from application.settings import BASE_DIR
|
||||
|
||||
|
||||
class CreateApp:
|
||||
|
||||
APPS_ROOT = os.path.join(BASE_DIR, "apps")
|
||||
SCRIPT_DIR = os.path.join(BASE_DIR, 'scripts', 'create_app')
|
||||
|
||||
def __init__(self, path: str):
|
||||
"""
|
||||
@params path: app 路径,根目录为apps,填写apps后面路径即可,例子:vadmin/auth
|
||||
"""
|
||||
self.app_path = os.path.join(self.APPS_ROOT, path)
|
||||
self.path = path
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
自动创建初始化 APP 结构,如何该路径已经存在,则不执行
|
||||
"""
|
||||
if self.exist(self.app_path):
|
||||
print(f"{self.app_path} 已经存在,无法自动创建,请删除后,重新执行。")
|
||||
return False
|
||||
print("开始生成 App 目录:", self.path)
|
||||
path = []
|
||||
for item in self.path.split("/"):
|
||||
path.append(item)
|
||||
self.create_pag(os.path.join(self.APPS_ROOT, *path))
|
||||
self.create_pag(os.path.join(self.app_path, "models"))
|
||||
self.create_pag(os.path.join(self.app_path, "params"))
|
||||
self.create_pag(os.path.join(self.app_path, "schemas"))
|
||||
self.generate_file("views.py")
|
||||
self.generate_file("crud.py")
|
||||
print("App 目录生成结束", self.app_path)
|
||||
|
||||
def create_pag(self, path: str) -> None:
|
||||
"""
|
||||
创建 python 包
|
||||
|
||||
@params path: 绝对路径
|
||||
"""
|
||||
if self.exist(path):
|
||||
return
|
||||
os.makedirs(path)
|
||||
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
params = {
|
||||
"create_datetime": now,
|
||||
"filename": "__init__.py",
|
||||
"desc": "初始化文件"
|
||||
}
|
||||
self.create_file(os.path.join(path, "__init__.py"), "init.py", **params)
|
||||
|
||||
def generate_file(self, name: str) -> None:
|
||||
"""
|
||||
创建文件
|
||||
"""
|
||||
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
params = {
|
||||
"create_datetime": now,
|
||||
}
|
||||
self.create_file(os.path.join(self.app_path, name), name, **params)
|
||||
|
||||
def create_file(self, filepath: str, name: str, **kwargs):
|
||||
"""
|
||||
创建文件
|
||||
"""
|
||||
with open(filepath, "w", encoding="utf-8") as f:
|
||||
content = self.__get_template(name)
|
||||
f.write(content.format(**kwargs))
|
||||
|
||||
@classmethod
|
||||
def exist(cls, path) -> bool:
|
||||
"""
|
||||
判断路径是否已经存在
|
||||
"""
|
||||
return os.path.exists(path)
|
||||
|
||||
def __get_template(self, name: str) -> str:
|
||||
"""
|
||||
获取模板内容
|
||||
"""
|
||||
template = open(os.path.join(self.SCRIPT_DIR, "template", name), 'r')
|
||||
content = template.read()
|
||||
template.close()
|
||||
return content
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = CreateApp("test/vv")
|
||||
app.run()
|
||||
|
7
kinit-api/scripts/create_app/template/crud.py
Normal file
7
kinit-api/scripts/create_app/template/crud.py
Normal file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @version : 1.0
|
||||
# @Creaet Time : {create_datetime}
|
||||
# @File : crud.py
|
||||
# @IDE : PyCharm
|
||||
# @desc :
|
7
kinit-api/scripts/create_app/template/init.py
Normal file
7
kinit-api/scripts/create_app/template/init.py
Normal file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @version : 1.0
|
||||
# @Creaet Time : {create_datetime}
|
||||
# @File : {filename}
|
||||
# @IDE : PyCharm
|
||||
# @desc : {desc}
|
18
kinit-api/scripts/create_app/template/views.py
Normal file
18
kinit-api/scripts/create_app/template/views.py
Normal file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @version : 1.0
|
||||
# @Creaet Time : {create_datetime}
|
||||
# @File : views.py
|
||||
# @IDE : PyCharm
|
||||
# @desc :
|
||||
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from utils.response import SuccessResponse
|
||||
from . import schemas, crud, models
|
||||
from core.dependencies import IdList
|
||||
from apps.vadmin.auth.utils.current import login_auth, Auth
|
||||
|
||||
app = APIRouter()
|
||||
|
||||
|
Binary file not shown.
327
kinit-api/scripts/initialize/data/test_kinit.sql
Normal file
327
kinit-api/scripts/initialize/data/test_kinit.sql
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : aliyun-mysql
|
||||
Source Server Type : MySQL
|
||||
Source Server Version : 80018 (8.0.18)
|
||||
Source Host : rm-bp181adf0phw2o0r05o.mysql.rds.aliyuncs.com:3306
|
||||
Source Schema : test_kinit
|
||||
|
||||
Target Server Type : MySQL
|
||||
Target Server Version : 80018 (8.0.18)
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 23/11/2022 22:25:06
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for alembic_version
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `alembic_version`;
|
||||
CREATE TABLE `alembic_version` (
|
||||
`version_num` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
|
||||
PRIMARY KEY (`version_num`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of alembic_version
|
||||
-- ----------------------------
|
||||
INSERT INTO `alembic_version` VALUES ('');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for vadmin_auth_menu
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `vadmin_auth_menu`;
|
||||
CREATE TABLE `vadmin_auth_menu` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`create_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`icon` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '菜单图标',
|
||||
`component` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '前端组件地址',
|
||||
`path` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '前端路由地址',
|
||||
`hidden` tinyint(1) NULL DEFAULT NULL COMMENT '是否隐藏',
|
||||
`menu_type` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '菜单类型',
|
||||
`parent_id` int(11) NULL DEFAULT NULL COMMENT '父菜单',
|
||||
`perms` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '权限标识',
|
||||
`order` int(11) NULL DEFAULT NULL COMMENT '排序',
|
||||
`disabled` tinyint(1) NULL DEFAULT NULL COMMENT '是否禁用',
|
||||
`redirect` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '重定向地址',
|
||||
`noCache` tinyint(1) NULL DEFAULT NULL COMMENT '如果设置为true,则不会被 <keep-alive> 缓存(默认 false)',
|
||||
`breadcrumb` tinyint(1) NULL DEFAULT NULL COMMENT '如果设置为false,则不会在breadcrumb面包屑中显示(默认 true)',
|
||||
`affix` tinyint(1) NULL DEFAULT NULL COMMENT '如果设置为true,则会一直固定在tag项中(默认 false)',
|
||||
`noTagsView` tinyint(1) NULL DEFAULT NULL COMMENT '如果设置为true,则不会出现在tag中(默认 false)',
|
||||
`canTo` tinyint(1) NULL DEFAULT NULL COMMENT '设置为true即使hidden为true,也依然可以进行路由跳转(默认 false)',
|
||||
`title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '名称',
|
||||
`delete_datetime` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
||||
`alwaysShow` tinyint(1) NULL DEFAULT NULL COMMENT '当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式,\n 只有一个时,会将那个子路由当做根路由显示在侧边栏,若你想不管路由下面的 children 声明的个数都显示你的根路由,\n 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由(默认 true)',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_auth_menu_id`(`id` ASC) USING BTREE,
|
||||
INDEX `parent_id`(`parent_id` ASC) USING BTREE,
|
||||
INDEX `ix_vadmin_auth_menu_perms`(`perms` ASC) USING BTREE,
|
||||
INDEX `ix_vadmin_auth_menu_title`(`title` ASC) USING BTREE,
|
||||
CONSTRAINT `vadmin_auth_menu_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `vadmin_auth_menu` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 29 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '菜单表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of vadmin_auth_menu
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for vadmin_auth_role
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `vadmin_auth_role`;
|
||||
CREATE TABLE `vadmin_auth_role` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`create_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '名称',
|
||||
`role_key` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '权限字符',
|
||||
`desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '描述',
|
||||
`is_admin` tinyint(1) NULL DEFAULT NULL COMMENT '是否为超级角色',
|
||||
`order` int(11) NULL DEFAULT NULL COMMENT '排序',
|
||||
`disabled` tinyint(1) NULL DEFAULT NULL COMMENT '是否禁用',
|
||||
`delete_datetime` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_auth_role_id`(`id` ASC) USING BTREE,
|
||||
INDEX `ix_vadmin_auth_role_name`(`name` ASC) USING BTREE,
|
||||
INDEX `ix_vadmin_auth_role_role_key`(`role_key` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '角色表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of vadmin_auth_role
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for vadmin_auth_role_menus
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `vadmin_auth_role_menus`;
|
||||
CREATE TABLE `vadmin_auth_role_menus` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`role_id` int(11) NOT NULL,
|
||||
`menu_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`, `role_id`, `menu_id`) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_auth_role_menus_id`(`id` ASC) USING BTREE,
|
||||
INDEX `menu_id`(`menu_id` ASC) USING BTREE,
|
||||
INDEX `role_id`(`role_id` ASC) USING BTREE,
|
||||
CONSTRAINT `vadmin_auth_role_menus_ibfk_1` FOREIGN KEY (`menu_id`) REFERENCES `vadmin_auth_menu` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT,
|
||||
CONSTRAINT `vadmin_auth_role_menus_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `vadmin_auth_role` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 47 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of vadmin_auth_role_menus
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for vadmin_auth_user
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `vadmin_auth_user`;
|
||||
CREATE TABLE `vadmin_auth_user` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`create_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`telephone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '手机号',
|
||||
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '姓名',
|
||||
`nickname` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '昵称',
|
||||
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密码',
|
||||
`avatar` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '头像',
|
||||
`gender` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '性别',
|
||||
`is_active` tinyint(1) NULL DEFAULT NULL COMMENT '是否可用',
|
||||
`is_cancel` tinyint(1) NULL DEFAULT NULL COMMENT '是否注销',
|
||||
`is_reset_password` tinyint(1) NULL DEFAULT NULL COMMENT '是否已经重置密码,没有重置的,登陆系统后必须重置密码',
|
||||
`last_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '最后一次登录IP',
|
||||
`last_login` datetime NULL DEFAULT NULL COMMENT '最近一次登录时间',
|
||||
`delete_datetime` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_auth_user_id`(`id` ASC) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_auth_user_telephone`(`telephone` ASC) USING BTREE,
|
||||
INDEX `ix_vadmin_auth_user_name`(`name` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 27 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of vadmin_auth_user
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for vadmin_auth_user_roles
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `vadmin_auth_user_roles`;
|
||||
CREATE TABLE `vadmin_auth_user_roles` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_id` int(11) NOT NULL,
|
||||
`role_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`, `user_id`, `role_id`) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_auth_user_roles_id`(`id` ASC) USING BTREE,
|
||||
INDEX `role_id`(`role_id` ASC) USING BTREE,
|
||||
INDEX `user_id`(`user_id` ASC) USING BTREE,
|
||||
CONSTRAINT `vadmin_auth_user_roles_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `vadmin_auth_role` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT,
|
||||
CONSTRAINT `vadmin_auth_user_roles_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `vadmin_auth_user` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of vadmin_auth_user_roles
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for vadmin_record_login
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `vadmin_record_login`;
|
||||
CREATE TABLE `vadmin_record_login` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`create_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`telephone` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '手机号',
|
||||
`status` tinyint(1) NULL DEFAULT NULL COMMENT '是否登录成功',
|
||||
`ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '登陆地址',
|
||||
`address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '登陆地点',
|
||||
`browser` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '浏览器',
|
||||
`system` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '操作系统',
|
||||
`response` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '响应信息',
|
||||
`request` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '请求信息',
|
||||
`delete_datetime` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
||||
`country` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '国家',
|
||||
`province` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '县',
|
||||
`city` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '城市',
|
||||
`county` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '区/县',
|
||||
`operator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '运营商',
|
||||
`postal_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '邮政编码',
|
||||
`area_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '地区区号',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_record_login_id`(`id` ASC) USING BTREE,
|
||||
INDEX `ix_vadmin_record_login_telephone`(`telephone` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 531 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '登录记录表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of vadmin_record_login
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for vadmin_record_sms_send
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `vadmin_record_sms_send`;
|
||||
CREATE TABLE `vadmin_record_sms_send` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`create_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`user_id` int(11) NULL DEFAULT NULL COMMENT '操作人',
|
||||
`status` tinyint(1) NULL DEFAULT NULL COMMENT '发送状态',
|
||||
`content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '发送内容',
|
||||
`telephone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '目标手机号',
|
||||
`desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '失败描述',
|
||||
`scene` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '发送场景',
|
||||
`delete_datetime` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_record_sms_send_id`(`id` ASC) USING BTREE,
|
||||
INDEX `user_id`(`user_id` ASC) USING BTREE,
|
||||
CONSTRAINT `vadmin_record_sms_send_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `vadmin_auth_user` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '短信发送记录表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of vadmin_record_sms_send
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for vadmin_system_dict_details
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `vadmin_system_dict_details`;
|
||||
CREATE TABLE `vadmin_system_dict_details` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`create_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`is_default` tinyint(1) NULL DEFAULT NULL COMMENT '是否默认',
|
||||
`dict_type_id` int(11) NULL DEFAULT NULL COMMENT '关联字典类型',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
|
||||
`disabled` tinyint(1) NULL DEFAULT NULL COMMENT '字典状态,是否禁用',
|
||||
`order` int(11) NULL DEFAULT NULL COMMENT '字典排序',
|
||||
`label` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '字典标签',
|
||||
`value` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '字典键值',
|
||||
`delete_datetime` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_system_dict_details_id`(`id` ASC) USING BTREE,
|
||||
INDEX `dict_type_id`(`dict_type_id` ASC) USING BTREE,
|
||||
INDEX `ix_vadmin_system_dict_details_label`(`label` ASC) USING BTREE,
|
||||
INDEX `ix_vadmin_system_dict_details_value`(`value` ASC) USING BTREE,
|
||||
CONSTRAINT `vadmin_system_dict_details_ibfk_1` FOREIGN KEY (`dict_type_id`) REFERENCES `vadmin_system_dict_type` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '字典详情表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of vadmin_system_dict_details
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for vadmin_system_dict_type
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `vadmin_system_dict_type`;
|
||||
CREATE TABLE `vadmin_system_dict_type` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`create_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`dict_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '字典名称',
|
||||
`dict_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '字典类型',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',
|
||||
`disabled` tinyint(1) NULL DEFAULT NULL COMMENT '字典状态,是否禁用',
|
||||
`delete_datetime` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_system_dict_type_id`(`id` ASC) USING BTREE,
|
||||
INDEX `ix_vadmin_system_dict_type_dict_name`(`dict_name` ASC) USING BTREE,
|
||||
INDEX `ix_vadmin_system_dict_type_dict_type`(`dict_type` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '字典类型表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of vadmin_system_dict_type
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for vadmin_system_settings
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `vadmin_system_settings`;
|
||||
CREATE TABLE `vadmin_system_settings` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`create_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`delete_datetime` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
||||
`config_label` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '配置表标签',
|
||||
`config_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '配置表键',
|
||||
`config_value` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '配置表内容',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注信息',
|
||||
`tab_id` int(11) NULL DEFAULT NULL COMMENT '关联tab标签',
|
||||
`disabled` tinyint(1) NULL DEFAULT NULL COMMENT '是否禁用',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_system_settings_id`(`id` ASC) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_system_settings_config_key`(`config_key` ASC) USING BTREE,
|
||||
INDEX `tab_id`(`tab_id` ASC) USING BTREE,
|
||||
CONSTRAINT `vadmin_system_settings_ibfk_1` FOREIGN KEY (`tab_id`) REFERENCES `vadmin_system_settings_tab` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '系统配置表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of vadmin_system_settings
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for vadmin_system_settings_tab
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `vadmin_system_settings_tab`;
|
||||
CREATE TABLE `vadmin_system_settings_tab` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`create_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_datetime` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`delete_datetime` datetime NULL DEFAULT NULL COMMENT '删除时间',
|
||||
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '标题',
|
||||
`tab_label` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'tab标题',
|
||||
`hidden` tinyint(1) NULL DEFAULT NULL COMMENT '是否隐藏',
|
||||
`classify` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '分类键',
|
||||
`tab_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'tab标识符',
|
||||
`disabled` tinyint(1) NULL DEFAULT NULL COMMENT '是否禁用',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_system_settings_tab_id`(`id` ASC) USING BTREE,
|
||||
UNIQUE INDEX `ix_vadmin_system_settings_tab_tab_name`(`tab_name` ASC) USING BTREE,
|
||||
INDEX `ix_vadmin_system_settings_tab_classify`(`classify` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '系统配置分类表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of vadmin_system_settings_tab
|
||||
-- ----------------------------
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
BIN
kinit-api/scripts/initialize/data/vadmin_auth_role.xlsx
Normal file
BIN
kinit-api/scripts/initialize/data/vadmin_auth_role.xlsx
Normal file
Binary file not shown.
BIN
kinit-api/scripts/initialize/data/vadmin_auth_user.xlsx
Normal file
BIN
kinit-api/scripts/initialize/data/vadmin_auth_user.xlsx
Normal file
Binary file not shown.
Binary file not shown.
BIN
kinit-api/scripts/initialize/data/vadmin_system_dict_type.xlsx
Normal file
BIN
kinit-api/scripts/initialize/data/vadmin_system_dict_type.xlsx
Normal file
Binary file not shown.
BIN
kinit-api/scripts/initialize/data/vadmin_system_settings.xlsx
Normal file
BIN
kinit-api/scripts/initialize/data/vadmin_system_settings.xlsx
Normal file
Binary file not shown.
Binary file not shown.
@ -1,53 +0,0 @@
|
||||
import base64
|
||||
from Crypto.Cipher import AES # 安装:pip install pycryptodome
|
||||
|
||||
|
||||
# 密钥(key), 密斯偏移量(iv) CBC模式加密
|
||||
# base64 详解:https://cloud.tencent.com/developer/article/1099008
|
||||
|
||||
_key = '0CoJUm6Qywm6ts68' # 自己密钥
|
||||
|
||||
|
||||
def aes_encrypt(data: str):
|
||||
"""
|
||||
加密
|
||||
"""
|
||||
vi = '0102030405060708'
|
||||
pad = lambda s: s + (16 - len(s) % 16) * chr(16 - len(s) % 16)
|
||||
data = pad(data)
|
||||
# 字符串补位
|
||||
cipher = AES.new(_key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8'))
|
||||
encrypted_bytes = cipher.encrypt(data.encode('utf8'))
|
||||
# 加密后得到的是bytes类型的数据
|
||||
encode_strs = base64.urlsafe_b64encode(encrypted_bytes)
|
||||
# 使用Base64进行编码,返回byte字符串
|
||||
# 对byte字符串按utf-8进行解码
|
||||
return encode_strs.decode('utf8')
|
||||
|
||||
|
||||
def aes_decrypt(data):
|
||||
"""
|
||||
解密
|
||||
"""
|
||||
vi = '0102030405060708'
|
||||
data = data.encode('utf8')
|
||||
encode_bytes = base64.urlsafe_b64decode(data)
|
||||
# 将加密数据转换位bytes类型数据
|
||||
cipher = AES.new(_key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8'))
|
||||
text_decrypted = cipher.decrypt(encode_bytes)
|
||||
unpad = lambda s: s[0:-s[-1]]
|
||||
text_decrypted = unpad(text_decrypted)
|
||||
# 补位
|
||||
text_decrypted = text_decrypted.decode('utf8')
|
||||
return text_decrypted
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
_data = '16658273438153332588-95YEUPJR' # 需要加密的内容
|
||||
|
||||
enctext = aes_encrypt(_data)
|
||||
print(enctext)
|
||||
|
||||
# enctext = "Wzll1oiVs9UKAySY1-xSy_CbrZmelVwyqu8P0CZTrrc="
|
||||
# _text_decrypted = aes_decrypt(_key, enctext)
|
||||
# print(_text_decrypted)
|
@ -10,7 +10,7 @@ from fastapi import UploadFile
|
||||
from core.exception import CustomException
|
||||
from utils import status
|
||||
from .excel_manage import ExcelManage
|
||||
from utils.file_manage import FileManage
|
||||
from utils.file.file_manage import FileManage
|
||||
from .write_xlsx import WriteXlsx
|
||||
from ..tools import list_dict_find
|
||||
from enum import Enum
|
||||
|
7
kinit-api/utils/file/__init__.py
Normal file
7
kinit-api/utils/file/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @version : 1.0
|
||||
# @Creaet Time : 2022/12/12 14:30
|
||||
# @File : __init__.py.py
|
||||
# @IDE : PyCharm
|
||||
# @desc : 简要说明
|
@ -12,8 +12,9 @@ from pydantic import BaseModel
|
||||
import oss2 # 安装依赖库:pip install oss2
|
||||
from oss2.models import PutObjectResult
|
||||
from core.logger import logger
|
||||
from utils.compress.cpressJPG import compress_jpg_png
|
||||
from utils.file_manage import FileManage
|
||||
from utils.file.compress.cpressJPG import compress_jpg_png
|
||||
from utils.file.file_manage import FileManage
|
||||
from utils.file.file_base import FileBase
|
||||
|
||||
|
||||
class BucketConf(BaseModel):
|
||||
@ -24,7 +25,7 @@ class BucketConf(BaseModel):
|
||||
baseUrl: str
|
||||
|
||||
|
||||
class AliyunOSS:
|
||||
class AliyunOSS(FileBase):
|
||||
"""
|
||||
阿里云对象存储
|
||||
|
||||
@ -53,6 +54,7 @@ class AliyunOSS:
|
||||
@param compress: 是否压缩该文件
|
||||
@return: 上传后的文件oss链接
|
||||
"""
|
||||
path = self.generate_path(path, file.filename)
|
||||
if compress:
|
||||
# 压缩图片
|
||||
file_path = await FileManage.save_tmp_file(file)
|
||||
@ -70,20 +72,19 @@ class AliyunOSS:
|
||||
return ""
|
||||
return self.baseUrl + path
|
||||
|
||||
def upload_local_file(self, path: str, filename: str) -> str:
|
||||
async def upload_file(self, path: str, file: UploadFile) -> str:
|
||||
"""
|
||||
上传本地文件
|
||||
上传文件
|
||||
|
||||
@param path: path由包含文件后缀,不包含Bucket名称组成的Object完整路径,例如abc/efg/123.jpg。
|
||||
@param filename: 本地文件路径
|
||||
@param file: 文件对象
|
||||
@return: 上传后的文件oss链接
|
||||
"""
|
||||
with open(filename, "rb") as f:
|
||||
result = self.bucket.put_object(path, f.read())
|
||||
path = self.generate_path(path, file.filename)
|
||||
file_data = await file.read()
|
||||
result = self.bucket.put_object(path, file_data)
|
||||
assert isinstance(result, PutObjectResult)
|
||||
if result.status != 200:
|
||||
logger.error(f"本地文件上传到OSS失败,状态码:{result.status}")
|
||||
print("本地文件上传路径", path)
|
||||
print(f"本地文件上传到OSS失败,状态码:{result.status}")
|
||||
logger.error(f"文件上传到OSS失败,状态码:{result.status}")
|
||||
return ""
|
||||
return self.baseUrl + path
|
@ -1,5 +1,5 @@
|
||||
from PIL import Image, ExifTags # 安装依赖包:pip3 install pillow
|
||||
from utils.compress import dynamic_quality
|
||||
from utils.file.compress import dynamic_quality
|
||||
import os
|
||||
import time
|
||||
|
67
kinit-api/utils/file/file_base.py
Normal file
67
kinit-api/utils/file/file_base.py
Normal file
@ -0,0 +1,67 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @version : 1.0
|
||||
# @Creaet Time : 2022/12/12 14:31
|
||||
# @File : file_base.py
|
||||
# @IDE : PyCharm
|
||||
# @desc : 简要说明
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import uuid
|
||||
from fastapi import UploadFile
|
||||
from core.exception import CustomException
|
||||
from utils import status
|
||||
from typing import Union
|
||||
|
||||
|
||||
class FileBase:
|
||||
|
||||
IMAGE_ACCEPT = ["image/png", "image/jpeg", "image/gif", "image/x-icon"]
|
||||
VIDEO_ACCEPT = ["audio/mp4", "video/mp4", "video/mpeg"]
|
||||
ALL_ACCEPT = [*IMAGE_ACCEPT, *VIDEO_ACCEPT]
|
||||
|
||||
@classmethod
|
||||
def generate_path(cls, path: str, filename):
|
||||
"""
|
||||
生成文件路径
|
||||
"""
|
||||
if path[0] == "/":
|
||||
path = path[1:]
|
||||
if path[-1] == "/":
|
||||
path = path[:-1]
|
||||
full_date = datetime.datetime.now().date()
|
||||
_filename = str(int(datetime.datetime.now().timestamp())) + str(uuid.uuid4())[:8]
|
||||
return f"{path}/{full_date}/{_filename}{os.path.splitext(filename)[-1]}"
|
||||
|
||||
@classmethod
|
||||
async def validate_file(cls, file: UploadFile, max_size: int = None, mime_types: list = None) -> bool:
|
||||
"""
|
||||
验证文件是否符合格式
|
||||
|
||||
@params max_size: 文件最大值,单位 MB
|
||||
"""
|
||||
if max_size:
|
||||
size = len(await file.read()) / 1024 / 1024
|
||||
if size > max_size:
|
||||
raise CustomException(f"上传文件过大,不能超过{max_size}MB", status.HTTP_ERROR)
|
||||
await file.seek(0)
|
||||
if mime_types:
|
||||
if file.content_type not in mime_types:
|
||||
raise CustomException(f"上传文件格式错误,只支持 {'/'.join(mime_types)} 格式!", status.HTTP_ERROR)
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def get_file_type(cls, content_type: str) -> Union[str, None]:
|
||||
"""
|
||||
获取文件类型
|
||||
|
||||
0: 图片
|
||||
1:视频
|
||||
"""
|
||||
if content_type in cls.IMAGE_ACCEPT:
|
||||
return "0"
|
||||
elif content_type in cls.VIDEO_ACCEPT:
|
||||
return "1"
|
||||
else:
|
||||
return None
|
@ -8,29 +8,19 @@
|
||||
import datetime
|
||||
import os
|
||||
import shutil
|
||||
from application.settings import TEMP_DIR, STATIC_ROOT, BASE_DIR, STATIC_DIR, STATIC_URL
|
||||
from application.settings import TEMP_DIR, STATIC_ROOT, BASE_DIR, STATIC_URL, STATIC_DIR
|
||||
from fastapi import UploadFile
|
||||
import sys
|
||||
from core.exception import CustomException
|
||||
from utils import status
|
||||
import uuid
|
||||
from utils.file.file_base import FileBase
|
||||
|
||||
|
||||
class FileManage:
|
||||
class FileManage(FileBase):
|
||||
"""
|
||||
上传文件管理
|
||||
"""
|
||||
|
||||
image_accept = ["image/png", "image/jpeg", "image/gif", "image/x-icon"]
|
||||
|
||||
def __init__(self, file: UploadFile, path: str):
|
||||
if path[0] == "/":
|
||||
path = path[1:]
|
||||
if path[-1] == "/":
|
||||
path = path[:-1]
|
||||
full_date = datetime.datetime.now().date()
|
||||
filename = str(int(datetime.datetime.now().timestamp())) + str(uuid.uuid4())[:8]
|
||||
self.path = f"{path}/{full_date}/{filename}{os.path.splitext(file.filename)[-1]}"
|
||||
self.path = self.generate_path(path, file.filename)
|
||||
self.file = file
|
||||
|
||||
async def save_image_local(self, accept: list = None) -> dict:
|
||||
@ -38,9 +28,8 @@ class FileManage:
|
||||
保存图片文件到本地
|
||||
"""
|
||||
if accept is None:
|
||||
accept = self.image_accept
|
||||
if self.file.content_type not in accept:
|
||||
raise CustomException(f"上传图片必须是 {'/'.join(accept)} 格式!", status.HTTP_ERROR)
|
||||
accept = self.IMAGE_ACCEPT
|
||||
await self.validate_file(self.file, max_size=5, mime_types=accept)
|
||||
return await self.save_local()
|
||||
|
||||
async def save_local(self) -> dict:
|
||||
@ -61,7 +50,7 @@ class FileManage:
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
async def save_tmp_file(file: UploadFile) -> str:
|
||||
async def save_tmp_file(file: UploadFile):
|
||||
"""
|
||||
保存临时文件
|
||||
"""
|
||||
@ -75,7 +64,7 @@ class FileManage:
|
||||
return filename
|
||||
|
||||
@staticmethod
|
||||
def copy(src: str, dst: str) -> None:
|
||||
def copy(src: str, dst: str):
|
||||
"""
|
||||
复制文件
|
||||
根目录为项目根目录,传过来的文件路径均为相对路径
|
||||
@ -95,4 +84,7 @@ class FileManage:
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print()
|
||||
# src = r"D:\ktianc\private\vv-reserve\reserve-api\static\system\2022-12-07\16703958210ab33912.ico"
|
||||
# dst = r"D:\ktianc\private\vv-reserve\reserve-api\static\system\favicon.ico"
|
||||
# shutil.copyfile(src, dst)
|
||||
pass
|
@ -1,17 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @version : 1.0
|
||||
# @Creaet Time : 2022/11/16 8:55
|
||||
# @File : test.py
|
||||
# @IDE : PyCharm
|
||||
# @desc : 测试文件
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class Scene(Enum):
|
||||
login = "template_code_1"
|
||||
reset_password = "template_code_2"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(Scene.login.value)
|
@ -235,9 +235,12 @@
|
||||
uni.showLoading({
|
||||
title: '图片生成中...',
|
||||
})
|
||||
uni.getImageInfo({
|
||||
src: _this.imageSrc,
|
||||
success: function (image) {
|
||||
// 将图片写入画布
|
||||
const ctx = uni.createCanvasContext('myCanvas')
|
||||
ctx.drawImage(_this.imageSrc, 0, 0, IMG_REAL_W, IMG_REAL_H)
|
||||
ctx.drawImage(image.path, 0, 0, IMG_REAL_W, IMG_REAL_H)
|
||||
ctx.draw(true, () => {
|
||||
// 获取画布要裁剪的位置和宽度 均为百分比 * 画布中图片的宽度 保证了在微信小程序中裁剪的图片模糊 位置不对的问题 canvasT = (_this.cutT / _this.cropperH) * (_this.imageH / pixelRatio)
|
||||
var canvasW = ((_this.cropperW - _this.cutL - _this.cutR) / _this.cropperW) * IMG_REAL_W
|
||||
@ -264,6 +267,11 @@
|
||||
})
|
||||
})
|
||||
},
|
||||
fail: function (err) {
|
||||
uni.hideLoading()
|
||||
}
|
||||
});
|
||||
},
|
||||
// 设置大小的时候触发的touchStart事件
|
||||
dragStart(e) {
|
||||
T_PAGE_X = e.touches[0].pageX
|
||||
|
Loading…
x
Reference in New Issue
Block a user