登录修改
BIN
core/core-frontend/public/images/code.png
Normal file
After Width: | Height: | Size: 316 B |
BIN
core/core-frontend/public/images/loginbg.png
Normal file
After Width: | Height: | Size: 356 KiB |
BIN
core/core-frontend/public/images/loginbtn.png
Normal file
After Width: | Height: | Size: 688 B |
BIN
core/core-frontend/public/images/loginform.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
core/core-frontend/public/images/password.png
Normal file
After Width: | Height: | Size: 268 B |
BIN
core/core-frontend/public/images/splitline1.png
Normal file
After Width: | Height: | Size: 124 B |
BIN
core/core-frontend/public/images/splitline2.png
Normal file
After Width: | Height: | Size: 120 B |
BIN
core/core-frontend/public/images/titleline.png
Normal file
After Width: | Height: | Size: 234 B |
BIN
core/core-frontend/public/images/username.png
Normal file
After Width: | Height: | Size: 332 B |
BIN
core/core-frontend/src/assets/img/code.png
Normal file
After Width: | Height: | Size: 316 B |
BIN
core/core-frontend/src/assets/img/loginform.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
core/core-frontend/src/assets/img/password.png
Normal file
After Width: | Height: | Size: 268 B |
BIN
core/core-frontend/src/assets/img/splitline1.png
Normal file
After Width: | Height: | Size: 124 B |
BIN
core/core-frontend/src/assets/img/splitline2.png
Normal file
After Width: | Height: | Size: 120 B |
BIN
core/core-frontend/src/assets/img/titleline.png
Normal file
After Width: | Height: | Size: 234 B |
BIN
core/core-frontend/src/assets/img/username.png
Normal file
After Width: | Height: | Size: 332 B |
@ -233,6 +233,13 @@ export const routes: AppRouteRecordRaw[] = [
|
||||
hidden: true,
|
||||
meta: {},
|
||||
component: () => import('@/viewsnew/application/SfcEditor/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/SystemLogin',
|
||||
name: 'SystemLogin',
|
||||
hidden: true,
|
||||
meta: {},
|
||||
component: () => import('@/viewsnew/application/SystemLogin.vue')
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import Navbar from '@/viewsnew/application/SfcEditor/Navbar.vue'
|
||||
// import Navbar from '@/viewsnew/application/SfcEditor/Navbar.vue'
|
||||
import Navbar from '@/viewsnew/application/sfcEditor/previewNavSfc.vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { getMenuTree } from '@/api/permission/menu'
|
||||
import { moduleList } from '@/api/application/module'
|
||||
const route = useRoute()
|
||||
const applicationId:any = ref('')
|
||||
const menuList = ref([])
|
||||
const isNavbar = ref(false)
|
||||
const projectName:any = ref('')
|
||||
const projectList:any = ref({})
|
||||
onMounted(()=>{
|
||||
if (route.query.id) {
|
||||
applicationId.value = route.query.id
|
||||
@ -23,14 +26,27 @@ function getmenuinfo() {
|
||||
}
|
||||
getMenuTree(params).then(res => {
|
||||
menuList.value = res.data
|
||||
isNavbar.value = true
|
||||
const paramss = {appId:applicationId.value}
|
||||
moduleList(paramss).then(ress => {
|
||||
var arr = ress.data.data
|
||||
let list:any = {}
|
||||
arr.forEach((item:any) => {
|
||||
if(item.type == '02' && item.node_type == '02'){
|
||||
list = item
|
||||
}
|
||||
})
|
||||
if(list.id){
|
||||
projectList.value = list
|
||||
isNavbar.value = true
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div class="system-box">
|
||||
<Navbar v-if="isNavbar" :menuList="menuList" :projectName="projectName"
|
||||
:isFixed="true" :applicationId="applicationId" :isExecuteEvent ="false">
|
||||
:isFixed="true" :projectId="projectList.id" :applicationId="applicationId" :isExecuteEvent="false">
|
||||
</Navbar>
|
||||
</div>
|
||||
</template>
|
||||
@ -39,5 +55,6 @@ function getmenuinfo() {
|
||||
.system-box {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
189
core/core-frontend/src/viewsnew/application/SfcEditor/login.vue
Normal file
@ -0,0 +1,189 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, onMounted, onBeforeUnmount, shallowRef } from 'vue'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
const router = useRouter()
|
||||
const props = defineProps({
|
||||
id: String,
|
||||
name: String
|
||||
})
|
||||
const form = ref({
|
||||
username: '',
|
||||
password: ''
|
||||
})
|
||||
const loginRules = ref({
|
||||
username: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' }
|
||||
]
|
||||
})
|
||||
const ruleFormRef = ref<FormInstance>()
|
||||
const loginTitle: any = ref('')
|
||||
const submitForm = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate((valid, fields) => {
|
||||
if (valid) {
|
||||
router.push({
|
||||
path: '/PreviewSystem',
|
||||
query: { id: props.id, name: props.name }
|
||||
})
|
||||
} else {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
loginTitle.value = props.name
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="login-box">
|
||||
<div class="login-container">
|
||||
<div class="login-title">
|
||||
<div class="login-title-left"><img src="@/assets/img/titleline.png" alt=""></div>
|
||||
<div class="login-title-text">{{ loginTitle }}</div>
|
||||
<div class="login-title-right"><img src="@/assets/img/titleline.png" alt=""></div>
|
||||
</div>
|
||||
<div class="login-form">
|
||||
<div class="login-form-title">欢迎登录</div>
|
||||
<el-form ref="ruleFormRef" :model="form" :rules="loginRules" label-width="0px" style="margin:0px 20px;">
|
||||
<el-form-item label="" prop="username">
|
||||
<div class="logininput">
|
||||
<el-input v-model="form.username" placeholder="请输入用户名">
|
||||
<template #prepend>
|
||||
<img src="@/assets/img/username.png" alt="">
|
||||
</template>
|
||||
</el-input>
|
||||
<img class="login-splitline" src="@/assets/img/splitline2.png" style="width:100%;height: 1px;" alt="">
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="" prop="password">
|
||||
<div class="logininput">
|
||||
<el-input v-model="form.password" placeholder="请输入密码" type="password">
|
||||
<template #prepend>
|
||||
<img src="@/assets/img/password.png" alt="">
|
||||
</template>
|
||||
</el-input>
|
||||
<img class="login-splitline" src="@/assets/img/splitline1.png" style="width:100%;height: 1px;" alt="">
|
||||
</div>
|
||||
</el-form-item>
|
||||
<div class="login-button" @click="submitForm(ruleFormRef)">登录</div>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.login-box {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: url(/images/loginbg.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-top: 8%;
|
||||
.login-container {
|
||||
|
||||
.login-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 60px;
|
||||
margin-bottom: 100px;
|
||||
|
||||
.login-title-left {
|
||||
transform: rotate(-180deg);
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.login-title-text {
|
||||
text-align: center;
|
||||
font-size: 35px;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
margin: 0px 30px;
|
||||
background: linear-gradient(to bottom, #ffffff, #0089ff);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.login-title-right {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.login-form {
|
||||
width: 400px;
|
||||
height: 350px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
background: url(/images/loginform.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
padding: 40px 20px;
|
||||
|
||||
.login-form-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.logininput {
|
||||
position: relative;
|
||||
height: 40px;
|
||||
width:100%;
|
||||
.login-splitline{
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.login-button{
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
background: url(/images/loginbtn.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
margin-top: 40px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
.logininput .el-input__wrapper{
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.logininput .el-input-group__prepend{
|
||||
box-shadow: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
.logininput .el-input__inner{
|
||||
color: #fff;
|
||||
}
|
||||
.logininput .el-form-item.is-error .el-input-tag__wrapper, .el-form-item.is-error .el-input-tag__wrapper.is-focus, .el-form-item.is-error .el-input-tag__wrapper:focus, .el-form-item.is-error .el-input-tag__wrapper:hover, .el-form-item.is-error .el-input__wrapper, .el-form-item.is-error .el-input__wrapper.is-focus, .el-form-item.is-error .el-input__wrapper:focus, .el-form-item.is-error .el-input__wrapper:hover, .el-form-item.is-error .el-select__wrapper, .el-form-item.is-error .el-select__wrapper.is-focus, .el-form-item.is-error .el-select__wrapper:focus, .el-form-item.is-error .el-select__wrapper:hover, .el-form-item.is-error .el-textarea__inner, .el-form-item.is-error .el-textarea__inner.is-focus, .el-form-item.is-error .el-textarea__inner:focus, .el-form-item.is-error .el-textarea__inner:hover{
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.login-form .el-form-item__error{
|
||||
padding-top: 4px ;
|
||||
}
|
||||
</style>
|
@ -156,7 +156,8 @@ function init(){
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: calc(100vh - 65px);
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
textarea {
|
||||
@ -167,7 +168,9 @@ textarea {
|
||||
}
|
||||
|
||||
.preview {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
166
core/core-frontend/src/viewsnew/application/SystemLogin.vue
Normal file
@ -0,0 +1,166 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref,watch, onMounted,onBeforeUnmount } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import * as VueRouter from 'vue-router'
|
||||
import { loadModule } from 'vue3-sfc-loader'
|
||||
import * as Vue from 'vue/dist/vue.esm-bundler.js'
|
||||
import { i18n } from '@/plugins/vue-i18n'
|
||||
import ElementPlus from 'element-plus'
|
||||
import less from 'less'
|
||||
import defaultTemplate from '@/viewsnew/application/SfcEditor/login.vue?raw'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const sfcCode = ref(defaultTemplate)
|
||||
const previewContainer = ref(null)
|
||||
let prevApp = null
|
||||
// 增强的Base64转换函数
|
||||
const convertToBase64 = async (imagePath) => {
|
||||
try {
|
||||
// 处理路径别名
|
||||
const resolvedPath = imagePath.replace('@/', '/src/')
|
||||
const response = await fetch(resolvedPath)
|
||||
if (!response.ok) throw new Error(`图片加载失败: ${response.status}`)
|
||||
const blob = await response.blob()
|
||||
return new Promise((resolve) => {
|
||||
const reader = new FileReader()
|
||||
reader.onloadend = () => resolve(reader.result)
|
||||
reader.readAsDataURL(blob)
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Base64转换失败:', error.message)
|
||||
return ''
|
||||
}
|
||||
}
|
||||
const runCode = async () => {
|
||||
try {
|
||||
if (prevApp) {
|
||||
prevApp.unmount()
|
||||
previewContainer.value.innerHTML = ''
|
||||
}
|
||||
const options = {
|
||||
moduleCache: {
|
||||
vue: Vue,
|
||||
'element-plus': ElementPlus,
|
||||
'vue/dist/vue.esm-bundler.js': Vue,
|
||||
'vue-router': VueRouter
|
||||
},
|
||||
getFile: async (fileName) => {
|
||||
if (fileName.startsWith('@/')) {
|
||||
const resolvedPath = fileName.replace('@/', '/src/')
|
||||
try {
|
||||
const response = await fetch(resolvedPath)
|
||||
return { content: await response.text() }
|
||||
} catch (e) {
|
||||
console.error(`文件加载失败: ${resolvedPath}`, e)
|
||||
return { content: '<!-- 文件加载失败 -->' }
|
||||
}
|
||||
}
|
||||
if (fileName === 'dynamic.vue') {
|
||||
let code = sfcCode.value
|
||||
// 增强的Less处理(支持scoped)
|
||||
const lessRegex = /<style\s+.*?lang="less".*?>(.*?)<\/style>/gis
|
||||
let match
|
||||
while ((match = lessRegex.exec(code)) !== null) {
|
||||
const [full, content] = match
|
||||
try {
|
||||
const { css } = await less.render(content, {
|
||||
paths: ['.'], // 设置解析路径
|
||||
filename: 'dynamic.less'
|
||||
})
|
||||
code = code.replace(full, `<style>${css}</style>`)
|
||||
} catch (e) {
|
||||
console.error('Less编译错误:', e.message)
|
||||
code = code.replace(full, `<style>/* Less Error: ${e.message} */</style>`)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理图片资源(增强路径处理)
|
||||
const imgRegex = /src=['"](.+?\.(png|jpg|jpeg))['"]/gi
|
||||
let imgMatch
|
||||
while ((imgMatch = imgRegex.exec(code)) !== null) {
|
||||
const [full, path] = imgMatch
|
||||
const base64 = await convertToBase64(path)
|
||||
code = code.replace(full, `src="${base64}"`)
|
||||
}
|
||||
return code
|
||||
.replace(/<\/script>/g, '<\\/script>')
|
||||
.replace(/\\\//g, '/')
|
||||
}
|
||||
|
||||
// 处理外部Less文件(支持别名)
|
||||
if (fileName.endsWith('.less')) {
|
||||
const resolvedPath = fileName.replace('@/', '/src/')
|
||||
try {
|
||||
const response = await fetch(resolvedPath)
|
||||
const content = await response.text()
|
||||
const { css } = await less.render(content, { filename: fileName })
|
||||
return { content: css, mediaType: 'text/css' }
|
||||
} catch (e) {
|
||||
return { content: `/* Less Error: ${e.message} */`, mediaType: 'text/css' }
|
||||
}
|
||||
}
|
||||
|
||||
return ''
|
||||
},
|
||||
addStyle: (css) => {
|
||||
const style = document.createElement('style')
|
||||
style.textContent = css
|
||||
document.head.appendChild(style)
|
||||
|
||||
},
|
||||
compiledCache: new Map(),
|
||||
compileTemplate: true
|
||||
}
|
||||
const componentModule = await loadModule('dynamic.vue', options)
|
||||
const component = componentModule.default || componentModule
|
||||
const dynamicProps = ref({
|
||||
id: route.query.id,
|
||||
name: route.query.name,
|
||||
})
|
||||
// prevApp = Vue.createApp({
|
||||
// render: () => Vue.h(component, dynamicProps.value)
|
||||
// })
|
||||
prevApp = Vue.createApp({
|
||||
render: () => Vue.h(component, {
|
||||
...dynamicProps.value,
|
||||
router: router,
|
||||
route: route
|
||||
})
|
||||
})
|
||||
|
||||
// 显式提供路由实例
|
||||
prevApp.use(router)
|
||||
prevApp.use(ElementPlus)
|
||||
prevApp.use(i18n)
|
||||
prevApp.mount(previewContainer.value)
|
||||
|
||||
} catch (error) {
|
||||
console.error('运行时错误:', error)
|
||||
previewContainer.value.innerHTML = `
|
||||
<div class="error">
|
||||
<h3>错误</h3>
|
||||
<pre>${error.message}</pre>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
runCode()
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="loginBox">
|
||||
<div ref="previewContainer" class="preview"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.loginBox {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
@ -73,9 +73,14 @@ function delClick(row){
|
||||
|
||||
}
|
||||
function preview(row){
|
||||
// const route = router.resolve({
|
||||
// path: '/PreviewSystem',
|
||||
// query: { id: row.id,name:row.name }
|
||||
// });
|
||||
// window.open(route.href, '_blank');
|
||||
const route = router.resolve({
|
||||
path: '/PreviewSystem',
|
||||
query: { id: row.id,name:row.name }
|
||||
path: '/SystemLogin',
|
||||
query: { id: row.id ,name:row.name}
|
||||
});
|
||||
window.open(route.href, '_blank');
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ onBeforeMount(() => {
|
||||
:download-status="downloadStatus"
|
||||
></dv-preview>
|
||||
<form-create v-if="isFormCreate" :moduleInfo="moduleInfo"></form-create>
|
||||
<Navbar v-if="isNavbar" :isFixed="true" :applicationId="applicationId"
|
||||
<Navbar class="navbarpreview" v-if="isNavbar" :isFixed="true" :applicationId="applicationId"
|
||||
:menuList="menuList" :projectId="projectId" :projectName="projectInfo.name" :isExecuteEvent="isExecuteEvent"></Navbar>
|
||||
</div>
|
||||
</div>
|
||||
@ -185,6 +185,11 @@ onBeforeMount(() => {
|
||||
position: relative;
|
||||
z-index:1;
|
||||
}
|
||||
.navbarpreview{
|
||||
width: calc(100% - 260px);
|
||||
height: calc(100vh - 60px);
|
||||
// overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.ed-message-box{
|
||||
|
@ -344,7 +344,6 @@ function addtable(){
|
||||
depttitle.value = '新增部门'
|
||||
deptdialog.value = true
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
ruleFormRef.value?.resetFields();
|
||||
dialogVisible.value = false;
|
||||
@ -353,8 +352,13 @@ function depthandleClose() {
|
||||
deptFormRef.value?.resetFields();
|
||||
deptdialog.value = false
|
||||
}
|
||||
function formatDateTime(dateTimeStr:any){
|
||||
return dateTimeStr.replace('T', ' ');
|
||||
function formatDateTime(dateArray:any){
|
||||
if (!Array.isArray(dateArray) || dateArray.length < 6) return 'Invalid Date'
|
||||
|
||||
const pad = (n: number) => n.toString().padStart(2, '0')
|
||||
|
||||
return `${dateArray[0]}-${pad(dateArray[1])}-${pad(dateArray[2])} ` +
|
||||
`${pad(dateArray[3])}:${pad(dateArray[4])}:${pad(dateArray[5])}`
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
@ -431,7 +435,7 @@ function formatDateTime(dateTimeStr:any){
|
||||
<el-table-column prop="lastmodifier" label="最近修改者"/>
|
||||
<el-table-column prop="lastmodifydate" label="最近修改日期" width="170">
|
||||
<template #default="scope">
|
||||
<span>{{formatDateTime(scope.row.lastmodifydate)}}</span>
|
||||
<span v-if="scope.row.lastmodifydate !== ''">{{formatDateTime(scope.row.lastmodifydate)}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" label="操作" width="80">
|
||||
|
@ -207,8 +207,13 @@ function handleClose() {
|
||||
ruleFormRef.value?.resetFields();
|
||||
dialogVisible.value = false;
|
||||
}
|
||||
function formatDateTime(dateTimeStr:any){
|
||||
return dateTimeStr.replace('T', ' ');
|
||||
function formatDateTime(dateArray:any){
|
||||
if (!Array.isArray(dateArray) || dateArray.length < 6) return 'Invalid Date'
|
||||
|
||||
const pad = (n: number) => n.toString().padStart(2, '0')
|
||||
|
||||
return `${dateArray[0]}-${pad(dateArray[1])}-${pad(dateArray[2])} ` +
|
||||
`${pad(dateArray[3])}:${pad(dateArray[4])}:${pad(dateArray[5])}`
|
||||
}
|
||||
function setisValid(row:any){
|
||||
tableloading.value = true
|
||||
@ -299,7 +304,7 @@ function menuChange(data: any, ids: any) {
|
||||
<el-table-column prop="lastmodifier" label="最近修改者" width="120"/>
|
||||
<el-table-column prop="lastmodifydate" label="最近修改日期" width="170">
|
||||
<template #default="scope">
|
||||
<span>{{formatDateTime(scope.row.lastmodifydate)}}</span>
|
||||
<span v-if="scope.row.lastmodifydate">{{formatDateTime(scope.row.lastmodifydate)}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" label="操作" width="100">
|
||||
|
@ -254,8 +254,12 @@ function handleCurrentChange(val: number){
|
||||
currentPage.value = val
|
||||
queryuserinfo()
|
||||
}
|
||||
function formatDateTime(dateTimeStr:any){
|
||||
return dateTimeStr.replace('T', ' ');
|
||||
function formatDateTime(dateArray:any){
|
||||
if (!Array.isArray(dateArray) || dateArray.length < 6) return 'Invalid Date'
|
||||
const pad = (n: number) => n.toString().padStart(2, '0')
|
||||
|
||||
return `${dateArray[0]}-${pad(dateArray[1])}-${pad(dateArray[2])} ` +
|
||||
`${pad(dateArray[3])}:${pad(dateArray[4])}:${pad(dateArray[5])}`
|
||||
}
|
||||
function setisValid(row:any){
|
||||
const params = {
|
||||
|