需求:现需要用uniapp做一个离线app,要求可以在本地新建并操作数据表,可导入导出数据。
- 建数据库(在项目根目录下的App.vue)
javascript
import DB from '@/sqlite/sqlite';
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
},
created: function() {
this.openSqlite();
},
destroyed: function() {
this.closeSqlite();
},
methods: {
async openSqlite() {
try {
// 判断数据库打开状态
var flag = await DB.isOpen();
if (!flag) {
// 创建/打开数据库
await DB.openSqlite();
console.log('数据库打开成功');
} else {
console.log('数据库已打开');
}
} catch (err) {
console.error('数据库操作失败:', error);
}
},
async closeSqlite() {
try {
await DB.closeSqlite();
console.log('数据库关闭成功');
} catch (error) {
console.error('数据库操作失败:', error);
}
},
},
}
- 建表
javascript
<template>
<view class="content">
<button @click="createTable">建表</button>
<button @click="insertTableData">插入数据</button>
<button @click="selectTableData">查询数据</button>
<button @click="updateTableData">更新数据</button>
<button @click="deleteTableData">删除数据</button>
<button @click="downLoadTableData">导出数据Excel文件</button>
<button @click="handleFileChange">上传.db文件</button>
<button @click="importTableData">导入sql脚本</button>
<button @click="exportDbToSql">导出sql脚本</button>
</view>
</template>
<script>
import DB from '@/sqlite/sqlite';
import * as XLSX from 'xlsx';
export default {
data() {
return {
}
},
methods: {
async createTable() {
await DB.createTable('users', 'id INTEGER PRIMARY KEY, name TEXT, age INTEGER');
console.log('表创建成功');
},
async insertTableData() {
await DB.insertTableData('users', '2, \'Alice\', 40');
console.log('数据插入成功');
},
async selectTableData() {
const result = await DB.selectTableData('student');
console.log('查询结果:', result);
},
async updateTableData() {
// 更新数据
await DB.updateTableData('users', 'age = 31', 'id', '1');
console.log('数据更新成功');
},
async deleteTableData() {
// 删除数据
await DB.deleteTableData('users', 'id', '1');
console.log('数据删除成功');
},
async downLoadTableData() {
const result = await DB.selectTableData('users');
this.exportToExcel(result, 'example');
},
tableToExcel(tableHtml) {
//列标题
let worksheet = "sheet1";
//下载的表格模板数据
let template = `<html xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns="http://www.w3.org/TR/REC-html40">
<head><!--[if gte mso 9]><xml encoding="UTF-8"><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>
<x:Name>${worksheet}</x:Name>
<x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>
</x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->
</head><body>${tableHtml}</body></html>`;
return template;
},
exportToExcel(data, filename) {
const sheet = XLSX.utils.json_to_sheet(data);
const htmlSheet = XLSX.utils.sheet_to_html(sheet);
const pattern = /<table(?:(?!<\/table>).|\n)*?<\/table>/;
const tableHtml = htmlSheet.match(pattern)[0];
const writeData = this.tableToExcel(tableHtml);
plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, function(fs) {
let root = fs.root;
// 直接在 documents 中创建文件
root.getFile(
filename + `${new Date().getTime()}.xlsx`, {
create: true,
},
(fileEntry) => {
fileEntry.createWriter(
(writer) => {
// 写入数据
writer.write(writeData);
// 写入文件成功完成的回调函数
writer.onwrite = (e) => {
uni.showToast({
title: `导出成功`,
icon: "none",
});
};
},
(err) => {
console.log(err, "创建文件写入器错误");
}
);
},
(err) => {
console.log(err);
}
);
});
},
// 上传文件同步数据库
handleFileChange(event) {
plus.io.chooseFile({
title: '选择文件', // 选择文件的标题提示
filter: '*', // 筛选文件类型,* 表示所有,也可设 '.pdf,.docx' 等
multiple: false // 是否多选
},
(res) => {
const fileInfo = res.files[0]; // 获取选中的文件信息
const localPath = fileInfo.path; // 文件本地路径
// 可通过 plus.io 进一步操作文件,如读取内容、转成可上传的格式
// 示例:转成临时文件路径,用于 uni.uploadFile
const tempFilePath = plus.io.convertLocalFileSystemURL(localPath);
const tempFilePath2 = plus.io.convertLocalFileSystemURL(fileInfo);
// 执行上传等操作
console.log(fileInfo);
console.log(localPath);
console.log(tempFilePath2);
// 上传1↓
// plus.io.resolveLocalFileSystemURL(tempFilePath2, (entry) => {
// entry.file((file) => {
// console.log(file);
// const fileReader = new plus.io.FileReader();
// fileReader.onload = (e) => {
// console.log(e.target.result);
// const buffer = e.target.result; // 文件内容的 Buffer 数据
// // 若服务端需要 FormData 格式,可构造后用 uni.request 上传
// const formData = new FormData();
// formData.append('file', new Blob([buffer]), file.name);
// console.log(formData,'formData');
// uni.request({
// url: 'https://your-server.com/upload',
// method: 'POST',
// header: {
// 'Content-Type': 'multipart/form-data'
// },
// data: formData,
// success: (res) => {
// console.log('上传成功:', res.data);
// }
// });
// };
// console.log(444);
// fileReader.readAsArrayBuffer(file);
// });
// });
// 上传2↓
uni.uploadFile({
url: 'https://your-server.com/upload', // 实际的服务端文件上传接口
filePaths: [tempFilePath2], // 前面选择文件得到的临时路径
name: 'file', // 与服务端约定的接收文件的字段名
formData: {
// 可附带其他业务参数,如用户 ID、文件分类等
userId: '123',
category: 'document'
},
success: (uploadRes) => {
const data = JSON.parse(uploadRes.data);
console.log('上传成功,服务端返回:', data);
// 可依据服务端返回做后续处理,如更新文件列表、提示用户等
},
fail: (err) => {
console.error('上传失败:', err);
}
});
},
(err) => {
console.error('选择文件失败:', err);
}
);
},
// 读取文件
importTableData() {
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, function(fs) {
fs.root.getFile('main.sql', {
create: false
}, function(fileEntry) {
fileEntry.file(function(file) {
var fileReader = new plus.io.FileReader();
fileReader.onloadend = async function(evt) {
// console.log('文件内容:', evt.target.result);
const sqlContent = evt.target.result;
const statements = sqlContent.split(';').filter(
Boolean); // 移除空语句
for (let statement of statements) {
await DB.importTableData(statement);
}
};
fileReader.readAsText(file, 'utf-8');
}, function(e) {
console.log('获取文件对象失败:', e);
});
}, function(e) {
console.log('打开文件失败:', e);
});
}, function(e) {
console.log('请求文件系统失败:', e);
});
},
// 导出sql脚本
// 导出数据库脚本到 SQL 文件
async exportDbToSql() {
try {
const tables = await DB.getAllTables();
if (tables.length === 0) {
uni.showToast({
title: '数据库无表',
icon: 'none'
});
return;
}
// 构建 SQL 内容(先删除表,再创建表,最后插入数据)
this.sqlContent = '-- 导出时间: ' + new Date().toLocaleString() + '\n\n';
for (const table of tables) {
// 1. 添加删除表语句(可选,导入时先清除旧表)
this.sqlContent += `DROP TABLE IF EXISTS ${table};\n`;
// 2. 添加建表语句
const createSql = await DB.getTableCreateSql(table);
this.sqlContent += createSql + '\n';
// 3. 添加数据 INSERT 语句
const dataSql = await DB.getTableDataSql(table);
if (dataSql) {
this.sqlContent += dataSql + '\n';
}
}
// 保存 SQL 文件到本地
await this.saveSqlToFile();
uni.showToast({
title: '导出成功',
icon: 'success'
});
} catch (e) {
console.error(' 导出失败:', e);
uni.showToast({
title: `导出失败: ${e}`,
icon: 'none'
});
} finally {
}
},
// 将 SQL 内容保存为文件
saveSqlToFile() {
return new Promise((resolve, reject) => {
// 文件路径:_doc 目录下的 export_xxx.sql (支持读写)
const fileName = `export_${new Date().getTime()}.sql`;
const filePath = `${plus.io.convertLocalFileSystemURL('_doc')}/${fileName}`;
// 写入文件(H5+ 文件系统 API)
const fs = plus.io.requestFileSystem(plus.io.PRIVATE_DOC, (fs) => {
fs.root.getFile(fileName, {
create: true
}, (fileEntry) => {
fileEntry.createWriter((writer) => {
writer.onwriteend = () => {
console.log(`SQL 文件已保存: ${filePath}`);
// 可在此处调用分享功能(如 uni.share 或打开文件路径)
uni.showModal({
title: '导出成功',
content: `文件路径: ${filePath}\n是否打开文件?`,
success: (res) => {
if (res.confirm) {
plus.runtime.openFile(
filePath
); // 打开文件(需系统支持 .sql 格式)
}
}
});
resolve(filePath);
};
writer.onerror = (e) => reject(`写入文件失败: ${e.message}`);
writer.write(this.sqlContent); // 写入 SQL 内容
}, (e) => reject(`创建写入流失败: ${e.message}`));
}, (e) => reject(`获取文件失败: ${e.message}`));
}, (e) => reject(`获取文件系统失败: ${e.message}`));
});
}
}
}
</script>