This commit is contained in:
朱进禄 2021-10-04 03:00:40 +08:00
parent 8253a1b62b
commit 22932ccaf9
8 changed files with 309 additions and 40 deletions

View File

@ -8,6 +8,8 @@ import SystemRole from './views/system/SystemRole.vue'
import SystemConfig from './views/system/SystemConfig.vue'
import Music from './views/api/Music.vue'
import Hitokoto from './views/api/Hitokoto.vue'
import SqlReplace from './views/tool/SqlReplace.vue'
const routes: Array<RouteRecordRaw> = [
{ path: '/login', name: 'Login', component: Login },
@ -18,6 +20,9 @@ const routes: Array<RouteRecordRaw> = [
{ path: '/system/config', name: 'SystemConfig', component: SystemConfig },
{ path: '/api/music', name: 'Music', component: Music },
{ path: '/api/hitokoto', name: 'Hitokoto', component: Hitokoto },
{ path: '/tool/sqlReplace', name: 'SqlReplace', component: SqlReplace },
]}
]

View File

@ -46,9 +46,6 @@ html,body,#app,.layout {
}
.btn-container {
margin-bottom: 10px;
button {
margin-right: 3px;
}
.search-btn {
float: right;
}

149
src/views/api/Hitokoto.vue Normal file
View File

@ -0,0 +1,149 @@
<template>
<div>
<el-form inline :model="search" @submit.prevent>
<el-form-item label="内容:">
<el-input size="small" v-model="search.content" />
</el-form-item>
<el-form-item label="类型:">
<el-select size="small" v-model="search.type" multiple collapse-tags>
<el-option v-for="item in typeList" :key="item.value" :value="item.value" :label="item.label" />
</el-select>
</el-form-item>
<el-form-item label="创建时间:">
<el-date-picker
v-model="search.createdAt"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期" />
</el-form-item>
</el-form>
<div class="btn-container">
<el-button size="small" type="primary" @click="addModal = true">添加</el-button>
<el-button size="small" type="danger" @click="deleteAll">删除</el-button>
<div class="search-btn">
<el-button type="primary" @click="loadDataBase(true)" size="small" icon="el-icon-search">搜索</el-button>
<el-button @click="reset" size="small" icon="el-icon-refresh-right">重置</el-button>
</div>
</div>
<div class="table-container">
<el-table :data="hitokotoData" v-loading="loading" stripe height="520" @selection-change="dataSelect">
<el-table-column type="selection" width="55" />
<el-table-column prop="type" label="类型" width="180">
<template #default="scope">
{{ findTypeText(scope.row.type) }}
</template>
</el-table-column>
<el-table-column prop="hitokoto" label="内容" />
<el-table-column prop="from" label="来自" width="180"/>
<el-table-column prop="creator" label="作者" width="180"/>
<el-table-column prop="number" label="编号" width="70"/>
<el-table-column prop="created_at" label="创建时间" width="180">
<template #default="scope">
{{ datetimeFormat(scope.row.created_at) }}
</template>
</el-table-column>
</el-table>
</div>
<div class="page-container">
<el-pagination background
:page-sizes="$store.state.pageSizeOpts"
:layout="$store.state.pageLayout"
:total="total"
@size-change="pageSizeChange"
@current-change="pageChange">
</el-pagination>
</div>
<el-dialog v-model="addModal" title="新增一言" >
<hitokoto-add ref="addForm" :typeList="typeList" :formData="formData" />
<template #footer>
<span class="dialog-footer">
<el-button @click="addModal = false">取消</el-button>
<el-button type="primary" @click="save" :loading="modalLoading">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import HitokotoAdd from './HitokotoAdd.vue'
import { Options } from 'vue-class-component'
import BaseList from '../../model/baselist'
import { Page } from '../../model/common.dto'
import HitokotoModel from '../../model/api/hitokoto'
import { AxiosResponse } from 'axios'
import { ElButton, ElForm, ElFormItem, ElInput, ElTable, ElTableColumn, ElPagination, ElDialog, ElSelect, ElOption, ElDatePicker, ElMessage, ElMessageBox } from 'element-plus'
import { ref } from 'vue'
let selectedData: string[] = []
@Options({
name: 'Hitokoto',
components: { ElButton, ElForm, ElFormItem, ElInput, ElTable, ElTableColumn, ElPagination, ElDialog, ElSelect, ElOption, ElDatePicker, HitokotoAdd }
})
export default class Hitokoto extends BaseList<HitokotoPage> {
private readonly addForm: any = ref('addForm')
search = new HitokotoPage()
typeList: {label: string, value: string}[] = []
hitokotoData: HitokotoModel[] = []
formData: {[propName:string]: string | null} = {}
addModal: boolean = false
async loadData() {
this.loading = true
const { data } = await this.$http.get<HitokotoPage, AxiosResponse<any>>('/api/hitokoto/list', {params:this.search})
selectedData = []
this.loading = false
this.total = data.total
this.hitokotoData = data.data
}
async save() {
this.addForm.$refs.hitokotoForm.validate(async (valid: boolean) => {
if(!valid) return
this.modalLoading = true
const { data } = await this.$http.post<any, AxiosResponse<any>>('/api/hitokoto/save', this.formData)
this.modalLoading = false
this.addModal = false
ElMessage.success(data.message)
this.loadData()
//
this.formData = {}
})
}
deleteAll() {
if(!selectedData.length) {
ElMessage.warning('请选择要删除的数据')
return
}
ElMessageBox.confirm(`是否确认删除选中的${selectedData.length}条数据?`, '确认删除', {type: 'warning'}).then(async () => {
const { data } = await this.$http.delete<any, AxiosResponse<any>>('/api/hitokoto/delete', {params:{_ids: selectedData}})
ElMessage.success(data.message)
this.loadData()
}).catch(() => {})
}
dataSelect(selection: HitokotoModel[]) {
selectedData = selection.map(item => item._id)
}
created() {
this.loadData()
this.$http.get('/api/common/config/hitokoto_type').then(({data}) => {
this.typeList = data
})
}
findTypeText(value: string): string | null {
const type = this.typeList.find(item => item.value === value)
return type ? type.label : null
}
}
class HitokotoPage extends Page {
content?: string
type?: string
createdAt?: [Date, Date]
reset() {
super.reset()
this.content = undefined
this.type = undefined
this.createdAt = undefined
}
}
</script>

View File

@ -0,0 +1,45 @@
<template>
<div>
<el-form ref="hitokotoForm" :model="formData" :rules="ruleValidate" :label-width="80">
<el-form-item label="内容" prop="hitokoto">
<el-input v-model="formData.hitokoto" type="textarea" :rows="4"/>
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="formData.type">
<el-option v-for="item in typeList" :value="item.value" :key="item.value" :label="item.label"></el-option>
</el-select>
</el-form-item>
<el-form-item label="来自">
<el-input v-model="formData.from" />
</el-form-item>
<el-form-item label="作者">
<el-input v-model="formData.creator" />
</el-form-item>
</el-form>
</div>
</template>
<script lang="ts">
import { Options, Vue } from 'vue-class-component'
import { ElForm, ElFormItem, ElInput, ElSelect, ElOption } from 'element-plus'
@Options({
name: 'SystemConfigAdd',
components: { ElForm, ElFormItem, ElInput, ElSelect, ElOption },
props: {
typeList: Array,
formData: Object
}
})
export default class HitokotoAdd extends Vue {
typeList!: {label: string, value: string}[]
formData!: {[propName:string]: string | null}
ruleValidate = {
hitokoto: [
{ required: true, message: '请输入内容', trigger: 'blur' }
],
type: [
{ required: true, message: '请选择类型', trigger: 'blur' }
],
}
}
</script>

View File

@ -25,7 +25,7 @@
</el-form-item>
</el-form>
<div class="btn-container">
<el-button type="success" plain size="small" icon="el-icon-caret-right" >播放</el-button>
<el-button type="success" plain size="small" icon="el-icon-caret-right" @click="playMusic">播放</el-button>
<div class="search-btn">
<el-button type="primary" @click="loadDataBase(true)" size="small" icon="el-icon-search">搜索</el-button>
<el-button @click="reset" size="small" icon="el-icon-refresh-right">重置</el-button>
@ -92,7 +92,7 @@
</template>
</el-dialog>
<el-dialog v-model="modifyModal" title="修改所属歌单" :width="470" >
<el-radio-group v-model="currentRow.lib_id">
<el-radio-group v-if="currentRow" v-model="currentRow.lib_id">
<el-radio v-for="item in musicLibs" :key="item._id" :label="item._id" border>{{item.name}}</el-radio>
</el-radio-group>
<template #footer>
@ -119,15 +119,9 @@ import { AxiosResponse } from 'axios'
import { ElButton, ElForm, ElFormItem, ElInput, ElTable, ElTableColumn, ElPagination, ElDialog, ElSelect, ElOption, ElRadioGroup, ElRadio, ElMessage, ElMessageBox } from 'element-plus'
import { ref } from 'vue'
import { MusicModel, MusicLibModel, MusicLyricModel, MusicPlayerItem } from '../../model/api/music'
import prettyBytes from 'pretty-bytes'
// import APlayer, {APlayer as APlayerComponent} from '@moefe/vue-aplayer'
// Vue.use(APlayer, {
// defaultCover: `${Vue.prototype.$http.defaults.baseURL}/api/common/randomBg?id=5ec7770b60990123b7340233`, //
// productionTip: false, //
// })
let selectedIds: string[] = []
@Options({
name: 'Music',
@ -184,33 +178,27 @@ export default class Music extends BaseList<MusicPage> {
return musicLib ? musicLib.name : null
}
//
// async playMusic() {
// //
// this.$Loading.start()
// try {
// const { data } = await this.$http.get('/api/music/list/all', {params: selectedIds.length ? {ids: selectedIds} : this.search})
// this.musicList = data.map((item: MusicModel, index: number) => {
// return {
// id: index + 1,
// name: item.title || item.name,
// artist: item.artist,
// album: item.album,
// url: `${this.$http.defaults.baseURL || ''}/api/common/music/get/${item._id}`,
// cover: `${this.$http.defaults.baseURL || ''}/api/common/music/album/${item._id}`,
// lrc: item.lyric_id ? `${this.$http.defaults.baseURL || ''}/api/common/music/lyric/${item.lyric_id}` : undefined
// }
// })
// //
// this.$Loading.finish()
// // ( )
// localStorage.removeItem('aplayer-setting')
// this.musicPlaying = true
// } catch (err) {
// console.error(err)
// ElMessage.error('')
// this.$Loading.error()
// }
// }
async playMusic() {
try {
const { data } = await this.$http.get<any, AxiosResponse<any>>('/api/music/list/all', {params: selectedIds.length ? {ids: selectedIds} : this.search})
this.musicList = data.map((item: MusicModel, index: number) => {
return {
id: index + 1,
name: item.title || item.name,
artist: item.artist,
album: item.album,
url: `${this.$http.defaults.baseURL || ''}/api/common/music/get/${item._id}`,
cover: `${this.$http.defaults.baseURL || ''}/api/common/music/album/${item._id}`,
lrc: item.lyric_id ? `${this.$http.defaults.baseURL || ''}/api/common/music/lyric/${item.lyric_id}` : undefined
}
})
// ( )
this.musicPlaying = true
} catch (err) {
console.error(err)
ElMessage.error('获取播放列表失败')
}
}
update(row: MusicModel) {
this.currentRow = row
this.modifyModal = true

View File

@ -56,7 +56,7 @@
<el-input v-model="formData.description" />
</el-form-item>
<el-form-item label="允许的请求类型">
<el-select v-model="formData.methods" multiple >
<el-select v-model="formData.methods" multiple collapse-tags>
<el-option value="GET">GET</el-option>
<el-option value="POST">POST</el-option>
<el-option value="PUT">PUT</el-option>

View File

@ -0,0 +1,74 @@
<template>
<div>
<el-form :label-width="100">
<el-form-item label="SQL语句">
<el-input v-model="sql" type="textarea" :rows="5"/>
</el-form-item>
<el-form-item label="参数">
<el-input v-model="params" type="textarea" :rows="3"/>
</el-form-item>
<el-form-item label="替换结果">
<el-input v-model="replaceResult" ref="resultInput" readonly/>
</el-form-item>
</el-form>
<div style="text-align:center">
<el-button-group size="large" >
<el-button type="primary" icon="el-icon-document-copy" @click="replacePlaceholder">替换占位符</el-button>
<el-button type="default" @click="clear">清空</el-button>
</el-button-group>
</div>
</div>
</template>
<script lang="ts">
import { Options, Vue } from 'vue-class-component'
import { ElForm, ElFormItem, ElInput, ElButtonGroup, ElButton, ElMessage } from 'element-plus'
import { ref } from 'vue'
@Options({
name: 'SqlReplace',
components: { ElForm, ElFormItem, ElInput, ElButtonGroup, ElButton }
})
export default class SqlReplace extends Vue {
private readonly inputInstance: any = ref('resultInput')
sql: string = ''
params: string = ''
replaceResult: string = ''
replacePlaceholder() {
let sql = this.sql
const reg = /(.+?)\s*\((String|Integer|Boolean)\),?/g
let execResult = reg.exec(this.params)
let replaceMent = ''
while(execResult && sql.indexOf('?') !== -1) {
switch(execResult[2]) {
case 'String':
replaceMent = `'${execResult[1].trim()}'`
break
case 'Integer':
replaceMent = execResult[1].trim()
break
case 'Boolean':
replaceMent = eval(execResult[1]) ? '1' : '0'
break
}
sql = sql.replace('?', replaceMent)
execResult = reg.exec(this.params)
}
this.replaceResult = sql
Promise.resolve('已复制到剪贴板').then(message => {
this.inputInstance.select()
if (document.execCommand('copy')) {
ElMessage.success(message)
} else {
ElMessage.warning('复制失败,请手动复制')
}
})
}
clear() {
this.sql = ''
this.params = ''
this.replaceResult = ''
}
}
</script>

View File

@ -21,6 +21,17 @@ export default defineConfig({
build: {
outDir: 'dist',
assetsDir: 'assets', // 静态资源的存放路径, 相对于outDir
cssCodeSplit: true // 是否拆分css
cssCodeSplit: true, // 是否拆分css
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('element-plus')) {
return 'element-plus'
} else if(id.includes('node_modules')) {
return 'vendor'
}
}
}
}
}
})