This commit is contained in:
2025-07-16 18:33:13 +08:00
parent e2c18bf8df
commit 122208d9cb
8 changed files with 617 additions and 179 deletions

View File

@ -1,23 +1,51 @@
<template>
<el-dialog :title="titleValue" width="1400px" :model-value="modelValue" append-to-body @close="closed">
<el-dialog
:title="titleValue"
width="1400px"
:model-value="modelValue"
append-to-body
@close="closed"
>
<div>
<el-form :model="listQuery" class="mosty-from-wrap" :inline="true">
<el-form-item label="标签名称">
<el-input placeholder="请输入标签名称" v-model="listQuery.bqMc" clearable ></el-input>
<el-input
placeholder="请输入标签名称"
v-model="listQuery.bqMc"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button type="success" @click="handleFilter">查询</el-button>
<el-button type="info" @click="reset"> 重置 </el-button>
</el-form-item>
</el-form>
<div class="tabBox" :class="props.Single ? 'tabBoxRadio' : ''" :key="keyVal" style="margin-top: 0px">
<el-table ref="multipleUserRef" @selection-change="handleSelectionChange" :data="tableData" v-loading="loading" border :row-key="keyid" style="width: 100%" height="450">
<el-table-column type="selection" width="55" :reserve-selection="true"/>
<el-table-column prop="bqMc" align="center" label="标签名称"/>
<el-table-column prop="bqDm" align="center" label="标签代码"/>
<div
class="tabBox"
:class="props.Single ? 'tabBoxRadio' : ''"
:key="keyVal"
style="margin-top: 0px"
>
<el-table
ref="multipleUserRef"
@selection-change="handleSelectionChange"
:data="tableData"
v-loading="loading"
border
:row-key="keyid"
style="width: 100%"
height="450"
>
<el-table-column
type="selection"
width="55"
:reserve-selection="true"
/>
<el-table-column prop="bqMc" align="center" label="标签名称" />
<el-table-column prop="bqDm" align="center" label="标签代码" />
<el-table-column prop="bqDj" align="center" label="标签等级">
<template #default="{ row }">
<DictTag :tag="false" :value="row.bqDj" :options="D_GS_BQ_DJ" />
<DictTag :tag="false" :value="row.bqDj" :options="D_GS_BQ_DJ" />
</template>
</el-table-column>
<el-table-column prop="bqYs" align="center" label="标签颜色">
@ -50,14 +78,14 @@
</template>
<script setup>
import { qcckGet} from "@/api/qcckApi.js";
import { defineProps, ref ,getCurrentInstance, watch} from "vue";
import { qcckGet } from "@/api/qcckApi.js";
import { defineProps, ref, getCurrentInstance, watch } from "vue";
const { proxy } = getCurrentInstance();
const { D_GS_BQ_DJ,D_GS_SSYJ } = proxy.$dict("D_GS_BQ_DJ","D_GS_SSYJ"); //获取字典数据
const { D_GS_BQ_DJ, D_GS_SSYJ } = proxy.$dict("D_GS_BQ_DJ", "D_GS_SSYJ"); //获取字典数据
const props = defineProps({
modelValue: {
type: Boolean,
default:false
default: false
},
titleValue: {
type: String,
@ -77,14 +105,14 @@ const props = defineProps({
default: []
}
});
const loading = ref(false)
const loading = ref(false);
const total = ref(0);
const listQuery = ref({
pages: 1,
size: 20
});
const keyVal = ref()
const keyVal = ref();
const multipleUserRef = ref(null);
const multipleSelectionUser = ref([]);
const tableData = ref([]);
@ -97,11 +125,10 @@ const closed = () => {
emits("update:modelValue", false);
};
const reset = () => {
listQuery.value = { pages: 1, size: 20, };
listQuery.value = { pages: 1, size: 20 };
getListData();
};
// 为用户分配角色
const onComfirm = () => {
const userList = multipleSelectionUser.value;
@ -133,21 +160,23 @@ const handleCurrentChange = (currentPage) => {
const getListData = () => {
keyVal.value++;
loading.value = true;
const params = { ...listQuery.value, bqLb:'02',}
qcckGet(params,'/mosty-gsxt/tbGsxtBqgl/selectPage').then(res=>{
loading.value = false;
tableData.value = res.records || [];
total.value = res.total;
multipleUser();
}).catch(()=>{
loading.value = false;
})
const params = { ...listQuery.value, bqLb: "02" };
qcckGet(params, "/mosty-gsxt/tbGsxtBqgl/selectPage")
.then((res) => {
loading.value = false;
tableData.value = res.records || [];
total.value = res.total;
multipleUser();
})
.catch(() => {
loading.value = false;
});
};
//列表回显
function multipleUser() {
tableData.value.forEach((item) => {
multipleUserRef.value.toggleRowSelection(item, false);
multipleUserRef.value.toggleRowSelection(item, false);
if (props.roleIds.some((id) => id == item.id)) {
multipleUserRef.value.toggleRowSelection(item, true);
}
@ -171,10 +200,13 @@ const handleSelectionChange = (val) => {
}
};
watch(()=>props.modelValue,val=>{
if(val) handleFilter();
},{immediate:true})
watch(
() => props.modelValue,
(val) => {
if (val) handleFilter();
},
{ immediate: true }
);
</script>
<style lang="scss" scoped>
@ -188,5 +220,4 @@ watch(()=>props.modelValue,val=>{
.tabBoxRadio .el-table__header-wrapper .el-checkbox {
display: none;
}
</style>

View File

@ -1,8 +1,15 @@
<template>
<!--选择图标-->
<div class="form-item-box choose-icon-zj" :style="{ width: width }">
<el-autocomplete v-bind="$attrs" v-model="modelValue" :fetch-suggestions="querySearch"
popper-class="choose-icon-zj-autocomplete" :placeholder="placeholder" @change="onInput" @select="handleSelect">
<el-autocomplete
v-bind="$attrs"
v-model="modelValue"
:fetch-suggestions="querySearch"
popper-class="choose-icon-zj-autocomplete"
:placeholder="placeholder"
@change="onInput"
@select="handleSelect"
>
<template #prefix>
<SvgIcon :icon="modelValue"></SvgIcon>
</template>
@ -57,8 +64,7 @@ const handleSelect = (item) => {
emits("update:modelValue", item.value);
};
const handleIconClick = (ev) => {
};
const handleIconClick = (ev) => {};
const loadAll = () => {
const svgRequire = require.context("@/icons/svg", false, /\.svg$/);

View File

@ -0,0 +1,238 @@
<template>
<div>
<el-dialog
v-model="modelValue"
title="文件解析"
width="1000px"
:show-close="true"
:center="true"
:close-on-click-modal="false"
:before-close="handleClose"
>
<h1>文件文本提取工具</h1>
<p>上传文件提取文本内容支持 .txt, .pdf, .docx, mp4 , mp3, wav</p>
<div class="container">
<input
type="file"
id="file-input"
accept=".txt,.pdf,.docx,'.mp4','.mp3','.wav'"
/>
<button @click="chooseFile">选择文件</button>
<p id="file-info">未选择文件</p>
</div>
<button id="extract-btn" disabled>提取文本</button>
<h3>提取结果</h3>
<div id="result">请先上传文件...</div>
<template #footer>
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="onComfirm">确认</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { nextTick, onMounted, ref } from "vue";
const props = defineProps({
modelValue: {
type: Boolean,
default: false
}
});
const emits = defineEmits(["update:modelValue", "change"]);
onMounted(() => {
nextTick(() => {
const fileInput = document.getElementById("file-input");
const fileInfo = document.getElementById("file-info");
const extractBtn = document.getElementById("extract-btn");
const resultDiv = document.getElementById("result");
let selectedFile = null;
// 监听文件选择
fileInput.addEventListener("change", function (e) {
if (e.target.files.length > 0) {
selectedFile = e.target.files[0];
fileInfo.textContent = `已选择: ${selectedFile.name} (${(
selectedFile.size / 1024
).toFixed(2)} KB)`;
extractBtn.disabled = false;
} else {
selectedFile = null;
fileInfo.textContent = "未选择文件";
extractBtn.disabled = true;
}
if (selectedFile.type == "video/mp4") {
upfileOnchange(selectedFile);
}
});
// 提取文本按钮点击事件
extractBtn.addEventListener("click", async function () {
if (!selectedFile) return (resultDiv.textContent = "请先选择文件");
resultDiv.textContent = "正在处理文件...";
try {
let text = "";
const fileType = selectedFile.name.split(".").pop().toLowerCase();
console.log(selectedFile);
if (fileType === "txt") {
// 处理文本文件
text = await readTextFile(selectedFile);
} else if (fileType === "pdf") {
// 处理PDF文件
text = await extractTextFromPDF(selectedFile);
} else if (fileType === "docx") {
// 处理Word文件
text = await extractTextFromDocx(selectedFile);
console.log(text, "===word");
} else if (["mp4", "mp3", "wav"].includes(fileType)) {
// 处理mp4,mp3,wav文件
await start();
text = "数据加载有点慢,请稍等。。。。";
setTimeout(() => {
resultDiv.textContent = videoText;
}, 2000);
} else {
throw new Error("不支持的文件类型");
}
resultDiv.textContent = text || "未提取到文本内容";
} catch (error) {
resultDiv.textContent = `处理失败: ${error.message}`;
console.error(error);
}
});
});
});
// 读取文本文件
function readTextFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => resolve(e.target.result);
reader.onerror = (e) => reject(new Error("文件读取失败"));
reader.readAsText(file);
});
}
// 提取PDF文本
async function extractTextFromPDF(file) {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onload = async function () {
try {
const typedArray = new Uint8Array(this.result);
const pdf = await pdfjsLib.getDocument(typedArray).promise;
let fullText = "";
for (let i = 1; i <= pdf.numPages; i++) {
const page = await pdf.getPage(i);
const textContent = await page.getTextContent();
const text = textContent.items.map((item) => item.str).join(" ");
fullText += text + "\n\n";
}
resolve(fullText);
} catch (error) {
reject(error);
}
};
fileReader.onerror = reject;
fileReader.readAsArrayBuffer(file);
});
}
// 提取Word文档文本
async function extractTextFromDocx(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = function (event) {
const arrayBuffer = event.target.result;
mammoth
.extractRawText({ arrayBuffer: arrayBuffer })
.then(function (result) {
resolve(result.value);
})
.catch(function (error) {
reject(error);
});
};
reader.onerror = reject;
reader.readAsArrayBuffer(file);
});
}
const onComfirm = () => {
const resultDiv = document.getElementById("result");
let obj = {
text: resultDiv.textContent
};
emits("change", obj);
};
// 关闭
const handleClose = () => {
const resultDiv = document.getElementById("result");
resultDiv.textContent = "请先上传文件";
const fileInfo = document.getElementById("file-info");
fileInfo.textContent = "未选择文件";
emits("update:modelValue", false);
};
const chooseFile = () => {
document.getElementById("file-input").click();
};
</script>
<style lang="scss" scoped>
.container {
border: 2px dashed #ccc;
padding: 20px;
text-align: center;
margin-bottom: 20px;
}
#file-input {
display: none;
}
button {
background: #4caf50;
color: white;
padding: 10px 15px;
border: none;
cursor: pointer;
font-size: 16px;
border-radius: 4px;
}
button:hover {
background: #45a049;
}
#result {
margin-top: 20px;
white-space: pre-wrap;
background: #f9f9f9;
padding: 15px;
border: 1px solid #ddd;
border-radius: 4px;
height: 320px;
overflow-y: auto;
}
#file-info {
margin: 10px 0;
font-style: italic;
color: #666;
}
::v-deep .el-dialog {
margin-top: 10px;
}
</style>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,35 +1,17 @@
<template>
<div class="exportBox">
<el-dialog
v-model="show"
title="导入文件"
width="400px"
:show-close="true"
:center="true"
:before-close="handleClose"
>
<el-dialog v-model="show" title="导入文件" width="400px" :show-close="true" :center="true" :before-close="handleClose">
<div class="uplodBox">
<el-upload
action="#"
drag
:on-success="handleSuccess"
:on-change="handleChange"
:show-file-list="true"
:file-list="fileDate"
accept=".xls,.xlsx"
:auto-upload="false"
>
<el-upload action="#" drag :on-success="handleSuccess" :on-change="handleChange" :show-file-list="true" :file-list="fileDate" accept=".xls,.xlsx" :auto-upload="false">
<el-icon class="el-icon-upload" size="100"><upload-filled /></el-icon>
<div class="el-upload-text">
拖动或者点击上传或者<span @click.stop="downloadModel" class="model">下载模板</span>
</div>
<div>仅支持扩展名.xls , xlsx</div>
<div>仅支持扩展名.xls , xlsx</div>
</el-upload>
</div>
<div class="check">
<el-checkbox true-label="true" false-label="false" v-model="isSelect"
>是否替换已存在的数据</el-checkbox
>
<el-checkbox true-label="true" false-label="false" v-model="isSelect">是否替换已存在的数据</el-checkbox>
</div>
<div class="foot">
<el-button @click="handleClose">取消</el-button>
@ -42,7 +24,6 @@
<script setup>
import axios from "axios";
import { ElMessage } from "element-plus";
import { qcckPost, qcckGet } from "@/api/qcckApi.js";
import { useStore } from "vuex";
import { ref, defineProps, defineEmits, watch } from "vue";
const store = useStore();
@ -60,30 +41,30 @@ const filesList = ref({});
const baseUrl = ref('')//上传地址
const modelUrl = ref('')//下载模板地址
watch(()=>props.lx,(val)=>{
switch (val) {
case 'policeF':
baseUrl.value = '/mosty-api/mosty-jcgl/tbJcglXfll/importData'
modelUrl.value = '/mosty-api/mosty-jcgl/tbJcglXfll/importTemplate'
break;
case 'car':
baseUrl.value = '/mosty-api/mosty-jcgl/tpJcglXfcl/importData'
modelUrl.value = '/mosty-api/mosty-jcgl/tpJcglXfcl/importTemplate'
break;
case 'jyqx':
baseUrl.value = '/mosty-api/mosty-jcgl/tpJcglJyqx/importData'
modelUrl.value = '/mosty-api/mosty-jcgl/tpJcglJyqx/importTemplate'
break;
case 'znzb':
baseUrl.value = '/mosty-api/mosty-jcgl/tpjcglZnzb/importData'
modelUrl.value = '/mosty-api/mosty-jcgl/tpjcglZnzb/importTemplate'
break;
case 'fjnr':
baseUrl.value = '/mosty-api/mosty-gsxt/tbGsxtRqfjNr/importFxnr'
// modelUrl.value = '/mosty-api/mosty-jcgl/tpjcglZnzb/importTemplate'
break;
default:
break;
}
switch (val) {
case 'policeF':
baseUrl.value = '/mosty-api/mosty-jcgl/tbJcglXfll/importData'
modelUrl.value = '/mosty-api/mosty-jcgl/tbJcglXfll/importTemplate'
break;
case 'car':
baseUrl.value = '/mosty-api/mosty-jcgl/tpJcglXfcl/importData'
modelUrl.value = '/mosty-api/mosty-jcgl/tpJcglXfcl/importTemplate'
break;
case 'jyqx':
baseUrl.value = '/mosty-api/mosty-jcgl/tpJcglJyqx/importData'
modelUrl.value = '/mosty-api/mosty-jcgl/tpJcglJyqx/importTemplate'
break;
case 'znzb':
baseUrl.value = '/mosty-api/mosty-jcgl/tpjcglZnzb/importData'
modelUrl.value = '/mosty-api/mosty-jcgl/tpjcglZnzb/importTemplate'
break;
case 'fjnr':
baseUrl.value = '/mosty-api/mosty-gsxt/tbGsxtRqfjNr/importFxnr'
// modelUrl.value = '/mosty-api/mosty-jcgl/tpjcglZnzb/importTemplate'
break;
default:
break;
}
},{
immediate:true