first commit

This commit is contained in:
2025-08-19 10:19:29 +08:00
commit 3b61e84a7f
3014 changed files with 2640574 additions and 0 deletions

View File

@ -0,0 +1,137 @@
<template>
<div class="book_file">
<!-- 添加或修改公司对话框 -->
<el-dialog v-model="isShowDialog" width="80vw" custom-class="book_file_loading" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div>查看资料文件</div>
</template>
<el-form ref="queryRef" :inline="true" label-width="100px">
<el-row>
<el-col :span="8" class="colBlock">
<el-form-item label="文件名称" prop="fileName">
<el-input v-model="formData.fileName" placeholder="请输入文件名称搜索" clearable @keyup.enter.native="getDataFileQuery" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item>
<el-button type="primary" @click="getDataFileQuery">
<el-icon><Search /></el-icon>搜索
</el-button>
<el-button @click="resetQuery" type="danger">
<el-icon><Refresh /></el-icon>清空
</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="content">
<div class="left_box" :style="treeList.length ? 'width: 70%' : 'width: 100%'">
<el-table v-loading="loading" :data="tableData" border height="63vh" :empty-text="emptyText">
<el-table-column label="序号" align="center" type="index" width="80px" />
<el-table-column label="文件名称" align="center" prop="fileName" min-width="100px" />
<el-table-column label="文件类型" align="center" prop="fileSuffix" width="100px" />
<el-table-column label="文件路径" align="center" min-width="100px">
<template #default="scope">
<span>{{ filterfilenPath(scope.row.filePath) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding" width="250px" fixed="right">
<template #default="scope">
<el-button type="success" link @click="onExport(scope.row)">
<el-icon><Download /></el-icon>下载
</el-button>
<el-button type="primary" link @click="onBook(scope.row)">
<el-icon><View /></el-icon>查看
</el-button>
</template>
</el-table-column>
</el-table>
<pagination :total="total" v-model:page="formData.pageNum" v-model:limit="formData.pageSize" @pagination="getDataFileQuery" />
</div>
</div>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { listKnowledgeDocument } from '@/api/design/technicalStandard';
import { useUserStoreHook } from '@/store/modules/user';
const emit = defineEmits(['onExport', 'onExportView', 'onBook']);
const stores = useUserStoreHook();
const loading = ref(false);
const tableData = ref<any[]>([]);
const isShowDialog = ref(false);
const formData = reactive({
fileName: '',
projectId: stores.selectedProject.id,
pageNum: 1,
pageSize: 10
});
const total = ref(0);
const emptyText = ref('暂无数据');
const treeList = ref<any[]>([]);
const openDialog = () => {
isShowDialog.value = true;
getDataFileQuery();
emptyText.value = '请输入文件名称进行搜索!';
resetForm();
};
const resetForm = () => {
tableData.value = [];
formData.fileName = '';
treeList.value = [];
emptyText.value = '暂无数据';
};
const getDataFileQuery = () => {
loading.value = true;
emptyText.value = '数据加载中……';
listKnowledgeDocument(formData).then((res: any) => {
loading.value = false;
tableData.value = [];
if (res.code == 200 && res.rows?.length) {
tableData.value = res.rows;
total.value = res.total;
} else {
emptyText.value = '没有查询到数据,请重新输入搜索';
}
});
};
const onBook = (row: any) => {
emit('onBook', row);
};
const onExport = (row: any) => {
emit('onExportView', row);
};
const resetQuery = () => {
tableData.value = [];
formData.fileName = '';
loading.value = false;
emptyText.value = '暂无数据';
};
const filterfilenPath = (val: string): string => {
return val.replace(/^.*?知识库\//, '知识库/');
};
defineExpose({ openDialog });
</script>
<style scoped lang="scss">
.book_file {
.content {
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
}
}
</style>

View File

@ -0,0 +1,190 @@
<template>
<div class="document_detail" id="document_detail">
<div class="move_pop" id="detial_pop">
<!-- <span>{{ title }}</span> -->
<div class="box">
<img v-if="type == 2" src="../icon/suo.png" @click="onFull(1)" />
<img v-else src="../icon/full.png" @click="onFull(2)" />
<span class="close" @click="onClose"></span>
</div>
</div>
<div class="box_app" id="box_app"></div>
</div>
</template>
<script lang="ts">
import { setMove } from '@/utils/moveDiv';
declare const CXO_API: any;
export default defineComponent({
name: 'index',
setup(props, { emit }) {
const { proxy } = <any>getCurrentInstance();
const state = reactive({
title: '',
type: 2
});
onMounted(() => {
setMove('detial_pop', 'document_detail');
});
// 打开弹窗
const openDialog = (obj) => {
state.title = obj.fileName;
init(obj);
};
const onError = function (event) {
//举例,强制保存后,判断文档内容是否保存成功
if (event.data) {
if (event.data.errorCode == 'forcesave') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//保存成功
} else {
//保存失败或异常
}
} else if (event.data.errorCode == 'setallcellvalue') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//填充成功
} else if (desc.error == -1) {
//当前文档正处于协同编辑中
} else {
//填充异常
}
} else if (event.data.errorCode == 'clearsheet') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//清除成功
} else if (desc.error == -1) {
//当前文档正处于协同编辑中
} else {
//清除异常
}
}
}
};
const onDocumentReady = function () {
// console.log('文档加载完成');
};
const init = (obj) => {
let documentKey = obj.id.toString() + new Date().getTime();
console.log('🚀 ~ init ~ url:', obj.fileUrl);
let type = obj.fileSuffix;
if (obj.fileSuffix.includes('.')) {
type = obj.fileSuffix.substring(1);
}
let documentType = 'word'; // docx doc
if (type == 'xlsx' || type == 'xls') {
documentType = 'cell'; //电子表格
} else if (type == 'ppt' || type == 'pptx') {
documentType = 'slide'; //演示文档文件
}
new CXO_API.CXEditor('box_app', {
document: {
fileType: type,
key: documentKey,
title: obj.fileName,
url: obj.fileUrl
},
documentType,
editorConfig: {
mode: 'view',
callbackUrl: ''
},
height: '100%',
events: {
onDocumentReady: onDocumentReady,
onError: onError
},
zoom: -1
});
};
const onClose = () => {
emit('onClose', false);
};
const onFull = (type) => {
// 全屏
let document_detail = document.getElementById('document_detail');
state.type = type;
if (type == 2) {
document_detail.style.width = '100%';
document_detail.style.height = '100%';
} else {
document_detail.style.width = '1200px';
document_detail.style.height = '80vh';
}
};
return {
proxy,
openDialog,
onClose,
onFull,
...toRefs(state)
};
}
});
</script>
<style lang="scss" scoped>
.document_detail {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 999999;
width: 100%;
height: 100%;
border: 1px solid #9f9f9f;
.box_app {
// width: 1300px !important;
// height: 80vh !important;
background-color: #f1f1f1;
}
.move_pop {
width: 100%;
// position: absolute;
// top: 0;
// right: 0%;
height: 24px;
// background: linear-gradient(#2a5095, #213f7b, #111e48);
background-color: #f4f5f6;
display: grid;
place-items: center;
> span {
color: #000000;
font-weight: bold;
font-size: 20px;
letter-spacing: 2px;
}
.box {
display: flex;
width: 60px;
position: absolute;
top: 0;
right: 10px;
// height: 100%;
align-items: center;
img {
width: 22px;
margin-top: 6px;
cursor: pointer;
}
.close {
position: absolute;
right: 2px;
/* top: -8px; */
color: #8d8d8d;
width: 24px;
height: 24px;
font-size: 20px;
//border: 2px solid #0ff;
border-radius: 50%;
display: grid;
place-items: center;
cursor: pointer;
}
}
}
}
</style>

View File

@ -0,0 +1,203 @@
<template>
<div class="document_detail_eidt" id="document_detail_eidt">
<div class="move_pop" id="detial_edit">
<!-- <span>{{ title }}</span> -->
<div class="box">
<img v-if="type == 2" src="../icon/full.png" @click="onFull(1)" />
<img v-else src="../icon/suo.png" @click="onFull(2)" />
<span class="close" @click="onClose"></span>
</div>
</div>
<div class="box_app" id="box_app_edit"></div>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted, ref, defineComponent, watch, getCurrentInstance } from 'vue';
import { setMove } from '@/utils/moveDiv';
import { useUserStoreHook } from '@/store/modules/user';
// Ensure CXO_API is available globally or import it if it's a module
// Example for global usage (e.g., included via script tag in index.html):
declare const CXO_API: any;
export default defineComponent({
name: 'index',
setup(props, { emit }) {
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const state = reactive({
title: '',
projectId: stores.selectedProject.id,
type: 2,
postUrl: ''
});
onMounted(() => {
setMove('detial_edit', 'document_detail_eidt');
});
// 打开弹窗
const openDialog = (obj, url) => {
state.postUrl = url;
state.title = obj.name;
init(obj);
};
const onError = function (event) {
console.log('编辑器错误: code ' + event.data.errorCode + ', 描述' + event.data.errorDescription);
//举例,强制保存后,判断文档内容是否保存成功
if (event.data) {
if (event.data.errorCode == 'forcesave') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//保存成功
} else {
//保存失败或异常
}
} else if (event.data.errorCode == 'setallcellvalue') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//填充成功
} else if (desc.error == -1) {
//当前文档正处于协同编辑中
} else {
//填充异常
}
} else if (event.data.errorCode == 'clearsheet') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//清除成功
} else if (desc.error == -1) {
//当前文档正处于协同编辑中
} else {
//清除异常
}
}
}
};
const onDocumentReady = function () {
console.log('文档加载完成');
};
const init = (obj) => {
let documentKey = obj.id.toString() + new Date().getTime();
let baseURL = import.meta.env.VITE_APP_BASE_API;
let type = obj.fileSuffix;
if (obj.fileSuffix.includes('.')) {
type = obj.fileSuffix.substring(1);
}
let documentType = 'word'; // docx doc
if (type == 'xlsx' || type == 'xls') {
documentType = 'cell'; //电子表格
} else if (type == 'ppt' || type == 'pptx') {
documentType = 'slide'; //演示文档文件
}
console.log(baseURL + state.postUrl + '?path=' + obj.filePath + '&id=' + obj.id);
new CXO_API.CXEditor('box_app_edit', {
document: {
fileType: obj.fileSuffix,
key: documentKey,
title: obj.fileName,
url: obj.fileUrl
},
documentType,
token: stores.token,
editorConfig: {
callbackUrl: baseURL + state.postUrl + obj.id + '?path=' + obj.filePath
},
events: {
onDocumentReady: onDocumentReady,
onError: onError
}
});
};
const onClose = () => {
emit('onClose', false);
};
const onFull = (type) => {
// 全屏
let document_detail = document.getElementById('document_detail_eidt');
state.type = type;
if (type == 2) {
// 弹框放大
document_detail.style.width = '100%';
document_detail.style.height = '100%';
} else {
// 弹框缩小
document_detail.style.width = '1200px';
document_detail.style.height = '80vh';
}
};
return {
proxy,
onFull,
openDialog,
onClose,
...toRefs(state)
};
}
});
</script>
<style lang="scss" scoped>
.document_detail_eidt {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 999999;
width: 100%;
height: 100%;
border: 1px solid #9f9f9f;
.box_app {
width: 1200px !important;
height: 80vh !important;
background-color: #f1f1f1;
margin-top: 100px;
}
.move_pop {
width: 100%;
// position: absolute;
// top: 0;
// right: 0%;
height: 24px;
// background: linear-gradient(#2a5095, #213f7b, #111e48);
background-color: #f4f5f6;
display: grid;
place-items: center;
> span {
color: #000000;
font-weight: bold;
font-size: 20px;
letter-spacing: 2px;
}
.box {
display: flex;
width: 60px;
position: absolute;
top: 0;
right: 10px;
// height: 100%;
align-items: center;
img {
width: 22px;
margin-top: 6px;
cursor: pointer;
}
.close {
position: absolute;
right: 2px;
/* top: -8px; */
color: #8d8d8d;
width: 24px;
height: 24px;
font-size: 20px;
//border: 2px solid #0ff;
border-radius: 50%;
display: grid;
place-items: center;
cursor: pointer;
}
}
}
}
</style>

View File

@ -0,0 +1,149 @@
<template>
<div class="system-document-container">
<el-card shadow="hover">
<div class="system-document-search mb-5">
<el-form :model="param" ref="queryRef" :inline="true" label-width="100px">
<el-row>
<el-col :span="2">
<el-button type="success" :disabled="multiple" @click="onRecyclingStation(null, true)">
<el-icon><RefreshRight /></el-icon>批量恢复
</el-button>
</el-col>
<el-col :span="2">
<el-button type="danger" :disabled="multiple" @click="onRecyclingStation(null, false)">
<el-icon><DeleteFilled /></el-icon>批量删除
</el-button>
</el-col>
</el-row>
</el-form>
</div>
<el-table v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" min-width="30px" />
<el-table-column label="文件名称" align="center" prop="fileName" min-width="100px" />
<el-table-column label="文件路径" align="center" min-width="100px">
<template #default="scope">
<span>{{ filterfilenPath(scope.row.filePath) }}</span>
</template>
</el-table-column>
<el-table-column label="删除时间" align="center" prop="createTime" min-width="100px" />
<el-table-column label="操作" align="center" class-name="small-padding" min-width="80px" fixed="right">
<template #default="scope">
<div>
<el-button type="success" link @click="onRecyclingStation(scope.row, true)">
<el-icon><RefreshRight /></el-icon>恢复
</el-button>
</div>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="param.pageNum" v-model:limit="param.pageSize" @pagination="getDocumentDataList" />
</el-card>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, getCurrentInstance, computed } from 'vue';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { documentDataAllList, templateRecycleBin, dataRecyclingStation } from '@/api/design/technicalStandard';
import { useUserStoreHook } from '@/store/modules/user';
const userStore = useUserStoreHook();
const currentProject = computed(() => userStore.selectedProject);
const loading = ref(false);
const queryRef = ref();
const multiple = ref(true);
const ids = ref<string>('');
const tableData = ref<any[]>([]);
const param = reactive({
type: 2,
projectId: currentProject.value?.id,
pageNum: 1,
pageSize: 10
});
const total = ref(0);
const value = ref('2');
const getDocumentDataList = () => {
loading.value = true;
tableData.value = [];
value.value = '2';
documentDataAllList(param).then((res: any) => {
tableData.value = res.rows ?? [];
total.value = res.total;
loading.value = false;
});
};
const handleSelectionChange = (selection: any[]) => {
ids.value = selection.map((item) => item.id).join(',');
multiple.value = !selection.length;
};
const onRecyclingStation = (row: any, flag: boolean) => {
let type = 2;
let selectedIds: string = '';
let title = '删除';
let msg = '你确定要删除所选文件或文件夹?';
if (row) {
selectedIds = row.id;
} else {
selectedIds = ids.value;
}
if (flag) {
type = 1;
title = '恢复';
msg = '你确定要恢复所选文件或文件夹?';
}
ElMessageBox.confirm(msg, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
const loadingInstance = ElLoading.service({
lock: true,
text: `正在${title}中……`,
background: 'rgba(0, 0, 0, 0.7)'
});
if (flag) {
dataRecyclingStation(selectedIds).then((res) => {
loadingInstance.close();
if (res.code == 200) {
getDocumentDataList();
ElMessage.success('操作成功');
}
});
} else {
templateRecycleBin(selectedIds).then((res) => {
loadingInstance.close();
if (res.code == 200) {
getDocumentDataList();
ElMessage.success('操作成功');
}
});
}
})
.catch(() => {});
};
const filterfilenPath = (val: string): string => {
return val.replace(/^.*?知识库\//, '知识库/');
};
defineExpose({
getDocumentDataList
});
</script>
<style lang="scss" scoped>
.colBlock {
display: block;
}
.colNone {
display: none;
}
</style>