修改bug,过鱼倒数修改,添加过鱼设施

This commit is contained in:
扈兆增 2026-06-11 09:36:40 +08:00
parent 34502b7ed2
commit f150c29d46
8 changed files with 915 additions and 263 deletions

View File

@ -167,3 +167,20 @@ export function getMonitorDataWaterTempVerticalHour(data: any) {
data
});
}
// 在线监测数据
export function getMonitorDataOnline(data: any) {
return request({
url: '/fp/fpssTable/qgc/GetKendoListCust',
method: 'post',
data
});
}
// 运行状态
export function getRunState(data: any) {
return request({
url: '/wmp-env-server/env/fp/query/qgc/sdfpssr/GetKendoListCust',
method: 'post',
data
});
}

View File

@ -0,0 +1,248 @@
<template>
<div>
<div class="mb-2">
时间
<a-range-picker
v-model:value="searchParams"
type="daterange"
:allow-clear="false"
value-format="YYYY-MM-DD HH:mm:ss"
/>
<a-button class="ml-2" type="primary" @click="initData">查询</a-button>
</div>
<BasicTable
ref="tableRef"
:scrollY="500"
:columns="columns"
:list-url="getMonitorDataOnline"
/>
<!-- 图片预览弹框 -->
<a-modal
v-model:open="imagePreviewVisible"
title="图片预览"
:footer="null"
width="800px"
>
<div style="text-align: center">
<img :src="previewImageUrl" style="width: 100%; height: 600px" />
</div>
</a-modal>
<!-- 视频预览弹框 -->
<a-modal
v-model:open="videoPreviewVisible"
title="视频预览"
:footer="null"
width="800px"
>
<div style="text-align: center">
<video
:src="previewVideoUrl"
controls
style="width: 100%; height: 600px"
></video>
</div>
</a-modal>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch, computed, h } from 'vue';
import { Button } from 'ant-design-vue';
import BasicTable from '@/components/BasicTable/index.vue';
import { getMonitorDataOnline } from '@/api/mapModal';
import { useModelStore } from '@/store/modules/model';
import dayjs from 'dayjs';
const loading = ref(false);
const modelStore = useModelStore();
const hasLoaded = ref(false);
const tableRef = ref();
const searchParams = ref([
dayjs().subtract(5, 'year').format('YYYY-MM-DD HH:mm:ss'),
dayjs().format('YYYY-MM-DD HH:mm:ss')
]);
//
const imagePreviewVisible = ref(false);
const previewImageUrl = ref('');
//
const videoPreviewVisible = ref(false);
const previewVideoUrl = ref('');
const openImagePreview = (url: string) => {
previewImageUrl.value = url;
imagePreviewVisible.value = true;
};
const openVideoPreview = (url: string) => {
previewVideoUrl.value = url;
videoPreviewVisible.value = true;
};
const props = defineProps({
isActive: { type: Boolean, default: false }
});
const columns = [
{
title: '测站名称',
dataIndex: 'stnm',
width: 240,
fixed: 'left'
},
{
title: '时间',
dataIndex: 'tm',
width: 120,
customRender: ({ text }: any) =>
text ? dayjs(text).format('YYYY-MM-DD') : '-'
},
{
title: '鱼种类',
dataIndex: 'ftp',
width: 100
},
{
title: '鱼长度(cm)',
dataIndex: 'length',
width: 100
},
{
title: '鱼宽度(cm)',
dataIndex: 'width',
width: 100
},
{
title: '鱼速度(m/s)',
dataIndex: 'fishspeed',
width: 100,
customRender: ({ text }: any) => (text ? Number(text).toFixed(2) : '-')
},
{
title: '鱼游向',
dataIndex: 'directionName',
width: 100
},
{
title: '水温(℃)',
dataIndex: 'temperature',
width: 100,
customRender: ({ text }: any) => {
const num = parseFloat(text);
return isNaN(num) ? '-' : num.toFixed(1);
}
},
{
title: '流速(m/s)',
dataIndex: 'speed',
width: 100,
customRender: ({ text }: any) => {
const num = parseFloat(text);
return isNaN(num) ? '-' : num.toFixed(2);
}
},
{
title: '轮廓图',
dataIndex: 'firstimgurl',
align: 'center',
width: 100,
customRender: ({ text }: any) => {
const hasValidUrl =
text &&
text !== '-' &&
text.trim() !== '' &&
text !== 'null' &&
text !== 'undefined';
return h(
Button,
{
type: 'link',
disabled: !hasValidUrl,
style: {
color: !hasValidUrl ? '#ccc' : '#1890ff',
cursor: !hasValidUrl ? 'not-allowed' : 'pointer'
},
onClick: () => {
if (hasValidUrl) {
openImagePreview(text);
}
}
},
() => '查看图片'
);
}
},
{
title: '短视频',
dataIndex: 'videourl',
align: 'center',
width: 100,
customRender: ({ text }: any) => {
console.log(text);
const hasValidUrl =
text &&
text !== '-' &&
text.trim() !== '' &&
text !== 'null' &&
text !== 'undefined';
return h(
Button,
{
type: 'link',
disabled: !hasValidUrl,
style: {
color: !hasValidUrl ? '#ccc' : '#1890ff',
cursor: !hasValidUrl ? 'not-allowed' : 'pointer'
},
onClick: () => {
if (hasValidUrl) {
openVideoPreview(text);
}
}
},
() => '查看视频'
);
}
}
];
const initData = async () => {
const filter = {
logic: 'and',
filters: [
{
field: 'tm',
operator: 'gte',
dataType: 'date',
value: searchParams.value[0]
},
{
field: 'tm',
operator: 'lte',
dataType: 'date',
value: searchParams.value[1]
},
{
field: 'stcd',
operator: 'in',
dataType: 'string',
value: ['008640203900001049', '008640203900011009']
}
]
};
tableRef.value?.getList(filter);
};
watch(
() => props.isActive,
active => {
if (active) {
initData();
}
}
);
</script>
<style scoped>
.fish-facility-monitor-data {
padding: 20px;
}
</style>

View File

@ -0,0 +1,226 @@
<template>
<div>
<div class="mb-2">
时间
<a-date-picker v-model:value="searchParams.tm" picker="year" />
<span class="ml-2"> 鱼类</span>
<a-select
v-model:value="searchParams.ftp"
placeholder="请选择"
class="w-[160px]"
:loading="loadFtp"
allowClear
>
<a-select-option
v-for="item in ftpList"
:key="item.id"
:value="item.id"
>
{{ item.name }}
</a-select-option>
</a-select>
<span class="ml-2"> 游向</span>
<a-select
v-model:value="searchParams.direction"
placeholder="请选择游向"
class="w-[120px]"
allowClear
:loading="loadDirection"
>
<a-select-option
v-for="item in direction"
:key="item.itemCode"
:value="item.itemCode"
>{{ item.dictName }}</a-select-option
>
</a-select>
<span class="ml-2"> 过鱼目标</span>
<a-tooltip title="暂无数据" placement="top">
<a-button size="small"><i class="iconfont icon-yulei"></i></a-button>
</a-tooltip>
<a-button class="ml-2" type="primary" @click="initData">查询</a-button>
</div>
<div class="flex justify-around mt-[20px] mb-[10px]">
<div>计划开始运行时间暂无数据</div>
<div>计划结束运行时间暂无数据</div>
<div>计划运行频率次暂无数据</div>
<div>计划全年运行次数暂无数据</div>
</div>
<BasicTable
ref="tableRef"
:scrollY="500"
:columns="columns"
:list-url="getRunState"
/>
<!-- 图片预览弹框 -->
<a-modal
v-model:open="imagePreviewVisible"
title="图片预览"
:footer="null"
width="800px"
>
<div style="text-align: center">
<img :src="previewImageUrl" style="width: 100%; height: 600px" />
</div>
</a-modal>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch, computed, h } from 'vue';
import { Button } from 'ant-design-vue';
import BasicTable from '@/components/BasicTable/index.vue';
import { getRunState } from '@/api/mapModal';
import { getDictItemsByCode } from '@/api/dict';
import { getFishDictoryDropdown } from '@/api/select';
import { useModelStore } from '@/store/modules/model';
import dayjs from 'dayjs';
const loading = ref(false);
const modelStore = useModelStore();
const hasLoaded = ref(false);
const tableRef = ref();
const searchParams = ref({
tm: dayjs(),
direction: null,
ftp: null
});
//
const loadDirection = ref(false);
const direction = ref([]);
//
const loadFtp = ref(false);
const ftpList = ref([]);
//
const imagePreviewVisible = ref(false);
const previewImageUrl = ref('');
const openImagePreview = (url: string) => {
previewImageUrl.value = url;
imagePreviewVisible.value = true;
};
const props = defineProps({
isActive: { type: Boolean, default: false }
});
const columns = [
{
title: '鱼类',
dataIndex: 'name',
width: 140
},
{
title: '过鱼数量(尾)',
dataIndex: 'fcnt',
width: 100
},
{
title: '游向',
dataIndex: 'direction',
width: 100,
customRender: ({ text }: any) => (text ? text : '-')
},
{
title: '开始时间',
dataIndex: 'strdt',
width: 120,
customRender: ({ text }: any) =>
text ? dayjs(text).format('YYYY-MM-DD') : '-'
},
{
title: '结束时间',
dataIndex: 'enddt',
width: 120,
customRender: ({ text }: any) =>
text ? dayjs(text).format('YYYY-MM-DD') : '-'
},
{
title: '附件',
dataIndex: 'firstimgurl',
align: 'center',
width: 100,
customRender: ({ text }: any) => {
const hasValidUrl =
text &&
text !== '-' &&
text.trim() !== '' &&
text !== 'null' &&
text !== 'undefined';
return h(
Button,
{
type: 'link',
disabled: !hasValidUrl,
style: {
color: !hasValidUrl ? '#ccc' : '#1890ff',
cursor: !hasValidUrl ? 'not-allowed' : 'pointer'
},
onClick: () => {
if (hasValidUrl) {
openImagePreview(text);
}
}
},
() => '查看附件'
);
}
}
];
const initData = async () => {
const filter = {
logic: 'and',
filters: [
{
field: 'strdt',
operator: 'gte',
dataType: 'date',
value: dayjs(searchParams.value.tm)
.startOf('year')
.format('YYYY-MM-DD HH:mm:ss')
},
{
field: 'strdt',
operator: 'lte',
dataType: 'date',
value: dayjs(searchParams.value.tm)
.endOf('year')
.format('YYYY-MM-DD HH:mm:ss')
},
{
field: 'stcd',
operator: 'in',
dataType: 'string',
value: ['008640203900011010']
}
]
};
tableRef.value?.getList(filter);
};
const getOptions = async () => {
loadDirection.value = true;
getDictItemsByCode({ dictCode: 'direction' }).then(res => {
direction.value = res.data || [];
loadDirection.value = false;
});
loadFtp.value = true;
getFishDictoryDropdown().then(res => {
ftpList.value = res.data || [];
loadFtp.value = false;
});
};
watch(
() => props.isActive,
active => {
if (active) {
getOptions();
initData();
}
}
);
</script>
<style scoped>
.fish-facility-monitor-data {
padding: 20px;
}
</style>

View File

@ -0,0 +1,11 @@
<template>
<div>
<h2>综合分析</h2>
</div>
</template>
<script setup lang="ts"></script>
<style scoped>
.fish-facility-monitor-data {
padding: 20px;
}
</style>

View File

@ -119,6 +119,21 @@
: ''
"
/>
<!-- 在线监测数据 -->
<FishFacilityMonitorData
v-show="currentActiveKey === 'FishFacilityMonitorData'"
:is-active="currentActiveKey === 'FishFacilityMonitorData'"
/>
<!-- 运行情况 -->
<FishFacilityRunState
v-show="currentActiveKey === 'FishFacilityRunState'"
:is-active="currentActiveKey === 'FishFacilityRunState'"
/>
<!-- 综合分析 -->
<FishZHFX
v-show="currentActiveKey === 'FishZHFX'"
:is-active="currentActiveKey === 'FishZHFX'"
/>
<!-- 预警提示 -->
<EarlyWarningAlert
v-show="currentActiveKey === 'tableTabs'"
@ -168,6 +183,9 @@ import VerticalWaterTemperature from './components/VerticalWaterTemperature.vue'
import WaterQuality from './components/WaterQuality.vue'; //
import EarlyWarningAlert from './components/EarlyWarningAlert.vue'; //
import FlowMeasure from './components/FlowMeasure.vue'; //
import FishFacilityMonitorData from './components/FishFacilityMonitorData.vue'; // 线
import FishFacilityRunState from './components/FishFacilityRunState.vue'; //
import FishZHFX from './components/FishZHFX.vue'; //
import EcologicalFlow from './components/EcologicalFlow.vue'; //
import Attachment from './components/Attachment.vue'; // /
import WaterTemperatureRep from './components/WaterTemperatureRep.vue'; //

View File

@ -25,9 +25,11 @@
</template>
<script lang="ts" setup>
import { ref, computed, onMounted, watch } from "vue";
import BasicSearch from "@/components/BasicSearch/index.vue";
import { useShuJuTianBaoStore } from "@/store/modules/shuJuTianBao";
import moment from 'moment';
import { ref, computed, onMounted, watch } from 'vue';
import BasicSearch from '@/components/BasicSearch/index.vue';
import { useShuJuTianBaoStore } from '@/store/modules/shuJuTianBao';
interface Props {
batchData: any[];
@ -36,8 +38,8 @@ interface Props {
const props = defineProps<Props>();
const emit = defineEmits<{
(e: "reset", values: any): void;
(e: "search-finish", values: any): void;
(e: 'reset', values: any): void;
(e: 'search-finish', values: any): void;
}>();
const shuJuTianBaoStore = useShuJuTianBaoStore();
@ -46,33 +48,46 @@ const basicSearchRef = ref<any>();
const btnLoading = ref<boolean>(false);
const initSearchData = {
rvcd: "all",
rvcd: 'all',
stcd: null,
reportMonth: moment().subtract(1, 'month').format('YYYY-MM')
};
const searchData = ref<any>({ ...initSearchData });
const searchList: any = computed(() => [
{
type: "waterStation",
name: "rvcd",
label: "流域",
type: 'waterStation',
name: 'rvcd',
label: '流域',
fieldProps: {
allowClear: true,
allowClear: true
},
options: [],
options: []
},
{
type: 'DataPicker',
name: 'reportMonth',
label: '月份',
picker: 'month',
fieldProps: {
allowClear: false,
format: 'YYYY-MM',
valueFormat: 'YYYY-MM'
},
options: []
}
]);
const onSearchFinish = (values: any) => {
emit("search-finish", values);
emit('search-finish', values);
};
const onValuesChange = (changedValues: any, allValues: any) => {
searchData.value = { ...searchData.value, ...allValues };
if (
Object.keys(changedValues)[0] == "rstcd" ||
Object.keys(changedValues)[0] == "rvcd"
Object.keys(changedValues)[0] == 'rstcd' ||
Object.keys(changedValues)[0] == 'rvcd'
) {
const formInstance = basicSearchRef.value?.formData;
formInstance.stcd = null;
@ -81,15 +96,16 @@ const onValuesChange = (changedValues: any, allValues: any) => {
const handleReset = () => {
localTypeDate.value = null;
emit("reset", initSearchData);
emit('reset', initSearchData);
};
defineExpose({
btnLoading,
searchData
});
onMounted(() => {
emit("search-finish", initSearchData);
shuJuTianBaoStore.getFpssOption("", "");
emit('search-finish', initSearchData);
shuJuTianBaoStore.getFpssOption('', '');
});
</script>

View File

@ -27,14 +27,36 @@
<!-- 其他列保持默认必须写 fallback否则其他列表头会消失 -->
<span v-else>{{ column.title }}</span>
</template>
a-text
</BasicTable>
<Modal
v-model:open="urgeModalVisible"
title="是否催促选择的用户?"
@ok="handleUrgeOk"
>
<div>
将对选中的
<span style="color: #ff4d4f; font-weight: bold"
>{{ batchData.length }} 位用户</span
>
发送<span style="color: #ff4d4f">过鱼数据填报催促通知</span>
</div>
<div style="margin-top: 16px">
<div style="margin-bottom: 8px">催促内容</div>
<Textarea
v-model:value="urgeContent"
placeholder="请输入催促内容"
:rows="4"
/>
</div>
</Modal>
</div>
</template>
<script lang="ts" setup>
import dayjs from 'dayjs';
import { ref, onMounted, h, computed } from 'vue';
import { Checkbox, Tooltip, message, Modal } from 'ant-design-vue';
import { Checkbox, Tooltip, message, Modal, Textarea } from 'ant-design-vue';
import BasicTable from '@/components/BasicTable/index.vue';
import GuoYuDaoShuTongJiSearch from './guoYuDaoShuTongJiSearch.vue';
import { statistics, batchUrgeContent } from '@/api/guoYuSheShiShuJuTianBao';
@ -44,6 +66,8 @@ const detailTableRef = ref();
const batchData = ref([]);
const tableDataList = ref<any[]>([]); // 便
const urgeModalVisible = ref(false);
const urgeContent = ref('');
// 1. Key ( id, stcd )
const getUniqueKey = (item: any) =>
@ -135,16 +159,9 @@ let columns = ref([
key: 'selection',
width: 60,
align: 'center',
//
customCell: record => {
return {
rowSpan: record._selectionRowSpan || 0
};
},
// 使 h Checkbox
customRender: ({ record }) => {
// Checkbox
if (record._selectionRowSpan && record._selectionRowSpan > 0) {
const groupKeys = getGroupKeys(record);
//
@ -161,7 +178,6 @@ let columns = ref([
indeterminate: isPartiallySelected && !isAllSelected,
onChange: (e: any) => handleGroupSelect(e.target.checked, groupKeys)
});
}
return null; //
}
},
@ -170,11 +186,6 @@ let columns = ref([
key: 'basinNames',
title: '流域',
width: 160,
customCell: (record, index) => {
return {
rowSpan: record._basinRowSpan || 0
};
},
customRender: ({ text }: any) => {
if (!text) return '-';
@ -206,11 +217,6 @@ let columns = ref([
key: 'stationNames',
title: '电站名称',
width: 160,
customCell: (record, index) => {
return {
rowSpan: record._stationRowSpan || 0
};
},
customRender: ({ text }: any) => {
if (!text) return '-';
@ -347,24 +353,31 @@ const handleDetailSearchFinish = (values: any) => {
dataType: 'date',
value: values.strdt[1] + ' 23:59:59'
},
values.rvcd !== "all" && {
field: "basinCode",
operator: "eq",
dataType: "string",
value: values.rvcd,
values.rvcd !== 'all' && {
field: 'basinCode',
operator: 'eq',
dataType: 'string',
value: values.rvcd
},
values.rstcd && {
field: 'stationCode',
operator: 'eq',
dataType: 'string',
value: values.rstcd
},
values.reportMonth && {
field: 'reportMonth',
operator: 'eq',
dataType: 'string',
value: values.reportMonth
}
].filter(Boolean);
const filter = {
logic: 'and',
filters: filters
};
selectedRowKeys.value = [];
batchData.value = [];
detailTableRef.value?.getList(filter);
};
@ -373,39 +386,35 @@ const handleDetailReset = (values: any) => {
handleDetailSearchFinish(values);
};
const urgeBtn = async () => {
Modal.confirm({
title: '是否催促选择的用户?',
content: h('div', {}, [
'将对选中的 ',
h(
'span',
{ style: { color: '#ff4d4f', fontWeight: 'bold' } },
batchData.value.length + ' 位用户'
),
'发送【',
h('span', { style: { color: '#ff4d4f' } }, '过鱼数据填报催促通知'),
'】'
]),
onOk: async () => {
const monthStr = searchRef.value.searchData.reportMonth;
const [year, month] = monthStr.split('-');
urgeContent.value = `根据生态环境部要求,请贵电站尽快完成${year}${parseInt(
month
)}月份过鱼数据的报送工作感谢支持`;
urgeModalVisible.value = true;
};
const handleUrgeOk = async () => {
let ids = [];
searchRef.value.btnLoading = true;
detailTableRef.value.loading = true;
batchData.value.forEach((item: any) => {
ids.push(item.userId);
});
let res: any = await batchUrgeContent({ userIds: ids });
let res: any = await batchUrgeContent({
userIds: ids,
content: urgeContent.value
});
if (res && res?.code == 0) {
message.success('催促成功');
detailTableRef.value.loading = false;
searchRef.value.btnLoading = false;
urgeModalVisible.value = false;
} else {
message.error('催促失败');
detailTableRef.value.loading = false;
searchRef.value.btnLoading = false;
}
}
});
};
//
onMounted(() => {});

View File

@ -1,11 +1,11 @@
<script lang="ts">
export default {
name: "user",
name: 'user'
};
</script>
<script setup lang="ts">
import { ref, onMounted, nextTick, watch } from "vue";
import { ref, onMounted, nextTick, watch } from 'vue';
import {
getTreelist,
gettableData,
@ -18,13 +18,13 @@ import {
delChoise,
getFishtree,
saveFishqvan,
getuserdata,
} from "@/api/user";
import { getDictItemsByCode } from "@/api/dict";
import { ElMessageBox, ElMessage } from "element-plus";
import { useAppStore } from "@/store/modules/app";
import Page from "@/components/Pagination/page.vue";
import { Search } from "@element-plus/icons-vue";
getuserdata
} from '@/api/user';
import { getDictItemsByCode } from '@/api/dict';
import { ElMessageBox, ElMessage } from 'element-plus';
import { useAppStore } from '@/store/modules/app';
import Page from '@/components/Pagination/page.vue';
import { Search } from '@element-plus/icons-vue';
// import { constant } from "lodash";
//
interface Tree {
@ -38,7 +38,7 @@ const loading = ref(false);
const queryParams = ref({
current: 1,
size: 10,
querystr: "",
querystr: ''
});
//
const total = ref();
@ -51,7 +51,7 @@ const infoForm = ref();
const treeloading = ref(true);
function getTree() {
const params = {
parentid: "0",
parentid: '0'
};
getTreelist(params)
.then((res: any) => {
@ -67,7 +67,7 @@ function getTree() {
treeloading.value = false;
});
}
const currentNodeKey = ref("");
const currentNodeKey = ref('');
function handleNodeClick(data: Tree, node: any) {
if (data.childList.length == 0) {
orgId.value = data.id;
@ -75,7 +75,7 @@ function handleNodeClick(data: Tree, node: any) {
getdata();
} else {
node.isCurrent = false;
currentNodeKey.value = "";
currentNodeKey.value = '';
nextTick(() => {
currentNodeKey.value = orgId.value;
});
@ -83,47 +83,53 @@ function handleNodeClick(data: Tree, node: any) {
}
const defaultProps = {
children: "childList",
label: "orgname",
children: 'childList',
label: 'orgname'
};
//
const dialogVisible = ref(false);
const title = ref("");
const title = ref('');
function addClick() {
title.value = "新增用户";
title.value = '新增用户';
dialogVisible.value = true;
info.value = {
id: "",
username: "",
nickname: "",
email: "",
phone: "",
roleinfo: [],
id: '',
username: '',
nickname: '',
email: '',
phone: '',
roleinfo: []
};
getrole();
}
//
const multipleSelection = ref([]);
const tableData = ref([]);
const orgId = ref("");
const orgId = ref('');
const originalStatusMap = ref<Map<string, any>>(new Map());
//
function getdata() {
const params = {
current: queryParams.value.current,
size: queryParams.value.size,
orgid: orgId.value,
username: queryParams.value.querystr,
username: queryParams.value.querystr
};
loading.value = true;
gettableData(params)
.then((res) => {
.then(res => {
total.value = res.data.total;
tableData.value = res.data.records;
queryParams.value.size = res.data.size;
queryParams.value.current = res.data.current;
dialog.value = true;
loading.value = false;
//
originalStatusMap.value = new Map();
res.data.records.forEach((item: any) => {
originalStatusMap.value.set(item.id, item.status);
});
})
.catch(() => {
loading.value = false;
@ -132,27 +138,32 @@ function getdata() {
//
function switchChange(row: any) {
const elmassage = ref("");
if (row.status == "0") {
elmassage.value = "确定停用该账号吗?";
} else if (row.status == "1") {
elmassage.value = "确定启用该账号吗?";
const originalStatus = originalStatusMap.value.get(row.id);
//
if (row.status == originalStatus) return;
const elmassage = ref('');
console.log('row', row);
if (row.status == '0') {
elmassage.value = '确定停用该账号吗?';
} else if (row.status == '1') {
elmassage.value = '确定启用该账号吗?';
}
ElMessageBox.confirm(elmassage.value, "提示信息", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
ElMessageBox.confirm(elmassage.value, '提示信息', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
let params = {
status: row.status,
id: row.id,
id: row.id
};
DataStatus(params).then(() => {
getdata();
ElMessage({
type: "success",
message: "改变成功",
type: 'success',
message: '改变成功'
});
});
})
@ -162,12 +173,12 @@ function switchChange(row: any) {
}
//
const info = ref({
id: "",
username: "",
nickname: "",
email: "",
phone: "",
roleinfo: [] as any[],
id: '',
username: '',
nickname: '',
email: '',
phone: '',
roleinfo: [] as any[]
});
//-
function editdepartment(row: any) {
@ -178,7 +189,7 @@ function editdepartment(row: any) {
info.value = JSON.parse(JSON.stringify(row));
info.value.roleinfo = selectID;
rolesdata.value = row.roles;
title.value = "修改用户";
title.value = '修改用户';
dialogVisible.value = true;
getrole();
@ -196,15 +207,15 @@ function confirmClick(formEl: any) {
nickname: info.value.nickname,
email: info.value.email,
phone: info.value.phone,
orgid: orgId.value,
orgid: orgId.value
};
const roleids = String(info.value.roleinfo);
updataUser(params, roleids).then(() => {
getdata();
dialogVisible.value = false;
ElMessage({
type: "success",
message: "修改成功",
type: 'success',
message: '修改成功'
});
});
} else {
@ -213,15 +224,15 @@ function confirmClick(formEl: any) {
nickname: info.value.nickname,
email: info.value.email,
phone: info.value.phone,
orgid: orgId.value,
orgid: orgId.value
};
const roleids = info.value.roleinfo;
addUsers(params, roleids).then((res) => {
addUsers(params, roleids).then(res => {
getdata();
dialogVisible.value = false;
ElMessage({
type: "success",
message: res.data.msg,
type: 'success',
message: res.data.msg
});
});
}
@ -230,8 +241,8 @@ function confirmClick(formEl: any) {
}
//
const moderules = ref({
username: [{ required: true, message: "请输入用户账号", trigger: "blur" }],
nickname: [{ required: true, message: "请输入用户名称", trigger: "blur" }],
username: [{ required: true, message: '请输入用户账号', trigger: 'blur' }],
nickname: [{ required: true, message: '请输入用户名称', trigger: 'blur' }]
});
//
@ -241,17 +252,17 @@ function handleClose() {
}
//
const userid = ref("");
const userid = ref('');
const resultPawss = ref(false);
const msgText = ref("");
const msgText = ref('');
function setpassword(row: any) {
ElMessageBox.confirm("确定要重置此账号密码吗?", "重置密码", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
ElMessageBox.confirm('确定要重置此账号密码吗?', '重置密码', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const params = {
id: userid.value,
id: userid.value
};
setpass(params).then((res: any) => {
if (res.code == 0) {
@ -272,7 +283,7 @@ function closeResult() {
//
const fishway = ref(false);
const userId = ref("");
const userId = ref('');
// ID
const fishhui = ref<any[]>([]);
const fishTreeDialog = ref(false);
@ -281,7 +292,7 @@ const fishTreeDialog = ref(false);
const isFishDataLoaded = ref(false);
async function openFishway(row: any) {
treeInput.value = "";
treeInput.value = '';
fishway.value = true;
userId.value = row.id;
@ -295,7 +306,7 @@ async function openFishway(row: any) {
await Promise.all([
getFishTree(), //
getuserdata({ userId: userId.value }).then((res: any) => {
console.log("用户权限数据:", res);
console.log('用户权限数据:', res);
if (res.code == 0) {
res.data.forEach((item: any) => {
fishhui.value.push(item.orgId);
@ -308,19 +319,19 @@ async function openFishway(row: any) {
userId: item.userId,
parentId: item.parentId,
orgLevel: item.orgLevel,
permissionType: item.permissionType,
permissionType: item.permissionType
});
});
}
}),
})
]);
//
isFishDataLoaded.value = true;
console.log("所有数据加载完成,准备回显");
console.log('所有数据加载完成,准备回显');
} catch (error) {
console.error("加载数据失败:", error);
ElMessage.error("加载数据失败,请重试");
console.error('加载数据失败:', error);
ElMessage.error('加载数据失败,请重试');
}
}
@ -328,9 +339,9 @@ async function openFishway(row: any) {
watch([fishway, isFishDataLoaded], ([newFishway, newDataLoaded]) => {
if (newFishway && newDataLoaded) {
//
console.log("开始回显, fishTreeRef:", fishTreeRef.value);
console.log("回显ID:", fishhui.value);
console.log("树数据:", fishData.value);
console.log('开始回显, fishTreeRef:', fishTreeRef.value);
console.log('回显ID:', fishhui.value);
console.log('树数据:', fishData.value);
// 使 nextTick DOM
nextTick(() => {
@ -346,7 +357,7 @@ watch([fishway, isFishDataLoaded], ([newFishway, newDataLoaded]) => {
fishhui.value,
fishData.value
);
console.log("需要展开的父节点codes:", parentCodesToExpand);
console.log('需要展开的父节点codes:', parentCodesToExpand);
// /
setTreeExpandState(parentCodesToExpand);
@ -354,8 +365,8 @@ watch([fishway, isFishDataLoaded], ([newFishway, newDataLoaded]) => {
//
const checkedKeys = fishTreeRef.value.getCheckedKeys();
const halfCheckedKeys = fishTreeRef.value.getHalfCheckedKeys();
console.log("回显完成 - 全选节点:", checkedKeys);
console.log("回显完成 - 半选节点:", halfCheckedKeys);
console.log('回显完成 - 全选节点:', checkedKeys);
console.log('回显完成 - 半选节点:', halfCheckedKeys);
//
fishTableData.value = tableDatafish.value;
@ -370,7 +381,7 @@ watch([fishway, isFishDataLoaded], ([newFishway, newDataLoaded]) => {
});
} else if (!newFishway) {
//
console.log("关闭对话框,清理数据");
console.log('关闭对话框,清理数据');
fishhui.value = [];
isFishDataLoaded.value = false;
// tree
@ -416,12 +427,12 @@ function fishHandleClose() {
// }
//
const treeInput = ref("");
const treeInput = ref('');
const fishProps = {
children: "children",
label: "name",
children: 'children',
label: 'name'
};
watch(treeInput, (val) => {
watch(treeInput, val => {
fishTreeRef.value!.filter(val);
});
function filterNode(value: string, data: any) {
@ -437,7 +448,7 @@ function getFishTree() {
fishTreeDialog.value = true;
const params = {
// type:'1',
engName: treeInput.value,
engName: treeInput.value
};
return getFishtree(params)
.then((res: any) => {
@ -466,13 +477,16 @@ function getAllChildrenIds(node: any): number[] {
}
// -
function areAllChildrenChecked(parentNode: any, checkedKeysArray: any[]): boolean {
function areAllChildrenChecked(
parentNode: any,
checkedKeysArray: any[]
): boolean {
const allChildrenIds = getAllChildrenIds(parentNode);
if (allChildrenIds.length === 0) {
return false;
}
// IDkeys
return allChildrenIds.every((code) => checkedKeysArray.includes(code));
return allChildrenIds.every(code => checkedKeysArray.includes(code));
}
// -
@ -496,7 +510,10 @@ function isNodeContainedByOtherParent(
}
// IDsID
function filterSelectedIds(checkedKeysArray: number[], allCheckedNodes: any[]): number[] {
function filterSelectedIds(
checkedKeysArray: number[],
allCheckedNodes: any[]
): number[] {
const resultIds: number[] = [];
const fullySelectedParentIds: number[] = [];
const filteredNodeIds = new Set<number>();
@ -507,7 +524,7 @@ function filterSelectedIds(checkedKeysArray: number[], allCheckedNodes: any[]):
if (areAllChildrenChecked(node, checkedKeysArray)) {
fullySelectedParentIds.push(node.code);
const childrenIds = getAllChildrenIds(node);
childrenIds.forEach((childId) => {
childrenIds.forEach(childId => {
filteredNodeIds.add(childId);
});
}
@ -516,9 +533,13 @@ function filterSelectedIds(checkedKeysArray: number[], allCheckedNodes: any[]):
// :
// 1. ""()
fullySelectedParentIds.forEach((parentId) => {
fullySelectedParentIds.forEach(parentId => {
if (
!isNodeContainedByOtherParent(parentId, fullySelectedParentIds, allCheckedNodes)
!isNodeContainedByOtherParent(
parentId,
fullySelectedParentIds,
allCheckedNodes
)
) {
resultIds.push(parentId);
}
@ -528,14 +549,18 @@ function filterSelectedIds(checkedKeysArray: number[], allCheckedNodes: any[]):
allCheckedNodes.forEach((node: any) => {
if (!filteredNodeIds.has(node.code) && !resultIds.includes(node.code)) {
if (
!isNodeContainedByOtherParent(node.code, fullySelectedParentIds, allCheckedNodes)
!isNodeContainedByOtherParent(
node.code,
fullySelectedParentIds,
allCheckedNodes
)
) {
resultIds.push(node.code);
}
}
});
console.log("过滤后的IDs:", resultIds);
console.log('过滤后的IDs:', resultIds);
return resultIds;
}
// code()
@ -590,7 +615,7 @@ function handleFishCheckChange(checkedNode: any, checkedInfo: any) {
// 使IDs
const resultIds = filterSelectedIds(checkedKeysArray, allCheckedNodes);
console.log("最终获取的IDs:", resultIds);
console.log('最终获取的IDs:', resultIds);
//
getFishTableData(resultIds);
@ -618,7 +643,7 @@ function getFishTableData(ids: any[]) {
userId: userId.value,
parentId: node.parentId,
orgLevel: node.orgLevel,
permissionType: "READ", //
permissionType: 'READ' //
});
}
@ -636,16 +661,16 @@ function getFishTableData(ids: any[]) {
const tableids: any = ref([]);
//
function fishDataHandleSelectionChange(val: any) {
console.log("选中的行数据:", val);
console.log('选中的行数据:', val);
fishTableSelection.value = val;
}
//
function delFishTable() {
ElMessageBox.confirm("确定移除选中权限吗?", "删除提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
ElMessageBox.confirm('确定移除选中权限吗?', '删除提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
// ID
@ -678,8 +703,8 @@ function delFishTable() {
}
ElMessage({
type: "success",
message: "删除成功",
type: 'success',
message: '删除成功'
});
//
@ -721,34 +746,36 @@ function fishSure() {
parentId: item.parentId,
orgLevel: item.orgLevel,
path: item.path,
permissionType: item.permissionType,
permissionType: item.permissionType
});
});
saveFishqvan({ userId: userId.value, dataScopeList: params }).then((res: any) => {
saveFishqvan({ userId: userId.value, dataScopeList: params }).then(
(res: any) => {
console.log(res);
if (res.code == 0) {
ElMessage({
message: "保存成功",
type: "success",
message: '保存成功',
type: 'success'
});
fishHandleClose();
}
});
}
);
}
//
function delclick(row: any) {
ElMessageBox.confirm("确定删除此用户吗?", "删除提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
ElMessageBox.confirm('确定删除此用户吗?', '删除提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const params = {
id: row.id,
id: row.id
};
deltableData(params).then(() => {
ElMessage({
type: "success",
message: "删除成功",
type: 'success',
message: '删除成功'
});
getdata();
});
@ -757,9 +784,9 @@ function delclick(row: any) {
//
function getrole() {
const params = {
rolename: "",
rolename: ''
};
getRole(params).then((res) => {
getRole(params).then(res => {
rolesdata.value = res;
});
}
@ -775,18 +802,18 @@ function delchoice() {
ids.value.forEach((item: any) => {
choice.push(item.id);
});
ElMessageBox.confirm("确定删除此用户吗?", "删除提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
ElMessageBox.confirm('确定删除此用户吗?', '删除提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const params = {
id: String(choice),
id: String(choice)
};
delChoise(params).then(() => {
ElMessage({
type: "success",
message: "删除成功",
type: 'success',
message: '删除成功'
});
getdata();
});
@ -799,14 +826,32 @@ function dateFormat(row: any) {
var date = new Date(daterc);
var year = date.getFullYear();
var month =
date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
var day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
var seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
date.getMonth() + 1 < 10
? '0' + (date.getMonth() + 1)
: date.getMonth() + 1;
date.getMonth() + 1 < 10
? '0' + (date.getMonth() + 1)
: date.getMonth() + 1;
var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
var minutes =
date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
var seconds =
date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
//
return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds;
return (
year +
'-' +
month +
'-' +
day +
' ' +
hours +
':' +
minutes +
':' +
seconds
);
}
}
@ -814,11 +859,11 @@ function dateFormat(row: any) {
//
function getName(arr: any[], type: any): string {
if (!arr || !Array.isArray(arr) || type === undefined || type === null) {
return "";
return '';
}
const item = arr.find((item: any) => item?.itemCode === type);
return item?.dictName || "";
return item?.dictName || '';
}
onMounted(() => {
@ -827,7 +872,7 @@ onMounted(() => {
});
const dictData = ref([]);
function getdictdata() {
getDictItemsByCode({ dictCode: "resourceType" }).then((res) => {
getDictItemsByCode({ dictCode: 'resourceType' }).then(res => {
dictData.value = res.data;
});
}
@ -835,18 +880,18 @@ const vMove = {
mounted(el: any) {
el.onmousedown = function (e: any) {
var init = e.clientX;
var parent: any = document.getElementById("silderLeft");
var parent: any = document.getElementById('silderLeft');
const initWidth: any = parent.offsetWidth;
document.onmousemove = function (e) {
var end = e.clientX;
var newWidth = end - init + initWidth;
parent.style.width = newWidth + "px";
parent.style.width = newWidth + 'px';
};
document.onmouseup = function () {
document.onmousemove = document.onmouseup = null;
};
};
},
}
};
// code
function getAllNodeCodes(nodes: any[]): number[] {
@ -863,11 +908,11 @@ function getAllNodeCodes(nodes: any[]): number[] {
//
function handleSelectAll() {
if (!fishTreeRef.value || !fishData.value || fishData.value.length === 0) {
ElMessage.warning("暂无数据可全选");
ElMessage.warning('暂无数据可全选');
return;
}
const allCodes = getAllNodeCodes(fishData.value);
console.log("全选 - 所有节点codes:", allCodes);
console.log('全选 - 所有节点codes:', allCodes);
fishTreeRef.value.setCheckedKeys(allCodes, true);
// 使
@ -881,16 +926,16 @@ function handleSelectAll() {
getFishTableData(filteredIds);
tableids.value = filteredIds;
console.log("全选 - 表格数据已更新过滤后IDs:", filteredIds);
console.log('全选 - 表格数据已更新过滤后IDs:', filteredIds);
}, 100);
ElMessage.success("已全选所有节点");
ElMessage.success('已全选所有节点');
}
//
function handleInvertSelection() {
if (!fishTreeRef.value || !fishData.value || fishData.value.length === 0) {
ElMessage.warning("暂无数据可操作");
ElMessage.warning('暂无数据可操作');
return;
}
@ -899,19 +944,23 @@ function handleInvertSelection() {
// keys
const halfCheckedKeys = fishTreeRef.value.getHalfCheckedKeys();
console.log("反选前 - 已选中codes:", checkedKeys);
console.log("反选前 - 半选codes:", halfCheckedKeys);
console.log('反选前 - 已选中codes:', checkedKeys);
console.log('反选前 - 半选codes:', halfCheckedKeys);
//
const currentSelectedKeys = [...new Set([...checkedKeys, ...halfCheckedKeys])];
console.log("反选前 - 当前有效选中状态:", currentSelectedKeys);
const currentSelectedKeys = [
...new Set([...checkedKeys, ...halfCheckedKeys])
];
console.log('反选前 - 当前有效选中状态:', currentSelectedKeys);
// codes
const allCodes = getAllNodeCodes(fishData.value);
// -
const invertedCodes = allCodes.filter((code) => !currentSelectedKeys.includes(code));
console.log("反选后 - 新的选中codes:", invertedCodes);
const invertedCodes = allCodes.filter(
code => !currentSelectedKeys.includes(code)
);
console.log('反选后 - 新的选中codes:', invertedCodes);
//
fishTreeRef.value.setCheckedKeys([], false);
@ -931,11 +980,11 @@ function handleInvertSelection() {
getFishTableData(filteredIds);
tableids.value = filteredIds;
console.log("反选 - 表格数据已更新过滤后IDs:", filteredIds);
console.log('反选 - 表格数据已更新过滤后IDs:', filteredIds);
}, 100);
}, 50);
ElMessage.success("已反选操作");
ElMessage.success('已反选操作');
}
//
@ -943,17 +992,17 @@ function handleClearSelection() {
if (!fishTreeRef.value) {
return;
}
console.log("取消选中 - 清空所有选中");
console.log('取消选中 - 清空所有选中');
fishTreeRef.value.setCheckedKeys([], true);
//
setTimeout(() => {
getFishTableData([]);
tableids.value = [];
console.log("取消选中 - 表格数据已清空");
console.log('取消选中 - 表格数据已清空');
}, 100);
ElMessage.success("已取消所有选中");
ElMessage.success('已取消所有选中');
}
</script>
@ -963,7 +1012,9 @@ function handleClearSelection() {
<el-tree
ref="treeRef"
:class="
useAppStore().size === 'default' ? 'silderLeft-large' : 'silderLeft-default'
useAppStore().size === 'default'
? 'silderLeft-large'
: 'silderLeft-default'
"
node-key="id"
:data="treedata"
@ -1000,12 +1051,19 @@ function handleClearSelection() {
style="width: 200px"
@keyup.enter="getdata"
/>
<el-button type="primary" style="margin-left: 10px" @click="getdata"
<el-button
type="primary"
style="margin-left: 10px"
@click="getdata"
>搜索</el-button
>
</div>
<div>
<el-button v-hasPerm="['add:user']" type="primary" @click="addClick">
<el-button
v-hasPerm="['add:user']"
type="primary"
@click="addClick"
>
<img
src="@/assets/MenuIcon/jscz_xz.png"
alt=""
@ -1018,8 +1076,7 @@ function handleClearSelection() {
@click="delchoice"
:disabled="multipleSelection.length <= 0"
:type="multipleSelection.length > 0 ? 'primary' : ''"
><el-icon style="margin-right: 5px">
<Delete /> </el-icon
><el-icon style="margin-right: 5px"> <Delete /> </el-icon
>删除</el-button
>
</div>
@ -1038,16 +1095,28 @@ function handleClearSelection() {
:header-cell-style="{
background: 'rgb(250 250 250)',
color: ' #383838',
height: '50px',
height: '50px'
}"
>
<el-table-column type="selection" width="50" align="center" />
<el-table-column type="index" label="序号" width="70" align="center" />
<el-table-column prop="nickname" label="用户姓名" width="140"></el-table-column>
<el-table-column
prop="nickname"
label="用户姓名"
width="140"
></el-table-column>
<!-- <el-table-column prop="avatar" label="头像"></el-table-column> -->
<el-table-column prop="email" label="邮箱"></el-table-column>
<el-table-column prop="phone" label="手机号" min-width="90"></el-table-column>
<el-table-column prop="username" label="登录账号" width="120"></el-table-column>
<el-table-column
prop="phone"
label="手机号"
min-width="90"
></el-table-column>
<el-table-column
prop="username"
label="登录账号"
width="120"
></el-table-column>
<!-- <el-table-column prop="custom1" label="登录账号"></el-table-column> -->
<el-table-column prop="rolename" label="所属角色" width="120">
<template #default="scope">
@ -1056,7 +1125,12 @@ function handleClearSelection() {
</span>
</template>
</el-table-column>
<el-table-column prop="status" label="账号状态" align="center" width="120">
<el-table-column
prop="status"
label="账号状态"
align="center"
width="120"
>
<template #default="scope">
<el-switch
v-model="scope.row.status"
@ -1065,7 +1139,9 @@ function handleClearSelection() {
@change="switchChange(scope.row)"
style="margin-right: 4px"
></el-switch>
<span v-if="scope.row.status == 1" style="color: #0099ff">启用</span>
<span v-if="scope.row.status == 1" style="color: #0099ff"
>启用</span
>
<span v-else style="color: #d7d7d7">停用</span>
</template>
</el-table-column>
@ -1140,7 +1216,12 @@ function handleClearSelection() {
width="620px"
draggable
>
<el-form ref="infoForm" :model="info" :rules="moderules" label-width="90px">
<el-form
ref="infoForm"
:model="info"
:rules="moderules"
label-width="90px"
>
<el-form-item label="用户姓名" prop="nickname">
<el-input
v-model="info.nickname"
@ -1170,7 +1251,12 @@ function handleClearSelection() {
></el-input>
</el-form-item>
<el-form-item label="所属角色">
<el-select v-model="info.roleinfo" placeholder=" " style="width: 100%" multiple>
<el-select
v-model="info.roleinfo"
placeholder=" "
style="width: 100%"
multiple
>
<el-option
v-for="item in rolesdata"
:key="item.id"
@ -1190,7 +1276,9 @@ function handleClearSelection() {
"
>
<el-button @click="handleClose"> </el-button>
<el-button type="primary" @click="confirmClick(infoForm)">保存</el-button>
<el-button type="primary" @click="confirmClick(infoForm)"
>保存</el-button
>
</span>
</el-dialog>
<!-- 过鱼设施权限维护 -->
@ -1223,9 +1311,15 @@ function handleClearSelection() {
</template>
</el-input>
<div class="button_div">
<el-button type="primary" @click="handleSelectAll">全选</el-button>
<el-button type="primary" @click="handleInvertSelection">反选</el-button>
<el-button type="primary" @click="handleClearSelection">取消选中</el-button>
<el-button type="primary" @click="handleSelectAll"
>全选</el-button
>
<el-button type="primary" @click="handleInvertSelection"
>反选</el-button
>
<el-button type="primary" @click="handleClearSelection"
>取消选中</el-button
>
</div>
</div>
@ -1265,13 +1359,23 @@ function handleClearSelection() {
:header-cell-style="{
background: 'rgb(250 250 250)',
color: ' #383838',
height: '50px',
height: '50px'
}"
>
<el-table-column type="selection" width="50" align="center" />
<el-table-column type="index" label="序号" width="70" align="center" />
<el-table-column
type="index"
label="序号"
width="70"
align="center"
/>
<el-table-column prop="name" label="名称"></el-table-column>
<el-table-column prop="type" label="类型" width="200" align="center">
<el-table-column
prop="type"
label="类型"
width="200"
align="center"
>
<template #default="scope">
<span>{{ getName(dictData, scope.row.type) }}</span>
</template>
@ -1310,7 +1414,9 @@ function handleClearSelection() {
append-to-body
:before-close="closeResult"
>
已将密码重置为<span style="color: #409eff; font-size: 16px">{{ msgText }}</span>
已将密码重置为<span style="color: #409eff; font-size: 16px">{{
msgText
}}</span>
<template #footer>
<span class="dialog-footer">
<el-button @click="closeResult">取消</el-button>
@ -1345,6 +1451,7 @@ function handleClearSelection() {
}
.fishTable {
flex: 1;
width: 100%;
height: 100%;