1
This commit is contained in:
325
src/views/jarvis/kdocs/index.vue
Normal file
325
src/views/jarvis/kdocs/index.vue
Normal file
@@ -0,0 +1,325 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-card>
|
||||
<div slot="header" class="clearfix">
|
||||
<span>金山文档 在线表格</span>
|
||||
<el-button style="float: right; padding: 3px 0" type="text" @click="handleRefresh" :loading="loading">刷新</el-button>
|
||||
</div>
|
||||
|
||||
<el-alert v-if="!isAuthorized" title="未授权" type="warning" :closable="false" show-icon>
|
||||
<template slot="default">
|
||||
<span>请完成金山文档开放平台授权(个人云)</span>
|
||||
<el-button type="primary" size="small" style="margin-left: 10px" @click="handleAuthorize">立即授权</el-button>
|
||||
</template>
|
||||
</el-alert>
|
||||
|
||||
<el-alert v-else title="已授权" type="success" :closable="false" show-icon>
|
||||
<template slot="default">
|
||||
<span>授权状态:正常</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
|
||||
<el-card v-if="isAuthorized && userInfo" style="margin-top: 20px">
|
||||
<div slot="header">用户信息</div>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="open_id">{{ userInfo.user_id || userInfo.open_id || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="昵称">{{ userInfo.nickname || userInfo.name || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<el-card v-if="isAuthorized" style="margin-top: 20px">
|
||||
<div slot="header">
|
||||
<span>文件列表(个人云扁平列表)</span>
|
||||
<el-button type="primary" size="small" style="float: right" @click="handleLoadFiles(true)">加载 / 刷新</el-button>
|
||||
</div>
|
||||
<p v-if="listHint" class="list-hint">{{ listHint }}</p>
|
||||
<el-table v-loading="fileListLoading" :data="fileList" border style="width: 100%">
|
||||
<el-table-column prop="file_name" label="文件名" min-width="200" />
|
||||
<el-table-column prop="file_token" label="file_token" min-width="260" show-overflow-tooltip />
|
||||
<el-table-column prop="file_type" label="类型" width="100" />
|
||||
<el-table-column label="操作" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" size="mini" @click="handleEditFile(scope.row)">编辑表格</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="hasMoreFiles" style="margin-top: 12px">
|
||||
<el-button type="default" size="small" :loading="fileListLoading" @click="handleLoadMore">加载更多</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-dialog title="编辑表格" :visible.sync="editDialogVisible" width="80%" :close-on-click-modal="false">
|
||||
<div v-if="currentFile">
|
||||
<el-form :inline="true" class="demo-form-inline">
|
||||
<el-form-item label="工作表">
|
||||
<el-select v-model="currentSheetIdx" placeholder="请选择" @change="handleLoadSheetData">
|
||||
<el-option
|
||||
v-for="sheet in sheetList"
|
||||
:key="sheet.sheet_idx + '-' + sheet.name"
|
||||
:label="sheet.name + ' (idx:' + sheet.sheet_idx + ')'"
|
||||
:value="sheet.sheet_idx"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="单元格范围">
|
||||
<el-input v-model="cellRange" placeholder="例如:A1:B10" style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleLoadSheetData">读取数据</el-button>
|
||||
<el-button type="success" @click="handleUpdateCells">保存数据</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table v-loading="sheetDataLoading" :data="sheetData" border style="width: 100%; margin-top: 20px">
|
||||
<el-table-column
|
||||
v-for="(col, index) in sheetColumns"
|
||||
:key="index"
|
||||
:prop="'col' + index"
|
||||
:label="getColumnLabel(index)"
|
||||
min-width="120"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row['col' + index]" size="small" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getKdocsAuthUrl,
|
||||
getKdocsTokenStatus,
|
||||
getKdocsUserInfo,
|
||||
getKdocsFileList,
|
||||
getKdocsSheetList,
|
||||
readKdocsCells,
|
||||
updateKdocsCells
|
||||
} from '@/api/jarvis/kdocs'
|
||||
|
||||
export default {
|
||||
name: 'KdocsCloud',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
isAuthorized: false,
|
||||
userInfo: null,
|
||||
userId: 'default_user',
|
||||
fileList: [],
|
||||
fileListLoading: false,
|
||||
listHint: '',
|
||||
hasMoreFiles: false,
|
||||
nextOffset: null,
|
||||
nextFilter: null,
|
||||
editDialogVisible: false,
|
||||
currentFile: null,
|
||||
currentSheetIdx: 0,
|
||||
sheetList: [],
|
||||
sheetData: [],
|
||||
sheetDataLoading: false,
|
||||
cellRange: 'A1:Z100',
|
||||
sheetColumns: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.checkAuthStatus()
|
||||
},
|
||||
methods: {
|
||||
async checkAuthStatus() {
|
||||
try {
|
||||
const response = await getKdocsTokenStatus(this.userId)
|
||||
if (response.code === 200) {
|
||||
this.isAuthorized = response.data.hasToken && response.data.isValid
|
||||
if (this.isAuthorized) {
|
||||
this.loadUserInfo()
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
},
|
||||
async loadUserInfo() {
|
||||
try {
|
||||
const response = await getKdocsUserInfo(this.userId)
|
||||
if (response.code === 200) {
|
||||
this.userInfo = response.data
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
},
|
||||
async handleAuthorize() {
|
||||
try {
|
||||
const response = await getKdocsAuthUrl()
|
||||
if (response.code === 200) {
|
||||
window.open(response.data, '_blank')
|
||||
this.$message.success('请在新窗口完成授权,完成后回到本页刷新')
|
||||
}
|
||||
} catch (e) {
|
||||
this.$message.error(e.msg || e.message || '获取授权地址失败')
|
||||
}
|
||||
},
|
||||
handleRefresh() {
|
||||
this.checkAuthStatus()
|
||||
if (this.isAuthorized) {
|
||||
this.handleLoadFiles(true)
|
||||
}
|
||||
},
|
||||
/** @param {boolean} reset 是否重置游标从第一页拉取 */
|
||||
async handleLoadFiles(reset) {
|
||||
if (!this.isAuthorized) {
|
||||
this.$message.warning('请先授权')
|
||||
return
|
||||
}
|
||||
if (reset) {
|
||||
this.nextOffset = null
|
||||
this.nextFilter = null
|
||||
this.fileList = []
|
||||
}
|
||||
this.fileListLoading = true
|
||||
this.listHint = ''
|
||||
try {
|
||||
const params = {
|
||||
userId: this.userId,
|
||||
page: 1,
|
||||
pageSize: 50
|
||||
}
|
||||
if (this.nextOffset != null) {
|
||||
params.next_offset = this.nextOffset
|
||||
}
|
||||
if (this.nextFilter) {
|
||||
params.next_filter = this.nextFilter
|
||||
}
|
||||
const response = await getKdocsFileList(params)
|
||||
if (response.code === 200) {
|
||||
const chunk = response.data.files || []
|
||||
this.fileList = reset ? chunk : this.fileList.concat(chunk)
|
||||
this.nextOffset = response.data.next_offset
|
||||
this.nextFilter = response.data.next_filter || null
|
||||
this.hasMoreFiles = !!response.data.has_more
|
||||
this.listHint =
|
||||
'file_token 请使用列表中的值(来自文档 open_id)。在线表格工作表请选 sheet_type 为 et 的 sheet;数据表为 db 时需用数据表 API。'
|
||||
}
|
||||
} catch (e) {
|
||||
this.$message.error(e.msg || e.message || '加载失败')
|
||||
} finally {
|
||||
this.fileListLoading = false
|
||||
}
|
||||
},
|
||||
handleLoadMore() {
|
||||
if (!this.hasMoreFiles) return
|
||||
this.handleLoadFiles(false)
|
||||
},
|
||||
async handleEditFile(file) {
|
||||
this.currentFile = file
|
||||
this.editDialogVisible = true
|
||||
try {
|
||||
const response = await getKdocsSheetList(this.userId, file.file_token)
|
||||
if (response.code === 200) {
|
||||
this.sheetList = response.data.sheets || []
|
||||
if (this.sheetList.length > 0) {
|
||||
const first = this.sheetList[0]
|
||||
this.currentSheetIdx = first.sheet_idx != null ? first.sheet_idx : 0
|
||||
this.handleLoadSheetData()
|
||||
} else {
|
||||
this.$message.warning('未获取到工作表列表')
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
this.$message.error(e.msg || e.message || '加载工作表失败')
|
||||
}
|
||||
},
|
||||
extractCellValues(payload) {
|
||||
if (!payload) return []
|
||||
if (Array.isArray(payload.values)) return payload.values
|
||||
if (payload.data && Array.isArray(payload.data.values)) return payload.data.values
|
||||
return []
|
||||
},
|
||||
async handleLoadSheetData() {
|
||||
if (!this.currentFile) return
|
||||
this.sheetDataLoading = true
|
||||
try {
|
||||
const response = await readKdocsCells({
|
||||
userId: this.userId,
|
||||
fileToken: this.currentFile.file_token,
|
||||
sheetIdx: this.currentSheetIdx,
|
||||
range: this.cellRange
|
||||
})
|
||||
if (response.code === 200) {
|
||||
this.processSheetData(this.extractCellValues(response.data))
|
||||
}
|
||||
} catch (e) {
|
||||
this.$message.error(e.msg || e.message || '读取失败')
|
||||
} finally {
|
||||
this.sheetDataLoading = false
|
||||
}
|
||||
},
|
||||
processSheetData(values) {
|
||||
if (!values || values.length === 0) {
|
||||
this.sheetData = []
|
||||
this.sheetColumns = []
|
||||
return
|
||||
}
|
||||
const maxCols = Math.max(...values.map(row => (row ? row.length : 0)))
|
||||
this.sheetColumns = Array.from({ length: maxCols }, (_, i) => i)
|
||||
this.sheetData = values.map(row => {
|
||||
const rowData = {}
|
||||
const r = row || []
|
||||
r.forEach((cell, index) => {
|
||||
rowData['col' + index] = cell !== null && cell !== undefined ? String(cell) : ''
|
||||
})
|
||||
for (let i = r.length; i < maxCols; i++) {
|
||||
rowData['col' + i] = ''
|
||||
}
|
||||
return rowData
|
||||
})
|
||||
},
|
||||
getColumnLabel(index) {
|
||||
let label = ''
|
||||
let num = index
|
||||
while (num >= 0) {
|
||||
label = String.fromCharCode(65 + (num % 26)) + label
|
||||
num = Math.floor(num / 26) - 1
|
||||
}
|
||||
return label
|
||||
},
|
||||
async handleUpdateCells() {
|
||||
if (!this.currentFile) return
|
||||
const values = this.sheetData.map(row => {
|
||||
return this.sheetColumns.map(colIndex => {
|
||||
const v = row['col' + colIndex]
|
||||
return v !== undefined ? v : ''
|
||||
})
|
||||
})
|
||||
try {
|
||||
const response = await updateKdocsCells({
|
||||
userId: this.userId,
|
||||
fileToken: this.currentFile.file_token,
|
||||
sheetIdx: this.currentSheetIdx,
|
||||
range: this.cellRange,
|
||||
values
|
||||
})
|
||||
if (response.code === 200) {
|
||||
this.$message.success('保存成功')
|
||||
}
|
||||
} catch (e) {
|
||||
this.$message.error(e.msg || e.message || '保存失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
.list-hint {
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user