Files
ruoyi-vue/src/views/jarvis/wps365/index.vue
2026-01-14 22:55:39 +08:00

454 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>