Compare commits

...

146 Commits

Author SHA1 Message Date
lcw
71487ac647 lcw 2025-08-06 14:25:36 +08:00
lcw
2b06febd8e lcw 2025-08-01 17:16:03 +08:00
42e9bd894c 解决冲突 2025-07-31 11:39:51 +08:00
820d543f4a 123 2025-07-31 11:19:06 +08:00
50ff873463 重点车辆 2025-07-31 10:38:34 +08:00
a5c48d796c Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-07-28 15:00:14 +08:00
058b870b35 更新 2025-07-28 15:00:10 +08:00
lcw
951ff3cba2 lcw 2025-07-28 11:00:43 +08:00
lcw
24351e4f7d Remove ignored files 2025-07-28 11:00:20 +08:00
lcw
33a5f56d83 lcw 2025-07-28 10:54:12 +08:00
lcw
81b2319acc lcw 2025-07-28 10:47:50 +08:00
b3b30026c9 更新退出登录 2025-07-28 10:04:49 +08:00
1c3a25f527 更新退出登录 2025-07-28 09:58:35 +08:00
bcbf0be923 更新 2025-07-25 15:22:39 +08:00
78c589bf3c 删除图片 2025-07-25 14:30:50 +08:00
4f4530bc2a 更新 2025-07-25 14:27:01 +08:00
cd4b85c587 更新数据 2025-07-25 09:49:45 +08:00
326d0f0d13 更新数据 2025-07-25 09:30:42 +08:00
73fc5e2a00 更新数据 2025-07-24 17:59:32 +08:00
a961f32d93 更新列表 2025-07-24 17:26:55 +08:00
1e1cbdf6f1 更新数据 2025-07-24 15:56:36 +08:00
1dc72750f6 更新数据 2025-07-24 15:02:47 +08:00
18e569cdd0 更新 2025-07-24 14:50:56 +08:00
3b30b2b834 更新页面 2025-07-24 14:40:46 +08:00
03d2e9f459 更新 2025-07-24 11:20:50 +08:00
2eb2a41b06 qwewq 2025-07-23 15:33:11 +08:00
3d439b62e6 123213 2025-07-23 15:32:53 +08:00
63442217fc 修改 2025-07-23 15:14:50 +08:00
b6e8df30ff 更新 2025-07-22 19:01:34 +08:00
e453742024 更新 2025-07-22 18:22:40 +08:00
6396f9c13c 跟新数据 2025-07-22 18:18:49 +08:00
3870addd51 更新数据 2025-07-22 18:00:05 +08:00
677f2c4a3b 更新数据 2025-07-22 17:29:45 +08:00
7d809e52d2 更新数据 2025-07-22 17:20:57 +08:00
36d23fcbdb 更新数据 2025-07-22 15:01:30 +08:00
3c1c42a8c5 更新 2025-07-22 14:08:37 +08:00
6d106674bd 更新 2025-07-22 13:55:06 +08:00
33ceb7a85a 更新 2025-07-22 13:52:05 +08:00
8ea67fd810 更新 2025-07-22 09:39:36 +08:00
a334d9f61e Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-07-22 09:37:14 +08:00
08ba25b66a 更新 2025-07-22 09:37:10 +08:00
fdab1188c0 12312 2025-07-21 23:06:28 +08:00
cf8651fb14 更新 2025-07-21 18:02:57 +08:00
49ae691b37 更新 2025-07-21 17:03:41 +08:00
211b947c3c 更新页面 2025-07-21 16:14:09 +08:00
fdf75c11d2 更新 2025-07-20 19:31:19 +08:00
b8f943ca79 更新 2025-07-20 19:20:12 +08:00
83d732d805 更新 2025-07-20 18:21:13 +08:00
c1abd76205 更新数据 2025-07-20 18:12:14 +08:00
2ab7f59898 更新 2025-07-20 18:03:51 +08:00
a6b918f762 更新数据 2025-07-20 16:02:24 +08:00
32de231f1b 更新 2025-07-20 15:20:29 +08:00
057cd0fda6 跟新 2025-07-19 20:36:02 +08:00
1074049a6b 更新 2025-07-19 20:33:14 +08:00
671e33492d 更新 2025-07-19 19:42:46 +08:00
465876a5cc 更新 2025-07-19 18:55:21 +08:00
8b92e91215 更新 2025-07-19 18:53:41 +08:00
f4bd352162 更新 2025-07-19 18:37:07 +08:00
fbd2431f63 更新数据 2025-07-19 17:08:53 +08:00
72a2e174c1 更新 2025-07-19 15:54:53 +08:00
874b4a5994 更新 2025-07-19 15:49:31 +08:00
5ccbc7f3d4 更新页面 2025-07-19 15:34:47 +08:00
ce8eee2380 更新 2025-07-19 14:06:46 +08:00
e447346af5 更新 2025-07-18 15:41:40 +08:00
92c3c00b98 更新页面 2025-07-18 15:41:15 +08:00
20cb6743cd 更新页面 2025-07-18 10:54:07 +08:00
e1c84d9b27 更新 2025-07-18 09:42:22 +08:00
cacb2218cd 更新 2025-07-18 09:31:54 +08:00
fcc7c7dc68 更新 2025-07-17 18:05:15 +08:00
3f4fa2dd0e 删除对于文件 2025-07-17 17:45:35 +08:00
26a946daae 更新 2025-07-17 17:44:24 +08:00
b470f5946b 更新图片解析 2025-07-17 17:29:41 +08:00
6367754737 更新 2025-07-17 12:02:43 +08:00
ba54ca1efb 更新数据 2025-07-17 11:58:57 +08:00
f80a0e5539 更新 2025-07-17 11:45:03 +08:00
a03780b352 更新 2025-07-17 11:28:18 +08:00
7407a43c85 更新 2025-07-16 20:59:42 +08:00
726bae2652 更新 2025-07-16 20:07:29 +08:00
596760a707 新增解析的js 2025-07-16 18:34:49 +08:00
122208d9cb 更新 2025-07-16 18:33:13 +08:00
e2c18bf8df 跟新 2025-07-16 13:49:12 +08:00
b98625f344 更新 2025-07-16 11:54:27 +08:00
3019295319 更新数据 2025-07-16 11:45:07 +08:00
91cadd297c 更新页面 2025-07-16 11:10:37 +08:00
896590f35c 更新 2025-07-16 11:03:44 +08:00
186f647473 更新 2025-07-16 10:21:53 +08:00
dfae83dae9 更新 2025-07-16 10:09:58 +08:00
ee12595e1f 更新 2025-07-15 20:55:29 +08:00
b6818d430e 更新 2025-07-15 20:46:37 +08:00
f01d911476 更新 2025-07-15 20:19:13 +08:00
9b9b2e6e8f 更新 2025-07-15 19:27:43 +08:00
0f5f6c27d2 更新 2025-07-15 18:20:55 +08:00
498caf263d 更新 2025-07-15 17:43:28 +08:00
a94687d5fa 更新 2025-07-15 17:32:57 +08:00
42cb2cb268 更新组件 2025-07-15 16:56:26 +08:00
3b6e0d6912 跟香港 2025-07-15 16:20:18 +08:00
26b52c0175 更新 2025-07-14 21:08:51 +08:00
6ff3f78b75 更新 2025-07-14 21:05:39 +08:00
b288168070 更新 2025-07-14 19:34:37 +08:00
39ae9755db 更新 2025-07-14 19:22:33 +08:00
c7c239e1ee 更新 2025-07-14 19:09:21 +08:00
b30a8b4a33 更新 2025-07-14 18:18:21 +08:00
446304ae1b 更新大屏 2025-07-14 18:15:09 +08:00
694ad9a54c 更新 2025-07-14 17:33:04 +08:00
e940744dd8 更新数据 2025-07-14 17:31:24 +08:00
09a47e5369 更新 2025-07-14 16:56:58 +08:00
6a2b4e12c5 更新 2025-07-14 16:53:38 +08:00
dc43ddd3c5 更新 2025-07-14 16:34:26 +08:00
f6d433fd65 更新 2025-07-14 16:12:14 +08:00
bfc6504e2d 更新大屏 2025-07-14 14:21:12 +08:00
813e5a9c97 更新 2025-07-14 10:34:19 +08:00
d32f7fe5bc 更新大屏 2025-07-14 10:09:55 +08:00
cd4f8a95d2 更新 2025-07-12 18:34:34 +08:00
7c9b3152f8 更新 2025-07-12 18:28:29 +08:00
15e23797ac 更新 2025-07-12 18:25:16 +08:00
bf1b90c578 更新 2025-07-12 18:21:54 +08:00
c438006604 更新 2025-07-12 18:14:01 +08:00
342754ca20 更新页面 2025-07-12 18:11:10 +08:00
0fe250f0fd 更新 2025-07-12 17:33:59 +08:00
f65adab730 更新 2025-07-12 16:45:32 +08:00
9039840986 更新 2025-07-12 16:43:04 +08:00
9cb8877486 跟香港 2025-07-11 18:01:15 +08:00
d3031e0aee 更新 2025-07-11 16:19:46 +08:00
193cc06752 更新 2025-07-11 16:17:18 +08:00
69bee283a8 更新页面 2025-07-11 15:08:23 +08:00
f5d605fc23 更新 2025-07-10 21:18:19 +08:00
f8559da65b 更新页面 2025-07-10 20:53:34 +08:00
a903362712 更新页面 2025-07-10 20:46:20 +08:00
2f443e33bd 更新页面 2025-07-10 20:37:45 +08:00
529089b73c 更新目录 2025-07-10 20:07:17 +08:00
a487cf59a1 更新 2025-07-10 19:55:38 +08:00
b90aa5371a 更新 2025-07-10 19:51:22 +08:00
e07beea359 更新页面 2025-07-10 19:07:56 +08:00
5e9638fba3 更新 2025-07-10 18:27:50 +08:00
d0d3da243c 更新 2025-07-10 18:00:22 +08:00
b2880cd82c 更新页面 2025-07-10 17:59:39 +08:00
5f6f37a166 更新页面 2025-07-10 12:09:51 +08:00
be93c68817 更新数据 2025-07-10 10:53:48 +08:00
7705b46451 更新 2025-07-09 21:12:24 +08:00
df1e33c9bf 更新 2025-07-09 20:00:38 +08:00
f3e0a1823e 更新 2025-07-09 14:01:00 +08:00
3346582af9 更新 2025-07-08 20:59:58 +08:00
e5ca357876 解决冲突 2025-07-08 20:12:45 +08:00
f6390c9002 更新页面 2025-07-08 20:10:24 +08:00
a825e90ec4 Merge branch 'main' of http://61.139.16.27:26684/zy_oyj/sgxt_web 2025-07-08 19:50:38 +08:00
e0ae89616b 优化代码 2025-07-08 19:50:28 +08:00
241 changed files with 68632 additions and 33200 deletions

4
.gitignore vendored
View File

@ -1,6 +1,8 @@
.DS_Store
node_modules
/dist
# dist/
# build/
gsxt/
# local env files
.env.local

20632
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,8 @@
"@fullcalendar/list": "^5.9.0",
"@fullcalendar/timegrid": "^5.9.0",
"@fullcalendar/vue3": "^5.9.0",
"@paddlejs-models/ocr": "^1.1.2",
"@paddlejs-models/ocrdet": "^0.0.3",
"@types/video.js": "^7.3.42",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
@ -24,12 +26,15 @@
"echarts-gl": "^2.0.9",
"el-table-infinite-scroll": "^3.0.6",
"element-plus": "2.0.2",
"file-saver": "^2.0.5",
"gifler": "^0.1.0",
"image-compressor.js": "^1.1.4",
"lodash": "^4.17.21",
"mitt": "^3.0.0",
"moment": "^2.30.1",
"ol": "^6.14.1",
"pinia": "^3.0.1",
"tesseract.js": "^6.0.1",
"vue": "^3.2.8",
"vue-router": "^4.0.11",
"vuex": "^4.0.2",

View File

@ -20,8 +20,8 @@
<%= htmlWebpackPlugin.options.title %>
</title>
<!-- 地图 -->
<script type="text/javascript" src="./pgis/eliMapboxgl.min.js"></script>
<!-- 地图 -->
<script type="text/javascript" src="./pgis/eliMapboxgl.min.js"></script>
<!-- 视频 -->
<script src="./static/js/vconsole.min.js"></script>
@ -31,26 +31,34 @@
<script src="./static/js/antd.min.js"></script>
<script src="./static/js/antd-with-locales.min.js"></script>
<!-- 文本提取 -->
<script src="./textPdf/pdf.min.js"></script>
<!-- 引入mammoth.js处理Word文件 -->
<script src="./textPdf/mammoth.browser.min.js"></script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to
continue.</strong>
</noscript>
<!-- 语音- 视频 提取 -->
<script src="./textVideo/recorder-core.js" charset="UTF-8"></script>
<script src="./textVideo/wav.js" charset="UTF-8"></script>
<script src="./textVideo/pcm.js" charset="UTF-8"></script>
<noscript><strong></strong> </noscript>
<div id="app"></div>
<script>
document.documentElement.addEventListener(
"touchmove",
var imgIsLoad = false
var videoText = ''
// 初始化PDF.js
pdfjsLib.GlobalWorkerOptions.workerSrc = "./textPdf/pdf.worker.min.js";
document.documentElement.addEventListener("touchmove",
function (event) {
if (event.touches.length > 1) {
event.preventDefault();
}
},
false
);
if (event.touches.length > 1) event.preventDefault();
}, false);
</script>
<script src="./textVideo/wsconnecter.js" charset="utf-8"></script>
<script src="./textVideo/textVideo.js" charset="utf-8"></script>
</body>
</html>

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

18
public/textPdf/mammoth.browser.min.js vendored Normal file

File diff suppressed because one or more lines are too long

22
public/textPdf/pdf.min.js vendored Normal file

File diff suppressed because one or more lines are too long

22
public/textPdf/pdf.worker.min.js vendored Normal file

File diff suppressed because one or more lines are too long

96
public/textVideo/pcm.js Normal file
View File

@ -0,0 +1,96 @@
/*
pcm编码器+编码引擎
https://github.com/xiangyuecn/Recorder
编码原理本编码器输出的pcm格式数据其实就是Recorder中的buffers原始数据经过了重新采样16位时为LE小端模式Little Endian并未经过任何编码处理
编码的代码和wav.js区别不大pcm加上一个44字节wav头即成wav文件所以要播放pcm就很简单了直接转成wav文件来播放已提供转换函数 Recorder.pcm2wav
*/
(function(){
"use strict";
Recorder.prototype.enc_pcm={
stable:true
,testmsg:"pcm为未封装的原始音频数据pcm数据文件无法直接播放支持位数8位、16位填在比特率里面采样率取值无限制"
};
Recorder.prototype.pcm=function(res,True,False){
var This=this,set=This.set
,size=res.length
,bitRate=set.bitRate==8?8:16;
var buffer=new ArrayBuffer(size*(bitRate/8));
var data=new DataView(buffer);
var offset=0;
// 写入采样数据
if(bitRate==8) {
for(var i=0;i<size;i++,offset++) {
//16转8据说是雷霄骅的 https://blog.csdn.net/sevennight1989/article/details/85376149 细节比blqw的按比例的算法清晰点虽然都有明显杂音
var val=(res[i]>>8)+128;
data.setInt8(offset,val,true);
};
}else{
for (var i=0;i<size;i++,offset+=2){
data.setInt16(offset,res[i],true);
};
};
True(new Blob([data.buffer],{type:"audio/pcm"}));
};
/**pcm直接转码成wav可以直接用来播放需同时引入wav.js
data: {
sampleRate:16000 pcm的采样率
bitRate:16 pcm的位数 取值8 或 16
blob:blob对象
}
data如果直接提供的blob将默认使用16位16khz的配置仅用于测试
True(wavBlob,duration)
False(msg)
**/
Recorder.pcm2wav=function(data,True,False){
if(data.slice && data.type!=null){//Blob 测试用
data={blob:data};
};
var sampleRate=data.sampleRate||16000,bitRate=data.bitRate||16;
if(!data.sampleRate || !data.bitRate){
console.warn("pcm2wav必须提供sampleRate和bitRate");
};
if(!Recorder.prototype.wav){
False("pcm2wav必须先加载wav编码器wav.js");
return;
};
var reader=new FileReader();
reader.onloadend=function(){
var pcm;
if(bitRate==8){
//8位转成16位
var u8arr=new Uint8Array(reader.result);
pcm=new Int16Array(u8arr.length);
for(var j=0;j<u8arr.length;j++){
pcm[j]=(u8arr[j]-128)<<8;
};
}else{
pcm=new Int16Array(reader.result);
};
Recorder({
type:"wav"
,sampleRate:sampleRate
,bitRate:bitRate
}).mock(pcm,sampleRate).stop(function(wavBlob,duration){
True(wavBlob,duration);
},False);
};
reader.readAsArrayBuffer(data.blob);
};
})();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,275 @@
/**
* Copyright FunASR (https://github.com/alibaba-damo-academy/FunASR). All Rights
* Reserved. MIT License (https://opensource.org/licenses/MIT)
*/
/* 2022-2023 by zhaoming,mali aihealthx.com */
// 连接; 定义socket连接类对象与语音对象
var wsconnecter = new WebSocketConnectMethod({ msgHandle: getJsonMessage, stateHandle: getConnState });
var audioBlob;
var isfilemode = true; // if it is in file mode
// 录音; 定义录音对象,wav格式
var rec = Recorder({
type: "pcm",
bitRate: 16,
sampleRate: 16000,
onProcess: recProcess
});
var sampleBuf = new Int16Array();
var rec_text = ""; // for online rec asr result
var offline_text = ""; // for offline rec asr result
var file_ext = "";
var file_sample_rate = 16000; //for wav file sample rate
var file_data_array; // array to save file data
var totalsend = 0;
addresschange();
function addresschange() {
var Uri = 'ws://192.168.0.232:10095';
Uri = Uri.replace(/wss/g, "https");
window.open(Uri, '_blank');
}
var readWavInfo = function (bytes) {
//读取wav文件头统一成44字节的头
if (bytes.byteLength < 44) {
return null;
};
var wavView = bytes;
var eq = function (p, s) {
for (var i = 0; i < s.length; i++) {
if (wavView[p + i] != s.charCodeAt(i)) {
return false;
};
};
return true;
};
if (eq(0, "RIFF") && eq(8, "WAVEfmt ")) {
var numCh = wavView[22];
if (wavView[20] == 1 && (numCh == 1 || numCh == 2)) {//raw pcm 单或双声道
var sampleRate = wavView[24] + (wavView[25] << 8) + (wavView[26] << 16) + (wavView[27] << 24);
var bitRate = wavView[34] + (wavView[35] << 8);
var heads = [wavView.subarray(0, 12)], headSize = 12;//head只保留必要的块
//搜索data块的位置
var dataPos = 0; // 44 或有更多块
for (var i = 12, iL = wavView.length - 8; i < iL;) {
if (wavView[i] == 100 && wavView[i + 1] == 97 && wavView[i + 2] == 116 && wavView[i + 3] == 97) {//eq(i,"data")
heads.push(wavView.subarray(i, i + 8));
headSize += 8;
dataPos = i + 8; break;
}
var i0 = i;
i += 4;
i += 4 + wavView[i] + (wavView[i + 1] << 8) + (wavView[i + 2] << 16) + (wavView[i + 3] << 24);
if (i0 == 12) {//fmt
heads.push(wavView.subarray(i0, i));
headSize += i - i0;
}
}
if (dataPos) {
var wavHead = new Uint8Array(headSize);
for (var i = 0, n = 0; i < heads.length; i++) {
wavHead.set(heads[i], n); n += heads[i].length;
}
return {
sampleRate: sampleRate
, bitRate: bitRate
, numChannels: numCh
, wavHead44: wavHead
, dataPos: dataPos
};
};
};
};
return null;
};
function upfileOnchange(files) {
this.files = [files];
var len = this.files.length;
for (let i = 0; i < len; i++) {
let fileAudio = new FileReader();
fileAudio.readAsArrayBuffer(this.files[i]);
file_ext = this.files[i].name.split('.').pop().toLowerCase();
var audioblob;
fileAudio.onload = function () {
audioblob = fileAudio.result;
file_data_array = audioblob;
}
fileAudio.onerror = function (e) {
console.log('error' + e);
}
}
// for wav file, we get the sample rate
if (file_ext == "wav") {
for (let i = 0; i < len; i++) {
let fileAudio = new FileReader();
fileAudio.readAsArrayBuffer(this.files[i]);
fileAudio.onload = function () {
audioblob = new Uint8Array(fileAudio.result);
var info = readWavInfo(audioblob);
file_sample_rate = info.sampleRate;
}
}
}
}
function play_file() {
var audioblob = new Blob([new Uint8Array(file_data_array)], { type: "audio/wav" });
var audio_record = document.getElementById('audio_record');
audio_record.src = (window.URL || webkitURL).createObjectURL(audioblob);
audio_record.controls = true;
}
function start_file_send() {
sampleBuf = new Uint8Array(file_data_array);
var chunk_size = 960; // for asr chunk_size [5, 10, 5]
while (sampleBuf.length >= chunk_size) {
sendBuf = sampleBuf.slice(0, chunk_size);
totalsend = totalsend + sampleBuf.length;
sampleBuf = sampleBuf.slice(chunk_size, sampleBuf.length);
wsconnecter.wsSend(sendBuf);
}
stop();
}
function stop() {
var chunk_size = new Array(5, 10, 5);
var request = {
"chunk_size": chunk_size,
"wav_name": "h5",
"is_speaking": false,
"chunk_interval": 10,
"mode": getAsrMode(),
};
if (sampleBuf.length > 0) {
wsconnecter.wsSend(sampleBuf);
sampleBuf = new Int16Array();
}
wsconnecter.wsSend(JSON.stringify(request));
// 控件状态更新
isRec = false;
if (isfilemode == false) {
//wait 3s for asr result
setTimeout(function () {
wsconnecter.wsStop();
}, 3000);
rec.stop(function (blob, duration) {
var audioBlob = Recorder.pcm2wav(data = { sampleRate: 16000, bitRate: 16, blob: blob },
function (theblob, duration) {
console.log(theblob);
var audio_record = document.getElementById('audio_record');
audio_record.src = (window.URL || webkitURL).createObjectURL(theblob);
audio_record.controls = true;
}, function (msg) {
console.log(msg);
}
);
}, function (errMsg) {
console.log("errMsg: " + errMsg);
});
}
// 停止连接
}
function getAsrMode() {
return 'offline';
}
function getHotwords() {
return null
}
function handleWithTimestamp(tmptext, tmptime) {
if (tmptime == null || tmptime == "undefined" || tmptext.length <= 0) {
return tmptext;
}
tmptext = tmptext.replace(/。|||、|\?|\.|\ /g, ","); // in case there are a lot of "。"
var words = tmptext.split(","); // split to chinese sentence or english words
var jsontime = JSON.parse(tmptime); //JSON.parse(tmptime.replace(/\]\]\[\[/g, "],[")); // in case there are a lot segments by VAD
var char_index = 0; // index for timestamp
var text_withtime = "";
for (var i = 0; i < words.length; i++) {
if (words[i] == "undefined" || words[i].length <= 0) {
continue;
}
if (/^[a-zA-Z]+$/.test(words[i])) { // if it is english
text_withtime = text_withtime + jsontime[char_index][0] / 1000 + ":" + words[i] + "\n";
char_index = char_index + 1; //for english, timestamp unit is about a word
}
else {
text_withtime = text_withtime + jsontime[char_index][0] / 1000 + ":" + words[i] + "\n";
char_index = char_index + words[i].length; //for chinese, timestamp unit is about a char
}
}
return text_withtime;
}
// 语音识别结果; 对jsonMsg数据解析,将识别结果附加到编辑框中
function getJsonMessage(jsonMsg) {
var rectxt = "" + JSON.parse(jsonMsg.data)['text'];
var asrmodel = JSON.parse(jsonMsg.data)['mode'];
var is_final = JSON.parse(jsonMsg.data)['is_final'];
var timestamp = JSON.parse(jsonMsg.data)['timestamp'];
if (asrmodel == "2pass-offline" || asrmodel == "offline") {
offline_text = offline_text + handleWithTimestamp(rectxt, timestamp); //rectxt; //.replace(/ +/g,"");
rec_text = offline_text;
} else {
rec_text = rec_text + rectxt;
}
videoText = rec_text;
if (is_final == true) {
play_file();
wsconnecter.wsStop();
btnConnect.disabled = false;
}
}
// 连接状态响应
function getConnState(connState) {
if (connState === 0) start_file_send();
}
// 识别启动、停止、清空操作
function start() {
var ret = wsconnecter.wsStart();//启动连接
return ret == 1 ? 1 : 0;
}
function recProcess(buffer, powerLevel, bufferDuration, bufferSampleRate, newBufferIdx, asyncEnd) {
if (isRec === true) {
var data_48k = buffer[buffer.length - 1];
var array_48k = new Array(data_48k);
var data_16k = Recorder.SampleData(array_48k, bufferSampleRate, 16000).data;
sampleBuf = Int16Array.from([...sampleBuf, ...data_16k]);
var chunk_size = 960; // for asr chunk_size [5, 10, 5]
while (sampleBuf.length >= chunk_size) {
sendBuf = sampleBuf.slice(0, chunk_size);
sampleBuf = sampleBuf.slice(chunk_size, sampleBuf.length);
wsconnecter.wsSend(sendBuf);
}
}
}
function getUseITN() {
return false;
}

86
public/textVideo/wav.js Normal file
View File

@ -0,0 +1,86 @@
/*
wav编码器+编码引擎
https://github.com/xiangyuecn/Recorder
当然最佳推荐使用mp3、wav格式代码也是优先照顾这两种格式
浏览器支持情况
https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats
编码原理给pcm数据加上一个44直接的wav头即成wav文件pcm数据就是Recorder中的buffers原始数据重新采样16位时为LE小端模式Little Endian实质上是未经过任何编码处理
*/
(function(){
"use strict";
Recorder.prototype.enc_wav={
stable:true
,testmsg:"支持位数8位、16位填在比特率里面采样率取值无限制"
};
Recorder.prototype.wav=function(res,True,False){
var This=this,set=This.set
,size=res.length
,sampleRate=set.sampleRate
,bitRate=set.bitRate==8?8:16;
//编码数据 https://github.com/mattdiamond/Recorderjs https://www.cnblogs.com/blqw/p/3782420.html https://www.cnblogs.com/xiaoqi/p/6993912.html
var dataLength=size*(bitRate/8);
var buffer=new ArrayBuffer(44+dataLength);
var data=new DataView(buffer);
var offset=0;
var writeString=function(str){
for (var i=0;i<str.length;i++,offset++) {
data.setUint8(offset,str.charCodeAt(i));
};
};
var write16=function(v){
data.setUint16(offset,v,true);
offset+=2;
};
var write32=function(v){
data.setUint32(offset,v,true);
offset+=4;
};
/* RIFF identifier */
writeString('RIFF');
/* RIFF chunk length */
write32(36+dataLength);
/* RIFF type */
writeString('WAVE');
/* format chunk identifier */
writeString('fmt ');
/* format chunk length */
write32(16);
/* sample format (raw) */
write16(1);
/* channel count */
write16(1);
/* sample rate */
write32(sampleRate);
/* byte rate (sample rate * block align) */
write32(sampleRate*(bitRate/8));// *1 声道
/* block align (channel count * bytes per sample) */
write16(bitRate/8);// *1 声道
/* bits per sample */
write16(bitRate);
/* data chunk identifier */
writeString('data');
/* data chunk length */
write32(dataLength);
// 写入采样数据
if(bitRate==8) {
for(var i=0;i<size;i++,offset++) {
//16转8据说是雷霄骅的 https://blog.csdn.net/sevennight1989/article/details/85376149 细节比blqw的按比例的算法清晰点虽然都有明显杂音
var val=(res[i]>>8)+128;
data.setInt8(offset,val,true);
};
}else{
for (var i=0;i<size;i++,offset+=2){
data.setInt16(offset,res[i],true);
};
};
True(new Blob([data.buffer],{type:"audio/wav"}));
}
})();

View File

@ -0,0 +1,119 @@
/**
* Copyright FunASR (https://github.com/alibaba-damo-academy/FunASR). All Rights
* Reserved. MIT License (https://opensource.org/licenses/MIT)
*/
/* 2021-2023 by zhaoming,mali aihealthx.com */
function WebSocketConnectMethod( config ) { //定义socket连接方法类
var speechSokt;
var connKeeperID;
var msgHandle = config.msgHandle;
var stateHandle = config.stateHandle;
this.wsStart = function () {
var Uri = 'ws://192.168.0.232:10095'; //"wss://111.205.137.58:5821/wss/" //设置wss asr online接口地址 如 wss://X.X.X.X:port/wss/
if(Uri.match(/wss:\S*|ws:\S*/))
{
console.log("Uri"+Uri);
}
else
{
alert("请检查wss地址正确性");
return 0;
}
if ( 'WebSocket' in window ) {
speechSokt = new WebSocket( Uri ); // 定义socket连接对象
speechSokt.onopen = function(e){onOpen(e);}; // 定义响应函数
speechSokt.onclose = function(e){
console.log("onclose ws!");
//speechSokt.close();
onClose(e);
};
speechSokt.onmessage = function(e){onMessage(e);};
speechSokt.onerror = function(e){onError(e);};
return 1;
}
else {
alert('当前浏览器不支持 WebSocket');
return 0;
}
};
// 定义停止与发送函数
this.wsStop = function () {
if(speechSokt != undefined) {
console.log("stop ws!");
speechSokt.close();
}
};
this.wsSend = function ( oneData ) {
if(speechSokt == undefined) return;
if ( speechSokt.readyState === 1 ) { // 0:CONNECTING, 1:OPEN, 2:CLOSING, 3:CLOSED
speechSokt.send( oneData );
}
};
// SOCEKT连接中的消息与状态响应
function onOpen( e ) {
// 发送json
var chunk_size = new Array( 5, 10, 5 );
var request = {
"chunk_size": chunk_size,
"wav_name": "h5",
"is_speaking": true,
"chunk_interval":10,
"itn":getUseITN(),
"mode":getAsrMode(),
};
if(isfilemode)
{
request.wav_format=file_ext;
if(file_ext=="wav")
{
request.wav_format="PCM";
request.audio_fs=file_sample_rate;
}
}
var hotwords=getHotwords();
if(hotwords!=null )
{
request.hotwords=hotwords;
}
console.log(JSON.stringify(request));
speechSokt.send(JSON.stringify(request));
console.log("连接成功");
stateHandle(0);
}
function onClose( e ) {
stateHandle(1);
}
function onMessage( e ) {
msgHandle( e );
}
function onError( e ) {
info_div.innerHTML="连接"+e;
console.log(e);
stateHandle(2);
}
}

View File

@ -6,11 +6,12 @@
</router-view>
</template>
<script setup>
import { ref, nextTick, provide, onMounted } from "vue";
import * as ocr from "@paddlejs-models/ocr";
import { ref, nextTick, provide, onMounted,getCurrentInstance } from "vue";
import { useStore } from "vuex";
import { getItem } from "@/utils/storage";
import { qcckPost, qcckGet, qcckPut, qcckDelete } from "@/api/qcckApi.js";
import { getItem, setItem} from "@/utils/storage";
import { generateNewStyle, writeNewStyle } from "@/utils/theme";
const { proxy } = getCurrentInstance();
const store = useStore();
generateNewStyle(store.getters.mainColor).then((newStyle) => {
writeNewStyle(newStyle);
@ -24,9 +25,25 @@ const reload = () => {
};
provide("reload", reload);
onMounted(() => {
let dept = getItem("deptId");
document.title = "林芝";
// initPage()
});
/**
*@Descripttion:图片页面初始化
*@Author: PengShuai
*/
const initPage = async () => {
try {
await ocr.init();// 模型初始化
imgIsLoad = true;
proxy.$message({ type: "success", message: "加载成功" });
} catch (err) {
proxy.$message({ type: "error", message: "加载失败,请刷新页面" });
imgIsLoad = false;
}
}
</script>
<style lang="scss">
@import "./styles/index.scss";

View File

@ -1,22 +1,17 @@
import request from "@/utils/request";
import axios from "axios";
const api = "/mosty-api";
const egisSpace = "/egis-space";
// 选择站口名称
export function egisSpaceGet(fun,coords){
let params = {
pageNum: 1,
pageSize: 1000,
keyword: "",
geometry: `{"type":"Polygon","coordinates":${JSON.stringify(coords)}}`,
};
params.geometry = encodeURIComponent(params.geometry)
let url = egisSpace + '/space/search/custom/ms-dy-intersections'
axios.get(url,{params}).then((res) => {
fun(res.data)
});
// 解析数据
export function ParsingText(data,fun){
axios({
method: 'post',
url: '/chat/completions',
data:data,
headers: { 'Authorization': 'Bearer sk-064b5c53131c4046883b718f2b31c050' }
}).then( (res) => {
fun(res)
})
}

View File

@ -599,7 +599,7 @@ export const selectUserDeptPage = (data = {}) => {
///unifiedLogin
export const unifiedLogin = (data) => {
return request({
url: api + `/unifiedLogin`,
url: api + `/ssoLogin`,
method: "POST",
data
});

View File

@ -3,261 +3,306 @@
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.homeBox{
.homeBox {
width: 100%;
height: 100vh;
.home-aside {
position: relative;
width: 442px;
top: 70px;
height: 100%;
height: calc(100vh - 72px);
overflow: hidden;
z-index: 10;
.asideTitle {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
box-sizing: border-box;
background: linear-gradient(90deg, #124CB3 0%, rgba(18, 76, 179, 0.23) 77%, rgba(18, 76, 179, 0) 100%);
border-radius: 0px 0px 0px 0px;
height: 40px;
.title {
font-weight: bold;
font-size: 16px;
color: #FFFFFF;
margin-right: 20px;
}
}
.asideCnt {
height: calc(100% - 40px);
}
.aside-middle {
height: calc(100%/2);
padding: 4px;
box-sizing: border-box;
}
}
.homeBtn {
height: 302px;
width: calc(100% - 894px);
position: absolute;
bottom: 2px;
left: 50%;
transform: translateX(-50%);
}
// 头部
.headBox {
position: fixed;
top: 0;
width: 100%;
height: 100vh;
.home-aside{
position: relative;
width: 442px;
top: 70px;
height: 70px;
background: rgba(0, 0, 0, 0.8);
z-index: 2;
.headBoxBg {
width: 100%;
height: 100%;
height: calc(100vh - 72px);
overflow: hidden;
z-index: 10;
.asideTitle{
background: url("~@/assets/images/home_head.png") no-repeat center center;
background-size: 100% 100%;
height: 151px;
}
.top-center {
position: absolute;
left: 50%;
top: 2%;
transform: translateX(-50%);
font-size: 56px;
letter-spacing: 2px;
font-family: "YSBTH";
white-space: nowrap;
background: linear-gradient(180deg, #FFFFFF 0%, #66B5FF 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 4px 4px 4px rgba(54, 255, 243, 0.15);
}
.topBtn {
display: flex;
position: absolute;
top: 22px;
.topBtn-item {
width: 190px;
height: 38px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
box-sizing: border-box;
background: linear-gradient( 90deg, #124CB3 0%, rgba(18,76,179,0.23) 77%, rgba(18,76,179,0) 100%);
border-radius: 0px 0px 0px 0px;
height: 40px;
.title{
font-weight: bold;
font-size: 16px;
color: #FFFFFF;
margin-right: 20px;
}
}
.asideCnt{
height: calc(100% - 40px);
}
.aside-middle{
height: calc(100%/2);
padding: 4px;
box-sizing: border-box;
}
}
.homeBtn{
height: 302px;
width: calc(100% - 894px);
position: absolute;
bottom: 2px;
left: 50%;
transform: translateX(-50%);
}
// 头部
.headBox {
position: fixed;
top: 0;
width: 100%;
height: 70px;
background: rgba(0,0,0,0.8);
z-index: 2;
.headBoxBg{
width: 100%;
height: 100%;
background: url("~@/assets/images/home_head.png") no-repeat center center;
justify-content: center;
background: url("~@/assets/images/home_btns.png") no-repeat center center;
background-size: 100% 100%;
height: 151px;
}
.top-center {
position: absolute;
left: 50%;
top: 2%;
transform: translateX(-50%);
font-size: 56px;
letter-spacing: 2px;
font-family: "YSBTH";
white-space: nowrap;
background: linear-gradient(180deg, #FFFFFF 0%, #66B5FF 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 4px 4px 4px rgba(54, 255, 243, 0.15);
}
.topBtn {
display: flex;
position: absolute;
top: 22px;
.topBtn-item {
width: 190px;
height: 38px;
display: flex;
align-items: center;
justify-content: center;
background: url("~@/assets/images/home_btns.png") no-repeat center center;
background-size: 100% 100%;
font-size: 18px;
cursor: pointer;
span {
font-family: "YSBTH";
margin-top: -4px;
@include textColor(#a1d6ff, #ffffff);
}
}
}
.topBtn-left {
left: 30px;
font-size: 12px;
.text {
font-size: 18px;
cursor: pointer;
span {
font-family: "YSBTH";
color: #0bb7ff;
}
.tests {
color: #0a99ff;
}
}
.leftBtn-yjbtn{
position: absolute;
left: 360px;
top: 20px;
.leftBtn-item{
width: 155px;
height: 38px;
line-height: 38px;
text-align: center;
background: url("~@/assets/images/home_btns.png") no-repeat center center;
background-size: 100% 100%;
font-size: 16px;
font-family: "YSBTH";
}
.btms{
margin-top: -4px;
@include textColor(#a1d6ff, #ffffff);
}
}
.yjbtnActive{
background: url("~@/assets/images/home_btns_active.png") no-repeat center center;
}
.topBtn-left {
left: 30px;
font-size: 12px;
.text {
font-family: "YSBTH";
color: #0bb7ff;
}
.tests {
color: #0a99ff;
}
}
.leftBtn-yjbtn {
position: absolute;
left: 360px;
top: 20px;
.leftBtn-item {
width: 155px;
height: 38px;
line-height: 38px;
text-align: center;
background: url("~@/assets/images/home_btns.png") no-repeat center center;
background-size: 100% 100%;
.btms{
font-size: 16px;
font-family: "YSBTH";
}
.btms {
@include textColor(#a1d6ff, #ffffff);
}
}
.yjbtnActive {
background: url("~@/assets/images/home_btns_active.png") no-repeat center center;
background-size: 100% 100%;
.btms {
@include textColor(#00ffff, #faff00);
}
}
.topBtn-right {
right: 270px;
top: 22px;
.topBtn-item {
background: url("~@/assets/images/home_btns_right.png") no-repeat center center;
background-size: 100% 100%;
}
.active-topBtn {
background: url("~@/assets/images/home_btns_right_active.png") no-repeat center center;
background-size: 100% 100%;
span {
@include textColor(#00ffff, #faff00);
}
}
.topBtn-right {
right: 270px;
top: 22px;
.topBtn-item {
background: url("~@/assets/images/home_btns_right.png") no-repeat center
center;
background-size: 100% 100%;
}
.active-topBtn {
background: url("~@/assets/images/home_btns_right_active.png") no-repeat
center center;
background-size: 100% 100%;
span {
@include textColor(#00ffff, #faff00);
}
}
}
.rightIcon {
position: absolute;
right: 20px;
top: 22px;
font-size: 17px;
z-index: 9;
span {
color: #0bb7ff;
cursor: pointer;
}
img {
width: 20px;
}
}
}
// 左边
.asideL{
position: absolute;
box-sizing: border-box;
left: 0px;
.asideL-top{
width: 100%;
height: 141px;
background: #052249;
}
.asideL-Bottom{
height: calc(100% - 141px);
.commom-aside{
height: calc((100%/3) - 6px);
margin-top: 7px;
background: #052249;
}
}
}
// 右边
.asideR{
position: absolute;
right: 0px;
.commom-aside-small{
height: calc(((100% - 146px) /3) - 6px);
background: #052249;
margin-top: 9px;
}
.commom-aside-big{
height: calc(((100% - (100% - 146px) /3)/2) - 6px);
margin-bottom: 9px;
background: #052249;
}
}
.home-center{
position: absolute;
left: 50%;
top: 70px;
transform: translateX(-50%);
width: calc(100% - 890px);
height: 80px;
z-index: 9;
background: #fff;
}
.home-foot-t{
.rightIcon {
position: absolute;
left: 50%;
bottom: 2px;
transform: translateX(-50%);
width: calc(100% - 920px);
height: calc((100% - 141px)/3 - 32px);
min-width: 560px;
overflow: hidden;
right: 20px;
top: 22px;
font-size: 17px;
z-index: 9;
background: url("~@/assets/images/right-1.png") no-repeat center center;
background-size: 100% 100%;
.comom-title{
background: url("~@/assets/images/bg18.png") no-repeat center center;
background-size: 100% 100%;
.title{
font-size: 22px;
font-family: 'YSBTH';
padding-left: 35px;
}
span {
color: #0bb7ff;
cursor: pointer;
}
img {
width: 20px;
}
}
// 公用
.comom-title{
background: url("~@/assets/images/bg17.png") no-repeat center center;
background-size: 100% 100%;
}
// 左边
.asideL {
position: absolute;
box-sizing: border-box;
left: 0px;
.asideL-top {
width: 100%;
height: 35px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
box-sizing: border-box;
.title{
height: 141px;
background: #052249;
}
.asideL-Bottom {
height: calc(100% - 141px);
.commom-aside {
height: calc((100%/3) - 6px);
margin-top: 7px;
background: #052249;
}
}
}
// 右边
.asideR {
position: absolute;
right: 0px;
.commom-aside-small {
height: calc(((100% - 146px) /3) - 6px);
background: #052249;
margin-top: 9px;
}
.commom-aside-big {
height: calc(((100% - (100% - 146px) /3)/2) - 6px);
margin-bottom: 9px;
background: #052249;
}
}
.home-center {
position: absolute;
left: 50%;
top: 70px;
transform: translateX(-50%);
width: calc(100% - 890px);
z-index: 9;
background: #052249;
height: calc(100% - (100% - 141px) / 3 - 45px);
.middle-top {
height: 80px;
}
.middle-bottom {
height: calc(100% - 90px);
}
}
.home-foot-t {
position: absolute;
left: 50%;
bottom: 2px;
transform: translateX(-50%);
width: calc(100% - 920px);
height: calc((100% - 141px)/3 - 32px);
min-width: 560px;
overflow: hidden;
z-index: 9;
background: url("~@/assets/images/right-1.png") no-repeat center center;
background-size: 100% 100%;
.comom-title {
background: url("~@/assets/images/bg18.png") no-repeat center center;
background-size: 100% 100%;
.title {
font-size: 22px;
font-family: 'YSBTH';
padding-left: 35px;
}
}
.comom-cnt{
height: calc(100% - 35px);
padding: 4px 10px;
box-sizing: border-box;
background: url("~@/assets/images/bg_13.png") no-repeat center center;
background-size: 100% 100%;
}
// 公用
.comom-title {
background: url("~@/assets/images/bg17.png") no-repeat center center;
background-size: 100% 100%;
width: 100%;
height: 35px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
box-sizing: border-box;
.title {
font-size: 22px;
font-family: 'YSBTH';
padding-left: 35px;
}
}
}
.comom-cnt {
height: calc(100% - 35px);
padding: 4px 10px;
box-sizing: border-box;
background: url("~@/assets/images/bg_13.png") no-repeat center center;
background-size: 100% 100%;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 540 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 948 B

BIN
src/assets/images/bg44.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
src/assets/images/bg46.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/assets/images/car.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
src/assets/images/ddtb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16 2C10.477 2 6 6.477 6 12C6 19.5 16 30 16 30C16 30 26 19.5 26 12C26 6.477 21.523 2 16 2ZM16 16C13.791 16 12 14.209 12 12C12 9.791 13.791 8 16 8C18.209 8 20 9.791 20 12C20 14.209 18.209 16 16 16Z" fill="#00f0ff" stroke="#ffffff" stroke-width="1"/>
</svg>

Before

Width:  |  Height:  |  Size: 401 B

BIN
src/assets/images/mxbg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 571 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 792 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,104 @@
<template>
<el-dialog v-model="showDialog" :destroy-on-close="true" title="新增车辆" @close="close" :close-on-click-modal="false">
<FormMessage v-model="listQuery" :formList="formData" labelWidth="120px" ref="elform" :rules="rules">
<template #bqList>
<div class="marks pointer" @click="chooseMarksVisible = true">
<span style="color: rgb(175 178 184);padding-left: 10px;"
v-if="!listQuery.bqList || listQuery.bqList.length == 0">请选择标签</span>
<span v-else>
<el-tag @close.stop="closeTag(idx)" type="success" closable v-for="(it, idx) in listQuery.bqList"
:key="idx">{{ it.bqMc }}</el-tag>
</span>
</div>
</template>
</FormMessage>
<template #footer>
<div class="flex just-center">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="submitForm">确认</el-button>
</div>
</template>
</el-dialog>
<ChooseMarks v-model="chooseMarksVisible" @choosed="choosed" :roleIds="roleIds" />
</template>
<script setup>
import ChooseMarks from "@/components/ChooseList/ChooseMarks/index.vue";
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { reactive, ref, getCurrentInstance } from 'vue';
const { proxy } = getCurrentInstance();
const { D_BZ_XB } = proxy.$dict("D_BZ_XB"); // 获取字典数据
const elform = ref()
const roleIds = ref([])
const showDialog = ref(false)
const chooseMarksVisible = ref(false)
const emit = defineEmits(['change'])
const listQuery = ref({})
const formData = ref([
{ label: "车牌号", prop: "hphm", type: "input" },
{ label: "车架号", prop: "clCjh", type: "input" },
{
label: "车辆颜色",
prop: "clYs",
type: "input",
},
{ label: "车辆所有人", prop: "clSyr", type: "input" },
{ label: "人员身份证", prop: "clSyrsfzh", type: "input" },
{ label: "责任单位", prop: "zrSsbmdm", depMc: 'zrSsbmmc', type: "department" },
{ label: "管辖单位", prop: "gxSsbmdm", depMc: 'gxSsbmmc', type: "department" },
{ label: "管控民警姓名", prop: "gkMjXm", type: "input" },
{ label: "管控民警警号", prop: "gkMjJh", type: "input" },
{ label: "管控原因", prop: "clLkyy", type: "textarea", width: "100%" },
{ label: "车辆照片", prop: "fjdz", type: "upload", width: "100%" },
])
const rules = reactive({
hphm: [{ required: true, message: "请输入车牌号", trigger: "blur" }],
clCjh: [{ required: true, message: "请输入车架号", trigger: "blur" }],
clYs: [{ required: true, message: "请输入车辆颜色", trigger: "blur" }],
clSyr: [{ required: true, message: "请输入车辆所有人", trigger: "blur" }],
clSyrsfzh: [{ required: true, message: "请输入人员身份证", trigger: "blur" }],
})
const init = () => {
showDialog.value = true;
}
// 选择标签
const choosed = (val) => {
listQuery.value.bqList = val.map(v => {
return { bqZl: v.bqLb, bqId: v.id, bqLx: v.bqLx, bqLb: v.bqLb, bqMc: v.bqMc, bqDm: v.bqDm }
});
roleIds.value = val.map(v => v.id)
}
// 删除数据
const closeTag = (idx) => {
listQuery.value.bqList.splice(idx, 1)
roleIds.value.splice(idx, 1)
}
const submitForm = () => {
elform.value.submit((val) => {
val.id = new Date().getTime()
emit('change', val)
showDialog.value = false;
})
}
const close = () => {
elform.value.reset();
listQuery.value.bqList = []
roleIds.value = []
showDialog.value = false;
}
defineExpose({ init })
</script>
<style lang="scss" scoped>
.marks {
width: 100%;
min-height: 32px;
border: 1px solid #e9e9e9;
border-radius: 4px;
}
</style>

View File

@ -0,0 +1,204 @@
<template>
<el-dialog width="1400px" :model-value="modelValue" append-to-body @close="closed">
<template #title>
<span class="mr10 f16">选择布控车辆</span>
<el-button type="primary" size="small" @click="zdyaddPerson">添加其他车辆</el-button>
</template>
<el-form :model="listQuery" :inline="true">
<el-form-item label="车牌号">
<el-input placeholder="请输入车牌号" v-model="listQuery.hphm" clearable ></el-input>
</el-form-item>
<el-form-item label="车架号">
<el-input placeholder="请输入车架号" v-model="listQuery.clCjh" clearable ></el-input>
</el-form-item>
<el-form-item label="车辆所有人">
<el-input placeholder="请输入车辆所有人" v-model="listQuery.clSyr" 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' : ''" style="margin-top: 0px">
<el-table ref="multipleUserRef" :key="keyTabel" v-loading="loading" @selection-change="handleSelectionChange" :data="tableData" border :row-key="keyid" style="width: 100%" height="450">
<el-table-column type="selection" width="55" :reserve-selection="true"/>
<el-table-column prop="hphm" align="center" label="车牌号"/>
<el-table-column prop="clCjh" align="center" label="车架号"/>
<el-table-column prop="clYs" align="center" label="车辆颜色"/>
<el-table-column prop="clSyr" align="center" label="车辆所有人"/>
<el-table-column prop="gxSsbmmc" align="center" label="管辖单位"/>
<el-table-column prop="gkMjXm" align="center" label="管控民警"/>
</el-table>
</div>
<div class="fenye flex just-end " :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
<template #footer>
<div class="flex just-center">
<el-button @click="closed">取消</el-button>
<el-button type="primary" @click="onComfirm">确认</el-button>
</div>
</template>
</el-dialog>
<!-- 自定义选添加人 -->
<AddPeo ref="addPerson" @change="changeZdy"></AddPeo>
</template>
<script setup>
import AddPeo from './addPeo.vue'
import { qcckGet} from "@/api/qcckApi.js";
import { defineProps, ref ,getCurrentInstance, watch} from "vue";
const { proxy } = getCurrentInstance();
const { D_BZ_XB,D_BZ_MZ } = proxy.$dict("D_BZ_XB","D_BZ_MZ"); //获取字典数据
const props = defineProps({
modelValue: {
type: Boolean,
default:false
},
LeaderType: {
type: String,
default: ""
},
//是否单选
Single: {
type: Boolean,
default: false
},
roleIds: {
type: Array,
default: []
},
});
const loading = ref(false)
const total = ref(0);
const listQuery = ref({
pageCurrent: 1,
pageSize: 20
});
const addPerson = ref()
const multipleUserRef = ref(null);
const multipleSelectionUser = ref([]);
const tableData = ref([]);
const emits = defineEmits(["update:modelValue", "choosed","choosedAdd"]);
const keyTabel = ref(0)
const keyid = (row) => {
return row.id;
};
const closed = () => {
emits("update:modelValue", false);
};
const reset = () => {
listQuery.value = { pageCurrent: 1, pageSize: 20, };
getListData();
};
// 为用户分配角色
const onComfirm = () => {
const userList = multipleSelectionUser.value;
let list = [];
let listId = [];
userList.forEach((val) => {
if (listId.indexOf(val.id) == -1) {
list.push(val);
listId.push(val.id);
}
});
emits("choosed", list);
closed();
};
// 自定义加人
const changeZdy = (val) => {
emits("choosedAdd", val);
closed();
}
/**
* pageSize 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.pageCurrent = currentPage;
getListData();
};
const getListData = () => {
keyTabel.value++
const params = {...listQuery.value}
loading.value = true;
qcckGet(params,'/mosty-gsxt/tbGsxtZdcl/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);
if (props.roleIds.some((id) => id == item.id)) {
multipleUserRef.value.toggleRowSelection(item, true);
}
});
}
const handleFilter = () => {
listQuery.value.pageCurrent = 1;
getListData();
};
const handleSelectionChange = (val) => {
if (props.Single) {
if (val.length > 1) {
let del_row = val.shift();
multipleUserRef.value.toggleRowSelection(del_row, false);
}
multipleSelectionUser.value = val;
} else {
multipleSelectionUser.value = val;
}
};
const zdyaddPerson = () => {
addPerson.value.init();
};
watch(()=>props.modelValue,val=>{
if(val) handleFilter();
},{immediate:true})
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
</style>
<style>
.tabBoxRadio .el-checkbox__inner {
border-radius: 50% !important;
}
.tabBoxRadio .el-table__header-wrapper .el-checkbox {
display: none;
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<el-dialog
:title="titleValue"
width="900px"
width="1400px"
:model-value="modelValue"
append-to-body
@close="closed"
@ -17,19 +17,20 @@
</el-form-item>
<el-form-item>
<el-button type="success" @click="handleFilter">查询</el-button>
<el-button type="info" @click="reset()"> 重置 </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
v-loading="loading"
ref="multipleUserRef"
@selection-change="handleSelectionChange"
:data="tableData"
v-loading="loading"
border
:row-key="keyid"
style="width: 100%"
@ -43,14 +44,13 @@
<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" />
</template>
</el-table-column>
<el-table-column prop="bqYs" align="center" label="标签颜色">
<template #default="{ row }">
<DictTag
:value="row.bqYs"
:tag="false"
:options="props.dic.D_GS_SSYJ"
/>
<DictTag :value="row.bqYs" :tag="false" :options="D_GS_SSYJ" />
</template>
</el-table-column>
</el-table>
@ -58,11 +58,11 @@
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@pageSize-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.current"
:current-page="listQuery.pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
:page-pageSize="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
@ -78,28 +78,18 @@
</template>
<script setup>
import { defineProps, ref, onMounted } 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 props = defineProps({
modelValue: {
type: Boolean,
required: true
},
dic: {
type: Object,
default: () => {}
},
bqDl: {
type: String,
default: "01"
},
bqLx: {
type: String,
default: "01"
default: false
},
titleValue: {
type: String,
default: "选择大类"
default: "选择标签"
},
LeaderType: {
type: String,
@ -108,35 +98,37 @@ const props = defineProps({
//
Single: {
type: Boolean,
default: true
default: false
},
roleIds: {
type: Array,
default: []
}
});
const loading = ref(false);
const total = ref(0);
const listQuery = ref({
current: 1,
size: 20
pageCurrent: 1,
pageSize: 20
});
const loading = ref(false);
const keyVal = ref();
const multipleUserRef = ref(null);
const multipleSelectionUser = ref([]);
const tableData = ref([]);
const emits = defineEmits(["update:modelValue", "chooseDate"]);
onMounted(() => {
handleFilter();
});
const emits = defineEmits(["update:modelValue", "choosed"]);
const keyid = (row) => {
return row.id;
};
const closed = () => {
emits("update:modelValue", false);
};
const reset = () => {
listQuery.value = { current: 1, size: 20 };
getDataList();
listQuery.value = { pageCurrent: 1, pageSize: 20 };
getListData();
};
const keyid = (row) => {
return row.id;
};
//
const onComfirm = () => {
const userList = multipleSelectionUser.value;
@ -148,42 +140,43 @@ const onComfirm = () => {
listId.push(val.id);
}
});
emits("chooseDate", list);
let data = { type: props.LeaderType, userList: userList };
emits("chooseDateLeader", data);
emits("choosed", list);
closed();
};
/**
* pageSize 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getDataList();
listQuery.value.pageSize = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.current = currentPage;
getDataList();
listQuery.value.pageCurrent = currentPage;
getListData();
};
//
const getDataList = () => {
const data = listQuery.value;
const getListData = () => {
keyVal.value++;
loading.value = true;
qcckGet(data, "/mosty-gsxt/tbGsxtBqzh/selectPage").then((res) => {
tableData.value = res?.records;
total.value = Number(res.total);
loading.value = false;
multipleUser();
});
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);
if (props.roleIds.some((id) => id == item.id)) {
multipleUserRef.value.toggleRowSelection(item, true);
}
@ -191,12 +184,10 @@ function multipleUser() {
}
const handleFilter = () => {
listQuery.value.current = 1;
getDataList();
listQuery.value.pageCurrent = 1;
getListData();
};
const multipleUserRef = ref(null);
const multipleSelectionUser = ref([]);
const handleSelectionChange = (val) => {
if (props.Single) {
if (val.length > 1) {
@ -208,6 +199,14 @@ const handleSelectionChange = (val) => {
multipleSelectionUser.value = val;
}
};
watch(
() => props.modelValue,
(val) => {
if (val) handleFilter();
},
{ immediate: true }
);
</script>
<style lang="scss" scoped>
@ -221,9 +220,4 @@ const handleSelectionChange = (val) => {
.tabBoxRadio .el-table__header-wrapper .el-checkbox {
display: none;
}
:deep(.el-dialog) {
background: #fff !important;
border-radius: 8px !important;
/* 其他样式 */
}
</style>

View File

@ -0,0 +1,213 @@
<template>
<el-dialog width="1400px" :model-value="modelValue" append-to-body @close="closed">
<template #title>
<span class="mr10 f16">选择布控群体</span>
</template>
<el-form :model="listQuery" :inline="true">
<el-form-item label="群体名称">
<el-input placeholder="请输入群体名称" v-model="listQuery.qtMc" 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' : ''" style="margin-top: 0px">
<el-table ref="multipleUserRef" v-loading="loading" :key="keyTabel" @selection-change="handleSelectionChange" :data="tableData" border :row-key="keyid" style="width: 100%" height="450">
<el-table-column type="selection" width="55" :reserve-selection="true"/>
<el-table-column type="expand">
<template #default="props">
<div class="pl20 pr10 pt10 pb10">
<el-table :data="props.row.zdryList" >
<el-table-column label="姓名" prop="ryXm" align="center" />
<el-table-column prop="rySfzh" align="center" label="身份证"/>
<el-table-column prop="ryXb" align="center" label="性别">
<template #default="{ row }">
<DictTag :tag="false" :value="row.ryXb" :options="D_BZ_XB" />
</template>
</el-table-column>
<el-table-column prop="ryMz" align="center" label="民族">
<template #default="{ row }">
<DictTag :value="row.ryMz" :tag="false" :options="D_BZ_MZ" />
</template>
</el-table-column>
<el-table-column prop="ryLxdh" align="center" label="手机号"/>
<el-table-column prop="xzdXz" align="center" label="现居住址"/>
<el-table-column prop="bqList" align="center" label="人员标签">
<template #default="{ row }">
<span v-if="row.bqList">
<span v-for="(it,idx) in row.bqList" :key="idx"> {{ it.bqMc }}</span>
</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
</el-table-column>
<el-table-column prop="qtMc" align="center" label="群体名称"/>
<el-table-column prop="qtFxdj" align="center" label="风险等级">
<template #default="{ row }">
<DictTag :value="row.qtFxdj" :tag="false" :options="D_GS_ZDQT_FXDJ" />
</template>
</el-table-column>
</el-table>
</div>
<div class="fenye flex just-end " :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
<template #footer>
<div class="flex just-center">
<el-button type="primary" @click="onComfirm">确认</el-button>
<el-button @click="closed">取消</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { qcckGet} from "@/api/qcckApi.js";
import { defineProps, ref ,getCurrentInstance, watch} from "vue";
const { proxy } = getCurrentInstance();
const { D_BZ_XB,D_GS_ZDQT_FXDJ,D_BZ_MZ } = proxy.$dict("D_BZ_XB","D_GS_ZDQT_FXDJ","D_BZ_MZ"); //获取字典数据
const props = defineProps({
modelValue: {
type: Boolean,
default:false
},
LeaderType: {
type: String,
default: ""
},
//是否单选
Single: {
type: Boolean,
default: false
},
roleIds: {
type: Array,
default: []
},
});
const loading = ref(false)
const total = ref(0);
const listQuery = ref({
pageCurrent: 1,
pageSize: 20
});
const multipleUserRef = ref(null);
const multipleSelectionUser = ref([]);
const tableData = ref([]);
const emits = defineEmits(["update:modelValue", "choosed"]);
const keyTabel = ref(0)
const keyid = (row) => {
return row.id;
};
const closed = () => {
emits("update:modelValue", false);
};
const reset = () => {
listQuery.value = { pageCurrent: 1, pageSize: 20, };
getListData();
};
// 为用户分配角色
const onComfirm = () => {
const userList = multipleSelectionUser.value;
let list = [];
let listId = [];
userList.forEach((val) => {
if (listId.indexOf(val.id) == -1) {
list.push(val);
listId.push(val.id);
}
});
emits("choosed", list);
closed();
};
/**
* pageSize 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.pageCurrent = currentPage;
getListData();
};
const getListData = () => {
keyTabel.value++
loading.value = true;
const params = {...listQuery.value}
qcckGet(params,'/mosty-gsxt/tbGsxtZdqt/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);
if (props.roleIds.some((id) => id == item.id)) {
multipleUserRef.value.toggleRowSelection(item, true);
}
});
}
const handleFilter = () => {
listQuery.value.pageCurrent = 1;
getListData();
};
const handleSelectionChange = (val) => {
if (props.Single) {
if (val.length > 1) {
let del_row = val.shift();
multipleUserRef.value.toggleRowSelection(del_row, false);
}
multipleSelectionUser.value = val;
} else {
multipleSelectionUser.value = val;
}
};
watch(()=>props.modelValue,val=>{
if(val) handleFilter();
},{immediate:true})
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
</style>
<style>
.tabBoxRadio .el-checkbox__inner {
border-radius: 50% !important;
}
.tabBoxRadio .el-table__header-wrapper .el-checkbox {
display: none;
}
</style>

View File

@ -2,8 +2,8 @@
<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-form-item label="线索名称">
<el-input placeholder="请输入线索名称" v-model="listQuery.xsMc" clearable ></el-input>
</el-form-item>
<el-form-item>
<el-button type="success" @click="handleFilter">查询</el-button>
@ -11,7 +11,7 @@
</el-form-item>
</el-form>
<div class="tabBox" :class="props.Single ? 'tabBoxRadio' : ''" style="margin-top: 0px">
<el-table ref="multipleUserRef" :key="keyTabel" @selection-change="handleSelectionChange" :data="tableData" border :row-key="keyid" style="width: 100%" height="450">
<el-table ref="multipleUserRef" v-loading="loading" :key="keyTabel" @selection-change="handleSelectionChange" :data="tableData" border :row-key="keyid" style="width: 100%" height="450">
<el-table-column type="selection" width="55" :reserve-selection="true"/>
<el-table-column prop="xsBh" align="center" label="线索编号"/>
<el-table-column prop="xsMc" align="center" label="线索名称"/>
@ -32,10 +32,10 @@
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@pageCurrent-change="handleCurrentChange"
:pageCurrent-page="listQuery.pageCurrent"
@current-change="handleCurrentChange"
:current-page="listQuery.pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
@ -80,6 +80,7 @@ const props = defineProps({
default: []
}
});
const loading = ref(false)
const total = ref(0);
const listQuery = ref({
pageCurrent: 1,
@ -134,11 +135,15 @@ const handleCurrentChange = (currentPage) => {
};
const getListData = () => {
keyTabel.value++
const params = {...listQuery.vlue}
const params = {...listQuery.value}
loading.value = true;
qcckGet(params,'/mosty-gsxt/qbcj/selectPage').then(res=>{
loading.value = false;
tableData.value = res.records || [];
total.value = res.total;
multipleUser();
}).catch(()=>{
loading.value = false;
})
};

View File

@ -0,0 +1,100 @@
<template>
<el-dialog v-model="showDialog" :destroy-on-close="true" title="新增人员" @close="close" :close-on-click-modal="false">
<FormMessage v-model="listQuery" :formList="formData" labelWidth="120px" ref="elform" :rules="rules">
<template #bqList>
<div class="marks pointer" @click="chooseMarksVisible = true">
<span style="color: rgb(175 178 184);padding-left: 10px;" v-if="!listQuery.bqList || listQuery.bqList.length == 0 ">请选择标签</span>
<span v-else >
<el-tag @close.stop="closeTag(idx)" type="success" closable v-for="(it,idx) in listQuery.bqList" :key="idx">{{ it.bqMc }}</el-tag >
</span>
</div>
</template>
</FormMessage>
<template #footer>
<div class="flex just-center">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="submitForm">确认</el-button>
</div>
</template>
</el-dialog>
<ChooseMarks v-model="chooseMarksVisible" @choosed="choosed" :roleIds="roleIds" />
</template>
<script setup>
import ChooseMarks from "@/components/ChooseList/ChooseMarks/index.vue";
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { reactive, ref,getCurrentInstance } from 'vue';
const { proxy } = getCurrentInstance();
const { D_BZ_XB } = proxy.$dict("D_BZ_XB"); // 获取字典数据
const elform = ref()
const roleIds = ref([])
const showDialog = ref(false)
const chooseMarksVisible = ref(false)
const emit = defineEmits(['change'])
const listQuery = ref({})
const formData = ref([
{ label: "人员姓名", prop: "ryXm", type: "input" ,width:'45%'},
{ label: "性别", prop: "ryXb", type: "select" ,width:'45%',options:D_BZ_XB},
{ label: "身份证号", prop: "rySfzh", type: "input" ,width:'45%'},
{ label: "手机号码", prop: "ryLxdh", type: "input",width:'45%' },
{ label: "户籍地址", prop: "hjdXz", type: "input",width:'100%'},
{ label: "户籍地派出所", prop: "hjdpcsdm",depMc:'hjdpcs', type: "department" ,width:'48%'},
{ label: "特征描述", prop: "qtTzms", type: "input" ,width:'100%'},
{ label: "人员标签", prop: "bqList", type: "slot" ,width:'100%'},
{ label: "车牌号", prop: "clCph", type: "input" ,width:'45%'},
{ label: "车架号", prop: "clCjh", type: "input" ,width:'45%'},
{ label: "人员照片", prop: "fjZp", type: "upload" ,width:'100%'},
])
const rules = reactive({
ryXm: [{ required: true, message: "请输入姓名", trigger: "blur" }],
rySfzh: [{ required: true, message: "请输入身份证号", trigger: "blur" }],
ryXb: [{ required: true, message: "请选择性别", trigger: "change" }],
ryLxdh: [{ required: true, message: "请输入手机号码", trigger: "blur" }],
hjdXz: [{ required: true, message: "请输入户籍地", trigger: "blur" }],
xzdXz: [{ required: true, message: "请输入现居住地址", trigger: "blur" }],
})
const init = () =>{
showDialog.value = true;
}
// 选择标签
const choosed = (val) => {
listQuery.value.bqList = val.map(v=>{
return { bqZl:v.bqLb , bqId:v.id, bqLx:v.bqLx, bqLb:v.bqLb, bqMc:v.bqMc, bqDm:v.bqDm }
});
roleIds.value = val.map(v=>v.id)
}
// 删除数据
const closeTag = (idx) =>{
listQuery.value.bqList.splice(idx,1)
roleIds.value.splice(idx,1)
}
const submitForm = () =>{
elform.value.submit((val)=>{
val.id = new Date().getTime()
emit('change',val)
showDialog.value = false;
})
}
const close = () =>{
elform.value.reset();
listQuery.value.bqList = []
roleIds.value = []
showDialog.value = false;
}
defineExpose({init})
</script>
<style lang="scss" scoped>
.marks{
width: 100%;
min-height: 32px;
border: 1px solid #e9e9e9;
border-radius: 4px;
}
</style>

View File

@ -0,0 +1,224 @@
<template>
<el-dialog width="1400px" :model-value="modelValue" append-to-body @close="closed">
<template #title>
<span class="mr10 f16">选择布控人员</span>
<el-button type="primary" size="small" @click="zdyaddPerson">添加其他人员</el-button>
</template>
<el-form :model="listQuery" :inline="true">
<el-form-item label="人员姓名">
<el-input placeholder="请输入人员姓名" v-model="listQuery.ryxm" clearable ></el-input>
</el-form-item>
<el-form-item label="身份证号">
<el-input placeholder="请输入身份证号" v-model="listQuery.sfzh" clearable ></el-input>
</el-form-item>
<el-form-item label="手机号码">
<el-input placeholder="请输入手机号码" v-model="listQuery.sjhm" 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' : ''" style="margin-top: 0px">
<el-table ref="multipleUserRef" :key="keyTabel" v-loading="loading" @selection-change="handleSelectionChange" :data="tableData" border :row-key="keyid" style="width: 100%" height="450">
<el-table-column type="selection" width="55" :reserve-selection="true"/>
<el-table-column prop="ryXm" align="center" label="姓名"/>
<el-table-column prop="rySfzh" align="center" label="身份证"/>
<el-table-column prop="ryXb" align="center" label="性别">
<template #default="{ row }">
<DictTag :tag="false" :value="row.ryXb" :options="D_BZ_XB" />
</template>
</el-table-column>
<el-table-column prop="ryMz" align="center" label="民族">
<template #default="{ row }">
<DictTag :value="row.ryMz" :tag="false" :options="D_BZ_MZ" />
</template>
</el-table-column>
<el-table-column prop="hjdXz" align="center" label="户籍地"/>
<el-table-column prop="xzdXz" align="center" label="现居住址"/>
<el-table-column prop="ryLxdh" align="center" label="手机号"/>
<el-table-column prop="qtXnsf" align="center" label="虚拟身份"/>
<el-table-column prop="clCph" align="center" label="车牌号"/>
<el-table-column prop="clCjh" align="center" label="车架号"/>
<el-table-column prop="qtTzms" align="center" label="特征描述"/>
<el-table-column prop="bqList" align="center" label="人员标签">
<template #default="{ row }">
<span v-if="row.bqList">
<span v-for="(it,idx) in row.bqList" :key="idx"> {{ it.bqMc }}</span>
</span>
</template>
</el-table-column>
</el-table>
</div>
<div class="fenye flex just-end " :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
<template #footer>
<div class="flex just-center">
<el-button @click="closed">取消</el-button>
<el-button type="primary" @click="onComfirm">确认</el-button>
</div>
</template>
</el-dialog>
<!-- 自定义选添加人 -->
<AddPeo ref="addPerson" @change="changeZdy"></AddPeo>
</template>
<script setup>
import AddPeo from './addPeo.vue'
import { qcckGet} from "@/api/qcckApi.js";
import { defineProps, ref ,getCurrentInstance, watch} from "vue";
const { proxy } = getCurrentInstance();
const { D_BZ_XB,D_BZ_MZ } = proxy.$dict("D_BZ_XB","D_BZ_MZ"); //获取字典数据
const props = defineProps({
modelValue: {
type: Boolean,
default:false
},
LeaderType: {
type: String,
default: ""
},
//是否单选
Single: {
type: Boolean,
default: false
},
roleIds: {
type: Array,
default: []
},
});
const loading = ref(false)
const total = ref(0);
const listQuery = ref({
pageCurrent: 1,
pageSize: 20
});
const addPerson = ref()
const multipleUserRef = ref(null);
const multipleSelectionUser = ref([]);
const tableData = ref([]);
const emits = defineEmits(["update:modelValue", "choosed","choosedAdd"]);
const keyTabel = ref(0)
const keyid = (row) => {
return row.id;
};
const closed = () => {
emits("update:modelValue", false);
};
const reset = () => {
listQuery.value = { pageCurrent: 1, pageSize: 20, };
getListData();
};
// 为用户分配角色
const onComfirm = () => {
const userList = multipleSelectionUser.value;
let list = [];
let listId = [];
userList.forEach((val) => {
if (listId.indexOf(val.id) == -1) {
list.push(val);
listId.push(val.id);
}
});
emits("choosed", list);
closed();
};
// 自定义加人
const changeZdy = (val) => {
emits("choosedAdd", val);
closed();
}
/**
* pageSize 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.pageCurrent = currentPage;
getListData();
};
const getListData = () => {
keyTabel.value++
const params = {...listQuery.value}
loading.value = true;
qcckGet(params,'/mosty-gsxt/tbGsxtZdry/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);
if (props.roleIds.some((id) => id == item.id)) {
multipleUserRef.value.toggleRowSelection(item, true);
}
});
}
const handleFilter = () => {
listQuery.value.pageCurrent = 1;
getListData();
};
const handleSelectionChange = (val) => {
if (props.Single) {
if (val.length > 1) {
let del_row = val.shift();
multipleUserRef.value.toggleRowSelection(del_row, false);
}
multipleSelectionUser.value = val;
} else {
multipleSelectionUser.value = val;
}
};
const zdyaddPerson = () => {
addPerson.value.init();
};
watch(()=>props.modelValue,val=>{
if(val) handleFilter();
},{immediate:true})
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
</style>
<style>
.tabBoxRadio .el-checkbox__inner {
border-radius: 50% !important;
}
.tabBoxRadio .el-table__header-wrapper .el-checkbox {
display: none;
}
</style>

View File

@ -8,6 +8,7 @@
:index="index"
:class="item.elTagType"
@click="handleItem(item)"
:style="{color: props.color}"
>{{ item.label || item.zdmc }}</span>
<el-tag
v-else
@ -33,6 +34,10 @@ const props = defineProps({
type: Array,
default: null
},
color:{
type:String,
default:'#6f6f74'
},
tag: false,
value: [Number, String, Array]
});

View File

@ -0,0 +1,399 @@
<template>
<div>
<el-dialog v-model="modelValue" title="文件解析" width="1000px" :show-close="true" :center="true" :close-on-click-modal="false" :before-close="handleClose" >
<div class="flex align-center">
<h3>提取文件类型</h3>
<el-radio-group v-model="active" @change="changeRadio">
<el-radio :label="'文件解析'">文件解析</el-radio>
<el-radio :label="'图片解析'">图片解析</el-radio>
</el-radio-group>
</div>
<!-- 文件解析 -->
<div v-show="active == '文件解析'">
<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">{{ fileText }}</p>
</div>
<button id="extract-btn" disabled>提取文本</button>
<h3>提取结果</h3>
<div id="result">{{ content }}</div>
</div>
<!-- 图片解析 -->
<div v-show="active == '图片解析'" v-loading="loading" element-loading-text="模型加载中......">
<div class="flex align-center just-between">
<h1>文件文本提取工具</h1>
<span title="刷新" class="pointer" >
<el-icon color="#0072ff" size="30px" @click="frashJs"><RefreshRight /></el-icon>
<el-icon color="#23c044" size="14px" v-if="hasLoad"><CircleCheckFilled /></el-icon>
<el-icon color="#e60e0e" size="14px" v-if="!hasLoad"><CircleCloseFilled /></el-icon>
</span>
</div>
<p>上传文件提取文本内容支持 .png, .jpg </p>
<div class="container flex" style="height: 248px;">
<div class="mr10">
<el-upload :headers="headers" accept=".png,.jpg,jpeg" action="/mosty-api/mosty-base/minio/image/upload/id" :show-file-list="false" :on-success="handlerSuccess" :on-change="onHandleChange" >
<el-button size="medium" type="primary">上传图片</el-button>
</el-upload>
<p id="file-info">{{ files.name || '未选择文件' }} </p>
</div>
<div class="box">
<div class="imd">
<img :src="image" v-if="image" style="width: 340px; max-height: 200px"/>
<img :src="image" ref="imageRef" v-show="false" />
</div>
<div class="imd" v-show="false">
<canvas ref="canvasRef"></canvas>
</div>
</div>
</div>
<h3>提取结果</h3>
<div class="textModel noScollLine" v-loading="linadingImg" element-loading-text="图片解析中......">
<p v-if="texts.length == 0">{{ alertText }}</p>
<template v-else>
<p v-for="(text, index) in texts" :key="index">{{ text }}</p>
</template>
</div>
</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 axios from "axios";
import * as ocr from "@paddlejs-models/ocr";
import { drawBox } from "@/utils/ocrUtils";
import { nextTick,reactive, ref,getCurrentInstance, watch } from "vue";
import { useStore } from "vuex";
const store = useStore();
const props = defineProps({
modelValue: {
type: Boolean,
default: false
}
});
const content = ref('请先上传文件...')
const fileText = ref('未选择文件')
const { proxy } = getCurrentInstance();
const emits = defineEmits(["update:modelValue", "change"]);
const active = ref('文件解析')
const hasLoad = ref(false)
const files = ref({})
const loading = ref(true)
const linadingImg = ref(false)
const image = ref('')
const alertText = ref('请先上传文件...')
const texts = ref([])
const imageRef = ref()
const canvasRef = ref()
const textStyle = reactive({
width: "",
height: ""
})
const headers = ref({
Authorization: store.getters.token
});
const fjdz = ref('') //附件地址
const fjmc = ref('') //附件地址
const initDemo = () =>{
loading.value = imgIsLoad ? false : true;
hasLoad.value = imgIsLoad ? true : false;
nextTick(() => {
const fileInput = document.getElementById("file-input");
const extractBtn = document.getElementById("extract-btn");
let selectedFile = null;
// 监听文件选择
fileInput.addEventListener("change", function (e) {
if (e.target.files.length > 0) {
selectedFile = e.target.files[0];
fileText.value = `已选择: ${selectedFile.name} (${( selectedFile.size / 1024 ).toFixed(2)} KB)`;
extractBtn.disabled = false;
fjmc.value = selectedFile.name;
uploadFile(selectedFile); //上传附件
} else {
selectedFile = null;
fileText.value = "未选择文件";
extractBtn.disabled = true;
}
if (selectedFile.type == "video/mp4") {
upfileOnchange(selectedFile);
}
});
// 提取文本按钮点击事件
extractBtn.addEventListener("click", async function () {
if (!selectedFile) return (content.value = "请先选择文件");
content.value = "正在处理文件...";
try {
let text = "";
const fileType = selectedFile.name.split(".").pop().toLowerCase();
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);
} else if (["mp4", "mp3", "wav"].includes(fileType)) {
// 处理mp4,mp3,wav文件
await start();
text = "数据加载有点慢,请稍等。。。。";
setTimeout(() => {
content.value = videoText;
}, 2000);
}else {
throw new Error("不支持的文件类型");
}
content.value = text || "未提取到文本内容";
} catch (error) {
content.value = `处理失败: ${error.message}`;
}
});
});
}
watch(()=>props.modelValue,val=>{
if(val) initDemo();
},{immediate:true,deep:true})
// 读取文本文件
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 handlerSuccess = (file) =>{
fjdz.value = file.data;
}
/**@Descripttion:图片上传事件*/
const onHandleChange = (file) => {
fjmc.value = file.name;
files.value = file;
image.value = URL.createObjectURL(file.raw);
linadingImg.value = true;
alertText.value = '图片文件解析中。。。'
setTimeout(() => {
getRecognize();
}, 600);
}
// 图片解析
const getRecognize = async () => {
const image = imageRef.value;
const canvas = canvasRef.value;
const res = await ocr.recognize(image);
const { text, points } = res;
drawBox(points, image, canvas);
textStyle.width = image.width - 40 + "px";
texts.value = text;
linadingImg.value = false;
alertText.value = '解析失败,请选择清晰一点的图片重试!'
}
// 切换标签
const changeRadio = (val) =>{
content.value = "请先上传文件...";
fileText.value = "选择文件";
files.value = {};
alertText.value = '请先上传文件...';
texts.value = [];
image.value = '';
fjmc.value = '';
if(val == '图片解析'){
if(!imgIsLoad) proxy.$message({ type: "error", message: "加载失败,请刷新页面" });
}
}
// 提交
const onComfirm = () => {
if(active.value == '文件解析'){
if(content.value == '请先上传文件...') return proxy.$message({ type: "warning", message: "请解析文件" });
emits("change", { text: content.value,fjdz:fjdz.value,fjmc:fjmc.value });
}else{
if(texts.value.length == 0) return proxy.$message({ type: "warning", message: "请解析文件" });
emits("change", {text:texts.value.join(',\n'),fjdz:fjdz.value,fjmc:fjmc.value});
}
handleClose()
};
// 关闭
const handleClose = () => {
content.value = "请先上传文件";
fileText.value = "未选择文件";
files.value = {}
alertText.value = '请先上传文件...';
texts.value = []
image.value = ''
active.value = '文件解析'
emits("update:modelValue", false);
};
// 上传附件
const uploadFile = (file) =>{
let formData = new FormData();
formData.append("file", file);
let token = localStorage.getItem('token');
axios({
method: 'post',
url: '/mosty-api/mosty-base/minio/image/upload/id',
data:formData,
headers: { "Content-type": "multipart/form-data",'Authorization': token }
}).then( (res) => {
fjdz.value = res.data ? res.data.data : null;
})
}
// 刷新js
const frashJs = async () =>{
if(!imgIsLoad){
try {
await ocr.init();// 模型初始化
imgIsLoad = true;
proxy.$message({ type: "success", message: "加载成功" });
} catch (err) {
proxy.$message({ type: "error", message: "加载失败,请刷新页面" });
imgIsLoad = 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: #0072ff;
color: white;
padding: 10px 15px;
border: none;
cursor: pointer;
font-size: 16px;
border-radius: 4px;
}
button:hover {
background: #0072ff;
}
#result {
margin-top: 20px;
white-space: pre-wrap;
background: #f9f9f9;
padding: 15px;
border: 1px solid #ddd;
border-radius: 4px;
height: 270px;
overflow-y: auto;
}
#file-info {
margin: 10px 0;
font-style: italic;
color: #666;
}
::v-deep .el-dialog {
margin-top: 10px;
}
.box{
display: flex;
.imd{
flex: 1;
}
}
.textModel{
margin-top: 20px;
white-space: pre-wrap;
background: #f9f9f9;
padding: 15px;
border: 1px solid #ddd;
border-radius: 4px;
height: 195px;
overflow-y: auto;
}
</style>

View File

@ -46,11 +46,15 @@ const mMap = ref(null); //地图对象
const mapUtil = ref(null); //地图工具对象
const zoomTarget = ref(6);
// 定义组件发出的事件
const emit = defineEmits(['mapLoaded'])
const props = defineProps({
mapid: {
type: String,
default: "mapDiv"
},
//是否显示可以切换地图底图
isShow: {
type: Boolean,
@ -79,13 +83,15 @@ let map;
let mapLayer;
let mapLayer1;
onMounted(() => {
console.log("xxxxxxx");
emitter.on("followUp", (res) => {
let box = document.getElementsByClassName("changeMap_box");
if (!box) return;
box[0].style.right = !res ? "4px" : "398px";
box[0].style.transition = "0.5s";
});
map = new EliMap({
id: props.mapid,
crs: "EPSG:3857",
@ -110,6 +116,8 @@ onMounted(() => {
url: 'http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
})
zoomTarget.value = map.mapboxGLMap.getZoom();
// 地图加载完成后发出事件
emit('mapLoaded')
});
mapUtil.value = new MapUtil(map);
@ -253,7 +261,7 @@ const mapSetLayer = (id, source) => {
//获取地图绘制的数据
const resFun = (coord, type, flag, data) => {
emitter.emit("coordString", {
coord: coord,
type: type,

View File

@ -0,0 +1,359 @@
<template>
<div :id="mapid" class="map"></div>
<div class="changeMap_box" v-if="props.isShow">
<el-switch v-model="conditionRoute" @change="handleSwitch" active-text="打开路况" inactive-text="关闭路况"
style="--el-switch-color: #13ce66; --el-switch-off-color: #ff4949" />
<!-- <el-carousel type="card" height="75px" :autoplay="false" indicator-position="none" :initial-index="3" @change="onMapImageChange">
<el-carousel-item>
<div class="mapImageItem">
<img :src="require('@/assets/images/slt.jpg')" alt="" />
<div>栅格浅色</div>
</div>
</el-carousel-item>
<el-carousel-item>
<div class="mapImageItem">
<img :src="require('@/assets/images/yxt.jpg')" alt="" />
<div>影像图</div>
</div>
</el-carousel-item>
<el-carousel-item>
<div class="mapImageItem">
<img :src="require('@/assets/images/yst.jpg')" alt="" />
<div>栅格深色</div>
</div>
</el-carousel-item>
<el-carousel-item>
<div class="mapImageItem">
<img :src="require('@/assets/images/shy.png')" alt="" />
<div>三合一</div>
</div>
</el-carousel-item>
</el-carousel> -->
<!-- 地图缩放 -->
<div class="zoomTargetBox">
<el-input-number :min="7" :max="18" v-model="zoomTarget" :step="1" step-strictly @change="handleZoom"></el-input-number>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, defineProps, nextTick } from "vue";
import { MapUtil } from "./mapUtil";
import emitter from "@/utils/eventBus.js";
import { getItem } from "@/utils/storage";
const conditionRoute = ref(true); //路况
const mMap = ref(null); //地图对象
const mapUtil = ref(null); //地图工具对象
const zoomTarget = ref(6);
const props = defineProps({
mapid: {
type: String,
default: "mapDiv"
},
//是否显示可以切换地图底图
isShow: {
type: Boolean,
default: false
},
//是否显示实时路况
isShowMvt: {
type: Boolean,
default: false
},
//是否显示地图层级
isShowZoom: {
type: Boolean,
default: false
},
//是否显示绘制控件
isShowDraw: {
type: Boolean,
default: false
}
});
try {
const userInfo = getItem("deptId")[0].deptCode;
} catch (error) { }
let map;
let mapLayer;
let mapLayer1;
onMounted(() => {
emitter.on("followUp", (res) => {
let box = document.getElementsByClassName("changeMap_box");
if (!box) return;
box[0].style.right = !res ? "4px" : "398px";
box[0].style.transition = "0.5s";
});
map = new EliMap({
id: props.mapid,
crs: "EPSG:4490",
style: {
glyphs: "./fonts/{fontstack}/{range}.pbf",
center: [94.36057012, 29.64276831],
zoom: 15
},
minZoom: 7,
maxZoom: 18,
});
window.map = map;
map.mapboxGLMap.on("load", () => {
map.addWMTSLayer(
"/PGIS_S_TileMapServer/Maps/XZDJ_SL/EzMap"
,
{
Service: "getImage",
Type: "RGB",
ZoomOffset: "0",
V: "0.3",
Zoom: "{z}",
Row: "{y}",
Col: "{x}"
},
{
tileSize: 300
}
);
zoomTarget.value = map.mapboxGLMap.getZoom();
});
mapUtil.value = new MapUtil(map);
mapUtil.value.Drawplot(); //初始化加载绘制工具
// 设置地图中心点及图层
emitter.on("setMapCenter", (res) => {
mapUtil.value.setMapCenter(res.location, res.zoomLevel);
});
emitter.on("removePlot", (flag) => {
mapUtil.value.removePlot(flag);
});
emitter.on("removeAll", (flag) => {
mapUtil.value.removeAll(flag);
});
// 撒点
emitter.on("addPointArea", (obj) => {
mapUtil.value.makerSki(obj);
});
// 鼠标滑过提示文字的点位
emitter.on("showPoint", (obj) => {
mapUtil.value.showPoint(obj);
});
// 清除覆盖物
emitter.on("deletePointArea", (res) => {
mapUtil.value.removeElement(res);
});
// 清除某个覆盖物的单个
emitter.on("deletePointAreaOne", (obj) => {
mapUtil.value.removeElementOne(obj.flag, obj.id);
});
// 清除某个覆盖物的单个
emitter.on("showSquire", (obj) => {
mapUtil.value.zdySquire(obj);
});
// 绘制图形 - 回显区域
emitter.on("drawShape", (res) => {
mapUtil.value.plot(res, resFun);
});
emitter.on("removeEara", (flag) => {
mapUtil.value.removeEara(flag);
});
// 回显图形
emitter.on("echoPlane", (res) => {
mapUtil.value.echoPlane(res);
});
//移除绘制区域
emitter.on("removeEara", (flag) => {
mapUtil.value.removeEara(flag);
});
// 回显线
emitter.on("echoLine", (res) => {
mapUtil.value.createLine(res, res.flag);
});
//创建边界面geojson
emitter.on("setBoundarys", (res) => {
mapUtil.value.createBoundarys(res);
});
// 移除边界
emitter.on("removeBj", (res) => {
mapUtil.value.removeBj(res);
});
// 轨迹回放
emitter.on("drawLineAnimation", (res) => {
mapUtil.value.displayLineAnimation(res);
});
// 聚合撒点
emitter.on("addPoint", (obj) => {
mapUtil.value.aggregateScatteringPoint(obj);
});
// 热力图显示
emitter.on("thermodynamicChart", (res) => {
mapUtil.value.showHeatDrawing(res);
});
// 扩散圆
emitter.on("diffusionCircle", (res) => {
mapUtil.value.diffusionCircle(res);
});
// 展示盘曲
emitter.on("showGapText", (obj) => {
mapUtil.value.gapText(obj);
});
// 获取当前地图中心点
emitter.on("getCurrentCenter", (res) => {
let centerPoint = map.mapboxGLMap.getCenter();
let coords = [centerPoint.lng, centerPoint.lat];
emitter.emit("getcentercoord", coords);
});
});
//切换地图底图
const onMapImageChange = (val) => {
//清除已经存在胡地图图层
if (map.mapboxGLMap.getLayer("SGQS_ID"))
map.mapboxGLMap.removeLayer("SGQS_ID");
if (map.mapboxGLMap.getLayer("YX_ID")) map.mapboxGLMap.removeLayer("YX_ID");
if (map.mapboxGLMap.getLayer("SGSG_ID"))
map.mapboxGLMap.removeLayer("SGSG_ID");
if (map.mapboxGLMap.getLayer("TDT_TITLE_ID"))
map.mapboxGLMap.removeLayer("TDT_TITLE_ID");
if (map.mapboxGLMap.getLayer("TDT_ROAD_ID"))
map.mapboxGLMap.removeLayer("TDT_ROAD_ID");
if (map.mapboxGLMap.getLayer("TDT_POI_ID"))
map.mapboxGLMap.removeLayer("TDT_POI_ID");
//设置图层
switch (val) {
case 0:
mapSetLayer("SGQS_ID", "SGQS");
break;
case 1:
mapSetLayer("YX_ID", "YX");
break;
case 2:
mapSetLayer("SGSG_ID", "SGSG");
break;
case 3:
mapSetLayer("TDT_TITLE_ID", "TDT_TITLE_SOURCES");
mapSetLayer("TDT_ROAD_ID", "TDT_ROAD_SOURCES");
mapSetLayer("TDT_POI_ID", "TDT_POI_SOURCES");
break;
}
if (map.mapboxGLMap.getLayer("realTimeTrafficlevelOne"))
map.mapboxGLMap.moveLayer("realTimeTrafficlevelOne");
if (map.mapboxGLMap.getLayer("map_id")) map.mapboxGLMap.moveLayer("map_id");
if (map.mapboxGLMap.getLayer("map_ids")) map.mapboxGLMap.moveLayer("map_ids");
};
//设置图层函数
const mapSetLayer = (id, source) => {
map.mapboxGLMap.addLayer({ id, type: "raster", source });
};
//获取地图绘制的数据
const resFun = (coord, type, flag, data) => {
emitter.emit("coordString", {
coord: coord,
type: type,
flag: flag,
data: data
});
};
// 地图层级
const handleZoom = (val) => {
map.mapboxGLMap.setZoom(val);
};
// 是否打开或者关闭路况
const handleSwitch = (val) => {
if (val) {
// 打开
} else {
// 关闭
}
};
onUnmounted(() => {
emitter.off("removePlot");
emitter.off("setMapCenter");
emitter.off("addPointArea");
emitter.off("showPoint");
emitter.off("deletePointArea");
emitter.off("deletePointAreaOne");
emitter.off("drawShape");
emitter.off("echoPlane");
emitter.off("removeEara");
emitter.off("echoLine");
emitter.off("addPoint");
emitter.off("thermodynamicChart");
emitter.off("drawLineAnimation");
emitter.off("aggregateScatteringPoint");
emitter.off("hotmap");
emitter.off("setBoundarys");
emitter.off("diffusionCircle");
emitter.off("SsCircle");
emitter.off("ClearssCircle");
});
</script>
<style lang="scss" scoped>
.map {
width: 100%;
height: 100%;
background-color: aliceblue;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
z-index: 1;
}
.changeMap_box {
position: absolute;
right: 398px;
bottom: 4px;
z-index: 9;
.mapImageItem {
border: 1px solid #08aae8;
background: rgb(9, 26, 70);
&>img {
width: 100%;
height: 50px;
}
&>div {
text-align: center;
position: relative;
top: -3px;
}
}
.zoomTargetBox {
margin-top: 10px;
margin-left: 23px;
}
::v-deep .el-input-number__decrease,
::v-deep .el-input-number__increase {
background: #133362;
color: #fff;
border: none;
}
::v-deep .el-input__inner {
background: #0c1641;
}
}
</style>

View File

@ -712,50 +712,8 @@ export function MapUtil(map) {
// 打开详情弹窗
MapUtil.prototype.openInfoDetail = (flag, data) => {
switch (flag) {
case "rx":
emitter.emit('showJzInfo', data);
break;
case 'gaj':
case 'pcs':
case 'jwz':
case 'xfq':
case 'zdfkd':
emitter.emit('showGazy', data);
break;
case 'kfd':
emitter.emit("changeGroupPoint", { lx: 'kfd', xffwlx: '2', xffwid: data.kfdId });
emitter.emit('showGazy', [data]);
break;
case 'sp':
emitter.emit('showGzy', data);
emitter.emit("showGzyInfo", data);
break;
case 'kk':
emitter.emit('showGzy', data);
break;
case 'aj':
case 'jqMap':
emitter.emit('showAj', data);
break;
case 'yj':
case 'yjMap':
emitter.emit("showYjxq", data);
break;
case 'dzjg':
case 'school':
case 'hospital':
case 'banck':
case 'shop':
emitter.emit("showShzy", data);
break;
case 'qchzc_map':
case 'jczMap_hm':
case 'jczMap_hhx':
emitter.emit("showJcz", [data]);
break;
case 'cyryMap':
console.log(data, '从业人员');
emitter.emit("showCyry", [data]);
case 'home_yj_map':
emitter.emit("showHomeYJ", data);
break;
}
}

View File

@ -0,0 +1,125 @@
<template>
<div style="border: 1px solid #ccc">
<!-- 工具栏 -->
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" />
<!-- 编辑器 -->
<Editor :style="`height: ${props.heightNumber}px; overflow-y: hidden`" v-model="editorVal" :defaultConfig="editorConfig" :mode="mode" @onCreated="handleCreated" @onChange="handChange" />
</div>
</template>
<script setup>
import { compressImage } from "@/utils/tools.js";
import "@wangeditor/editor/dist/css/style.css";
import { qcckPost } from "@/api/qcckApi.js";
import { ElMessage } from "element-plus";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import {
ref,
onMounted,
shallowRef,
onBeforeUnmount,
defineEmits,
defineProps,
watch
} from "vue";
const props = defineProps({
// 编辑器内容
modelValue: {
type: String,
default: ""
},
markitVal: {
type: String,
default: ""
},
placeholder: {
type: String,
default: "请输入内容。。。。"
},
heightNumber: {
type: Number,
default: 500
}
});
const editorVal = ref("");
const editorRef = shallowRef();
const mode = "default";
const valueHtml = ref(""); //内容
//工具配置
const toolbarConfig = {
excludeKeys: ["blockquote", "codeBlock"] //清除不必要的工具,引用和代码块
};
const emits = defineEmits(["update:modelValue", "changeFn"]);
//编辑器配置
const editorConfig = {
withCredentials: true, //允许跨域
placeholder: props.placeholder, //提示语
MENU_CONF: {
uploadImage: {
// 自定义上传图片
async customUpload(file, insertFn) {
let fileBlob = await compressImage(file);
let fileData = new File([fileBlob], fileBlob.name, {
type: fileBlob.type
});
if (fileData.size > 2 * 1024 * 1024) {
ElMessage({
message: "图片超过2MB",
type: "success"
});
} else {
await uploadFn(fileData, insertFn);
}
}
// server: "/mosty-api/mosty-base/minio/image/upload",
// base64LimitSize: 10000 * 1024,
},
uploadVideo: {
// 自定义上传视频
async customUpload(file, insertFn) {
await uploadFn(file, insertFn);
}
}
}
};
watch(
[() => props.markitVal, () => editorRef.value],
(val) => {
// if (val) editorRef.value = val;
if ((val[0] && val[1]) || val[0] == "") {
editorVal.value = val[0];
}
},
{ deep: true, immediate: true }
);
const uploadFn = (file, insertFn) => {
let param = new FormData();
param.append("file", file);
qcckPost(param, "/mosty-base/minio/image/upload").then((res) => {
insertFn(res);
});
};
//编辑器创建成功
const handleCreated = (editor) => {
editorRef.value = editor;
};
//内容发生变化
const handChange = (editor) => {
// console.log(editor.getHtml(),'editor.getText()');
// 判断是否是一个空段落,是空就传空文本
if (editor.isEmpty()) {
emits("changeFn", editor.getText());
} else {
emits("changeFn", editor.getHtml());
}
};
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor) editor.destroy();
});
</script>
<style lang="scss" scoped>
</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

@ -1,187 +0,0 @@
<template>
<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-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' : ''" style="margin-top: 0px">
<el-table ref="multipleUserRef" :key="keyTabel" @selection-change="handleSelectionChange" :data="tableData" 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" />
</template>
</el-table-column>
<el-table-column prop="bqYs" align="center" label="标签颜色">
<template #default="{ row }">
<DictTag :value="row.bqYs" :tag="false" :options="D_GS_SSYJ" />
</template>
</el-table-column>
</el-table>
</div>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@pageCurrent-change="handleCurrentChange"
:pageCurrent-page="listQuery.pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="closed">取消</el-button>
<el-button type="primary" @click="onComfirm">确认</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
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 props = defineProps({
modelValue: {
type: Boolean,
default:false
},
titleValue: {
type: String,
default: "选择标签"
},
LeaderType: {
type: String,
default: ""
},
//是否单选
Single: {
type: Boolean,
default: false
},
roleIds: {
type: Array,
default: []
}
});
const total = ref(0);
const listQuery = ref({
pageCurrent: 1,
pageSize: 20
});
const multipleUserRef = ref(null);
const multipleSelectionUser = ref([]);
const tableData = ref([]);
const emits = defineEmits(["update:modelValue", "choosed"]);
const keyTabel = ref(0)
const keyid = (row) => {
return row.id;
};
const closed = () => {
emits("update:modelValue", false);
};
const reset = () => {
listQuery.value = { pageCurrent: 1, pageSize: 20, };
getListData();
};
// 为用户分配角色
const onComfirm = () => {
const userList = multipleSelectionUser.value;
let list = [];
let listId = [];
userList.forEach((val) => {
if (listId.indexOf(val.id) == -1) {
list.push(val);
listId.push(val.id);
}
});
emits("choosed", list);
closed();
};
/**
* pageSize 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.pageCurrent = currentPage;
getListData();
};
const getListData = () => {
keyTabel.value++
const params = {bqLb:'02',...listQuery.vlue}
qcckGet(params,'/mosty-gsxt/tbGsxtBqgl/selectPage').then(res=>{
tableData.value = res.records || [];
total.value = res.total;
multipleUser();
})
};
//列表回显
function multipleUser() {
tableData.value.forEach((item) => {
multipleUserRef.value.toggleRowSelection(item, false);
if (props.roleIds.some((id) => id == item.id)) {
multipleUserRef.value.toggleRowSelection(item, true);
}
});
}
const handleFilter = () => {
listQuery.value.pageCurrent = 1;
getListData();
};
const handleSelectionChange = (val) => {
if (props.Single) {
if (val.length > 1) {
let del_row = val.shift();
multipleUserRef.value.toggleRowSelection(del_row, false);
}
multipleSelectionUser.value = val;
} else {
multipleSelectionUser.value = val;
}
};
watch(()=>props.modelValue,val=>{
if(val) handleFilter();
},{immediate:true})
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
</style>
<style>
.tabBoxRadio .el-checkbox__inner {
border-radius: 50% !important;
}
.tabBoxRadio .el-table__header-wrapper .el-checkbox {
display: none;
}
</style>

View File

@ -1,18 +1,31 @@
<template>
<div class="form-item-box" :style="{ width: width }">
<el-date-picker style="width:100%" v-model="modelValue" type="date" v-bind="$attrs" @change="onInput" :placeholder="placeholder" value-format="YYYY-MM-DD"/>
<el-date-picker
style="width:100%"
v-model="localModelValue"
:type="props.type"
v-bind="$attrs"
@change="onInput"
:placeholder="placeholder"
:value-format="props.format"
/>
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from "@/constant";
import { ref, defineProps, defineEmits, defineExpose } from "vue";
import { ref, defineProps, defineEmits, defineExpose, computed } from "vue";
const props = defineProps({
//获取组件传值
placeholder: {
default: "请填写",
type: String
},
format:{
default: "YYYY-MM-DD",
type: String
},
modelValue: {
default: "",
type: String
@ -21,12 +34,21 @@ const props = defineProps({
default: COMPONENT_WIDTH,
type: String
},
type: {
default: "date",
type: String
}
});
const emits = defineEmits(["update:modelValue"]);
// 使用计算属性处理双向绑定
const localModelValue = computed({
get: () => props.modelValue,
set: (value) => emits("update:modelValue", value)
});
const onInput = (e) => {
emits("update:modelValue", e);
};
</script>
</script>

View File

@ -20,6 +20,7 @@ import { COMPONENT_WIDTH } from "@/constant";
import { qcckPost, qcckGet, qcckFlvGet } from "@/api/qcckApi.js";
import { ref, defineProps, defineEmits, defineExpose, computed, onMounted, watch } from "vue";
import { selectDeptPage } from "@/api/user-manage";
import { tr } from "element-plus/es/locale.mjs";
const props = defineProps({
//获取组件传值
placeholder: {
@ -41,9 +42,13 @@ const props = defineProps({
width: {
default: COMPONENT_WIDTH,
type: String
},
isAll:{
default: false,
type: Boolean
}
});
const modelShow = ref(false);
const firstLoad = ref(true)
const oldmodelValue = ref([]);
const listQuery = ref({
deptname: "",
@ -61,7 +66,12 @@ const endProps = {
lazy: true,
lazyLoad(node, resolve) {
listQuery.value.parentid = node.data.id;
selectDeptPage(listQuery.value).then((res) => {
let params = { ...listQuery.value };
if(props.isAll && firstLoad.value) {
params.parentid = 1;
firstLoad.value = false;
}
selectDeptPage(params).then((res) => {
depList.value = depList.value.concat(res)
//处理部门是否包含下级
for (let i = 0; i < res.length; i++) {
@ -73,7 +83,9 @@ const endProps = {
};
const tableData = ref([]);
const getSysMenuTree = async () => {
const res = await selectDeptPage(listQuery.value);
let params = { ...listQuery.value }
if(props.isAll) params.parentid = 1;
const res = await selectDeptPage(params);
tableData.value = res;
depList.value = res
};

View File

@ -1,287 +0,0 @@
<template>
<div>
<el-dialog
:title="titleValue"
width="1400px"
:model-value="modelValue"
@close="closed"
>
<el-form :model="listQuery" :inline="true">
<el-form-item label="所属部门">
<MOSTY.Department width="100%" clearable v-model="listQuery.ssbmdm" />
</el-form-item>
<el-form-item label="圈层名称">
<el-input
v-model="listQuery.qcmc"
placeholder="请输入圈层名称"
clearable
/>
</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" style="margin-top: 0px" v-if="modelValue">
<el-table
ref="multipleUserRef"
@selection-change="handleSelectionChange"
:data="tableData"
border
style="width: 100%"
:row-key="keyid"
height="450"
>
<el-table-column
type="selection"
width="55"
:reserve-selection="true"
v-if="props.multiple"
/>
<el-table-column width="55" #default="{ row }" v-else>
<el-radio v-model="ridioIndex" :label="row.id"></el-radio>
</el-table-column>
<el-table-column
label="序号"
type="index"
align="center"
sortable
width="80"
/>
<el-table-column
sortable
prop="ssbm"
label="所属部门"
show-overflow-tooltip
align="center"
></el-table-column>
<el-table-column
sortable
prop="qcmc"
show-overflow-tooltip
label="圈层名称"
align="center"
>
</el-table-column>
<el-table-column
sortable
prop="qclx"
show-overflow-tooltip
label="圈层类型"
align="center"
>
<template #default="{ row }">
<dict-tag :options="D_BZ_QCLX" :value="row.qclx" :tag="false" />
</template>
</el-table-column>
<el-table-column
sortable
prop="qcjb"
show-overflow-tooltip
label="圈层等级"
align="center"
>
<template #default="{ row }">
<dict-tag :options="D_BZ_QCDJ" :value="row.qcjb" :tag="false" />
</template>
</el-table-column>
</el-table>
</div>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.pageCurrent"
:page-sizes="[2, 5, 10, 20]"
:page-size="listQuery.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="closed">取消</el-button>
<el-button type="primary" @click="onComfirm">确认</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import * as rule from "@/utils/rules.js";
import * as MOSTY from "@/components/MyComponents/index";
import { ElMessage } from "element-plus";
import { qcckGet, qcckPost } from "@/api/qcckApi.js";
import {
defineProps,
watch,
ref,
onMounted,
nextTick,
getCurrentInstance
} from "vue";
const { proxy } = getCurrentInstance();
const { D_BZ_QCLX, D_BZ_QCDJ } = proxy.$dict("D_BZ_QCLX", "D_BZ_QCDJ");
const props = defineProps({
//是否显示
modelValue: {
type: Boolean,
required: true
},
//标题
titleValue: {
type: String,
default: "选择圈层"
},
//是否多选
multiple: {
default: true,
type: Boolean
},
//已经选中得数据回显
data: {
type: Array,
default: []
}
});
const keyid = (row) => {
return row.id;
};
const total = ref(0);
const ridioIndex = ref(null);
const listQuery = ref({
pageCurrent: 1,
pageSize: 20,
qcmc: "",
ssbmdm: ""
});
const form = ref({});
const tableData = ref([]);
const emits = defineEmits(["close", "choosedQc"]);
const closed = () => {
emits("close", false);
};
const reset = () => {
listQuery.value = {
pageCurrent: 1,
pageSize: 20,
qcmc: "",
ssbmdm: ""
};
getListData();
};
//确认选中
const onComfirm = () => {
if (props.multiple) {
//多选
const List = JSON.parse(JSON.stringify(multipleSelectionUser.value));
if (List.length === 0) {
proxy.$message.warning("请选择圈层");
return;
}
emits("choosedQc", List);
} else {
//单选
if (![ridioIndex.value][0]) {
proxy.$message.warning("请选择圈层");
return;
}
const info = tableData.value.find((item) => {
return item.id === ridioIndex.value;
});
emits("choosedQc", [info]);
}
closed();
};
onMounted(() => {
getListData();
});
/**
* pageSize 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.pageSize = currentPage;
getListData();
};
//圈层数据
const getListData = async () => {
qcckGet(listQuery.value, "/mosty-jcgl/qc/selectQcList").then((res) => {
tableData.value = res?.records;
multipleUser(props.data, tableData.value);
total.value = Number(res.total);
});
};
const handleFilter = () => {
listQuery.value.pageCurrent = 1;
getListData();
};
const multipleUserRef = ref(null); //表单
//多选选中的数据
const multipleSelectionUser = ref([]);
const handleSelectionChange = (val) => {
multipleSelectionUser.value = val;
};
//回显
function multipleUser(row, list) {
if (row) {
if (props.multiple) {
row.forEach((item) => {
list.forEach((select) => {
if (item.id == select.id) {
if (multipleUserRef.value) {
multipleUserRef.value.toggleRowSelection(select, true);
}
}
});
});
}
}
}
watch(
() => props.modelValue,
(val) => {
if (val === true) {
handleFilter();
}
}
);
watch(
() => props.data,
(val) => {
if (multipleUserRef.value) multipleUser(val, tableData.value);
}
);
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
::v-deep .el-form--inline {
padding-left: 0 !important;
}
::v-deep .el-radio__label {
display: none;
}
</style>
<style lang="scss">
.el-dialog {
// --el-dialog-bg-color: #fff !important;
}
// .el-dialog__title {
// color: #fff !important;
// }
</style>

View File

@ -1,23 +1,11 @@
<template>
<div class="form-item-box" :class="props.showBtn?'showBtn-upload':''" :style="{ width: width }">
<el-upload
v-bind="$attrs"
:headers="headers"
:multiple="false"
class="avatar-uploader"
:limit="props.limit"
:action="actionUrl"
:list-type=" props.showBtn ? '' :'picture-card'"
:file-list="fileList"
show-file-list
:on-exceed="handleExceed"
:on-success="handlerSuccess"
:before-upload="beforeImgUpload"
>
<div class="form-item-box" :class="props.showBtn ? 'showBtn-upload' : ''" :style="{ width: width }">
<el-upload v-bind="$attrs" :headers="headers" :multiple="false" class="avatar-uploader" :limit="props.limit"
:action="actionUrl" :list-type="props.showBtn ? '' : 'picture-card'" :file-list="fileList" show-file-list
:on-exceed="handleExceed" :on-success="handlerSuccess" :before-upload="beforeImgUpload">
<template #default>
<el-button v-if="props.showBtn" size="small" type="primary">上传文件</el-button>
<el-icon v-else> <Plus /> </el-icon>
<el-icon v-else><Plus /></el-icon>
</template>
<template #file="{ file }" v-if="!props.showBtn">
<div v-if="props.isImg">
@ -26,42 +14,22 @@
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<el-icon> <zoom-in /></el-icon>
</span>
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleRemove(file, fileList)"
>
<el-icon>
<Delete />
</el-icon>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file, fileList)">
<el-icon><Delete /></el-icon>
</span>
</span>
</div>
<div v-else>
<div class="file-wrap">
<span>
<svg-icon :icon="getSuffix(file.name)" />
</span>
<span><svg-icon :icon="getSuffix(file.name)" /></span>
<span class="file-name">{{ file.name }}</span>
</div>
<span class="el-upload-list__item-actions">
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleDownload(file)"
>
<el-icon>
<Download />
</el-icon>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleDownload(file)">
<el-icon><Download /></el-icon>
</span>
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleRemove(file, fileList)"
>
<el-icon>
<Delete />
</el-icon>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file, fileList)">
<el-icon><Delete /></el-icon>
</span>
</span>
</div>
@ -75,14 +43,7 @@
<script setup>
import { COMPONENT_WIDTH } from "@/constant";
import {
ref,
defineProps,
defineEmits,
computed,
watch,
onMounted
} from "vue";
import { ref, defineProps, defineEmits, computed, watch, onMounted } from "vue";
import { ElMessage } from "element-plus";
import { useStore } from "vuex";
const props = defineProps({
@ -103,17 +64,25 @@ const props = defineProps({
default: COMPONENT_WIDTH,
type: String
},
showBtn:{
type:Boolean,
default:false
showBtn: {
type: Boolean,
default: false
},
isAll: {
type: Boolean,
default: false
}
});
const actionUrl = computed(() =>
props.isImg
? "/mosty-api/mosty-base/minio/image/upload/id"
: "/mosty-api/mosty-base/minio/file/upload"
);
const actionUrl = computed(() => {
if (props.isAll) {
return "/mosty-api/mosty-base/minio/image/upload/id";
} else {
return props.isImg
? "/mosty-api/mosty-base/minio/image/upload/id"
: "/mosty-api/mosty-base/minio/file/upload";
}
});
const emits = defineEmits(["update:modelValue", "handleChange"]);
@ -174,8 +143,6 @@ const getSuffix = (fileName) => {
//否则返回other
return "OTHER";
};
const imageUrl = ref("");
const store = useStore();
const dialogImageUrl = ref("");
const dialogVisible = ref(false);
@ -184,23 +151,44 @@ const headers = ref({
Authorization: store.getters.token
});
onMounted(() => {
if (props.modelValue) {
fileList.value = props.modelValue.map((el) => {
return {
url: `/mosty-api/mosty-base/minio/image/download/` + el
};
});
}
});
const fileList = ref([]);
watch(
() => props.modelValue,
(val) => {
let arr = val ? val : [];
if (arr && arr.length > 0) {
if (!props.sfUrl) {
fileList.value = arr.map((el) => {
if (Object.prototype.toString.call(el) === "[object Object]") {
return {
url: `/mosty-api/mosty-base/minio/image/download/` + el,
name: el.name
};
} else {
return { url: `/mosty-api/mosty-base/minio/image/download/` + el };
}
});
} else {
fileList.value = arr.map((el) => {
if (Object.prototype.toString.call(el) === "[object Object]") {
return { url: el, name: el.name };
} else {
return { url: el };
}
});
}
}
},
{ immediate: true }
);
const handlerSuccess = (res, file) => {
file.url = `/mosty-api/mosty-base/minio/image/download/` + res.data;
fileList.value.push(file);
props.modelValue.push(res.data);
let arr = props.modelValue ? props.modelValue : [];
arr.push(res.data);
emits("update:modelValue", arr);
emits("handleChange", props.modelValue);
emits("update:modelValue", props.modelValue);
};
const handleExceed = (files, fileList) => {
@ -225,9 +213,6 @@ const beforeImgUpload = (file) => {
return true;
}
};
const handleAvatarSuccess = (res, file) => {
imageUrl.value = URL.createObjectURL(file.raw);
};
//查询图片
const handlePictureCardPreview = (file) => {
dialogImageUrl.value = file.url;
@ -245,6 +230,7 @@ const handleRemove = (file) => {
emits("handleChange", props.modelValue);
emits("update:modelValue", props.modelValue);
};
const propsModelValue = ref();
</script>
<style lang="scss" scoped>

View File

@ -16,7 +16,6 @@ import StationSelect from "./StationSelect/index.vue";
import Provinces from "./Provinces2/index.vue";
import MarkdownEdit from "./MarkdownEdit/index.vue";
import FileUpload from "./FileUpload/index.vue";
import RichOnly from "./RichOnly/index.vue";
import Date from "./Date/index.vue";
import Empty from "./Empty/index.vue";
export {
@ -38,7 +37,6 @@ export {
Provinces,
MarkdownEdit,
FileUpload,
RichOnly,
Date,
Empty
};

View File

@ -29,10 +29,7 @@
:header-cell-class-name="() => 'myTableHeadBgColorDark'"
:highlight-current-row="getConfiger.showSelectType === 'radio'"
:row-style="{
height:
getConfiger.rowHeight === 'auto'
? getConfiger.rowHeight
: getConfiger.rowHeight + 'px'
height: getConfiger.rowHeight === 'auto' ? getConfiger.rowHeight : getConfiger.rowHeight + 'px'
}"
>
<el-table-column

View File

@ -1,161 +1,57 @@
<template>
<el-form
ref="elform"
:model="listQuery"
:label-width="props.labelWidth"
:rules="props.rules"
:inline="props.inline"
label-position="right"
>
<el-form-item
v-for="(item,idx) in props.formList"
:style="item.width && { width: item.width }"
:prop="item.prop"
:label="item.label"
:label-width="item.labelWidth"
:key="idx"
>
<el-form ref="elform" :model="listQuery" :label-width="props.labelWidth" :rules="props.rules" :inline="props.inline"
label-position="right" :disabled="props.disabled">
<el-form-item v-for="(item, idx) in props.formList" :style="item.width && { width: item.width }" :prop="item.prop"
:label="item.label" :label-width="item.labelWidth" :key="idx">
<!-- input表单 input-->
<MOSTY.Other
v-if="item.type == 'input'"
width="100%"
clearable
v-model="listQuery[item.prop]"
:placeholder="`请输入${item.label}`"
:disabled="item.disabled"
/>
<el-input
v-model="listQuery[item.prop]"
v-else-if="item.type == 'textarea'"
type="textarea"
:rows="3"
:placeholder="`请输入${item.label}`"
:disabled="item.disabled"
/>
<MOSTY.Other v-if="item.type == 'input'" width="100%" clearable v-model="listQuery[item.prop]"
:placeholder="`请输入${item.label}`" :disabled="item.disabled" />
<el-input v-model="listQuery[item.prop]" v-else-if="item.type == 'textarea'" type="textarea" :rows="3"
:placeholder="`请输入${item.label}`" :disabled="item.disabled" />
<!-- 数值 inputNumber-->
<el-input
type="number"
v-model="listQuery[item.prop]"
v-else-if="item.type == 'inputNumber'"
:placeholder="`请输入${item.label}`"
:disabled="item.disabled"
/>
<el-input type="number" v-model="listQuery[item.prop]" v-else-if="item.type == 'inputNumber'"
:placeholder="`请输入${item.label}`" :disabled="item.disabled" />
<!-- 数值 number-->
<el-input-number
v-model="listQuery[item.prop]"
v-else-if="item.type == 'number'"
style="width: 100%"
:min="item.min || 0"
:max="item.max || 1000"
:disabled="item.disabled"
/>
<el-input-number v-model="listQuery[item.prop]" v-else-if="item.type == 'number'" style="width: 100%"
:min="item.min || 0" :max="item.max || 1000" :disabled="item.disabled" />
<!--选择 select-->
<MOSTY.Select
v-else-if="item.type == 'select'"
filterable
:multiple="item.multiple"
v-model="listQuery[item.prop]"
:dictEnum="item.options"
width="100%"
clearable
:placeholder="`请选择${item.label}`"
:disabled="item.disabled"
/>
<MOSTY.Select v-else-if="item.type == 'select'" filterable :multiple="item.multiple"
v-model="listQuery[item.prop]" :dictEnum="item.options" width="100%" clearable :placeholder="`请选择${item.label}`"
:disabled="item.disabled" />
<!-- 部门department -->
<template v-else-if="item.type === 'department'">
<MOSTY.Department style="width: 100%;" clearable v-model="listQuery[item.prop]" />
<MOSTY.Department style="width: 100%;" clearable :isAll="item.isAll" @getDepValue="getdep($event, item.depMc)"
v-model="listQuery[item.prop]" :placeholder="listQuery[item.depMc] ? listQuery[item.depMc] : '请选择'" />
</template>
<!-- 上传 upload -->
<MOSTY.Upload
v-else-if="item.type == 'upload'"
width="100%"
v-model="listQuery[item.prop]"
:isImg="item.isImg"
:disabled="item.disabled"
/>
<MOSTY.Upload v-else-if="item.type == 'upload'" width="100%" v-model="listQuery[item.prop]" :isImg="item.isImg"
:disabled="item.disabled" />
<!--选择checkbox -->
<MOSTY.CheckBox
v-else-if="item.type == 'checkbox'"
width="100%"
clearable
v-model="listQuery[item.prop]"
:checkList="item.options"
:placeholder="`请选择${item.label}`"
:disabled="item.disabled"
/>
<MOSTY.CheckBox v-else-if="item.type == 'checkbox'" width="100%" clearable v-model="listQuery[item.prop]"
:checkList="item.options" :placeholder="`请选择${item.label}`" :disabled="item.disabled" />
<!-- 单选radio -->
<el-radio-group
v-model="listQuery[item.prop]"
v-else-if="item.type == 'radio'"
:disabled="item.disabled"
>
<el-radio
v-for="obj in item.options"
:key="obj.value"
:label="obj.value"
>{{ obj.label }}</el-radio
>
<el-radio-group v-model="listQuery[item.prop]" v-else-if="item.type == 'radio'" :disabled="item.disabled">
<el-radio v-for="obj in item.options" :key="obj.value" :label="obj.value">{{ obj.label }}</el-radio>
</el-radio-group>
<!-- 时间选择 -->
<el-time-picker
v-else-if="item.type == 'time'"
v-model="listQuery[item.prop]"
placeholder="选择时间"
style="width: 100%"
:disabled="item.disabled"
/>
<el-date-picker
v-else-if="item.type == 'date'"
v-model="listQuery[item.prop]"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择日期"
style="width: 100%"
:disabled="item.disabled"
/>
<el-date-picker
v-else-if="item.type == 'datetime'"
v-model="listQuery[item.prop]"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择时间"
style="width: 100%"
:disabled="item.disabled"
/>
<el-date-picker
v-else-if="item.type == 'datetimerange'"
v-model="listQuery[item.prop]"
type="datetimerange"
:shortcuts="shortcuts"
range-separator="To"
value-format="YYYY-MM-DD HH:mm:ss"
start-placeholder="选择开始时间"
end-placeholder="选择结束时间"
style="width: 100%"
:disabled="item.disabled"
/>
<el-date-picker
v-else-if="item.type == 'daterange'"
v-model="listQuery[item.prop]"
type="daterange"
range-separator="To"
value-format="YYYY-MM-DD"
start-placeholder="选择开始日期"
end-placeholder="选择开始日期"
style="width: 100%"
:disabled="item.disabled"
/>
<el-time-picker v-else-if="item.type == 'time'" v-model="listQuery[item.prop]" placeholder="选择时间"
style="width: 100%" :disabled="item.disabled" />
<el-date-picker v-else-if="item.type == 'date'" v-model="listQuery[item.prop]" type="date"
value-format="YYYY-MM-DD" placeholder="选择日期" style="width: 100%" :disabled="item.disabled" />
<el-date-picker v-else-if="item.type == 'datetime'" v-model="listQuery[item.prop]" type="datetime"
value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择时间" style="width: 100%" :disabled="item.disabled" />
<el-date-picker v-else-if="item.type == 'datetimerange'" v-model="listQuery[item.prop]" type="datetimerange"
:shortcuts="shortcuts" range-separator="To" value-format="YYYY-MM-DD HH:mm:ss" start-placeholder="选择开始时间"
end-placeholder="选择结束时间" style="width: 100%" :disabled="item.disabled" />
<el-date-picker v-else-if="item.type == 'daterange'" v-model="listQuery[item.prop]" type="daterange"
range-separator="To" value-format="YYYY-MM-DD" start-placeholder="选择开始日期" end-placeholder="选择开始日期"
style="width: 100%" :disabled="item.disabled" />
<el-switch
v-else-if="item.type == 'switch'"
v-model="listQuery[item.prop]"
class="ml-2"
:disabled="item.disabled"
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
/>
<el-switch v-else-if="item.type == 'switch'" v-model="listQuery[item.prop]" class="ml-2" :disabled="item.disabled"
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949" />
<template v-else-if="item.type === 'slot'">
<slot :name="item.prop"></slot>
@ -165,7 +61,7 @@
</template>
<script setup>
import * as MOSTY from "@/components/MyComponents/index";
import { ref, defineProps, defineEmits, defineExpose, watch } from "vue";
import { ref, defineProps, defineEmits, defineExpose, watch, watchEffect } from "vue";
const props = defineProps({
//循环的值
formList: {
@ -184,9 +80,13 @@ const props = defineProps({
type: Object,
default: {}
},
inline:{
type:Boolean,
default:true
inline: {
type: Boolean,
default: true
},
disabled: {
type: Boolean,
default: false
}
});
const elform = ref();
@ -200,28 +100,32 @@ const submit = (resfun) => {
});
};
const reset = () =>{
const getdep = (e, val) => {
if (val) listQuery.value[val] = e ? e.orgName : '';
}
const reset = () => {
elform.value.resetFields()
}
watch(
() => listQuery.value,
(newVal) => {
// 修改这里的watch逻辑避免无限循环
let isUpdatingFromProps = false;
watch(() => listQuery.value, (newVal) => {
if (newVal && !isUpdatingFromProps) {
emits("update:modelValue", newVal);
},
{ immediate: true, deep: true }
);
}
}, { deep: true });
watch(
() => props.modelValue,
(newVal) => {
// 只有在新值确实变化时才更新(避免空值覆盖)
if (newVal && Object.keys(newVal).length > 0) {
listQuery.value = { ...newVal };
}
},
{ immediate: true, deep: true }
);
watch(() => props.modelValue, (newVal) => {
// 只有在新值确实变化时才更新(避免空值覆盖)
if (newVal && Object.keys(newVal).length > 0) {
isUpdatingFromProps = true;
listQuery.value = { ...newVal };
setTimeout(() => {
isUpdatingFromProps = false;
}, 0);
}
}, { immediate: true, deep: true });
defineExpose({ submit,reset });
defineExpose({ submit, reset });
</script>

View File

@ -1,12 +1,10 @@
<template>
<div style="width: 100%">
<div style="width: 100%" :class="getConfiger.showSelectType === 'radio' ? 'tabBoxRadio' : ''">
<!-- hasChildren要在tableData中定义表示当前行有没有下一级 children要在tableData中定义表示下一级的数据-->
<el-table
ref="multipleTableRef"
:data="tableData"
@selection-change="handleSelectionChange"
@current-change="handleCurrentChange"
@row-click="singleElection"
:row-key="getConfiger.rowKey"
:border="getConfiger.border"
:default-expand-all="getConfiger.defaultExpandAll"
@ -21,23 +19,7 @@
:highlight-current-row="getConfiger.showSelectType === 'radio'"
:row-style="{ height: getConfiger.rowHeight === 'auto' ? getConfiger.rowHeight : getConfiger.rowHeight + 'px'}"
>
<el-table-column
type="selection"
width="55"
v-if="getConfiger.showSelectType === 'checkBox'"
/>
<el-table-column
width="55"
v-else-if="getConfiger.showSelectType === 'radio'"
#default="{ row }"
>
<el-radio
class="radio"
v-model="getConfiger.radioChoose"
:label="row[getConfiger.rowKey]"
>&nbsp;</el-radio
>
</el-table-column>
<el-table-column type="selection" width="55" />
<el-table-column
type="index"
label="序号"
@ -148,19 +130,16 @@ onMounted(() => {
});
// 可选的时候选择的数据
const handleSelectionChange = (val) => {
emit("chooseData", val);
};
// 单选的时候选择的数据
const handleCurrentChange = (val) => {
currentRow.value = val;
emit("chooseData", val);
};
const singleElection = (val) => {
if (getConfiger.showSelectType === "radio") {
getConfiger.radioChoose = val[getConfiger.rowKey];
if(getConfiger.showSelectType === 'radio' && val.length > 1){
let del_row = val.shift();
multipleTableRef.value.toggleRowSelection(del_row, false);
currentRow.value = val;
emit("chooseData", val);
}else{
emit("chooseData", val);
}
};
// 懒加载数据的方法
const load = (date, treeNode, resolve) => {
setTimeout(() => {
@ -184,25 +163,14 @@ const load = (date, treeNode, resolve) => {
function setDefaultChoose() {
nextTick(() => {
// 多选的默认选中
if (
props.tableConfiger.defaultSelectKeys?.length > 0 &&
props.tableConfiger.showSelectType === "checkBox"
) {
if ( props.tableConfiger.defaultSelectKeys?.length > 0 && props.tableConfiger.showSelectType === "checkBox" ) {
props.tableData.forEach((item) => {
if (
props.tableConfiger.defaultSelectKeys.findIndex(
(v) => v === item[props.tableConfiger.rowKey]
) > -1
) {
if ( props.tableConfiger.defaultSelectKeys.findIndex( (v) => v === item[props.tableConfiger.rowKey] ) > -1) {
multipleTableRef.value.toggleRowSelection(item, true);
}
});
// 单选的默认选中
} else if (
props.tableConfiger.defaultSelectKeys &&
props.tableConfiger.defaultSelectKeys?.length > 0 &&
props.tableConfiger.showSelectType === "radio"
) {
} else if ( props.tableConfiger.defaultSelectKeys && props.tableConfiger.defaultSelectKeys?.length > 0 && props.tableConfiger.showSelectType === "radio" ) {
getConfiger.radioChoose = props.tableConfiger.defaultSelectKeys[0];
}
});
@ -212,3 +180,12 @@ function setDefaultChoose() {
<style lang = "scss">
</style>
<style>
.tabBoxRadio .el-checkbox__inner {
border-radius: 50% !important;
}
.tabBoxRadio .el-table__header-wrapper .el-checkbox {
display: none;
}
</style>

View File

@ -9,12 +9,7 @@
<template>
<div class="fenye" :style="{ top: tableHeight+10 + 'px' }">
<el-pagination
:current-page="
pageData.configer.currentPage ||
pageData.configer.pageNo ||
pageData.configer.current ||
pageData.configer.pageCurrent ||
pageData.configer.pageNum"
:current-page=" pageData.configer.currentPage || pageData.configer.pageNo || pageData.configer.current || pageData.configer.pageCurrent || pageData.configer.pageNum"
:page-size="pageData.configer.pageSize || pageData.configer.size"
:page-sizes="pageSizeArr"
:small="small"

View File

@ -63,10 +63,18 @@
value-format="YYYY-MM-DD"
>
</el-date-picker>
<el-date-picker
v-else-if="item.showType === 'datetime'"
v-model="searchObj[item.prop]"
type="datetime"
:placeholder="item.placeholder"
value-format="YYYY-MM-DD HH:mm:ss"
>
</el-date-picker>
<!-- checkbox -->
<template v-else-if="item.showType === 'department'">
<MOSTY.Department clearable v-model="item.ssbmdm" />
<MOSTY.Department clearable v-model="searchObj[item.prop]" />
</template>
<!-- checkbox -->
<template v-else-if="item.showType === 'checkbox'">
@ -117,7 +125,6 @@
<!-- 级联选择 -->
<el-cascader
v-else-if="item.showType === 'cascader'"
@change="changeca"
v-model="searchObj[item.prop]"
:props="item.props"
:show-all-levels="item.showAllLevels"
@ -143,11 +150,8 @@
import {
ref,
reactive,
watch,
watchEffect,
nextTick,
getCurrentInstance,
toRefs
} from "vue";
import * as MOSTY from "@/components/MyComponents/index";
const { proxy } = getCurrentInstance();
@ -175,6 +179,12 @@ const props = defineProps({
defaultVal: "",
label: "输入"
},
{
showType: "department",
prop: "deptKey",
defaultVal: "",
label: "输入"
},
{
showType: "daterange",
prop: "daterangeKey",
@ -207,9 +217,6 @@ const props = defineProps({
{
showType: "radio",
defaultVal: ""
// prop: "cascaderKey",
// label: "级联选择",
// checkStrictly: false //点击任意选中
},
{
showType: "defaultTime",
@ -229,16 +236,9 @@ const props = defineProps({
}
});
let loadingPage = ref(false);
const isShowDate = ref(false);
const emit = defineEmits(["submit", "reset"]);
let searchObj = reactive({});
const timeConfig = reactive({
//时间字典筛选和自定义日期组件相关数据
typeValue: "01", //时间字典类型默认
timeArry: [] //时间筛选自定义默认值
});
//全所或自定义选择按钮
const slectType = ref("qs");
// select 的一些默认配置
const selectDefault = {
clearable: true, // 是否可以清空
@ -354,53 +354,6 @@ const dateShortcuts = [
}
}
];
//自定义时间选择 item 配置项 value 选中的值
const screenSelect = (item, value) => {
if (value == "08") {
searchObj[item.prop] = value;
isShowDate.value = true;
} else {
timeConfig.typeValue = value;
searchObj[item.prop] = value;
submit();
}
};
//自定义时间确定时间
const chooseDateOk = (item) => {
timeConfig.typeValue = "08";
if (timeConfig.timeArry && timeConfig.timeArry.length) {
//选择了时间
searchObj[item.propStart] = timeConfig.timeArry[0];
searchObj[item.propEnd] = timeConfig.timeArry[1];
} else {
//清空了时间
searchObj[item.prop] = "01";
timeConfig.typeValue = "01";
}
isShowDate.value = false;
submit();
};
//全所-部门选择回调
const organizatioHland = (val) => {
let item = getArr.find((item) => item.showType == "qsOrZdy");
searchObj[item.propBm] = val?.data?.orgCode || "";
if (!val || val == "") {
//清空了部门选择后清空责任区ID
slectType.value = "qs";
delete searchObj[item.propZrq];
}
submit();
};
//全所-责任区回调
const zrqHland = (val) => {
let item = getArr.find((item) => item.showType == "qsOrZdy");
searchObj[item.propZrq] = val || ""; //责任区选择
submit();
};
//自定义时间取消事件
const popoverCancel = (item) => {
isShowDate.value = false;
};
// 设置不可选的日期
const disabledDate = (time) => {
return time.getTime() > Date.now();
@ -505,10 +458,6 @@ const cascaderLazyProps = reactive({
resolve(options);
}
});
// 级联框选择
function changeca(v) {
console.log("vvvv", v);
}
// 获取到传过来的参数
let getArr = reactive([]);
const submit = () => {
@ -521,25 +470,22 @@ const reset = () => {
emit("submit", searchObj);
emit("reset", false);
};
let dataOptions = reactive([]); //时间字典筛选
watchEffect(() => {
loadingPage.value = true;
getArr = JSON.parse(JSON.stringify(props.searchArr));
getArr = getArr.map((item) => {
let arr = JSON.parse(JSON.stringify(props.searchArr));
getArr = arr.map((item) => {
switch (item.showType) {
case "select":
item = { ...selectDefault, ...item };
item.options = reactive(item.options);
getOptions[item.prop] = item.options;
break;
case "input":
item = { ...inputDefault, ...item };
case "input":
item = { ...inputDefault, ...item };
break;
case "daterange":
item = { ...daterangeDefault, ...item };
if (item.defaultShortcuts) {
item.shortcuts = shortcuts;
}
if (item.defaultShortcuts) item.shortcuts = shortcuts;
break;
case "date":
item = { ...defaultDate, ...item };

View File

@ -1,5 +1,5 @@
<template>
<el-dialog v-model="showDialog" :destroy-on-close="true" :title="title+'人员'" @close="close" :close-on-click-modal="false">
<el-dialog v-model="modelValue" :destroy-on-close="true" :title="title+'人员'" @close="close" :close-on-click-modal="false">
<FormMessage v-model="listQuery" :formList="formData" labelWidth="120px" ref="elform" :rules="rules">
<template #bqList>
<div class="marks pointer" @click="chooseMarksVisible = true">
@ -21,7 +21,7 @@
</template>
<script setup>
import ChooseMarks from "@/components/MyComponents/ChooseMarks/index.vue";
import ChooseMarks from "@/components/ChooseList/ChooseMarks/index.vue";
import FormMessage from "@/components/aboutTable/FormMessage.vue";
import { reactive, ref } from 'vue';
const props = defineProps({
@ -29,11 +29,14 @@ const props = defineProps({
type:Object,
default:{}
},
modelValue:{
type:Boolean,
default:false
}
})
const chooseMarksVisible = ref(false)
const roleIds = ref([])
const elform = ref()
const showDialog = ref(false)
const emit = defineEmits(['change'])
const listQuery = ref({})
const formData = ref([
@ -41,7 +44,7 @@ const formData = ref([
{ label: "性别", prop: "xb", type: "select",options:props.dic.D_BZ_XB ,width:'48%'},
{ label: "身份证号", prop: "sfzh", type: "input" ,width:'48%'},
{ label: "户籍地", prop: "hjdz", type: "input",width:'48%' },
{ label: "户籍地派出所", prop: "hjdpcsdm", type: "department" ,width:'48%'},
{ label: "户籍地派出所", prop: "hjdpcsdm",depMc:'hjdpcs', type: "department" ,width:'48%'},
{ label: "标签", prop: "bqList", type: "slot",width:'100%' },
{ label: "是否挑头人", prop: "sfttr", type: "select",options:props.dic.D_BZ_SF ,width:'48%'},
{ label: "是否响应人", prop: "sfxyr", type: "select" ,options:props.dic.D_BZ_SF,width:'48%' },
@ -60,7 +63,6 @@ const order = ref(null)
const init = (type,row,index) =>{
title.value = type == 'add' ? '新增' :'编辑';
order.value = index;
showDialog.value = true;
if(row) listQuery.value = {...row};
}
@ -82,13 +84,13 @@ const submitForm = () =>{
elform.value.submit((val)=>{
let obj = { data:val,type:title.value ,index:order.value}
emit('change',obj)
showDialog.value = false;
emit('update:modelValue',false)
})
}
const close = () =>{
elform.value.reset();
showDialog.value = false;
emit('update:modelValue',false)
}
defineExpose({init})

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

View File

@ -0,0 +1,114 @@
<template>
<el-dialog v-model="modelValue" center width="1000px" :destroy-on-close="true" title="报告模板" @close="close" :close-on-click-modal="false">
<div class="cntBox">
<!-- 工具栏 -->
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" />
<!-- 编辑器 -->
<Editor :style="`height: ${props.heightNumber}px; overflow-y: hidden`" v-model="textContent" :defaultConfig="editorConfig" :mode="mode" @onCreated="handleCreated" @onChange="handChange" />
</div>
<template #footer>
<el-button type="primary">暂存</el-button>
<el-button type="primary">下载</el-button>
<el-button type="primary" @click="close">取消</el-button>
</template>
</el-dialog>
</template>
<script setup>
import { compressImage } from "@/utils/tools.js";
import "@wangeditor/editor/dist/css/style.css";
import { qcckPost } from "@/api/qcckApi.js";
import { ElMessage } from "element-plus";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { ref, shallowRef, onBeforeUnmount, defineEmits, defineProps, watch } from "vue";
const props = defineProps({
modelValue:{
type:Boolean,
default:false
},
// 编辑器内容
textContent: {
type: String,
default: ""
},
placeholder: {
type: String,
default: "请输入内容。。。。"
},
heightNumber: {
type: Number,
default: 448
}
});
const editorRef = shallowRef();
const mode = "default";
//工具配置
const toolbarConfig = {
excludeKeys: ["blockquote", "codeBlock"] //清除不必要的工具,引用和代码块
};
const emits = defineEmits(["update:textContent", "changeFn"]);
//编辑器配置
const editorConfig = {
withCredentials: true, //允许跨域
placeholder: props.placeholder, //提示语
MENU_CONF: {
uploadImage: {
// 自定义上传图片
async customUpload(file, insertFn) {
let fileBlob = await compressImage(file);
let fileData = new File([fileBlob], fileBlob.name, { type: fileBlob.type });
if (fileData.size > 2 * 1024 * 1024) {
ElMessage({ message: "图片超过2MB", type: "success" });
} else {
await uploadFn(fileData, insertFn);
}
}
},
uploadVideo: {
// 自定义上传视频
async customUpload(file, insertFn) {
await uploadFn(file, insertFn);
}
}
}
};
const uploadFn = (file, insertFn) => {
let param = new FormData();
param.append("file", file);
qcckPost(param, "/mosty-base/minio/image/upload").then((res) => {
insertFn(res);
});
};
//编辑器创建成功
const handleCreated = (editor) => {
editorRef.value = editor;
};
//内容发生变化
const handChange = (editor) => {
console.log(editor.getHtml(),'====editor.getHtml()');
// 判断是否是一个空段落,是空就传空文本
if (editor.isEmpty()) {
emits("changeFn", editor.getText());
} else {
emits("changeFn", editor.getHtml());
}
};
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor) editor.destroy();
});
</script>
<style lang="scss" scoped>
.cntBox{
height: 60vh;
padding: 8px;
box-sizing: border-box;
overflow: hidden;
overflow-y: auto;
border: 1px dashed #e9e9e9;
}
</style>

Some files were not shown because too many files have changed in this diff Show More