修改数据填报,添加鱼种类下载按钮增加延迟时间5分钟,登录添加记住密码
This commit is contained in:
parent
fb582add0f
commit
24d56e2944
@ -9,6 +9,6 @@ VITE_APP_BASE_API = '/dev-api'
|
|||||||
## 开发环境API地址
|
## 开发环境API地址
|
||||||
# VITE_APP_BASE_URL = 'http://localhost:8093'
|
# VITE_APP_BASE_URL = 'http://localhost:8093'
|
||||||
VITE_APP_BASE_URL = 'http://10.84.121.21:8093'
|
VITE_APP_BASE_URL = 'http://10.84.121.21:8093'
|
||||||
VITE_APP_BASE_API_URL = 'https://211.99.26.225:12130/prod-api'
|
VITE_APP_BASE_API_URL = 'http://10.84.121.21:8093'
|
||||||
## 开发环境预览 图片视频地址
|
## 开发环境预览 图片视频地址
|
||||||
VITE_APP_PREVIEW_URL = 'https://211.99.26.225:12125'
|
VITE_APP_PREVIEW_URL = 'https://211.99.26.225:12125'
|
||||||
|
|||||||
BIN
frontend/public/file/鱼种类字典数据.xlsx
Normal file
BIN
frontend/public/file/鱼种类字典数据.xlsx
Normal file
Binary file not shown.
12
frontend/src/components/MapModal/components/BasicInfo.vue
Normal file
12
frontend/src/components/MapModal/components/BasicInfo.vue
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
基本信息
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
生态流量
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
生态流量泄放设施
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
全景影像
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
电站监测数据
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
12
frontend/src/components/MapModal/components/SsspLayer.vue
Normal file
12
frontend/src/components/MapModal/components/SsspLayer.vue
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
视频
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
阶段属性
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
预警提示
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
119
frontend/src/components/MapModal/index.vue
Normal file
119
frontend/src/components/MapModal/index.vue
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
v-model:open="visible"
|
||||||
|
:title="title"
|
||||||
|
width="800px"
|
||||||
|
:footer="null"
|
||||||
|
:closable="true"
|
||||||
|
@cancel="handleClose"
|
||||||
|
class="map-modal"
|
||||||
|
>
|
||||||
|
<div class="map-modal-content">
|
||||||
|
<a-tabs v-model:activeKey="currentActiveKey">
|
||||||
|
<a-tab-pane
|
||||||
|
v-for="tab in tabsConfig"
|
||||||
|
:key="tab.key"
|
||||||
|
:tab="tab.title"
|
||||||
|
>
|
||||||
|
<!-- 根据 key 动态渲染子组件 -->
|
||||||
|
<div v-if="currentActiveKey === 'basicInfo'" class="tab-pane-container">
|
||||||
|
<!-- 假设 BasicInfo 是预定义的组件 -->
|
||||||
|
<BasicInfo :data="modalData" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="currentActiveKey === 'mapView'" class="tab-pane-container">
|
||||||
|
<!-- 假设 MapView 是预定义的组件 -->
|
||||||
|
<MapView :data="modalData" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="currentActiveKey === 'surrounding'" class="tab-pane-container">
|
||||||
|
<!-- 其他预定义组件 -->
|
||||||
|
<SurroundingInfo :data="modalData" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="empty-placeholder">
|
||||||
|
未找到对应 Key ({{ currentActiveKey }}) 的组件配置
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
// 导入预定义的 Tab 内容组件
|
||||||
|
// 请根据实际路径调整导入地址
|
||||||
|
import BasicInfo from './components/BasicInfo.vue';
|
||||||
|
import MapView from './components/MapView.vue';
|
||||||
|
import SurroundingInfo from './components/SurroundingInfo.vue';
|
||||||
|
|
||||||
|
// 定义 Tab 配置项接口
|
||||||
|
interface TabItem {
|
||||||
|
key: string;
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义 Props
|
||||||
|
const props = defineProps<{
|
||||||
|
visible: boolean;
|
||||||
|
title?: string;
|
||||||
|
activeKey?: string; // 外部控制的当前激活 tab
|
||||||
|
tabsConfig?: TabItem[]; // Tab 配置列表,用于生成 Tab 头
|
||||||
|
data?: any; // 可选:传递给内部组件的数据
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 定义 Emits
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:visible', value: boolean): void;
|
||||||
|
(e: 'change', key: string): void; // 当 tab 切换时触发
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 内部维护的 activeKey
|
||||||
|
const currentActiveKey = ref<string>(props.activeKey || '');
|
||||||
|
|
||||||
|
// 监听外部传入的 activeKey 变化
|
||||||
|
watch(() => props.activeKey, (newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
currentActiveKey.value = newVal;
|
||||||
|
}
|
||||||
|
}, { immediate: true });
|
||||||
|
|
||||||
|
// 监听内部 tab 切换,通知父组件
|
||||||
|
watch(currentActiveKey, (newVal) => {
|
||||||
|
emit('change', newVal);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const handleClose = () => {
|
||||||
|
emit('update:visible', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 为了方便模板中使用,将 props.data 暴露给模板
|
||||||
|
const modalData = ref(props.data);
|
||||||
|
watch(() => props.data, (newVal) => {
|
||||||
|
modalData.value = newVal;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.map-modal {
|
||||||
|
:deep(.ant-modal-body) {
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-modal-content {
|
||||||
|
min-height: 300px; // 增加高度以容纳内容
|
||||||
|
|
||||||
|
.tab-pane-container {
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-placeholder {
|
||||||
|
color: #999;
|
||||||
|
text-align: center;
|
||||||
|
padding: 40px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
1312
frontend/src/components/MapModal/setting.config.ts
Normal file
1312
frontend/src/components/MapModal/setting.config.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,11 +2,12 @@ import axios from 'axios';
|
|||||||
import { message, Modal } from 'ant-design-vue';
|
import { message, Modal } from 'ant-design-vue';
|
||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
import { useUserStoreHook } from '@/store/modules/user';
|
import { useUserStoreHook } from '@/store/modules/user';
|
||||||
|
import router from '@/router';
|
||||||
|
|
||||||
// 创建 axios 实例
|
// 创建 axios 实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||||
timeout: 100000,
|
timeout: 300000, // 5分钟
|
||||||
headers: { 'Content-Type': 'application/json;charset=utf-8' }
|
headers: { 'Content-Type': 'application/json;charset=utf-8' }
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -63,6 +64,7 @@ service.interceptors.response.use(
|
|||||||
cancelButtonProps: { disabled: false },
|
cancelButtonProps: { disabled: false },
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
router.push('/login');
|
||||||
window.location.href = '/';
|
window.location.href = '/';
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -114,13 +114,14 @@
|
|||||||
<span>登录</span>
|
<span>登录</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
<div style="width: 100%;display: flex;align-items: center;justify-content: space-between;">
|
<div style="width: 100%;display: flex;align-items: center;justify-content: space-between;">
|
||||||
<a-button type="link" size="mini" block @click="showForgotPasswordPage"
|
<a-checkbox v-model:checked="remember" style="margin-top: 10px;">记住密码</a-checkbox>
|
||||||
|
<a-button type="link" size="mini" @click="showForgotPasswordPage"
|
||||||
:style="{ marginTop: '10px', border: 'none' }">
|
:style="{ marginTop: '10px', border: 'none' }">
|
||||||
忘记密码
|
忘记密码
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button type="link" size="mini" block @click="goRegister"
|
<a-button type="link" size="mini" @click="goRegister"
|
||||||
:style="{ marginTop: '10px', border: 'none' }">
|
:style="{ marginTop: '10px', border: 'none' }">
|
||||||
注册
|
用户注册
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -188,6 +189,7 @@ import { UserOutlined, LockOutlined, MobileOutlined } from "@ant-design/icons-vu
|
|||||||
import { getCaptcha, sendSmsCode, smsLoginApi, resetPassword } from "@/api/auth";
|
import { getCaptcha, sendSmsCode, smsLoginApi, resetPassword } from "@/api/auth";
|
||||||
import { message } from "ant-design-vue";
|
import { message } from "ant-design-vue";
|
||||||
import { setToken } from "@/utils/auth";
|
import { setToken } from "@/utils/auth";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
// 组件依赖
|
// 组件依赖
|
||||||
|
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
@ -367,10 +369,19 @@ function onFinish() {
|
|||||||
if (user.password !== state.cookiePass) {
|
if (user.password !== state.cookiePass) {
|
||||||
user.password = encrypt(user.password);
|
user.password = encrypt(user.password);
|
||||||
}
|
}
|
||||||
console.log(user);
|
|
||||||
userStore
|
userStore
|
||||||
.login(user)
|
.login(user)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
if (remember.value == true) {
|
||||||
|
Cookies.set('username', user.username, { expires: 30 });
|
||||||
|
Cookies.set('password', user.password, { expires: 30 });
|
||||||
|
Cookies.set('rememberMe', String(remember.value), { expires: 30 });
|
||||||
|
} else {
|
||||||
|
// 如果用户取消勾选记住密码,应该移除 cookie
|
||||||
|
Cookies.remove('username');
|
||||||
|
Cookies.remove('password');
|
||||||
|
Cookies.remove('rememberMe');
|
||||||
|
}
|
||||||
router.push({ path: "/" });
|
router.push({ path: "/" });
|
||||||
state.loading = false;
|
state.loading = false;
|
||||||
message.success("登录成功");
|
message.success("登录成功");
|
||||||
@ -492,6 +503,22 @@ function getOtherQuery(query: any) {
|
|||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
function getCookie() {
|
||||||
|
const username = Cookies.get("username");
|
||||||
|
let password = Cookies.get("password");
|
||||||
|
const rememberMe = Cookies.get("rememberMe");
|
||||||
|
rememberMe == "true" ? (remember.value = Boolean(rememberMe)) : false;
|
||||||
|
// 保存cookie里面的加密后的密码
|
||||||
|
state.cookiePass = password === undefined ? "" : password;
|
||||||
|
password = password === undefined ? state.loginData.password : password;
|
||||||
|
state.loginData = {
|
||||||
|
username: username === undefined ? state.loginData.username : username,
|
||||||
|
password: decrypt(password),
|
||||||
|
code: "",
|
||||||
|
uuid: "",
|
||||||
|
};
|
||||||
|
remember.value = rememberMe === undefined ? false : Boolean(rememberMe);
|
||||||
|
}
|
||||||
function getCode() {
|
function getCode() {
|
||||||
getCaptcha().then((result: any) => {
|
getCaptcha().then((result: any) => {
|
||||||
codeUrl.value = result.data.img;
|
codeUrl.value = result.data.img;
|
||||||
@ -736,6 +763,7 @@ const handleResetPassword = async () => {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getCode();
|
getCode();
|
||||||
|
getCookie();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -268,7 +268,7 @@
|
|||||||
v-if="!isView"
|
v-if="!isView"
|
||||||
v-model:file-list="videoFileList"
|
v-model:file-list="videoFileList"
|
||||||
list-type="text"
|
list-type="text"
|
||||||
:multiple="false"
|
:multiple="true"
|
||||||
accept=".mp4"
|
accept=".mp4"
|
||||||
:before-upload="beforeVideoUpload"
|
:before-upload="beforeVideoUpload"
|
||||||
@preview="handleVideoPreview"
|
@preview="handleVideoPreview"
|
||||||
@ -566,7 +566,14 @@ const handleImageRemove = (file: any) => {
|
|||||||
|
|
||||||
// 移除视频
|
// 移除视频
|
||||||
const handleVideoRemove = (file: any) => {
|
const handleVideoRemove = (file: any) => {
|
||||||
videoFileList.value = [];
|
// 找到该文件在列表中的索引
|
||||||
|
const index = videoFileList.value.indexOf(file);
|
||||||
|
if (index > -1) {
|
||||||
|
// 创建新数组并移除该项
|
||||||
|
const newFileList = videoFileList.value.slice();
|
||||||
|
newFileList.splice(index, 1);
|
||||||
|
videoFileList.value = newFileList;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// 1. 定义一个初始化表单的函数
|
// 1. 定义一个初始化表单的函数
|
||||||
const initForm = () => {
|
const initForm = () => {
|
||||||
|
|||||||
@ -62,7 +62,9 @@
|
|||||||
</a-tooltip> -->
|
</a-tooltip> -->
|
||||||
<a-tooltip title="鱼种类字典数据下载">
|
<a-tooltip title="鱼种类字典数据下载">
|
||||||
<a-button>
|
<a-button>
|
||||||
鱼种类字典数据下载
|
<a href="/file/鱼种类字典数据.xlsx" download="鱼种类字典数据.xlsx">
|
||||||
|
鱼种类字典数据下载
|
||||||
|
</a>
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip title="操作手册下载">
|
<a-tooltip title="操作手册下载">
|
||||||
|
|||||||
@ -159,7 +159,7 @@
|
|||||||
<a-form-item label="选中记录数">
|
<a-form-item label="选中记录数">
|
||||||
<span>{{ selectedRows.length }} 条</span>
|
<span>{{ selectedRows.length }} 条</span>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="审批意见" required>
|
<a-form-item label="审批意见">
|
||||||
<a-textarea v-model:value="batchApproveForm.approveComment" :rows="4" placeholder="请输入审批意见(必填)"
|
<a-textarea v-model:value="batchApproveForm.approveComment" :rows="4" placeholder="请输入审批意见(必填)"
|
||||||
:maxlength="500" show-count />
|
:maxlength="500" show-count />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@ -668,6 +668,9 @@ const handleShowApprovalLog = (record: any) => {
|
|||||||
dataType: "string",
|
dataType: "string",
|
||||||
value: record.id,
|
value: record.id,
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
sort:[
|
||||||
|
{ field: "operateTime", order: "desc" }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
approvalLogTableRef.value?.getList(filter);
|
approvalLogTableRef.value?.getList(filter);
|
||||||
@ -835,10 +838,10 @@ const handleBatchApprove = () => {
|
|||||||
// 确认批量审批
|
// 确认批量审批
|
||||||
const handleBatchApproveConfirm = async () => {
|
const handleBatchApproveConfirm = async () => {
|
||||||
// 验证审批意见
|
// 验证审批意见
|
||||||
if (!batchApproveForm.value.approveComment || batchApproveForm.value.approveComment.trim() === '') {
|
// if (!batchApproveForm.value.approveComment || batchApproveForm.value.approveComment.trim() === '') {
|
||||||
message.warning('请填写审批意见');
|
// message.warning('请填写审批意见');
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 检查是否有已通过的记录
|
// 检查是否有已通过的记录
|
||||||
const hasApprovedRecord = selectedRows.value.some(row => row.status != 'PENDING');
|
const hasApprovedRecord = selectedRows.value.some(row => row.status != 'PENDING');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user