feat:增加docker部署
This commit is contained in:
6
Dockerfile
Normal file
6
Dockerfile
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
FROM nginx:1.27.0
|
||||||
|
COPY dist/ /usr/share/nginx/html/
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||||
|
RUN echo 'Asia/Shanghai' > /etc/timezone
|
||||||
|
RUN chmod -R 755 /usr/share/nginx/html/
|
||||||
25
nginx.conf
Normal file
25
nginx.conf
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
listen [::]:80 default_server;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
client_max_body_size 500M;
|
||||||
|
|
||||||
|
location /study-agent/ {
|
||||||
|
alias /usr/share/nginx/html/;
|
||||||
|
try_files $uri $uri/ /study-agent/index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /study-api/ {
|
||||||
|
proxy_pass http://host.docker.internal:8001/;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,12 +5,13 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vue-tsc -b && vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vueup/vue-quill": "^1.5.5",
|
"@vueup/vue-quill": "^1.5.5",
|
||||||
"axios": "^1.18.1",
|
"axios": "^1.18.1",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"dayjs": "^1.11.21",
|
"dayjs": "^1.11.21",
|
||||||
"element-plus": "^2.14.3",
|
"element-plus": "^2.14.3",
|
||||||
"filesize": "^11.0.22",
|
"filesize": "^11.0.22",
|
||||||
|
|||||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -14,6 +14,9 @@ importers:
|
|||||||
axios:
|
axios:
|
||||||
specifier: ^1.18.1
|
specifier: ^1.18.1
|
||||||
version: 1.18.1
|
version: 1.18.1
|
||||||
|
crypto-js:
|
||||||
|
specifier: ^4.2.0
|
||||||
|
version: 4.2.0
|
||||||
dayjs:
|
dayjs:
|
||||||
specifier: ^1.11.21
|
specifier: ^1.11.21
|
||||||
version: 1.11.21
|
version: 1.11.21
|
||||||
@@ -734,6 +737,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
|
crypto-js@4.2.0:
|
||||||
|
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
|
||||||
|
|
||||||
cssesc@3.0.0:
|
cssesc@3.0.0:
|
||||||
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
|
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -2817,6 +2823,8 @@ snapshots:
|
|||||||
shebang-command: 2.0.0
|
shebang-command: 2.0.0
|
||||||
which: 2.0.2
|
which: 2.0.2
|
||||||
|
|
||||||
|
crypto-js@4.2.0: {}
|
||||||
|
|
||||||
cssesc@3.0.0: {}
|
cssesc@3.0.0: {}
|
||||||
|
|
||||||
csstype@3.2.3: {}
|
csstype@3.2.3: {}
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ import { QuillEditor } from '@vueup/vue-quill'
|
|||||||
import '@vueup/vue-quill/dist/vue-quill.snow.css'
|
import '@vueup/vue-quill/dist/vue-quill.snow.css'
|
||||||
import { uploadLibraryFileApi } from '@/apis/library.ts'
|
import { uploadLibraryFileApi } from '@/apis/library.ts'
|
||||||
import { getModuleOptions } from '@/utils/libraryUtil.ts'
|
import { getModuleOptions } from '@/utils/libraryUtil.ts'
|
||||||
|
import { getFileExtension, getFileHashName } from '@/utils/file.ts'
|
||||||
|
|
||||||
const libraryStore = useLibraryStore()
|
const libraryStore = useLibraryStore()
|
||||||
const libraryFileFormRef = ref<FormInstance>()
|
const libraryFileFormRef = ref<FormInstance>()
|
||||||
@@ -166,9 +167,11 @@ const upload = async (options: UploadRequestOptions) => {
|
|||||||
const { file } = options
|
const { file } = options
|
||||||
libraryStore.currentFile.size = file.size
|
libraryStore.currentFile.size = file.size
|
||||||
libraryStore.currentFile.type = 'image'
|
libraryStore.currentFile.type = 'image'
|
||||||
|
const fileName = `${getFileHashName(file)}.${getFileExtension(file.name)}`
|
||||||
|
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', file)
|
formData.append('file', file)
|
||||||
|
formData.append('filename', fileName)
|
||||||
|
|
||||||
const loading = ElLoading.service({
|
const loading = ElLoading.service({
|
||||||
lock: true,
|
lock: true,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-empty v-if="!filterLibraryFileList.length" description="暂无文件" :image-size="80" />
|
<el-empty v-if="!filterLibraryFileList.length" description="暂无数据"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { usePracticeStore } from '@/stores/practice.ts'
|
import { usePracticeStore } from '@/stores/practice.ts'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElLoading, ElMessage } from 'element-plus'
|
||||||
|
|
||||||
const practiceStore = usePracticeStore()
|
const practiceStore = usePracticeStore()
|
||||||
|
|
||||||
@@ -65,7 +65,20 @@ const submitAnswerClick = async () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loading = ElLoading.service({
|
||||||
|
lock: true,
|
||||||
|
text: '答案提交中 请等待',
|
||||||
|
background: 'rgba(0, 0, 0, 0.7)'
|
||||||
|
})
|
||||||
|
try {
|
||||||
await practiceStore.checkQuestion()
|
await practiceStore.checkQuestion()
|
||||||
|
ElMessage.success('提交成功')
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
ElMessage.error('提交失败 请联系管理员')
|
||||||
|
} finally {
|
||||||
|
loading.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||||
import Layout from '../layout/index.vue'
|
import Layout from '../layout/index.vue'
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
@@ -42,7 +42,7 @@ const routes = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHashHistory(),
|
||||||
routes
|
routes
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -42,9 +42,12 @@ export const useLibraryStore = defineStore('library', {
|
|||||||
this.fileList = await queryLibraryFileListApi()
|
this.fileList = await queryLibraryFileListApi()
|
||||||
this.subjectTree = getSubjectTree(this.fileList)
|
this.subjectTree = getSubjectTree(this.fileList)
|
||||||
this.subjectOptions = getSubjectOptions(this.subjectTree)
|
this.subjectOptions = getSubjectOptions(this.subjectTree)
|
||||||
|
|
||||||
|
if (this.subjectOptions.length > 0) {
|
||||||
this.selectedSubject = this.subjectOptions[0].value
|
this.selectedSubject = this.subjectOptions[0].value
|
||||||
this.moduleOptions = getModuleOptions(this.subjectTree, this.selectedSubject)
|
this.moduleOptions = getModuleOptions(this.subjectTree, this.selectedSubject)
|
||||||
this.selectedModule = this.moduleOptions[0].value
|
this.selectedModule = this.moduleOptions[0].value
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async queryFileById(id: number) {
|
async queryFileById(id: number) {
|
||||||
this.currentFile = await queryLibraryFileByIdApi(id)
|
this.currentFile = await queryLibraryFileByIdApi(id)
|
||||||
|
|||||||
13
src/utils/file.ts
Normal file
13
src/utils/file.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import * as CryptoJS from 'crypto-js'
|
||||||
|
|
||||||
|
const hashSHA256 = (message: string) => {
|
||||||
|
return CryptoJS.SHA256(message).toString(CryptoJS.enc.Hex)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getFileHashName = (file: File) => {
|
||||||
|
return hashSHA256(`${file.name}_${file.lastModified}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getFileExtension = (name: string) => {
|
||||||
|
return name.substring(name.lastIndexOf('.') + 1).toLowerCase()
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mistake-record">
|
<div class="mistake-record">
|
||||||
<div class="mistake-list">
|
<div v-if="mistakeStore.mistakeList.length" class="mistake-list">
|
||||||
<el-card
|
<el-card
|
||||||
v-for="item in mistakeStore.mistakeList"
|
v-for="item in mistakeStore.mistakeList"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@@ -30,6 +30,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<el-empty v-else description="暂无数据"></el-empty>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<library-filter />
|
<library-filter v-if="libraryStore.fileList.length" />
|
||||||
|
|
||||||
<practice-question v-if="practiceStore.hasStart"/>
|
<practice-question v-if="practiceStore.hasStart"/>
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export default defineConfig({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
base: '/study-agent/',
|
||||||
resolve: {
|
resolve: {
|
||||||
// 配置路径别名
|
// 配置路径别名
|
||||||
alias: {
|
alias: {
|
||||||
|
|||||||
Reference in New Issue
Block a user