454 lines
12 KiB
Vue
454 lines
12 KiB
Vue
<template>
|
||
<div class="app-container">
|
||
<el-card>
|
||
<div slot="header" class="clearfix">
|
||
<span>WPS365 在线表格管理</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>请先完成WPS365授权,才能使用文档编辑功能</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>
|
||
<el-button
|
||
type="danger"
|
||
size="small"
|
||
style="margin-left: 10px"
|
||
@click="handleRefreshToken">
|
||
刷新Token
|
||
</el-button>
|
||
</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="用户ID">{{ userInfo.user_id || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="用户名">{{ userInfo.name || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="邮箱">{{ userInfo.email || '-' }}</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">
|
||
加载文件
|
||
</el-button>
|
||
</div>
|
||
<el-table
|
||
v-loading="fileListLoading"
|
||
:data="fileList"
|
||
border
|
||
style="width: 100%">
|
||
<el-table-column prop="file_name" label="文件名" width="200" />
|
||
<el-table-column prop="file_token" label="文件Token" width="250" />
|
||
<el-table-column prop="file_type" label="类型" width="100" />
|
||
<el-table-column label="操作" width="200">
|
||
<template slot-scope="scope">
|
||
<el-button
|
||
type="primary"
|
||
size="mini"
|
||
@click="handleViewFile(scope.row)">
|
||
查看
|
||
</el-button>
|
||
<el-button
|
||
type="success"
|
||
size="mini"
|
||
@click="handleEditFile(scope.row)">
|
||
编辑
|
||
</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<pagination
|
||
v-show="fileTotal > 0"
|
||
:total="fileTotal"
|
||
:page.sync="queryParams.page"
|
||
:limit.sync="queryParams.pageSize"
|
||
@pagination="handleLoadFiles"
|
||
/>
|
||
</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, index) in sheetList"
|
||
:key="index"
|
||
:label="sheet.name"
|
||
:value="index">
|
||
</el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="单元格范围">
|
||
<el-input
|
||
v-model="cellRange"
|
||
placeholder="例如:A1:B10"
|
||
style="width: 200px">
|
||
</el-input>
|
||
</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">
|
||
</el-input>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
</el-dialog>
|
||
</el-card>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
getWPS365AuthUrl,
|
||
getWPS365TokenStatus,
|
||
getWPS365UserInfo,
|
||
getWPS365FileList,
|
||
getWPS365SheetList,
|
||
readWPS365Cells,
|
||
updateWPS365Cells,
|
||
refreshWPS365Token
|
||
} from '@/api/jarvis/wps365'
|
||
|
||
export default {
|
||
name: 'WPS365',
|
||
data() {
|
||
return {
|
||
loading: false,
|
||
isAuthorized: false,
|
||
userInfo: null,
|
||
userId: '', // 这里应该从登录用户获取,暂时使用配置
|
||
|
||
// 文件列表
|
||
fileList: [],
|
||
fileListLoading: false,
|
||
fileTotal: 0,
|
||
queryParams: {
|
||
page: 1,
|
||
pageSize: 20
|
||
},
|
||
|
||
// 编辑对话框
|
||
editDialogVisible: false,
|
||
currentFile: null,
|
||
currentSheetIdx: 0,
|
||
sheetList: [],
|
||
sheetData: [],
|
||
sheetDataLoading: false,
|
||
cellRange: 'A1:Z100',
|
||
sheetColumns: []
|
||
}
|
||
},
|
||
created() {
|
||
// 初始化时检查授权状态
|
||
// TODO: 从当前登录用户获取userId
|
||
this.userId = 'default_user' // 临时值,需要替换为实际用户ID
|
||
this.checkAuthStatus()
|
||
},
|
||
methods: {
|
||
/**
|
||
* 检查授权状态
|
||
*/
|
||
async checkAuthStatus() {
|
||
try {
|
||
const response = await getWPS365TokenStatus(this.userId)
|
||
if (response.code === 200) {
|
||
this.isAuthorized = response.data.hasToken && response.data.isValid
|
||
if (this.isAuthorized) {
|
||
this.loadUserInfo()
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('检查授权状态失败', error)
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 加载用户信息
|
||
*/
|
||
async loadUserInfo() {
|
||
try {
|
||
const response = await getWPS365UserInfo(this.userId)
|
||
if (response.code === 200) {
|
||
this.userInfo = response.data
|
||
}
|
||
} catch (error) {
|
||
console.error('加载用户信息失败', error)
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 处理授权
|
||
*/
|
||
async handleAuthorize() {
|
||
try {
|
||
const response = await getWPS365AuthUrl()
|
||
if (response.code === 200) {
|
||
// 在新窗口打开授权页面
|
||
window.open(response.data, '_blank')
|
||
this.$message.success('请在新窗口中完成授权,授权完成后刷新此页面')
|
||
}
|
||
} catch (error) {
|
||
this.$message.error('获取授权URL失败:' + (error.msg || error.message))
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 刷新Token
|
||
*/
|
||
async handleRefreshToken() {
|
||
try {
|
||
// TODO: 从存储中获取refreshToken
|
||
const response = await refreshWPS365Token({
|
||
refreshToken: '' // 需要从存储中获取
|
||
})
|
||
if (response.code === 200) {
|
||
this.$message.success('Token刷新成功')
|
||
this.checkAuthStatus()
|
||
}
|
||
} catch (error) {
|
||
this.$message.error('刷新Token失败:' + (error.msg || error.message))
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 刷新
|
||
*/
|
||
handleRefresh() {
|
||
this.checkAuthStatus()
|
||
if (this.isAuthorized) {
|
||
this.handleLoadFiles()
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 加载文件列表
|
||
*/
|
||
async handleLoadFiles() {
|
||
if (!this.isAuthorized) {
|
||
this.$message.warning('请先完成授权')
|
||
return
|
||
}
|
||
|
||
this.fileListLoading = true
|
||
try {
|
||
const response = await getWPS365FileList({
|
||
userId: this.userId,
|
||
page: this.queryParams.page,
|
||
pageSize: this.queryParams.pageSize
|
||
})
|
||
if (response.code === 200) {
|
||
this.fileList = response.data.files || []
|
||
this.fileTotal = response.data.total || 0
|
||
}
|
||
} catch (error) {
|
||
this.$message.error('加载文件列表失败:' + (error.msg || error.message))
|
||
} finally {
|
||
this.fileListLoading = false
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 查看文件
|
||
*/
|
||
handleViewFile(file) {
|
||
this.$message.info('查看文件功能开发中')
|
||
},
|
||
|
||
/**
|
||
* 编辑文件
|
||
*/
|
||
async handleEditFile(file) {
|
||
this.currentFile = file
|
||
this.editDialogVisible = true
|
||
|
||
// 加载工作表列表
|
||
try {
|
||
const response = await getWPS365SheetList(this.userId, file.file_token)
|
||
if (response.code === 200) {
|
||
this.sheetList = response.data.sheets || []
|
||
if (this.sheetList.length > 0) {
|
||
this.currentSheetIdx = 0
|
||
this.handleLoadSheetData()
|
||
}
|
||
}
|
||
} catch (error) {
|
||
this.$message.error('加载工作表列表失败:' + (error.msg || error.message))
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 加载工作表数据
|
||
*/
|
||
async handleLoadSheetData() {
|
||
if (!this.currentFile) {
|
||
return
|
||
}
|
||
|
||
this.sheetDataLoading = true
|
||
try {
|
||
const response = await readWPS365Cells({
|
||
userId: this.userId,
|
||
fileToken: this.currentFile.file_token,
|
||
sheetIdx: this.currentSheetIdx,
|
||
range: this.cellRange
|
||
})
|
||
|
||
if (response.code === 200) {
|
||
const values = response.data.values || []
|
||
this.processSheetData(values)
|
||
}
|
||
} catch (error) {
|
||
this.$message.error('加载工作表数据失败:' + (error.msg || error.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.length))
|
||
this.sheetColumns = Array.from({ length: maxCols }, (_, i) => i)
|
||
|
||
// 转换为表格数据格式
|
||
this.sheetData = values.map(row => {
|
||
const rowData = {}
|
||
row.forEach((cell, index) => {
|
||
rowData['col' + index] = cell !== null && cell !== undefined ? String(cell) : ''
|
||
})
|
||
// 填充空列
|
||
for (let i = row.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 value = row['col' + colIndex]
|
||
return value !== undefined ? value : ''
|
||
})
|
||
})
|
||
|
||
try {
|
||
const response = await updateWPS365Cells({
|
||
userId: this.userId,
|
||
fileToken: this.currentFile.file_token,
|
||
sheetIdx: this.currentSheetIdx,
|
||
range: this.cellRange,
|
||
values: values
|
||
})
|
||
|
||
if (response.code === 200) {
|
||
this.$message.success('更新成功')
|
||
}
|
||
} catch (error) {
|
||
this.$message.error('更新失败:' + (error.msg || error.message))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.app-container {
|
||
padding: 20px;
|
||
}
|
||
</style>
|
||
|