update
修复 offset bug 前后端添加 get_files_in_folder API 更改拼写 respond 为 response 添加 HTTP GET 方法获取文件 一个根组件 前端支持搜索文件夹,多页浏览 前端支持播放音乐 前端支持更新和重置数据库 前端全局唯一音乐播放器
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
|||||||
"msw-open-music/internal/pkg/database"
|
"msw-open-music/internal/pkg/database"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
@@ -36,23 +37,63 @@ type ResetRequest struct {
|
|||||||
type SearchFilesRequest struct {
|
type SearchFilesRequest struct {
|
||||||
Filename string `json:"filename"`
|
Filename string `json:"filename"`
|
||||||
Limit int64 `json:"limit"`
|
Limit int64 `json:"limit"`
|
||||||
Offset int64 `json:"offest"`
|
Offset int64 `json:"offset"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchFoldersRequest struct {
|
type SearchFoldersRequest struct {
|
||||||
Foldername string `json:"foldername"`
|
Foldername string `json:"foldername"`
|
||||||
Limit int64 `json:"limit"`
|
Limit int64 `json:"limit"`
|
||||||
Offset int64 `json:"offest"`
|
Offset int64 `json:"offset"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchFilesRespond struct {
|
type SearchFilesResponse struct {
|
||||||
Files []database.File `json:"files"`
|
Files []database.File `json:"files"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchFoldersRespond struct {
|
type SearchFoldersResponse struct {
|
||||||
Folders []database.Folder `json:"folders"`
|
Folders []database.Folder `json:"folders"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetFilesInFolderRequest struct {
|
||||||
|
Folder_id int64 `json:"folder_id"`
|
||||||
|
Limit int64 `json:"limit"`
|
||||||
|
Offset int64 `json:"offset"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetFilesInFolderResponse struct {
|
||||||
|
Files *[]database.File `json:"files"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleGetFilesInFolder(w http.ResponseWriter, r *http.Request) {
|
||||||
|
getFilesInFolderRequest := &GetFilesInFolderRequest{
|
||||||
|
Folder_id: -1,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.NewDecoder(r.Body).Decode(getFilesInFolderRequest)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check empyt
|
||||||
|
if getFilesInFolderRequest.Folder_id < 0 {
|
||||||
|
api.HandleErrorString(w, r, `"folder_id" can't be none or negative`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := api.Db.GetFilesInFolder(getFilesInFolderRequest.Folder_id, getFilesInFolderRequest.Limit, getFilesInFolderRequest.Offset)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
getFilesInFolderResponse := &GetFilesInFolderResponse{
|
||||||
|
Files: &files,
|
||||||
|
}
|
||||||
|
|
||||||
|
json.NewEncoder(w).Encode(getFilesInFolderResponse)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) CheckToken(token string) (error) {
|
func (api *API) CheckToken(token string) (error) {
|
||||||
if token != api.token {
|
if token != api.token {
|
||||||
return errors.New("token not matched")
|
return errors.New("token not matched")
|
||||||
@@ -182,15 +223,15 @@ func (api *API) HandleSearchFiles(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
searchFilesRespond := &SearchFilesRespond{}
|
searchFilesResponse := &SearchFilesResponse{}
|
||||||
|
|
||||||
searchFilesRespond.Files, err = api.Db.SearchFiles(searchFilesRequest.Filename, searchFilesRequest.Limit, searchFilesRequest.Offset)
|
searchFilesResponse.Files, err = api.Db.SearchFiles(searchFilesRequest.Filename, searchFilesRequest.Limit, searchFilesRequest.Offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(searchFilesRespond)
|
json.NewEncoder(w).Encode(searchFilesResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleSearchFolders(w http.ResponseWriter, r *http.Request) {
|
func (api *API) HandleSearchFolders(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -211,21 +252,48 @@ func (api *API) HandleSearchFolders(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
searchFoldersRespond := &SearchFoldersRespond{}
|
searchFoldersResponse := &SearchFoldersResponse{}
|
||||||
|
|
||||||
searchFoldersRespond.Folders, err = api.Db.SearchFolders(searchFoldersRequest.Foldername, searchFoldersRequest.Limit, searchFoldersRequest.Offset)
|
searchFoldersResponse.Folders, err = api.Db.SearchFolders(searchFoldersRequest.Foldername, searchFoldersRequest.Limit, searchFoldersRequest.Offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(searchFoldersRespond)
|
json.NewEncoder(w).Encode(searchFoldersResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetFileRequest struct {
|
type GetFileRequest struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleGetFileDirect(w http.ResponseWriter, r *http.Request) {
|
||||||
|
q := r.URL.Query()
|
||||||
|
ids := q["id"]
|
||||||
|
if len(ids) == 0 {
|
||||||
|
api.HandleErrorString(w, r, `parameter "id" can't be empty`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id, err := strconv.Atoi(ids[0])
|
||||||
|
if err != nil {
|
||||||
|
api.HandleErrorString(w, r, `parameter "id" should be an integer`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file, err := api.Db.GetFile(int64(id))
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
path, err := file.Path()
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.ServeFile(w, r, path)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) HandleGetFile(w http.ResponseWriter, r *http.Request) {
|
func (api *API) HandleGetFile(w http.ResponseWriter, r *http.Request) {
|
||||||
getFilesRequest := &GetFileRequest{
|
getFilesRequest := &GetFileRequest{
|
||||||
ID: -1,
|
ID: -1,
|
||||||
@@ -286,8 +354,10 @@ func NewAPI(dbName string, Addr string) (*API, error) {
|
|||||||
// mount api
|
// mount api
|
||||||
apiMux.HandleFunc("/hello", api.HandleOK)
|
apiMux.HandleFunc("/hello", api.HandleOK)
|
||||||
apiMux.HandleFunc("/get_file", api.HandleGetFile)
|
apiMux.HandleFunc("/get_file", api.HandleGetFile)
|
||||||
|
apiMux.HandleFunc("/get_file_direct", api.HandleGetFileDirect)
|
||||||
apiMux.HandleFunc("/search_files", api.HandleSearchFiles)
|
apiMux.HandleFunc("/search_files", api.HandleSearchFiles)
|
||||||
apiMux.HandleFunc("/search_folders", api.HandleSearchFolders)
|
apiMux.HandleFunc("/search_folders", api.HandleSearchFolders)
|
||||||
|
apiMux.HandleFunc("/get_files_in_folder", api.HandleGetFilesInFolder)
|
||||||
// below needs token
|
// below needs token
|
||||||
apiMux.HandleFunc("/walk", api.HandleWalk)
|
apiMux.HandleFunc("/walk", api.HandleWalk)
|
||||||
apiMux.HandleFunc("/reset", api.HandleReset)
|
apiMux.HandleFunc("/reset", api.HandleReset)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ var dropFilesQuery = `DROP TABLE files;`
|
|||||||
var dropFolderQuery = `DROP TABLE folders;`
|
var dropFolderQuery = `DROP TABLE folders;`
|
||||||
var getFileQuery = `SELECT files.id, files.folder_id, files.filename, folders.foldername, files.filesize FROM files JOIN folders ON files.folder_id = folders.id WHERE files.id = ? LIMIT 1;`
|
var getFileQuery = `SELECT files.id, files.folder_id, files.filename, folders.foldername, files.filesize FROM files JOIN folders ON files.folder_id = folders.id WHERE files.id = ? LIMIT 1;`
|
||||||
var searchFoldersQuery = `SELECT id, folder, foldername FROM folders WHERE foldername LIKE ? LIMIT ? OFFSET ?;`
|
var searchFoldersQuery = `SELECT id, folder, foldername FROM folders WHERE foldername LIKE ? LIMIT ? OFFSET ?;`
|
||||||
|
var getFilesInFolderQuery = `SELECT id, filename, filesize FROM files WHERE folder_id = ? LIMIT ? OFFSET ?;`
|
||||||
|
|
||||||
type Database struct {
|
type Database struct {
|
||||||
sqlConn *sql.DB
|
sqlConn *sql.DB
|
||||||
@@ -48,6 +49,7 @@ type Stmt struct {
|
|||||||
dropFolder *sql.Stmt
|
dropFolder *sql.Stmt
|
||||||
getFile *sql.Stmt
|
getFile *sql.Stmt
|
||||||
searchFolders *sql.Stmt
|
searchFolders *sql.Stmt
|
||||||
|
getFilesInFolder *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
type File struct {
|
type File struct {
|
||||||
@@ -66,6 +68,27 @@ type Folder struct {
|
|||||||
Foldername string `json:"foldername"`
|
Foldername string `json:"foldername"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (database *Database) GetFilesInFolder(folder_id int64, limit int64, offset int64) ([]File, error) {
|
||||||
|
rows, err := database.stmt.getFilesInFolder.Query(folder_id, limit, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
files := make([]File, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
file := File{
|
||||||
|
Db: database,
|
||||||
|
Folder_id: folder_id,
|
||||||
|
}
|
||||||
|
err = rows.Scan(&file.ID, &file.Filename, &file.Filesize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
files = append(files, file)
|
||||||
|
}
|
||||||
|
return files, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (database *Database) SearchFolders(foldername string, limit int64, offset int64) ([]Folder, error) {
|
func (database *Database) SearchFolders(foldername string, limit int64, offset int64) ([]Folder, error) {
|
||||||
rows, err := database.stmt.searchFolders.Query("%"+foldername+"%", limit, offset)
|
rows, err := database.stmt.searchFolders.Query("%"+foldername+"%", limit, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -323,6 +346,12 @@ func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init getFilesInFolder stmt
|
||||||
|
stmt.getFilesInFolder, err = sqlConn.Prepare(getFilesInFolderQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return stmt, err
|
return stmt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<component-search-files></component-search-files>
|
<root-component></root-component>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
<script src="vue.js"></script>
|
<script src="vue.js"></script>
|
||||||
|
|||||||
264
web/index.js
264
web/index.js
@@ -1,30 +1,220 @@
|
|||||||
const app = Vue.createApp({
|
const app = Vue.createApp({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
search_filenames: '',
|
|
||||||
download_total: 0,
|
|
||||||
download_loaded: 0,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
app.component('root-component', {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
playing_audio_file: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `
|
||||||
|
<component-audio-player :file=playing_audio_file></component-audio-player>
|
||||||
|
<component-search-folders @play_audio="play_audio"></component-search-folders>
|
||||||
|
<component-search-files @play_audio="play_audio"></component-search-files>
|
||||||
|
<component-update-database></component-update-database>
|
||||||
|
`,
|
||||||
methods: {
|
methods: {
|
||||||
|
play_audio(file) {
|
||||||
|
console.log(file)
|
||||||
|
this.playing_audio_file = file
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
app.component('component-search-folders', {
|
||||||
|
emits: ['play_audio'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
search_foldernames: "",
|
||||||
|
folders: [],
|
||||||
|
offset: 0,
|
||||||
|
limit: 10,
|
||||||
|
folder_offset: 0,
|
||||||
|
folder_limit: 10,
|
||||||
|
files_in_folder: [],
|
||||||
|
playing_audio_file: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `
|
||||||
|
<input type="text" v-model="search_foldernames" />
|
||||||
|
<button @click="first_search_folders">Search Folders</Button>
|
||||||
|
|
||||||
|
<button @click="last_page">Last Page</button>
|
||||||
|
<span>{{ offset }}~{{ offset + folders.length }}</span>
|
||||||
|
<button @click="next_page">Next Page</button>
|
||||||
|
|
||||||
|
<table border="1">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Folder Name</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="folder in folders">
|
||||||
|
<td>{{ folder.id }}</td>
|
||||||
|
<td>{{ folder.foldername }}</td>
|
||||||
|
<td><button @click="get_files_in_folder(folder)">View</button></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table border="1">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Filename</th>
|
||||||
|
<th>Folder Name</th>
|
||||||
|
<th>Size</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="file in files_in_folder">
|
||||||
|
<component-file :file=file @play_audio="$emit('play_audio', file)"></component-file>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`,
|
||||||
|
methods: {
|
||||||
|
get_files_in_folder(folder) {
|
||||||
|
axios.post('/api/v1/get_files_in_folder', {
|
||||||
|
folder_id: folder.id,
|
||||||
|
limit: this.folder_limit,
|
||||||
|
offset: this.folder_offset,
|
||||||
|
}).then((response) => {
|
||||||
|
this.files_in_folder = response.data.files
|
||||||
|
})
|
||||||
|
},
|
||||||
|
last_page() {
|
||||||
|
this.offset = this.offset - this.limit
|
||||||
|
if (this.offset < 0) {
|
||||||
|
this.offset = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.search_folders()
|
||||||
|
},
|
||||||
|
next_page() {
|
||||||
|
this.offset = this.offset + this.limit
|
||||||
|
this.search_folders()
|
||||||
|
},
|
||||||
|
first_search_folders() {
|
||||||
|
this.offset = 0
|
||||||
|
this.search_folders()
|
||||||
|
},
|
||||||
|
search_folders() {
|
||||||
|
axios.post('/api/v1/search_folders', {
|
||||||
|
foldername: this.search_foldernames,
|
||||||
|
limit: this.limit,
|
||||||
|
offset: this.offset,
|
||||||
|
}).then((response) => {
|
||||||
|
this.folders = response.data.folders
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
app.component('component-update-database', {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
token: "",
|
||||||
|
root: "",
|
||||||
|
pattern: [".flac", ".mp3"],
|
||||||
|
pattern_tmp: "",
|
||||||
|
s: "",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `
|
||||||
|
<table border="1">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Token</td>
|
||||||
|
<td><input type="text" v-model="token" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Root</td>
|
||||||
|
<td><input type="text" v-model="root" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><button @click="add_pattern">Add Pattern</button></td>
|
||||||
|
<td><input type="text" v-model="pattern_tmp" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Pattern List</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="p in pattern">
|
||||||
|
<td>{{ p }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><button @click="update_database">Update</button></td>
|
||||||
|
<td><button @click="reset_database">Reset</button></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Status</td>
|
||||||
|
<td>{{ s }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`,
|
||||||
|
methods: {
|
||||||
|
add_pattern() {
|
||||||
|
this.pattern.push(this.pattern_tmp)
|
||||||
|
this.pattern_tmp = ""
|
||||||
|
},
|
||||||
|
reset_database() {
|
||||||
|
axios.post('/api/v1/reset', {
|
||||||
|
token: this.token,
|
||||||
|
}).then((response) => {
|
||||||
|
this.s = response.data.status
|
||||||
|
}).catch((err) => {
|
||||||
|
this.s = err.response.data.status
|
||||||
|
})
|
||||||
|
},
|
||||||
|
update_database() {
|
||||||
|
this.s = "Updating..."
|
||||||
|
axios.post('/api/v1/walk', {
|
||||||
|
token: this.token,
|
||||||
|
root: this.root,
|
||||||
|
pattern: this.pattern,
|
||||||
|
}).then((response) => {
|
||||||
|
this.s = response.data.status
|
||||||
|
}).catch((err) => {
|
||||||
|
this.s = err.response.data.status
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
app.component('component-file', {
|
app.component('component-file', {
|
||||||
props: ['file'],
|
props: ['file'],
|
||||||
|
emits: ['play_audio'],
|
||||||
template: `
|
template: `
|
||||||
<td>{{ file.id }}</td>
|
<td>{{ file.id }}</td>
|
||||||
<td>{{ file.filename }}</td>
|
<td>{{ file.filename }}</td>
|
||||||
|
<td>{{ file.foldername }}</td>
|
||||||
<td>{{ computed_readable_size }}</td>
|
<td>{{ computed_readable_size }}</td>
|
||||||
<td><button @click="download_file(file)">{{ computed_download_status }}</button></td>
|
<td>
|
||||||
|
<button @click="download_file(file)" :disabled="disabled">{{ computed_download_status }}</button>
|
||||||
|
<button @click="emit_play_audio">Play</button>
|
||||||
|
</td>
|
||||||
`,
|
`,
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
download_loaded: 0,
|
download_loaded: 0,
|
||||||
|
disabled: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
emit_play_audio() {
|
||||||
|
this.$emit("play_audio", this.file)
|
||||||
|
},
|
||||||
download_file(file) {
|
download_file(file) {
|
||||||
|
this.disabled = true
|
||||||
axios({
|
axios({
|
||||||
url: '/api/v1/get_file',
|
url: '/api/v1/get_file',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -33,7 +223,6 @@ app.component('component-file', {
|
|||||||
id: file.id,
|
id: file.id,
|
||||||
},
|
},
|
||||||
onDownloadProgress: ProgressEvent => {
|
onDownloadProgress: ProgressEvent => {
|
||||||
console.log(ProgressEvent.loaded)
|
|
||||||
this.download_loaded = ProgressEvent.loaded
|
this.download_loaded = ProgressEvent.loaded
|
||||||
}
|
}
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
@@ -43,6 +232,8 @@ app.component('component-file', {
|
|||||||
link.setAttribute('download', file.filename);
|
link.setAttribute('download', file.filename);
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
|
this.download_loaded = 0
|
||||||
|
this.disabled = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -72,41 +263,86 @@ app.component('component-file', {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
app.component('component-audio-player', {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: ["file"],
|
||||||
|
template: `
|
||||||
|
<video v-if="computed_show" :src="computed_playing_audio_file_url" controls autoplay>
|
||||||
|
</video>
|
||||||
|
`,
|
||||||
|
computed: {
|
||||||
|
computed_playing_audio_file_url() {
|
||||||
|
return '/api/v1/get_file_direct?id=' + this.file.id
|
||||||
|
},
|
||||||
|
computed_show() {
|
||||||
|
return this.file.id ? true : false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
app.component('component-search-files', {
|
app.component('component-search-files', {
|
||||||
|
emits: ['play_audio'],
|
||||||
template: `
|
template: `
|
||||||
<input type="text" name="filename" v-model="search_filenames" />
|
<input type="text" name="filename" v-model="search_filenames" />
|
||||||
<input type="button" value="Search" @click="search_files(this)" />
|
<button @click="first_search_files">Search</button>
|
||||||
|
<button @click="last_page">Last Page</button>
|
||||||
|
<span>{{ offset }}~{{ offset + files.length }}</span>
|
||||||
|
<button @click="next_page">Next Page</button>
|
||||||
<table border="1">
|
<table border="1">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
<th>Filename</th>
|
<th>Filename</th>
|
||||||
|
<th>Folder Name</th>
|
||||||
<th>Size</th>
|
<th>Size</th>
|
||||||
<th>Action</th>
|
<th>Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="file in files">
|
<tr v-for="file in files">
|
||||||
<component-file :file=file></component-file>
|
<component-file :file=file @play_audio="$emit('play_audio', file)"></component-file>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
`,
|
`,
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
search_filenames: '',
|
||||||
files: [],
|
files: [],
|
||||||
|
offset: 0,
|
||||||
|
limit: 10,
|
||||||
|
playing_audio_file: {},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
search_files(app) {
|
first_search_files() {
|
||||||
axios.post('http://localhost:8080/api/v1/search_files', {
|
this.offset = 0
|
||||||
filename: app.search_filenames,
|
this.search_files()
|
||||||
limit: 10,
|
},
|
||||||
offset: 0,
|
search_files() {
|
||||||
}).then(function(response) {
|
axios.post('/api/v1/search_files', {
|
||||||
app.files = response.data.files
|
filename: this.search_filenames,
|
||||||
|
limit: this.limit,
|
||||||
|
offset: this.offset,
|
||||||
|
}).then((response) => {
|
||||||
|
this.files = response.data.files
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
last_page() {
|
||||||
|
this.offset = this.offset - this.limit
|
||||||
|
if (this.offset < 0) {
|
||||||
|
this.offset = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.search_files()
|
||||||
|
},
|
||||||
|
next_page() {
|
||||||
|
this.offset = this.offset + this.limit
|
||||||
|
this.search_files()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|||||||
Reference in New Issue
Block a user