mirror of
https://github.com/Jinnrry/PMail.git
synced 2025-02-20 11:43:09 +08:00
代码分离,功能优化 (#204)
* feat: 代码分离,功能优化 1. 代码迁移到 ts. 2. 分离 axios 部分代码. 3. 增加 pinia 支持,全局状态代码迁移到相对应的 store. 4. 代码格式优化, 用 === 代替 ==. 5. 代码声明更改,用 const 代替 var 声明. 6. Header 使用 Router 导航. 7. v-for 增加 key. * fix[fe]: 移除过时的 prop 引用 * fix[fe]: 移除过时的 prop 引用 * fix[fe]: 修复 logo 上面有横线的问题 * fix[fe]: 修复 logo 上面有横线的问题 --------- Co-authored-by: zhe28 <huangze28@foxmail.com>
This commit is contained in:
parent
dbb671df67
commit
ad0167f6fd
@ -15,6 +15,7 @@
|
||||
"element-plus": "^2.3.6",
|
||||
"pinia": "^2.0.36",
|
||||
"vue": "^3.3.2",
|
||||
"vue-icons-plus": "^0.1.6",
|
||||
"vue-router": "^4.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -23,6 +24,7 @@
|
||||
"eslint-plugin-vue": "^9.11.0",
|
||||
"unplugin-auto-import": "^0.16.4",
|
||||
"unplugin-vue-components": "^0.25.0",
|
||||
"vite": "^4.3.5"
|
||||
"vite": "^4.3.5",
|
||||
"vue-tsc": "^2.1.6"
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
<script setup>
|
||||
import { RouterView } from 'vue-router'
|
||||
import {RouterView, useRoute} from 'vue-router'
|
||||
import HomeHeader from '@/components/HomeHeader.vue'
|
||||
import HomeAside from '@/components/HomeAside.vue';
|
||||
import { watch, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import {ref, watch} from 'vue'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const pageName = ref(route.name)
|
||||
|
||||
watch(
|
||||
() => route.fullPath,
|
||||
(n, o) => {
|
||||
() => {
|
||||
pageName.value = route.name
|
||||
}
|
||||
)
|
||||
@ -19,13 +19,13 @@ watch(
|
||||
|
||||
<template>
|
||||
<div id="main">
|
||||
<HomeHeader />
|
||||
<HomeHeader/>
|
||||
<div id="content">
|
||||
<div id="aside" v-if="pageName != 'login' && pageName != 'setup'">
|
||||
<HomeAside />
|
||||
<div id="aside" v-if="pageName !== 'login' && pageName !== 'setup'">
|
||||
<HomeAside/>
|
||||
</div>
|
||||
<div id="body">
|
||||
<RouterView />
|
||||
<RouterView/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,13 +1,36 @@
|
||||
<template>
|
||||
<div id="main">
|
||||
<el-tree :expand-on-click-node="false" :data="data" :props="defaultProps" :defaultExpandAll="true" :class="node">
|
||||
<el-tree
|
||||
:expand-on-click-node="false"
|
||||
:data="data"
|
||||
:defaultExpandAll="true"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div>
|
||||
<span v-if="data.id != -1"> {{ data.label }}</span>
|
||||
<el-input v-if="data.id == -1" v-model="data.label" @blur="onInputBlur(data)"></el-input>
|
||||
<el-button v-if="data.id != 0" @click="del(node, data)" size="small" type="danger" circle> -
|
||||
<span v-if="data.id !== -1"> {{ data.label }}</span>
|
||||
<el-input
|
||||
v-if="data.id === -1"
|
||||
v-model="data.label"
|
||||
@blur="onInputBlur(data)"
|
||||
></el-input>
|
||||
<el-button
|
||||
v-if="data.id !== 0"
|
||||
@click="del(node, data)"
|
||||
size="small"
|
||||
type="danger"
|
||||
circle
|
||||
>
|
||||
-
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="data.id !== 0"
|
||||
@click="add(data)"
|
||||
size="small"
|
||||
type="primary"
|
||||
circle
|
||||
>
|
||||
+
|
||||
</el-button>
|
||||
<el-button v-if="data.id != 0" @click="add(data)" size="small" type="primary" circle> + </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
@ -17,82 +40,84 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, getCurrentInstance } from 'vue'
|
||||
import lang from '../i18n/i18n';
|
||||
import { reactive } from "vue";
|
||||
import lang from "../i18n/i18n";
|
||||
import { http } from "@/utils/axios";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
const data = reactive([])
|
||||
const app = getCurrentInstance()
|
||||
const $http = app.appContext.config.globalProperties.$http
|
||||
const data = reactive([]);
|
||||
|
||||
$http.get('/api/group').then(res => {
|
||||
data.push(...res.data)
|
||||
})
|
||||
http.get("/api/group").then((res) => {
|
||||
data.push(...res.data);
|
||||
});
|
||||
|
||||
const del = function (node, data) {
|
||||
if (data.id != -1) {
|
||||
this.$axios.post("/api/group/del", { "id": data.id }).then(res => {
|
||||
if (res.errorNo != 0) {
|
||||
if (data.id !== -1) {
|
||||
this.$axios.post("/api/group/del", { id: data.id }).then((res) => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage({
|
||||
message: res.errorMsg,
|
||||
type: 'error',
|
||||
})
|
||||
type: "error",
|
||||
});
|
||||
} else {
|
||||
const pc = node.parent.childNodes
|
||||
const pc = node.parent.childNodes;
|
||||
for (let i = 0; i < pc.length; i++) {
|
||||
if (pc[i].id == node.id) {
|
||||
pc.splice(i, 1)
|
||||
return
|
||||
if (pc[i].id === node.id) {
|
||||
pc.splice(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
const pc = node.parent.childNodes
|
||||
const pc = node.parent.childNodes;
|
||||
for (let i = 0; i < pc.length; i++) {
|
||||
if (pc[i].id == node.id) {
|
||||
pc.splice(i, 1)
|
||||
return
|
||||
if (pc[i].id === node.id) {
|
||||
pc.splice(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const add = function (item) {
|
||||
if (item.children == null) {
|
||||
item.children = []
|
||||
item.children = [];
|
||||
}
|
||||
item.children.push({
|
||||
"children": [],
|
||||
"label": "",
|
||||
"id": "-1",
|
||||
"parent_id": item.id
|
||||
})
|
||||
}
|
||||
children: [],
|
||||
label: "",
|
||||
id: "-1",
|
||||
parent_id: item.id,
|
||||
});
|
||||
};
|
||||
|
||||
const addRoot = function () {
|
||||
data.push({
|
||||
"children": [],
|
||||
"label": "",
|
||||
"id": "-1",
|
||||
"parent_id": 0
|
||||
})
|
||||
}
|
||||
children: [],
|
||||
label: "",
|
||||
id: "-1",
|
||||
parent_id: 0,
|
||||
});
|
||||
};
|
||||
|
||||
const onInputBlur = function (item) {
|
||||
if (item.label != "") {
|
||||
this.$axios.post("/api/group/add", { "name": item.label, "parent_id": item.parent_id }).then(res => {
|
||||
if (res.errorNo != 0) {
|
||||
if (item.label !== "") {
|
||||
http
|
||||
.post("/api/group/add", { name: item.label, parent_id: item.parent_id })
|
||||
.then((res) => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage({
|
||||
message: res.errorMsg,
|
||||
type: 'error',
|
||||
})
|
||||
type: "error",
|
||||
});
|
||||
} else {
|
||||
this.$axios.get('/api/group').then(res => {
|
||||
data.splice(0, data.length)
|
||||
data.push(...res.data)
|
||||
})
|
||||
this.$axios.get("/api/group").then((res) => {
|
||||
data.splice(0, data.length);
|
||||
data.push(...res.data);
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -1,58 +1,49 @@
|
||||
<template>
|
||||
<div id="main">
|
||||
<input id="search" :placeholder="lang.search">
|
||||
<el-tree :data="data" :props="defaultProps" :defaultExpandAll="true" @node-click="handleNodeClick" :class="node" />
|
||||
<input id="search" :placeholder="lang.search" />
|
||||
<el-tree
|
||||
:data="data"
|
||||
:defaultExpandAll="true"
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
import { reactive, ref } from 'vue'
|
||||
import useGroupStore from '../stores/group'
|
||||
import lang from '../i18n/i18n';
|
||||
import { getCurrentInstance } from 'vue'
|
||||
const app = getCurrentInstance()
|
||||
const $http = app.appContext.config.globalProperties.$http
|
||||
|
||||
const groupStore = useGroupStore()
|
||||
const router = useRouter()
|
||||
|
||||
|
||||
const data = ref([])
|
||||
|
||||
|
||||
$http.get('/api/group').then(res => {
|
||||
data.value = res.data
|
||||
})
|
||||
|
||||
import { useRouter } from "vue-router";
|
||||
import { ref } from "vue";
|
||||
import useGroupStore from "../stores/group";
|
||||
import lang from "../i18n/i18n";
|
||||
import { http } from "@/utils/axios";
|
||||
|
||||
const groupStore = useGroupStore();
|
||||
const router = useRouter();
|
||||
const data = ref([]);
|
||||
|
||||
http.get("/api/group").then((res) => {
|
||||
if (res.data) data.value = res.data;
|
||||
});
|
||||
|
||||
const handleNodeClick = function (data) {
|
||||
if (data.tag != null) {
|
||||
groupStore.name = data.label
|
||||
groupStore.tag = data.tag
|
||||
groupStore.name = data.label;
|
||||
groupStore.tag = data.tag;
|
||||
router.push({
|
||||
name: "list",
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
#main {
|
||||
width: 243px;
|
||||
background-color: #F1F1F1;
|
||||
background-color: #f1f1f1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#search {
|
||||
background-color: #D6E7F7;
|
||||
background-color: #d6e7f7;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
padding-left: 10px;
|
||||
@ -62,10 +53,10 @@ const handleNodeClick = function (data) {
|
||||
}
|
||||
|
||||
.el-tree {
|
||||
background-color: #F1F1F1;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.add_group{
|
||||
.add_group {
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
padding-left: 15px;
|
||||
|
@ -1,33 +1,35 @@
|
||||
<template>
|
||||
<div id="header_main">
|
||||
<div id="logo">
|
||||
<span style="padding-left: 20px;">PMail</span>
|
||||
<router-link to="/" style="text-underline: none">
|
||||
<el-text :line-clamp="1" size="large"><h1>Pmail</h1></el-text>
|
||||
</router-link>
|
||||
</div>
|
||||
<div id="settings" @click="settings" v-if="$isLogin">
|
||||
<div id="settings" @click="settings" v-if="isLogin">
|
||||
<el-icon style="font-size: 25px;">
|
||||
<Setting style="color:#FFFFFF" />
|
||||
<TbSettings style="color:#FFFFFF"/>
|
||||
</el-icon>
|
||||
</div>
|
||||
<el-drawer v-model="openSettings" size="80%" :title="lang.settings">
|
||||
<el-tabs tab-position="left">
|
||||
<el-tab-pane :label="lang.security">
|
||||
<SecuritySettings />
|
||||
<SecuritySettings/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="lang.group_settings">
|
||||
<GroupSettings />
|
||||
<GroupSettings/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="lang.rule_setting">
|
||||
<RuleSettings />
|
||||
<RuleSettings/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane v-if="$userInfos.is_admin" :label="lang.user_management">
|
||||
<UserManagement />
|
||||
<el-tab-pane v-if="userInfos.is_admin" :label="lang.user_management">
|
||||
<UserManagement/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="lang.plugin_settings">
|
||||
<PluginSettings />
|
||||
<PluginSettings/>
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
@ -37,29 +39,30 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Setting } from '@element-plus/icons-vue';
|
||||
import { ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {TbSettings} from "vue-icons-plus/tb";
|
||||
import {ref} from 'vue'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import SecuritySettings from '@/components/SecuritySettings.vue'
|
||||
import lang from '../i18n/i18n';
|
||||
import GroupSettings from './GroupSettings.vue';
|
||||
import RuleSettings from './RuleSettings.vue';
|
||||
import UserManagement from './UserManagement.vue';
|
||||
import { getCurrentInstance } from 'vue'
|
||||
import PluginSettings from './PluginSettings.vue';
|
||||
const app = getCurrentInstance()
|
||||
const $http = app.appContext.config.globalProperties.$http
|
||||
const $isLogin = app.appContext.config.globalProperties.$isLogin
|
||||
const $userInfos = app.appContext.config.globalProperties.$userInfos
|
||||
import {http} from "@/utils/axios";
|
||||
import {useGlobalStatusStore} from "@/stores/useGlobalStatusStore";
|
||||
|
||||
const globalStatus = useGlobalStatusStore();
|
||||
const isLogin = globalStatus.isLogin;
|
||||
const userInfos = globalStatus.userInfos;
|
||||
|
||||
|
||||
const openSettings = ref(false)
|
||||
const settings = function () {
|
||||
if (Object.keys($userInfos.value).length == 0) {
|
||||
$http.post("/api/user/info", {}).then(res => {
|
||||
if (res.errorNo == 0) {
|
||||
$userInfos.value = res.data
|
||||
if (Object.keys(userInfos).length === 0) {
|
||||
http.post("/api/user/info", {}).then(res => {
|
||||
if (res.errorNo === 0) {
|
||||
userInfos.value = res.data
|
||||
openSettings.value = true;
|
||||
|
||||
} else {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
@ -67,18 +70,18 @@ const settings = function () {
|
||||
})
|
||||
}
|
||||
})
|
||||
}else{
|
||||
} else {
|
||||
openSettings.value = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
#header_main {
|
||||
height: 50px;
|
||||
background-color: #000;
|
||||
@ -96,6 +99,11 @@ const settings = function () {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#logo h1 {
|
||||
padding-left: 20px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#search {
|
||||
height: 3rem;
|
||||
width: 100%;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div id="main">
|
||||
<el-tabs>
|
||||
<el-tab-pane v-for="(src, name) in pluginList" :label="name">
|
||||
<el-tab-pane v-for="(src, name) in pluginList" :key="src" :label="name">
|
||||
<iframe :src="src"></iframe>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
@ -9,16 +9,16 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, getCurrentInstance } from 'vue'
|
||||
const app = getCurrentInstance()
|
||||
const $http = app.appContext.config.globalProperties.$http
|
||||
import {reactive} from 'vue'
|
||||
import {http} from "@/utils/axios";
|
||||
|
||||
const pluginList = reactive({})
|
||||
|
||||
$http.get('/api/plugin/list').then(res => {
|
||||
http.get('/api/plugin/list').then(res => {
|
||||
if (res.data != null && res.data.length > 0) {
|
||||
for (let i = 0; i < res.data.length; i++) {
|
||||
let name = res.data[i];
|
||||
pluginList[name] = "/api/plugin/settings/"+ name +"/index.html";
|
||||
pluginList[name] = "/api/plugin/settings/" + name + "/index.html";
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -27,7 +27,7 @@ $http.get('/api/plugin/list').then(res => {
|
||||
|
||||
<style scoped>
|
||||
|
||||
iframe{
|
||||
iframe {
|
||||
width: 100%;
|
||||
border: 0;
|
||||
}
|
||||
|
@ -1,22 +1,22 @@
|
||||
<template>
|
||||
<el-table :data="data" :show-header="true">
|
||||
<el-table-column prop="id" label="id" />
|
||||
<el-table-column prop="name" :label="lang.rule_name" />
|
||||
<el-table-column prop="id" label="id"/>
|
||||
<el-table-column prop="name" :label="lang.rule_name"/>
|
||||
<el-table-column prop="action" :label="lang.rule_do">
|
||||
<template #default="scope">
|
||||
{{ ActionName[scope.row.action] }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="params" :label="lang.rule_params" />
|
||||
<el-table-column prop="sort" :label="lang.rule_priority" />
|
||||
<el-table-column prop="params" :label="lang.rule_params"/>
|
||||
<el-table-column prop="sort" :label="lang.rule_priority"/>
|
||||
<el-table-column>
|
||||
<template #default="scope">
|
||||
<div style="display: flex; align-items: center">
|
||||
<el-button size="small" type="primary" :icon="Edit" circle @click="editRule(scope.row)" />
|
||||
<el-button size="small" type="primary" :icon="Edit" circle @click="editRule(scope.row)"/>
|
||||
<el-popconfirm confirm-button-text="Yes" cancel-button-text="No, Thanks" :icon="InfoFilled"
|
||||
@confirm="delRule(scope.row.id)" icon-color="#626AEF" :title="lang.del_rule_confirm">
|
||||
<template #reference>
|
||||
<el-button size="small" type="danger" :icon="Delete" circle />
|
||||
<el-button size="small" type="danger" :icon="Delete" circle/>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
@ -29,58 +29,56 @@
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<el-dialog v-model="dialogVisible" :title="lang.new_rule" width="60%">
|
||||
<div style="text-align: left; padding-left: 20px;">
|
||||
<el-form v-model="addRuleForm" :inline="true" label-position="top">
|
||||
<el-form-item style="width: 400px;" :label="lang.rule_name">
|
||||
<el-input v-model="addRuleForm.name" />
|
||||
<el-input v-model="addRuleForm.name"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="lang.rule_priority">
|
||||
<el-input v-model="addRuleForm.sort" type="number" oninput="value=value.replace(/[^\-\d]/g, '')" />
|
||||
<el-input v-model="addRuleForm.sort" type="number" oninput="value=value.replace(/[^\-\d]/g, '')"/>
|
||||
</el-form-item>
|
||||
<el-divider />
|
||||
<el-divider/>
|
||||
<div style="width: 100%;">{{ lang.rule_desc }}</div>
|
||||
<div style="width: 100%;">
|
||||
<div v-for="(rule, index) in addRuleForm.rules">
|
||||
<div v-for="(rule, index) in addRuleForm.rules" :key="index">
|
||||
<el-select v-model="rule.field" placeholder="Select">
|
||||
<el-option key="From" :label="lang.from" value="From" />
|
||||
<el-option key="Subject" :label="lang.subject" value="Subject" />
|
||||
<el-option key="To" :label="lang.to" value="To" />
|
||||
<el-option key="Cc" :label="lang.cc" value="Cc" />
|
||||
<el-option key="Content" :label="lang.content" value="Content" />
|
||||
<el-option key="From" :label="lang.from" value="From"/>
|
||||
<el-option key="Subject" :label="lang.subject" value="Subject"/>
|
||||
<el-option key="To" :label="lang.to" value="To"/>
|
||||
<el-option key="Cc" :label="lang.cc" value="Cc"/>
|
||||
<el-option key="Content" :label="lang.content" value="Content"/>
|
||||
</el-select>
|
||||
|
||||
<el-select v-model="rule.type" placeholder="Select">
|
||||
<el-option key="equal" :label="lang.equal" value="equal" />
|
||||
<el-option key="contains" :label="lang.contains" value="contains" />
|
||||
<el-option key="regex" :label="lang.regex" value="regex" />
|
||||
<el-option key="equal" :label="lang.equal" value="equal"/>
|
||||
<el-option key="contains" :label="lang.contains" value="contains"/>
|
||||
<el-option key="regex" :label="lang.regex" value="regex"/>
|
||||
</el-select>
|
||||
|
||||
<el-input v-model="rule.rule" style="width: 350px;" />
|
||||
<el-button size="small" type="danger" :icon="Delete" @click="removeRuleLine(index)" circle />
|
||||
<el-input v-model="rule.rule" style="width: 350px;"/>
|
||||
<el-button size="small" type="danger" :icon="Delete" @click="removeRuleLine(index)" circle/>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding-top: 7px;">
|
||||
<el-button size="small" type="primary" :icon="Plus" circle @click="addRule()" />
|
||||
<el-button size="small" type="primary" :icon="Plus" circle @click="addRule()"/>
|
||||
</div>
|
||||
<el-divider />
|
||||
<el-divider/>
|
||||
<div style="width: 100%;">{{ lang.rule_do }}</div>
|
||||
<el-form-item>
|
||||
<el-select v-model="addRuleForm.action" placeholder="Select" @change="ruleTypeChange()">
|
||||
<el-option key="mark_read" :label="lang.mark_read" :value="READ" />
|
||||
<el-option key="move" :label="lang.move" :value="MOVE" />
|
||||
<el-option key="delete" :label="lang.delete" :value="DELETE" />
|
||||
<el-option key="forward" :label="lang.forward" :value="FORWARD" />
|
||||
<el-option key="mark_read" :label="lang.mark_read" :value="READ"/>
|
||||
<el-option key="move" :label="lang.move" :value="MOVE"/>
|
||||
<el-option key="delete" :label="lang.delete" :value="DELETE"/>
|
||||
<el-option key="forward" :label="lang.forward" :value="FORWARD"/>
|
||||
</el-select>
|
||||
<el-select v-if="addRuleForm.action == 4" v-model="addRuleForm.params" @click="reflushGroupInfos">
|
||||
<el-option v-for="gp in groupData.list" :key="gp.id" :label="gp.name" :value="gp.id" />
|
||||
<el-select v-if="addRuleForm.action === 4" v-model="addRuleForm.params" @click="reflushGroupInfos">
|
||||
<el-option v-for="gp in groupData.list" :key="gp.id" :label="gp.name" :value="gp.id"/>
|
||||
</el-select>
|
||||
|
||||
<el-input v-if="addRuleForm.action == 2" v-model="addRuleForm.params" style="width: 250px;"
|
||||
placeholder="Forward Email Address" />
|
||||
<el-input v-if="addRuleForm.action === 2" v-model="addRuleForm.params" style="width: 250px;"
|
||||
placeholder="Forward Email Address"/>
|
||||
|
||||
</el-form-item>
|
||||
|
||||
@ -97,19 +95,11 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue';
|
||||
import {reactive, ref} from 'vue';
|
||||
import lang from '../i18n/i18n';
|
||||
import {
|
||||
Plus,
|
||||
Delete,
|
||||
Edit,
|
||||
InfoFilled
|
||||
} from '@element-plus/icons-vue'
|
||||
|
||||
|
||||
import { getCurrentInstance } from 'vue'
|
||||
const app = getCurrentInstance()
|
||||
const $http = app.appContext.config.globalProperties.$http
|
||||
import {Delete, Edit, InfoFilled, Plus} from '@element-plus/icons-vue'
|
||||
import {http} from "@/utils/axios";
|
||||
import {ElNotification} from "element-plus";
|
||||
|
||||
const data = ref([])
|
||||
const dialogVisible = ref(false)
|
||||
@ -126,7 +116,7 @@ const ActionName = {
|
||||
}
|
||||
|
||||
const init = function () {
|
||||
$http.post("/api/rule/get").then((res) => {
|
||||
http.post("/api/rule/get").then((res) => {
|
||||
data.value = res.data
|
||||
})
|
||||
}
|
||||
@ -138,7 +128,7 @@ const groupData = reactive({
|
||||
})
|
||||
|
||||
const reflushGroupInfos = function () {
|
||||
$http.get('/api/group/list').then(res => {
|
||||
http.get('/api/group/list').then(res => {
|
||||
if (res.data != null) {
|
||||
groupData.list = res.data
|
||||
for (let i = 0; i < groupData.list.length; i++) {
|
||||
@ -167,11 +157,11 @@ const addRuleForm = reactive({
|
||||
})
|
||||
|
||||
const delRule = function (id) {
|
||||
$http.post("/api/rule/del", { "id": id }).then((res) => {
|
||||
http.post("/api/rule/del", {"id": id}).then((res) => {
|
||||
ElNotification({
|
||||
title: res.errorNo == 0 ? lang.succ : lang.fail,
|
||||
title: res.errorNo === 0 ? lang.succ : lang.fail,
|
||||
message: res.data,
|
||||
type: res.errorNo == 0 ? 'success' : 'error',
|
||||
type: res.errorNo === 0 ? 'success' : 'error',
|
||||
})
|
||||
|
||||
init()
|
||||
@ -210,8 +200,8 @@ const submitRule = function () {
|
||||
|
||||
addRuleForm.sort = parseInt(addRuleForm.sort)
|
||||
|
||||
$http.post(api, addRuleForm).then((res) => {
|
||||
if (res.errorNo != 0) {
|
||||
http.post(api, addRuleForm).then((res) => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElNotification({
|
||||
title: lang.fail,
|
||||
message: res.data,
|
||||
@ -238,7 +228,6 @@ const submitRule = function () {
|
||||
}
|
||||
|
||||
|
||||
|
||||
const ruleTypeChange = function () {
|
||||
addRuleForm.params = ''
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<el-form :model="ruleForm" :rules="rules" status-icon>
|
||||
|
||||
<el-divider content-position="left">{{lang.modify_pwd}}</el-divider>
|
||||
<el-divider content-position="left">{{ lang.modify_pwd }}</el-divider>
|
||||
|
||||
<el-form-item :label="lang.modify_pwd" prop="new_pwd">
|
||||
<el-input type="password" v-model="ruleForm.new_pwd" />
|
||||
<el-input type="password" v-model="ruleForm.new_pwd"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="lang.enter_again" prop="new_pwd2">
|
||||
<el-input type="password" v-model="ruleForm.new_pwd2" />
|
||||
<el-input type="password" v-model="ruleForm.new_pwd2"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
@ -17,7 +17,7 @@
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider content-position="left">{{lang.logout}}</el-divider>
|
||||
<el-divider content-position="left">{{ lang.logout }}</el-divider>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="logout">
|
||||
{{ lang.logout }}
|
||||
@ -27,13 +27,10 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { ElNotification } from 'element-plus'
|
||||
import {reactive} from 'vue'
|
||||
import {ElNotification} from 'element-plus'
|
||||
import lang from '../i18n/i18n';
|
||||
|
||||
import { getCurrentInstance } from 'vue'
|
||||
const app = getCurrentInstance()
|
||||
const $http = app.appContext.config.globalProperties.$http
|
||||
import {http} from "@/utils/axios";
|
||||
|
||||
const ruleForm = reactive({
|
||||
new_pwd: "",
|
||||
@ -41,24 +38,24 @@ const ruleForm = reactive({
|
||||
})
|
||||
|
||||
const rules = reactive({
|
||||
new_pwd: [{ required: true, message: lang.err_required_pwd, trigger: 'blur' },],
|
||||
new_pwd2: [{ required: true, message: lang.err_required_pwd, trigger: 'blur' },],
|
||||
new_pwd: [{required: true, message: lang.err_required_pwd, trigger: 'blur'},],
|
||||
new_pwd2: [{required: true, message: lang.err_required_pwd, trigger: 'blur'},],
|
||||
|
||||
})
|
||||
|
||||
const logout = function(){
|
||||
$http.post("/api/logout", { }).then(res => {
|
||||
const logout = function () {
|
||||
http.post("/api/logout", {}).then(() => {
|
||||
location.reload();
|
||||
})
|
||||
}
|
||||
|
||||
const submit = function () {
|
||||
if (ruleForm.new_pwd == ""){
|
||||
if (ruleForm.new_pwd === "") {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (ruleForm.new_pwd != ruleForm.new_pwd2) {
|
||||
if (ruleForm.new_pwd !== ruleForm.new_pwd2) {
|
||||
ElNotification({
|
||||
title: 'Error',
|
||||
message: lang.err_pwd_diff,
|
||||
@ -66,11 +63,11 @@ const submit = function () {
|
||||
})
|
||||
return
|
||||
}
|
||||
$http.post("/api/settings/modify_password", { password: ruleForm.new_pwd }).then(res => {
|
||||
http.post("/api/settings/modify_password", {password: ruleForm.new_pwd}).then(res => {
|
||||
ElNotification({
|
||||
title: res.errorNo == 0 ? lang.succ : lang.fail,
|
||||
title: res.errorNo === 0 ? lang.succ : lang.fail,
|
||||
message: res.data,
|
||||
type: res.errorNo == 0 ? 'success' : 'error',
|
||||
type: res.errorNo === 0 ? 'success' : 'error',
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div id="main">
|
||||
<el-table :data="userList" style="width: 100%">
|
||||
<el-table-column label="ID" prop="ID" />
|
||||
<el-table-column :label="lang.account" prop="Account" />
|
||||
<el-table-column :label="lang.user_name" prop="Name" />
|
||||
<el-table-column label="ID" prop="ID"/>
|
||||
<el-table-column :label="lang.account" prop="Account"/>
|
||||
<el-table-column :label="lang.user_name" prop="Name"/>
|
||||
<el-table-column :label="lang.disabled" prop="Disabled">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.Disabled == 1 ? lang.disabled : lang.enabled }}</span>
|
||||
<span>{{ scope.row.Disabled === 1 ? lang.disabled : lang.enabled }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="right">
|
||||
@ -24,30 +24,29 @@
|
||||
</el-table>
|
||||
<div id="paginationBox">
|
||||
<el-pagination v-model:current-page="currentPage" small background layout="prev, pager, next"
|
||||
:page-count="totalPage" class="mt-4" @current-change="reflushList" />
|
||||
:page-count="totalPage" class="mt-4" @current-change="reflushList"/>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<el-dialog v-model="userInfoDialog" :title="title" width="500">
|
||||
<el-form>
|
||||
<el-form-item label-width="100px" :label="lang.account">
|
||||
<el-input :disabled="editModel == 'edit'" v-model="editUserInfo.account" autocomplete="off" />
|
||||
<el-input :disabled="editModel === 'edit'" v-model="editUserInfo.account" autocomplete="off"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label-width="100px" :label="lang.user_name">
|
||||
<el-input v-model="editUserInfo.name" autocomplete="off" />
|
||||
<el-input v-model="editUserInfo.name" autocomplete="off"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label-width="100px" :label="lang.password">
|
||||
<el-input :placeholder="lang.resetPwd" v-model="editUserInfo.password" autocomplete="off" />
|
||||
<el-input :placeholder="lang.resetPwd" v-model="editUserInfo.password" autocomplete="off"/>
|
||||
</el-form-item>
|
||||
|
||||
<div style="display: flex;">
|
||||
<div
|
||||
style="display: inline-flex;justify-content: flex-end;align-items: flex-start;flex: 0 0 auto;font-size: var(--el-form-label-font-size); height: 32px;line-height: 32px;padding: 0 12px 0 60px;box-sizing: border-box; ">
|
||||
<el-switch v-model="editUserInfo.disabled" class="ml-2" :active-text="lang.disabled"
|
||||
:inactive-text="lang.enabled" />
|
||||
:inactive-text="lang.enabled"/>
|
||||
</div>
|
||||
|
||||
|
||||
@ -70,11 +69,12 @@
|
||||
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, getCurrentInstance } from 'vue'
|
||||
import {reactive, ref} from 'vue'
|
||||
import lang from '../i18n/i18n';
|
||||
import {http} from "@/utils/axios";
|
||||
import {ElNotification} from "element-plus";
|
||||
|
||||
const userList = reactive([])
|
||||
const app = getCurrentInstance()
|
||||
const $http = app.appContext.config.globalProperties.$http
|
||||
const currentPage = ref(1)
|
||||
const totalPage = ref(1)
|
||||
const userInfoDialog = ref(false)
|
||||
@ -88,7 +88,7 @@ const editUserInfo = reactive({
|
||||
const title = ref(lang.editUser)
|
||||
|
||||
const reflushList = function () {
|
||||
$http.post('/api/user/list', { "current_page": currentPage.value, "page_size": 10 }).then(res => {
|
||||
http.post('/api/user/list', {"current_page": currentPage.value, "page_size": 10}).then(res => {
|
||||
userList.length = 0
|
||||
|
||||
totalPage.value = res.data.total_page
|
||||
@ -100,14 +100,14 @@ const reflushList = function () {
|
||||
const handleEdit = function (idx, row) {
|
||||
editUserInfo.account = row.Account
|
||||
editUserInfo.name = row.Name
|
||||
editUserInfo.disabled = row.Disabled == 1
|
||||
editUserInfo.disabled = row.Disabled === 1
|
||||
editUserInfo.password = ""
|
||||
editModel.value = "edit"
|
||||
title.value = lang.editUser
|
||||
userInfoDialog.value = true
|
||||
}
|
||||
|
||||
const createUser = function(){
|
||||
const createUser = function () {
|
||||
editUserInfo.account = ""
|
||||
editUserInfo.name = ""
|
||||
editUserInfo.disabled = false
|
||||
@ -119,50 +119,48 @@ const createUser = function(){
|
||||
|
||||
|
||||
const submit = function () {
|
||||
if (editModel.value == 'edit') {
|
||||
if (editModel.value === 'edit') {
|
||||
|
||||
let newData = {
|
||||
"account": editUserInfo.account,
|
||||
"username": editUserInfo.name,
|
||||
"disabled": editUserInfo.disabled ? 1 : 0
|
||||
}
|
||||
if (editUserInfo.password != "") {
|
||||
if (editUserInfo.password !== "") {
|
||||
newData["password"] = editUserInfo.password
|
||||
}
|
||||
|
||||
$http.post('/api/user/edit', newData).then(res => {
|
||||
http.post('/api/user/edit', newData).then(res => {
|
||||
ElNotification({
|
||||
title: res.errorNo == 0 ? lang.succ : lang.fail,
|
||||
message: res.errorNo == 0 ? "" : res.data,
|
||||
type: res.errorNo == 0 ? 'success' : 'error',
|
||||
title: res.errorNo === 0 ? lang.succ : lang.fail,
|
||||
message: res.errorNo === 0 ? "" : res.data,
|
||||
type: res.errorNo === 0 ? 'success' : 'error',
|
||||
})
|
||||
if (res.errorNo == 0) {
|
||||
if (res.errorNo === 0) {
|
||||
reflushList()
|
||||
userInfoDialog.value = false
|
||||
}
|
||||
})
|
||||
}else{
|
||||
} else {
|
||||
let newData = {
|
||||
"account": editUserInfo.account,
|
||||
"username": editUserInfo.name,
|
||||
"disabled": editUserInfo.disabled ? 1 : 0,
|
||||
"password":editUserInfo.password
|
||||
"password": editUserInfo.password
|
||||
}
|
||||
|
||||
$http.post('/api/user/create', newData).then(res => {
|
||||
http.post('/api/user/create', newData).then(res => {
|
||||
ElNotification({
|
||||
title: res.errorNo == 0 ? lang.succ : lang.fail,
|
||||
message: res.errorNo == 0 ? "" : res.data,
|
||||
type: res.errorNo == 0 ? 'success' : 'error',
|
||||
title: res.errorNo === 0 ? lang.succ : lang.fail,
|
||||
message: res.errorNo === 0 ? "" : res.data,
|
||||
type: res.errorNo === 0 ? 'success' : 'error',
|
||||
})
|
||||
if (res.errorNo == 0) {
|
||||
if (res.errorNo === 0) {
|
||||
reflushList()
|
||||
userInfoDialog.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
var lang = {
|
||||
let lang = {
|
||||
"logout": "Logout",
|
||||
"resetPwd": "Reset the account password",
|
||||
"disabled": "Disabled",
|
||||
@ -71,11 +71,11 @@ var lang = {
|
||||
"ssl_auto": "Automatically configure SSL certificates (recommended)",
|
||||
"wait_desc": "Please Wait.",
|
||||
"dns_challenge_wait": "DNS propagation and cache refreshes take a long time, and a wait of 10-30 minutes is possible here.",
|
||||
"ssl_challenge_type":"Challenge Type",
|
||||
"ssl_auto_http":"Http Request",
|
||||
"ssl_auto_dns":"DNS Records",
|
||||
"ssl_challenge_type": "Challenge Type",
|
||||
"ssl_auto_http": "Http Request",
|
||||
"ssl_auto_dns": "DNS Records",
|
||||
"challenge_typ_desc": "If PMail uses port 80 directly, it is recommended that you use the HTTP challenge method.",
|
||||
"oomain_service_provider":"Domain Name Service Provider",
|
||||
"oomain_service_provider": "Domain Name Service Provider",
|
||||
"ssl_manuallyf": "Manually configure an SSL certificate",
|
||||
"ssl_key_path": "ssl key file path",
|
||||
"ssl_crt_path": "ssl crt file path",
|
||||
@ -86,32 +86,31 @@ var lang = {
|
||||
"del_btn": "Delete",
|
||||
"move_btn": "Move",
|
||||
"read_btn": "Readed",
|
||||
"dangerous":"The content of this email is not secure!",
|
||||
"rule_setting":"Rules",
|
||||
"new_rule":"New mail receiving rules",
|
||||
"rule_name":"Rule Name",
|
||||
"rule_priority":"Rule Priority(Larger values are executed first)",
|
||||
"rule_desc":"When a new message arrives that meets all these conditions:",
|
||||
"rule_do":"Do the following:",
|
||||
"from":"From Email Address",
|
||||
"subject":"Email Subject",
|
||||
"content":"Email Content",
|
||||
"equal":"Equal",
|
||||
"regex":"Regex Match",
|
||||
"contains":"Contains",
|
||||
"mark_read":"Mark Read",
|
||||
"delete":"Delete",
|
||||
"forward":"Forward",
|
||||
"move":"Move to group",
|
||||
"del_rule_confirm":"Are you sure to delete this?",
|
||||
"rule_params":"Executed params",
|
||||
"dangerous": "The content of this email is not secure!",
|
||||
"rule_setting": "Rules",
|
||||
"new_rule": "New mail receiving rules",
|
||||
"rule_name": "Rule Name",
|
||||
"rule_priority": "Rule Priority(Larger values are executed first)",
|
||||
"rule_desc": "When a new message arrives that meets all these conditions:",
|
||||
"rule_do": "Do the following:",
|
||||
"from": "From Email Address",
|
||||
"subject": "Email Subject",
|
||||
"content": "Email Content",
|
||||
"equal": "Equal",
|
||||
"regex": "Regex Match",
|
||||
"contains": "Contains",
|
||||
"mark_read": "Mark Read",
|
||||
"delete": "Delete",
|
||||
"forward": "Forward",
|
||||
"move": "Move to group",
|
||||
"del_rule_confirm": "Are you sure to delete this?",
|
||||
"rule_params": "Executed params",
|
||||
"autoSSLWarn": "PMail is not currently running on port 80. If you want PMail to manage SSL certificates automatically, please forward the /.well-known/* route to PMail. See https://github.com/Jinnrry/PMail/issues/94 for details.",
|
||||
"err_db_dsn_empty": "Database path cannot be empty!",
|
||||
};
|
||||
|
||||
|
||||
|
||||
var zhCN = {
|
||||
const zhCN = {
|
||||
"logout": "注销",
|
||||
"resetPwd": "重置账号密码",
|
||||
"disabled": "禁用",
|
||||
@ -182,10 +181,10 @@ var zhCN = {
|
||||
"web_domain": "Web域名地址",
|
||||
"dns_desc": "请将以下信息添加到DNS记录中",
|
||||
"ssl_auto": "自动配置SSL证书(推荐)",
|
||||
"oomain_service_provider":"域名服务商",
|
||||
"ssl_auto_http":"HTTP请求",
|
||||
"ssl_auto_dns":"DNS记录",
|
||||
"ssl_challenge_type":"验证方式",
|
||||
"oomain_service_provider": "域名服务商",
|
||||
"ssl_auto_http": "HTTP请求",
|
||||
"ssl_auto_dns": "DNS记录",
|
||||
"ssl_challenge_type": "验证方式",
|
||||
"ssl_manuallyf": "手动配置SSL证书",
|
||||
"challenge_typ_desc": "如果PMail直接使用80端口,建议使用HTTP验证方式。",
|
||||
"wait_desc": "请稍等",
|
||||
@ -199,38 +198,29 @@ var zhCN = {
|
||||
"del_btn": "删除",
|
||||
"move_btn": "移动",
|
||||
"read_btn": "已读",
|
||||
"dangerous":"该邮件内容不安全!",
|
||||
"rule_setting":"规则",
|
||||
"new_rule":"新建收信规则",
|
||||
"rule_name":"规则名称",
|
||||
"rule_priority":"优先级(值越大越先执行)",
|
||||
"rule_desc":"以下规则全部满足时:",
|
||||
"rule_do":"执行操作:",
|
||||
"from":"发件人地址",
|
||||
"subject":"邮件主题",
|
||||
"content":"邮件内容",
|
||||
"equal":"等于",
|
||||
"regex":"正则匹配",
|
||||
"contains":"包含",
|
||||
"mark_read":"标记已读",
|
||||
"delete":"删除",
|
||||
"forward":"转发",
|
||||
"move":"移动分组",
|
||||
"del_rule_confirm":"确定要删除吗?",
|
||||
"rule_params":"执行参数",
|
||||
"dangerous": "该邮件内容不安全!",
|
||||
"rule_setting": "规则",
|
||||
"new_rule": "新建收信规则",
|
||||
"rule_name": "规则名称",
|
||||
"rule_priority": "优先级(值越大越先执行)",
|
||||
"rule_desc": "以下规则全部满足时:",
|
||||
"rule_do": "执行操作:",
|
||||
"from": "发件人地址",
|
||||
"subject": "邮件主题",
|
||||
"content": "邮件内容",
|
||||
"equal": "等于",
|
||||
"regex": "正则匹配",
|
||||
"contains": "包含",
|
||||
"mark_read": "标记已读",
|
||||
"delete": "删除",
|
||||
"forward": "转发",
|
||||
"move": "移动分组",
|
||||
"del_rule_confirm": "确定要删除吗?",
|
||||
"rule_params": "执行参数",
|
||||
"autoSSLWarn": "PMail当前未使用80端口启动,如果想要PMail自动管理SSL证书,请将/.well-known/*路由转发到PMail。 详见https://github.com/Jinnrry/PMail/issues/94",
|
||||
"err_db_dsn_empty": "数据库路径不能为空!",
|
||||
}
|
||||
|
||||
switch (navigator.language) {
|
||||
case "zh":
|
||||
lang = zhCN
|
||||
break
|
||||
case "zh-CN":
|
||||
lang = zhCN
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
if (navigator.language === "zh-CN" || navigator.language === "zh") lang = zhCN
|
||||
|
||||
export default lang;
|
113
fe/src/main.js
113
fe/src/main.js
@ -3,119 +3,10 @@ import 'element-plus/dist/index.css'
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import {ref} from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import {router} from './router'
|
||||
|
||||
const app = createApp(App)
|
||||
app.config.globalProperties.$isLogin = ref(true)
|
||||
app.config.globalProperties.$userInfos = ref({})
|
||||
app.use(createPinia())
|
||||
app.use(router)
|
||||
|
||||
|
||||
|
||||
import axios from 'axios'
|
||||
import lang from './i18n/i18n';
|
||||
//创建axios的一个实例
|
||||
var $http = axios.create({
|
||||
baseURL: import.meta.env.VITE_APP_URL, //接口统一域名
|
||||
timeout: 60000, //设置超时
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=UTF-8;',
|
||||
'Lang': lang.lang
|
||||
}
|
||||
})
|
||||
|
||||
//请求拦截器
|
||||
$http.interceptors.request.use((config) => {
|
||||
//若请求方式为post,则将data参数转为JSON字符串
|
||||
if (config.method === 'POST') {
|
||||
config.data = JSON.stringify(config.data);
|
||||
}
|
||||
return config;
|
||||
}, (error) =>
|
||||
// 对请求错误做些什么
|
||||
Promise.reject(error));
|
||||
|
||||
//响应拦截器
|
||||
$http.interceptors.response.use((response) => {
|
||||
//响应成功
|
||||
if (response.data.errorNo == 403) {
|
||||
app.config.globalProperties.$isLogin.value = false
|
||||
|
||||
router.replace({
|
||||
path: '/login',
|
||||
query: {
|
||||
redirect: router.currentRoute.fullPath
|
||||
}
|
||||
})
|
||||
}
|
||||
//响应成功
|
||||
if (response.data.errorNo == 402) {
|
||||
router.replace({
|
||||
path: '/setup',
|
||||
query: {
|
||||
redirect: router.currentRoute.fullPath
|
||||
}
|
||||
})
|
||||
}
|
||||
return response.data;
|
||||
}, (error) => {
|
||||
//响应错误
|
||||
if (error.response && error.response.status) {
|
||||
const status = error.response.status
|
||||
let message = ""
|
||||
switch (status) {
|
||||
case 400:
|
||||
message = '请求错误';
|
||||
break;
|
||||
case 401:
|
||||
message = '请求错误';
|
||||
break;
|
||||
case 403:
|
||||
router.replace({
|
||||
path: '/login',
|
||||
query: {
|
||||
redirect: router.currentRoute.fullPath
|
||||
}
|
||||
})
|
||||
break;
|
||||
case 404:
|
||||
message = '请求地址出错';
|
||||
break;
|
||||
case 408:
|
||||
message = '请求超时';
|
||||
break;
|
||||
case 500:
|
||||
message = '服务器内部错误!';
|
||||
break;
|
||||
case 501:
|
||||
message = '服务未实现!';
|
||||
break;
|
||||
case 502:
|
||||
message = '网关错误!';
|
||||
break;
|
||||
case 503:
|
||||
message = '服务不可用!';
|
||||
break;
|
||||
case 504:
|
||||
message = '网关超时!';
|
||||
break;
|
||||
case 505:
|
||||
message = 'HTTP版本不受支持';
|
||||
break;
|
||||
default:
|
||||
message = '请求失败'
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
|
||||
// 注册到全局
|
||||
app.config.globalProperties.$http = $http
|
||||
|
||||
app.use(createPinia())
|
||||
app.mount('#app')
|
||||
|
||||
|
@ -46,4 +46,4 @@ const router = createRouter({
|
||||
|
||||
|
||||
|
||||
export default router
|
||||
export {router};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import lang from '../i18n/i18n';
|
||||
|
||||
|
15
fe/src/stores/useGlobalStatusStore.js
Normal file
15
fe/src/stores/useGlobalStatusStore.js
Normal file
@ -0,0 +1,15 @@
|
||||
import {defineStore} from "pinia";
|
||||
|
||||
const useGlobalStatusStore = defineStore('useGlobalStatusStore', {
|
||||
state() {
|
||||
return {
|
||||
isLogin: true,
|
||||
userInfos:{}
|
||||
}
|
||||
},
|
||||
getters: {},
|
||||
actions: {}
|
||||
})
|
||||
|
||||
|
||||
export {useGlobalStatusStore};
|
103
fe/src/utils/axios.js
Normal file
103
fe/src/utils/axios.js
Normal file
@ -0,0 +1,103 @@
|
||||
import axios from 'axios'
|
||||
import lang from '../i18n/i18n';
|
||||
import {useGlobalStatusStore} from "@/stores/useGlobalStatusStore";
|
||||
import {router} from "@/router";
|
||||
|
||||
//创建axios的一个实例
|
||||
const http = axios.create({
|
||||
baseURL: import.meta.env.VITE_APP_URL, //接口统一域名
|
||||
timeout: 60000, //设置超时
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=UTF-8;',
|
||||
'Lang': lang.lang
|
||||
}
|
||||
});
|
||||
|
||||
//请求拦截器
|
||||
http.interceptors.request.use((config) => {
|
||||
//若请求方式为post,则将data参数转为JSON字符串
|
||||
if (config.method === 'POST') {
|
||||
config.data = JSON.stringify(config.data);
|
||||
}
|
||||
return config;
|
||||
}, (error) =>
|
||||
// 对请求错误做些什么
|
||||
Promise.reject(error));
|
||||
|
||||
//响应拦截器
|
||||
http.interceptors.response.use(async (response) => {
|
||||
const globalStatus = useGlobalStatusStore();
|
||||
//响应成功
|
||||
if (response.data.errorNo === 403) {
|
||||
globalStatus.isLogin = false
|
||||
|
||||
await router.replace({
|
||||
path: '/login',
|
||||
query: {
|
||||
redirect: router.currentRoute.fullPath
|
||||
}
|
||||
});
|
||||
}
|
||||
//响应成功
|
||||
if (response.data.errorNo === 402) {
|
||||
await router.replace({
|
||||
path: '/setup',
|
||||
query: {
|
||||
redirect: router.currentRoute.fullPath
|
||||
}
|
||||
});
|
||||
}
|
||||
return response.data;
|
||||
}, async (error) => {
|
||||
//响应错误
|
||||
if (error.response && error.response.status) {
|
||||
let message = ""
|
||||
switch (error.response.status) {
|
||||
case 400:
|
||||
message = '请求错误';
|
||||
break;
|
||||
case 401:
|
||||
message = '请求错误';
|
||||
break;
|
||||
case 403:
|
||||
await router.replace({
|
||||
path: '/login',
|
||||
query: {
|
||||
redirect: router.currentRoute.fullPath
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 404:
|
||||
message = '请求地址出错';
|
||||
break;
|
||||
case 408:
|
||||
message = '请求超时';
|
||||
break;
|
||||
case 500:
|
||||
message = '服务器内部错误!';
|
||||
break;
|
||||
case 501:
|
||||
message = '服务未实现!';
|
||||
break;
|
||||
case 502:
|
||||
message = '网关错误!';
|
||||
break;
|
||||
case 503:
|
||||
message = '服务不可用!';
|
||||
break;
|
||||
case 504:
|
||||
message = '网关超时!';
|
||||
break;
|
||||
case 505:
|
||||
message = 'HTTP版本不受支持';
|
||||
break;
|
||||
default:
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
message = '请求失败';
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
export {http};
|
@ -15,18 +15,18 @@
|
||||
<div style="display: flex; flex-direction:column;">
|
||||
<div style=" margin-bottom: 10px;">
|
||||
<el-form-item :label="lang.sender" prop="sender">
|
||||
<el-input style="max-width: 200px" :disabled="!$userInfos.is_admin"
|
||||
v-model="ruleForm.sender" :placeholder="lang.sender_desc" />
|
||||
<el-input style="max-width: 200px" :disabled="!userInfos.is_admin"
|
||||
v-model="ruleForm.sender" :placeholder="lang.sender_desc"/>
|
||||
<div>@</div>
|
||||
<el-select v-model="ruleForm.pickDomain">
|
||||
<el-option :value="item" v-for="item in ruleForm.domains">{{ item }}</el-option>
|
||||
<el-option :value="item" v-for="item in ruleForm.domains" :key="item">{{ item }}</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<el-form-item :label="lang.nick_name" >
|
||||
<el-input style="max-width: 300px" v-model="ruleForm.nickName" />
|
||||
<el-form-item :label="lang.nick_name">
|
||||
<el-input style="max-width: 300px" v-model="ruleForm.nickName"/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
@ -57,17 +57,19 @@
|
||||
<div id="editor">
|
||||
<div style="border: 1px solid #ccc">
|
||||
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig"
|
||||
:mode="mode" />
|
||||
:mode="mode"/>
|
||||
<Editor style="height: 300px;" v-model="valueHtml" :defaultConfig="editorConfig" :mode="mode"
|
||||
@onCreated="handleCreated" />
|
||||
@onCreated="handleCreated"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="fileList">
|
||||
<ol>
|
||||
<li v-for="(item, index) in fileList">{{ item.name }} <el-icon @click="delFile(index)">
|
||||
<Close />
|
||||
</el-icon> </li>
|
||||
<li v-for="(item, index) in fileList" :key="item">{{ item.name }}
|
||||
<el-icon @click="delFile(index)">
|
||||
<Close/>
|
||||
</el-icon>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
@ -81,8 +83,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
@ -108,30 +108,31 @@
|
||||
|
||||
<script setup>
|
||||
import '@wangeditor/editor/dist/css/style.css' // 引入 css
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { onBeforeUnmount, ref, shallowRef, reactive, onMounted } from 'vue'
|
||||
import { Close } from '@element-plus/icons-vue';
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {onBeforeUnmount, reactive, ref, shallowRef} from 'vue'
|
||||
import {Close} from '@element-plus/icons-vue';
|
||||
import lang from '../i18n/i18n';
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
import { i18nChangeLanguage } from '@wangeditor/editor'
|
||||
import { useRouter } from 'vue-router';
|
||||
const router = useRouter();
|
||||
import {Editor, Toolbar} from '@wangeditor/editor-for-vue'
|
||||
import {i18nChangeLanguage} from '@wangeditor/editor'
|
||||
import {useRouter} from 'vue-router';
|
||||
import {http} from "@/utils/axios";
|
||||
import useGroupStore from '../stores/group'
|
||||
const groupStore = useGroupStore()
|
||||
import { getCurrentInstance } from 'vue'
|
||||
const app = getCurrentInstance()
|
||||
const $http = app.appContext.config.globalProperties.$http
|
||||
const $isLogin = app.appContext.config.globalProperties.$isLogin
|
||||
const $userInfos = app.appContext.config.globalProperties.$userInfos
|
||||
import {useGlobalStatusStore} from "@/stores/useGlobalStatusStore";
|
||||
|
||||
if (lang.lang == "zhCn") {
|
||||
const router = useRouter();
|
||||
|
||||
const groupStore = useGroupStore()
|
||||
|
||||
const globalStatus = useGlobalStatusStore();
|
||||
const userInfos = globalStatus.userInfos
|
||||
|
||||
if (lang.lang === "zhCn") {
|
||||
i18nChangeLanguage('zh-CN')
|
||||
} else {
|
||||
i18nChangeLanguage('en')
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 内容 HTML
|
||||
const valueHtml = ref('<p>hello</p>')
|
||||
|
||||
@ -147,7 +148,6 @@ editorConfig.MENU_CONF['uploadImage'] = {
|
||||
}
|
||||
const mode = ref()
|
||||
const fileRef = ref();
|
||||
const pickFile = ref();
|
||||
const ruleFormRef = ref()
|
||||
const ruleForm = reactive({
|
||||
nickName: '',
|
||||
@ -162,10 +162,10 @@ const fileList = reactive([]);
|
||||
|
||||
|
||||
const init = function () {
|
||||
if (Object.keys($userInfos.value).length == 0) {
|
||||
$http.post("/api/user/info", {}).then(res => {
|
||||
if (res.errorNo == 0) {
|
||||
$userInfos.value = res.data
|
||||
if (Object.keys(userInfos.value).length === 0) {
|
||||
http.post("/api/user/info", {}).then(res => {
|
||||
if (res.errorNo === 0) {
|
||||
userInfos.value = res.data
|
||||
ruleForm.sender = res.data.account
|
||||
ruleForm.domains = res.data.domains
|
||||
ruleForm.pickDomain = res.data.domains[0]
|
||||
@ -178,10 +178,10 @@ const init = function () {
|
||||
}
|
||||
})
|
||||
} else {
|
||||
ruleForm.sender = $userInfos.value.account
|
||||
ruleForm.domains = $userInfos.value.domains
|
||||
ruleForm.pickDomain = $userInfos.value.domains[0]
|
||||
ruleForm.nickName = $userInfos.value.name
|
||||
ruleForm.sender = userInfos.value.account
|
||||
ruleForm.domains = userInfos.value.domains
|
||||
ruleForm.pickDomain = userInfos.value.domains[0]
|
||||
ruleForm.nickName = userInfos.value.name
|
||||
}
|
||||
|
||||
}
|
||||
@ -199,12 +199,8 @@ const validateSender = function (rule, value, callback) {
|
||||
}
|
||||
|
||||
const checkEmail = function (str) {
|
||||
var re = /.+@.+\..+/
|
||||
if (re.test(str)) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
const re = /.+@.+\..+/;
|
||||
return re.test(str);
|
||||
}
|
||||
|
||||
const validateReceivers = function (rule, value, callback) {
|
||||
@ -222,7 +218,7 @@ const validateCc = function (rule, value, callback) {
|
||||
for (let index = 0; index < ruleForm.cc.length; index++) {
|
||||
let element = ruleForm.cc[index];
|
||||
if (!checkEmail(element)) {
|
||||
callback(new Error(err_email_format))
|
||||
callback(new Error(lang.err_email_format))
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -231,16 +227,16 @@ const validateCc = function (rule, value, callback) {
|
||||
|
||||
const rules = reactive({
|
||||
sender: [
|
||||
{ validator: validateSender, trigger: 'change' }
|
||||
{validator: validateSender, trigger: 'change'}
|
||||
],
|
||||
receivers: [
|
||||
{ validator: validateReceivers, trigger: 'change' }
|
||||
{validator: validateReceivers, trigger: 'change'}
|
||||
],
|
||||
cc: [
|
||||
{ validator: validateCc, trigger: 'change' }
|
||||
{validator: validateCc, trigger: 'change'}
|
||||
],
|
||||
subject: [
|
||||
{ required: true, message: lang.err_title_must, trigger: 'change' },
|
||||
{required: true, message: lang.err_title_must, trigger: 'change'},
|
||||
],
|
||||
})
|
||||
|
||||
@ -282,8 +278,8 @@ const send = function (formEl) {
|
||||
|
||||
let text = editorRef.value.getText()
|
||||
|
||||
$http.post("/api/email/send", {
|
||||
from: { name: ruleForm.nickName, email: ruleForm.sender + "@" + ruleForm.pickDomain },
|
||||
http.post("/api/email/send", {
|
||||
from: {name: ruleForm.nickName, email: ruleForm.sender + "@" + ruleForm.pickDomain},
|
||||
to: objectTos,
|
||||
cc: objectCcs,
|
||||
subject: ruleForm.subject,
|
||||
@ -311,13 +307,9 @@ const send = function (formEl) {
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const upload = function () {
|
||||
fileRef.value.dispatchEvent(new MouseEvent('click'))
|
||||
}
|
||||
|
@ -1,24 +1,26 @@
|
||||
<template>
|
||||
<div id="main">
|
||||
<div id="title">{{ detailData.subject }}</div>
|
||||
<el-divider />
|
||||
<el-divider/>
|
||||
|
||||
<div>
|
||||
<div>{{ lang.to }}:
|
||||
<el-tooltip v-for="to in tos" class="box-item" effect="dark" :content="to.EmailAddress" placement="top">
|
||||
<el-tag size="small" type="info">{{to.Name != '' ? to.Name : to.EmailAddress }}</el-tag>
|
||||
<el-tooltip v-for="to in tos" :key.prop="to" class="box-item" effect="dark" :content="to.EmailAddress" placement="top">
|
||||
<el-tag size="small" type="info">{{ to.Name !== '' ? to.Name : to.EmailAddress }}</el-tag>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<div v-if="showCC">{{ lang.cc }}:
|
||||
<el-tooltip v-for="item in ccs" class="box-item" effect="dark" :content="item.EmailAddress" placement="top">
|
||||
<el-tag size="small" type="info">{{item.Name != '' ? item.Name : item.EmailAddress }}</el-tag>
|
||||
<el-tooltip v-for="item in ccs" :key="item" class="box-item" effect="dark" :content="item.EmailAddress" placement="top">
|
||||
<el-tag size="small" type="info">{{ item.Name !== '' ? item.Name : item.EmailAddress }}</el-tag>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<div>{{ lang.sender }}:
|
||||
<el-tooltip class="box-item" effect="dark" :content="detailData.from_address" placement="top">
|
||||
<el-tag size="small" type="info">{{detailData.from_name != '' ? detailData.from_name : detailData.from_address }}</el-tag>
|
||||
<el-tag size="small" type="info">
|
||||
{{ detailData.from_name !== '' ? detailData.from_name : detailData.from_address }}
|
||||
</el-tag>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
@ -26,8 +28,8 @@
|
||||
{{ detailData.send_date }}
|
||||
</div>
|
||||
</div>
|
||||
<el-divider />
|
||||
<div class="content" id="text" v-if="detailData.html == ''">
|
||||
<el-divider/>
|
||||
<div class="content" id="text" v-if="detailData.html === ''">
|
||||
{{ detailData.text }}
|
||||
</div>
|
||||
|
||||
@ -36,12 +38,14 @@
|
||||
</div>
|
||||
|
||||
<div v-if="detailData.attachments.length > 0" style="">
|
||||
<el-divider />
|
||||
<el-divider/>
|
||||
{{ lang.attachment }}:
|
||||
<a class="att" v-for="item in detailData.attachments"
|
||||
:href="'/attachments/download/' + detailData.id + '/' + item.Index"> <el-icon>
|
||||
<Document />
|
||||
</el-icon> {{ item.Filename }} </a>
|
||||
<a class="att" v-for="item in detailData.attachments" :key="item"
|
||||
:href="'/attachments/download/' + detailData.id + '/' + item.Index">
|
||||
<el-icon>
|
||||
<Document/>
|
||||
</el-icon>
|
||||
{{ item.Filename }} </a>
|
||||
</div>
|
||||
|
||||
|
||||
@ -50,38 +54,34 @@
|
||||
|
||||
<script setup>
|
||||
|
||||
import { reactive, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { Document } from '@element-plus/icons-vue';
|
||||
import {ref} from 'vue'
|
||||
import {useRoute} from 'vue-router'
|
||||
import {Document} from '@element-plus/icons-vue';
|
||||
import lang from '../i18n/i18n';
|
||||
|
||||
import { getCurrentInstance } from 'vue'
|
||||
const app = getCurrentInstance()
|
||||
const $http = app.appContext.config.globalProperties.$http
|
||||
|
||||
import {http} from "@/utils/axios";
|
||||
|
||||
const route = useRoute()
|
||||
const detailData = ref({
|
||||
attachments:[]
|
||||
attachments: []
|
||||
})
|
||||
|
||||
const tos = ref()
|
||||
const ccs = ref()
|
||||
const showCC = ref(false)
|
||||
|
||||
$http.post("/api/email/detail", { id: parseInt(route.params.id) }).then(res => {
|
||||
http.post("/api/email/detail", {id: parseInt(route.params.id)}).then(res => {
|
||||
detailData.value = res.data
|
||||
if (res.data.to != "" && res.data.to != null) {
|
||||
if (res.data.to !== "" && res.data.to != null) {
|
||||
tos.value = JSON.parse(res.data.to)
|
||||
}
|
||||
if (res.data.cc != "" && res.data.cc != null) {
|
||||
if (res.data.cc !== "" && res.data.cc != null) {
|
||||
ccs.value = JSON.parse(res.data.cc)
|
||||
|
||||
}
|
||||
|
||||
if (ccs.value != null && ccs.value != undefined){
|
||||
if (ccs.value != null) {
|
||||
showCC.value = ccs.value.length > 0
|
||||
}else{
|
||||
} else {
|
||||
showCC.value = false
|
||||
}
|
||||
})
|
||||
@ -100,18 +100,19 @@ $http.post("/api/email/detail", { id: parseInt(route.params.id) }).then(res => {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#userItem {}
|
||||
#userItem {
|
||||
}
|
||||
|
||||
.content {
|
||||
/* background-color: aliceblue; */
|
||||
}
|
||||
|
||||
a,a:link,a:visited,a:hover,a:active{
|
||||
a, a:link, a:visited, a:hover, a:active {
|
||||
text-decoration: none;
|
||||
color:inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.att{
|
||||
display:block;
|
||||
.att {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
@ -12,20 +12,24 @@
|
||||
<el-dropdown style="margin-left: 12px;">
|
||||
<el-button size="small">
|
||||
{{ lang.move_btn }}
|
||||
<el-icon class="el-icon--right"><arrow-down /></el-icon>
|
||||
<el-icon class="el-icon--right">
|
||||
<EpArrowDownBold />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="move(group.id)" v-for="group in groupList">{{ group.name
|
||||
}}</el-dropdown-item>
|
||||
<el-dropdown-item @click="move(group.id)" v-for="group in groupList" :key="group.id">{{
|
||||
group.name
|
||||
}}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<div id="table">
|
||||
<el-table ref="taskTableDataRef" @selection-change="selectionLineChange" :data="data" :show-header="true"
|
||||
<el-table ref="taskTableDataRef" :data="data" :show-header="true"
|
||||
:border="false" @row-click="rowClick" :row-style="rowStyle">
|
||||
<el-table-column type="selection" width="30" />
|
||||
<el-table-column type="selection" width="30"/>
|
||||
<el-table-column prop="is_read" label="" width="50">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
@ -38,7 +42,7 @@
|
||||
</el-tooltip>
|
||||
|
||||
</span>
|
||||
<span style="font-weight: 900;color: #FF0000;" v-if="scope.row.error != ''">
|
||||
<span style="font-weight: 900;color: #FF0000;" v-if="scope.row.error !== ''">
|
||||
<el-tooltip effect="dark" :content="scope.row.error" placement="top-start">
|
||||
!
|
||||
</el-tooltip>
|
||||
@ -50,15 +54,18 @@
|
||||
<el-table-column prop="title" :label="lang.sender" width="150">
|
||||
<template #default="scope">
|
||||
<el-tooltip class="box-item" effect="dark" :content="scope.row.sender.EmailAddress" placement="top">
|
||||
<el-tag size="small" type="info">{{scope.row.sender.Name != '' ? scope.row.sender.Name : scope.row.sender.EmailAddress }}</el-tag>
|
||||
<el-tag size="small" type="info">
|
||||
{{ scope.row.sender.Name !== '' ? scope.row.sender.Name : scope.row.sender.EmailAddress }}
|
||||
</el-tag>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="title" :label="lang.to" width="150">
|
||||
<template #default="scope">
|
||||
<el-tooltip v-for="toInfo in scope.row.to" class="box-item" effect="dark" :content="toInfo.EmailAddress" placement="top">
|
||||
<el-tag size="small" type="info">{{toInfo.Name != '' ? toInfo.Name : toInfo.EmailAddress }}</el-tag>
|
||||
<el-tooltip v-for="toInfo in scope.row.to" :key="toInfo" class="box-item" effect="dark" :content="toInfo.EmailAddress"
|
||||
placement="top">
|
||||
<el-tag size="small" type="info">{{ toInfo.Name !== '' ? toInfo.Name : toInfo.EmailAddress }}</el-tag>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -81,70 +88,59 @@
|
||||
</el-table>
|
||||
</div>
|
||||
<div id="pagination">
|
||||
<el-pagination background layout="prev, pager, next" :page-count="totalPage" @current-change="pageChange" />
|
||||
<el-pagination background layout="prev, pager, next" :page-count="totalPage" @current-change="pageChange"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
<script setup>
|
||||
|
||||
import { ArrowDown } from '@element-plus/icons-vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import {EpArrowDownBold} from "vue-icons-plus/ep";
|
||||
import {RouterLink, useRouter} from 'vue-router'
|
||||
import {ref, watch} from 'vue'
|
||||
import useGroupStore from '../stores/group'
|
||||
import lang from '../i18n/i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
|
||||
import { getCurrentInstance } from 'vue'
|
||||
const app = getCurrentInstance()
|
||||
const $http = app.appContext.config.globalProperties.$http
|
||||
import {http} from "@/utils/axios";
|
||||
import {ElMessage, ElMessageBox} from "element-plus";
|
||||
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
|
||||
const groupStore = useGroupStore()
|
||||
|
||||
const groupList = ref([])
|
||||
|
||||
const taskTableDataRef = ref(null)
|
||||
|
||||
let tag = groupStore.tag;
|
||||
|
||||
if (tag == "") {
|
||||
if (tag === "") {
|
||||
tag = '{"type":0,"status":-1}'
|
||||
}
|
||||
|
||||
|
||||
watch(groupStore, async (newV, oldV) => {
|
||||
watch(groupStore, async (newV) => {
|
||||
tag = newV.tag;
|
||||
if (tag == "") {
|
||||
if (tag === "") {
|
||||
tag = '{"type":0,"status":-1}'
|
||||
}
|
||||
data.value = []
|
||||
$http.post("/api/email/list", { tag: tag, page_size: 10 }).then(res => {
|
||||
http.post("/api/email/list", {tag: tag, page_size: 10}).then(res => {
|
||||
data.value = res.data.list
|
||||
totalPage.value = res.data.total_page
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
const data = ref([])
|
||||
const totalPage = ref(0)
|
||||
|
||||
const updateList = function () {
|
||||
$http.post("/api/email/list", { tag: tag, page_size: 10 }).then(res => {
|
||||
http.post("/api/email/list", {tag: tag, page_size: 10}).then(res => {
|
||||
data.value = res.data.list
|
||||
totalPage.value = res.data.total_page
|
||||
})
|
||||
}
|
||||
|
||||
const updateGroupList = function () {
|
||||
$http.post("/api/group/list").then(res => {
|
||||
http.post("/api/group/list").then(res => {
|
||||
groupList.value = res.data
|
||||
})
|
||||
}
|
||||
@ -152,7 +148,7 @@ const updateGroupList = function () {
|
||||
updateList()
|
||||
updateGroupList()
|
||||
|
||||
const rowClick = function (row, column, event) {
|
||||
const rowClick = function (row) {
|
||||
router.push("/detail/" + row.id)
|
||||
}
|
||||
|
||||
@ -163,8 +159,8 @@ const markRead = function () {
|
||||
ids.push(element.id)
|
||||
});
|
||||
|
||||
$http.post("/api/email/read", { "ids": ids }).then(res => {
|
||||
if (res.errorNo == 0) {
|
||||
http.post("/api/email/read", {"ids": ids}).then(res => {
|
||||
if (res.errorNo === 0) {
|
||||
updateList()
|
||||
} else {
|
||||
ElMessage({
|
||||
@ -193,8 +189,8 @@ const move = function (group_id) {
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
$http.post("/api/email/move", { "group_id": group_id, "ids": ids }).then(res => {
|
||||
if (res.errorNo == 0) {
|
||||
http.post("/api/email/move", {"group_id": group_id, "ids": ids}).then(res => {
|
||||
if (res.errorNo === 0) {
|
||||
updateList()
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
@ -209,12 +205,10 @@ const move = function (group_id) {
|
||||
})
|
||||
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
const del = function () {
|
||||
let rows = taskTableDataRef.value?.getSelectionRows()
|
||||
let ids = []
|
||||
@ -235,8 +229,8 @@ const del = function () {
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
$http.post("/api/email/del", { "ids": ids ,"forcedDel":groupTag.status == 3 }).then(res => {
|
||||
if (res.errorNo == 0) {
|
||||
http.post("/api/email/del", {"ids": ids, "forcedDel": groupTag.status === 3}).then(res => {
|
||||
if (res.errorNo === 0) {
|
||||
updateList()
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
@ -251,17 +245,16 @@ const del = function () {
|
||||
})
|
||||
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const rowStyle = function ({ row, rowIndwx }) {
|
||||
return { 'cursor': 'pointer' }
|
||||
const rowStyle = function () {
|
||||
return {'cursor': 'pointer'}
|
||||
}
|
||||
|
||||
const pageChange = function (p) {
|
||||
$http.post("/api/email/list", { tag: tag, page_size: 10, current_page: p }).then(res => {
|
||||
http.post("/api/email/list", {tag: tag, page_size: 10, current_page: p}).then(res => {
|
||||
data.value = res.data.list
|
||||
})
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div id="main">
|
||||
<div id="form">
|
||||
<el-form :model="form" label-width="120px" @keyup.enter.native="onSubmit">
|
||||
<el-form :model="form" label-width="120px" @keyup.enter="onSubmit">
|
||||
<el-form-item :label="lang.account">
|
||||
<el-input v-model="form.account" placeholder="User Name" />
|
||||
<el-input v-model="form.account" placeholder="User Name"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="lang.password">
|
||||
<el-input v-model="form.password" placeholder="Password" type="password" />
|
||||
<el-input v-model="form.password" placeholder="Password" type="password"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">{{ lang.login }}</el-button>
|
||||
@ -19,15 +19,17 @@
|
||||
|
||||
<script setup>
|
||||
|
||||
import { reactive } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import router from "@/router"; //根路由对象
|
||||
import {reactive} from 'vue'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {router} from "@/router"; //根路由对象
|
||||
import lang from '../i18n/i18n';
|
||||
import { getCurrentInstance } from 'vue'
|
||||
const app = getCurrentInstance()
|
||||
const $http = app.appContext.config.globalProperties.$http
|
||||
const $isLogin = app.appContext.config.globalProperties.$isLogin
|
||||
const $userInfos = app.appContext.config.globalProperties.$userInfos
|
||||
import {http} from "@/utils/axios";
|
||||
import {useGlobalStatusStore} from "@/stores/useGlobalStatusStore";
|
||||
|
||||
const globalStatus = useGlobalStatusStore();
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let isLogin = globalStatus.isLogin
|
||||
const userInfos = globalStatus.userInfos
|
||||
|
||||
const form = reactive({
|
||||
account: '',
|
||||
@ -35,12 +37,12 @@ const form = reactive({
|
||||
})
|
||||
|
||||
const onSubmit = () => {
|
||||
$http.post("/api/login", form).then(res => {
|
||||
if (res.errorNo != 0) {
|
||||
http.post("/api/login", form).then(res => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage.error(res.errorMsg)
|
||||
} else {
|
||||
$isLogin.value = true
|
||||
$userInfos.value = res.data
|
||||
isLogin = true
|
||||
userInfos.value = res.data
|
||||
router.replace({
|
||||
path: '/',
|
||||
query: {
|
||||
|
@ -1,26 +1,23 @@
|
||||
<template>
|
||||
<div id="main">
|
||||
<el-steps :active="active" align-center finish-status="success" id="status">
|
||||
<el-step :title="lang.welcome" />
|
||||
<el-step :title="lang.setDatabase" />
|
||||
<el-step :title="lang.setAdminPassword" />
|
||||
<el-step :title="lang.SetDomail" />
|
||||
<el-step :title="lang.setDNS" />
|
||||
<el-step :title="lang.setSSL" />
|
||||
<el-step :title="lang.welcome"/>
|
||||
<el-step :title="lang.setDatabase"/>
|
||||
<el-step :title="lang.setAdminPassword"/>
|
||||
<el-step :title="lang.SetDomail"/>
|
||||
<el-step :title="lang.setDNS"/>
|
||||
<el-step :title="lang.setSSL"/>
|
||||
</el-steps>
|
||||
|
||||
|
||||
<div v-if="active == 0" class="ctn">
|
||||
<div v-if="active === 0" class="ctn">
|
||||
<div class="desc">
|
||||
<h2>{{ lang.tks_pmail }}</h2>
|
||||
<div style="margin-top: 10px;">{{ lang.guid_desc }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div v-if="active == 1" class="ctn">
|
||||
<div v-if="active === 1" class="ctn">
|
||||
<div class="desc">
|
||||
<h2>{{ lang.select_db }}</h2>
|
||||
<div style="margin-top: 10px;">{{ lang.db_desc }}</div>
|
||||
@ -30,23 +27,23 @@
|
||||
<el-form-item :label="lang.type">
|
||||
<el-select :placeholder="lang.db_select_ph" v-model="dbSettings.type"
|
||||
@change="dbSettings.dsn = ''">
|
||||
<el-option label="MySQL" value="mysql" />
|
||||
<el-option label="SQLite3" value="sqlite" />
|
||||
<el-option label="PostgreSQL" value="postgres" />
|
||||
<el-option label="MySQL" value="mysql"/>
|
||||
<el-option label="SQLite3" value="sqlite"/>
|
||||
<el-option label="PostgreSQL" value="postgres"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="lang.mysql_dsn" v-if="dbSettings.type == 'mysql'">
|
||||
<el-form-item :label="lang.mysql_dsn" v-if="dbSettings.type === 'mysql'">
|
||||
<el-input :rows="2" type="textarea" v-model="dbSettings.dsn"
|
||||
placeholder="root:12345@tcp(127.0.0.1:3306)/pmail?parseTime=True&loc=Local"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="lang.pg_dsn" v-if="dbSettings.type == 'postgres'">
|
||||
<el-form-item :label="lang.pg_dsn" v-if="dbSettings.type === 'postgres'">
|
||||
<el-input :rows="2" type="textarea" v-model="dbSettings.dsn"
|
||||
placeholder="postgres://postgres:12345@127.0.0.1:5432/pmail?sslmode=disable"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="lang.sqlite_db_path" v-if="dbSettings.type == 'sqlite'">
|
||||
<el-form-item :label="lang.sqlite_db_path" v-if="dbSettings.type === 'sqlite'">
|
||||
<el-input v-model="dbSettings.dsn" placeholder="./config/pmail.db"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@ -54,7 +51,7 @@
|
||||
</div>
|
||||
|
||||
|
||||
<div v-if="active == 2" class="ctn">
|
||||
<div v-if="active === 2" class="ctn">
|
||||
<div class="desc">
|
||||
<h2>{{ lang.setAdminPassword }}</h2>
|
||||
<!-- <div style="margin-top: 10px;">{{ lang.domain_desc }}</div> -->
|
||||
@ -81,7 +78,7 @@
|
||||
</div>
|
||||
|
||||
|
||||
<div v-if="active == 3" class="ctn">
|
||||
<div v-if="active === 3" class="ctn">
|
||||
<div class="desc">
|
||||
<h2>{{ lang.SetDomail }}</h2>
|
||||
<!-- <div style="margin-top: 10px;">{{ lang.domain_desc }}</div> -->
|
||||
@ -100,10 +97,14 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="lang.multi_domain_setting">
|
||||
<span>{{ lang.multi_domain_setting_desc }} <el-button @click="addDomain" size="small"
|
||||
type="success" :icon="Plus" circle></el-button></span>
|
||||
<el-input :placeholder="'domain' + i + '.com'" v-for="(item, i) in domainSettings.multi_domain"
|
||||
v-model="domainSettings.multi_domain[i]"></el-input>
|
||||
<span>{{ lang.multi_domain_setting_desc }}
|
||||
<el-button @click="addDomain" size="small"
|
||||
type="success" :icon="Plus"
|
||||
circle>
|
||||
</el-button>
|
||||
</span>
|
||||
<el-input :placeholder="'domain' + i + '.com'" v-for="(item, i) in domainSettings.multi_domain "
|
||||
v-model="domainSettings.multi_domain[i]" :key="item"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
@ -111,45 +112,46 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="active == 4" class="ctn_s">
|
||||
<div v-if="active === 4" class="ctn_s">
|
||||
|
||||
<div class="desc">
|
||||
<h2>{{ lang.setDNS }}</h2>
|
||||
<div style="margin-top: 10px;">{{ lang.dns_desc }}</div>
|
||||
</div>
|
||||
<div class="form" width="600px" v-for="(info,domain) in dnsInfos">
|
||||
<div class="form" width="600px" v-for="(info,domain) in dnsInfos" :key="info">
|
||||
<h3>{{ domain }}</h3>
|
||||
<el-table :data="info" border style="width: 100%">
|
||||
<el-table-column prop="host" label="HOSTNAME" width="110px" >
|
||||
<el-table-column prop="host" label="HOSTNAME" width="110px">
|
||||
<template #default="scope">
|
||||
<div style="display: flex; align-items: center">
|
||||
<el-tooltip :content="lang.dns_root_desc" placement="top" v-if="scope.row.host == '' || scope.row.host == '@' ">
|
||||
<el-tooltip :content="lang.dns_root_desc" placement="top"
|
||||
v-if="scope.row.host === '' || scope.row.host === '@' ">
|
||||
{{ scope.row.host }}
|
||||
</el-tooltip>
|
||||
<span v-else>{{ scope.row.host }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="type" label="TYPE" width="110px" />
|
||||
<el-table-column prop="type" label="TYPE" width="110px"/>
|
||||
<el-table-column prop="value" label="VALUE">
|
||||
<template #default="scope">
|
||||
<div style="display: flex; align-items: center">
|
||||
<el-tooltip :content="scope.row.tips" placement="top" v-if="scope.row.tips != ''">
|
||||
<el-tooltip :content="scope.row.tips" placement="top" v-if="scope.row.tips !== ''">
|
||||
{{ scope.row.value }}
|
||||
</el-tooltip>
|
||||
<span v-else>{{ scope.row.value }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="ttl" label="TTL" width="110px" />
|
||||
<el-table-column prop="ttl" label="TTL" width="110px"/>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-alert :closable="false" title="Warning!" type="error" center
|
||||
v-if="active == 5 && sslSettings.type == 0 && port != 80" :description="lang.autoSSLWarn" />
|
||||
v-if="active === 5 && sslSettings.type === 0 && port !== 80" :description="lang.autoSSLWarn"/>
|
||||
|
||||
<div v-if="active == 5" class="ctn">
|
||||
<div v-if="active === 5" class="ctn">
|
||||
<div class="desc">
|
||||
<h2>{{ lang.setSSL }}</h2>
|
||||
<div style="margin-top: 10px;">{{ lang.setSSL }}</div>
|
||||
@ -158,16 +160,16 @@
|
||||
<el-form label-width="120px">
|
||||
<el-form-item :label="lang.type">
|
||||
<el-select :placeholder="lang.ssl_auto" v-model="sslSettings.type" :disabled="dnsChecking">
|
||||
<el-option :label="lang.ssl_auto" value="0" />
|
||||
<el-option :label="lang.ssl_manuallyf" value="1" />
|
||||
<el-option :label="lang.ssl_auto" value="0"/>
|
||||
<el-option :label="lang.ssl_manuallyf" value="1"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="lang.ssl_challenge_type" v-if="sslSettings.type == '0'">
|
||||
<el-form-item :label="lang.ssl_challenge_type" v-if="sslSettings.type === '0'">
|
||||
<el-select :placeholder="lang.ssl_auto_http" v-model="sslSettings.challenge"
|
||||
:disabled="dnsChecking">
|
||||
<el-option :label="lang.ssl_auto_http" value="http" />
|
||||
<el-option :label="lang.ssl_auto_dns" value="dns" />
|
||||
<el-option :label="lang.ssl_auto_http" value="http"/>
|
||||
<el-option :label="lang.ssl_auto_dns" value="dns"/>
|
||||
</el-select>
|
||||
|
||||
<el-tooltip class="box-item" effect="dark" :content="lang.challenge_typ_desc"
|
||||
@ -177,14 +179,11 @@
|
||||
</el-form-item>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<el-form-item :label="lang.ssl_key_path" v-if="sslSettings.type == '1'">
|
||||
<el-form-item :label="lang.ssl_key_path" v-if="sslSettings.type === '1'">
|
||||
<el-input placeholder="./config/ssl/private.key" v-model="sslSettings.key_path"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="lang.ssl_crt_path" v-if="sslSettings.type == '1'">
|
||||
<el-form-item :label="lang.ssl_crt_path" v-if="sslSettings.type === '1'">
|
||||
<el-input placeholder="./config/ssl/public.crt" v-model="sslSettings.crt_path"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@ -196,13 +195,13 @@
|
||||
|
||||
<div v-if="dnsChecking">
|
||||
<label>{{ lang.dns_desc }}</label>
|
||||
<el-table :data="sslSettings.paramsList" border v-loading="sslSettings.paramsList.length == 0">
|
||||
<el-table-column prop="host" label="HOSTNAME" width="110px" />
|
||||
<el-table-column prop="type" label="TYPE" width="110px" />
|
||||
<el-table :data="sslSettings.paramsList" border v-loading="sslSettings.paramsList.length === 0">
|
||||
<el-table-column prop="host" label="HOSTNAME" width="110px"/>
|
||||
<el-table-column prop="type" label="TYPE" width="110px"/>
|
||||
<el-table-column prop="value" label="VALUE">
|
||||
<template #default="scope">
|
||||
<div style="display: flex; align-items: center">
|
||||
<el-tooltip :content="scope.row.tips" placement="top" v-if="scope.row.tips != ''">
|
||||
<el-tooltip :content="scope.row.tips" placement="top" v-if="scope.row.tips !== ''">
|
||||
{{ scope.row.value }}
|
||||
</el-tooltip>
|
||||
<span v-else>{{ scope.row.value }}</span>
|
||||
@ -210,7 +209,7 @@
|
||||
</template>
|
||||
|
||||
</el-table-column>
|
||||
<el-table-column prop="ttl" label="TTL" width="110px" />
|
||||
<el-table-column prop="ttl" label="TTL" width="110px"/>
|
||||
</el-table>
|
||||
|
||||
</div>
|
||||
@ -218,26 +217,22 @@
|
||||
|
||||
<el-button :element-loading-text="waitDesc" v-loading.fullscreen.lock="fullscreenLoading" id="next"
|
||||
style="margin-top: 12px" @click="next">{{
|
||||
lang.next }}</el-button>
|
||||
lang.next
|
||||
}}
|
||||
</el-button>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {reactive, ref} from 'vue'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import lang from '../i18n/i18n';
|
||||
import axios from 'axios'
|
||||
import { getCurrentInstance } from 'vue'
|
||||
import {
|
||||
Plus
|
||||
} from '@element-plus/icons-vue'
|
||||
|
||||
|
||||
const app = getCurrentInstance()
|
||||
const $http = app.appContext.config.globalProperties.$http
|
||||
const waitDesc = ref(lang.wait_desc)
|
||||
import {Plus} from '@element-plus/icons-vue'
|
||||
import {http} from "@/utils/axios";
|
||||
|
||||
const waitDesc = ref(lang.wait_desc);
|
||||
|
||||
const adminSettings = reactive({
|
||||
"account": "admin",
|
||||
@ -287,11 +282,16 @@ const setPassword = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (adminSettings.password != adminSettings.password2) {
|
||||
if (adminSettings.password !== adminSettings.password2) {
|
||||
ElMessage.error(lang.err_pwd_diff)
|
||||
} else {
|
||||
$http.post("/api/setup", { "action": "set", "step": "password", "account": adminSettings.account, "password": adminSettings.password }).then((res) => {
|
||||
if (res.errorNo != 0) {
|
||||
http.post("/api/setup", {
|
||||
"action": "set",
|
||||
"step": "password",
|
||||
"account": adminSettings.account,
|
||||
"password": adminSettings.password
|
||||
}).then((res) => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage.error(res.errorMsg)
|
||||
} else {
|
||||
active.value++;
|
||||
@ -302,11 +302,11 @@ const setPassword = () => {
|
||||
}
|
||||
|
||||
const getPassword = () => {
|
||||
$http.post("/api/setup", { "action": "get", "step": "password" }).then((res) => {
|
||||
if (res.errorNo != 0) {
|
||||
http.post("/api/setup", {"action": "get", "step": "password"}).then((res) => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage.error(res.errorMsg)
|
||||
} else {
|
||||
adminSettings.hadSeted = res.data != ""
|
||||
adminSettings.hadSeted = res.data !== ""
|
||||
if (adminSettings.hadSeted) {
|
||||
adminSettings.account = res.data
|
||||
adminSettings.password = "*******"
|
||||
@ -319,8 +319,8 @@ const getPassword = () => {
|
||||
|
||||
|
||||
const getDbConfig = () => {
|
||||
$http.post("/api/setup", { "action": "get", "step": "database" }).then((res) => {
|
||||
if (res.errorNo != 0) {
|
||||
http.post("/api/setup", {"action": "get", "step": "database"}).then((res) => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage.error(res.errorMsg)
|
||||
} else {
|
||||
dbSettings.type = res.data.db_type;
|
||||
@ -330,8 +330,8 @@ const getDbConfig = () => {
|
||||
}
|
||||
|
||||
const getDomainConfig = () => {
|
||||
$http.post("/api/setup", { "action": "get", "step": "domain" }).then((res) => {
|
||||
if (res.errorNo != 0) {
|
||||
http.post("/api/setup", {"action": "get", "step": "domain"}).then((res) => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage.error(res.errorMsg)
|
||||
} else {
|
||||
domainSettings.web_domain = res.data.web_domain;
|
||||
@ -349,8 +349,13 @@ const setDbConfig = () => {
|
||||
message: lang.err_db_dsn_empty,
|
||||
type: "error",
|
||||
});
|
||||
$http.post("/api/setup", { "action": "set", "step": "database", "db_type": dbSettings.type, "db_dsn": dbSettings.dsn }).then((res) => {
|
||||
if (res.errorNo != 0) {
|
||||
http.post("/api/setup", {
|
||||
"action": "set",
|
||||
"step": "database",
|
||||
"db_type": dbSettings.type,
|
||||
"db_dsn": dbSettings.dsn
|
||||
}).then((res) => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage.error(res.errorMsg)
|
||||
} else {
|
||||
active.value++;
|
||||
@ -360,8 +365,8 @@ const setDbConfig = () => {
|
||||
}
|
||||
|
||||
const getDNSConfig = () => {
|
||||
$http.post("/api/setup", { "action": "get", "step": "dns" }).then((res) => {
|
||||
if (res.errorNo != 0) {
|
||||
http.post("/api/setup", {"action": "get", "step": "dns"}).then((res) => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage.error(res.errorMsg)
|
||||
} else {
|
||||
dnsInfos.value = res.data
|
||||
@ -371,12 +376,12 @@ const getDNSConfig = () => {
|
||||
|
||||
|
||||
const getSSLConfig = () => {
|
||||
$http.post("/api/setup", { "action": "get", "step": "ssl" }).then((res) => {
|
||||
if (res.errorNo != 0) {
|
||||
http.post("/api/setup", {"action": "get", "step": "ssl"}).then((res) => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage.error(res.errorMsg)
|
||||
} else {
|
||||
sslSettings.type = res.data.type
|
||||
if (sslSettings.type == "2") {
|
||||
if (sslSettings.type === "2") {
|
||||
sslSettings.type = "0"
|
||||
sslSettings.challenge = "dns"
|
||||
}
|
||||
@ -392,24 +397,23 @@ const setSSLConfig = () => {
|
||||
fullscreenLoading.value = true;
|
||||
|
||||
let sslType = sslSettings.type;
|
||||
if (sslType == "0" && sslSettings.challenge == "dns") {
|
||||
if (sslType === "0" && sslSettings.challenge === "dns") {
|
||||
sslType = "2"
|
||||
}
|
||||
|
||||
|
||||
|
||||
$http.post("/api/setup", {
|
||||
http.post("/api/setup", {
|
||||
"action": "set",
|
||||
"step": "ssl",
|
||||
"ssl_type": sslType,
|
||||
"key_path": sslSettings.key_path,
|
||||
"crt_path": sslSettings.crt_path
|
||||
}).then((res) => {
|
||||
if (res.errorNo != 0) {
|
||||
if (res.errorNo !== 0) {
|
||||
fullscreenLoading.value = false;
|
||||
ElMessage.error(res.errorMsg)
|
||||
} else {
|
||||
if (sslType == 2) {
|
||||
if (sslType === 2) {
|
||||
fullscreenLoading.value = false;
|
||||
dnsChecking.value = true;
|
||||
getSSLDNSParams();
|
||||
@ -422,18 +426,18 @@ const setSSLConfig = () => {
|
||||
|
||||
const checkStatus = () => {
|
||||
axios.post("/api/ping", {}).then((res) => {
|
||||
if (res.data.errorNo != 0) {
|
||||
if (res.data.errorNo !== 0) {
|
||||
setTimeout(function () {
|
||||
checkStatus()
|
||||
}, 1000);
|
||||
} else {
|
||||
if(sslSettings.type == 1){
|
||||
if (sslSettings.type === 1) {
|
||||
window.location.href = "http://" + domainSettings.web_domain;
|
||||
}else{
|
||||
} else {
|
||||
window.location.href = "https://" + domainSettings.web_domain;
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
}).catch(() => {
|
||||
setTimeout(function () {
|
||||
checkStatus()
|
||||
}, 1000);
|
||||
@ -442,14 +446,14 @@ const checkStatus = () => {
|
||||
|
||||
|
||||
const setDomainConfig = () => {
|
||||
$http.post("/api/setup", {
|
||||
http.post("/api/setup", {
|
||||
"action": "set",
|
||||
"step": "domain",
|
||||
"web_domain": domainSettings.web_domain,
|
||||
"smtp_domain": domainSettings.smtp_domain,
|
||||
"multi_domain": domainSettings.multi_domain.join(",")
|
||||
}).then((res) => {
|
||||
if (res.errorNo != 0) {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage.error(res.errorMsg)
|
||||
} else {
|
||||
active.value++;
|
||||
@ -459,8 +463,8 @@ const setDomainConfig = () => {
|
||||
}
|
||||
|
||||
const getSSLDNSParams = () => {
|
||||
$http.post("/api/setup", { "action": "getParams", "step": "ssl" }).then((res) => {
|
||||
if (res.errorNo != 0) {
|
||||
http.post("/api/setup", {"action": "getParams", "step": "ssl"}).then((res) => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage.error(res.errorMsg)
|
||||
} else {
|
||||
sslSettings.paramsList = res.data
|
||||
@ -468,14 +472,13 @@ const getSSLDNSParams = () => {
|
||||
}
|
||||
})
|
||||
|
||||
if (sslSettings.paramsList.length == 0) {
|
||||
if (sslSettings.paramsList.length === 0) {
|
||||
setTimeout(function () {
|
||||
getSSLDNSParams()
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -526,7 +529,8 @@ const next = () => {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
#status {}
|
||||
#status {
|
||||
}
|
||||
|
||||
.ctn {
|
||||
display: flex;
|
||||
@ -539,5 +543,6 @@ const next = () => {
|
||||
|
||||
}
|
||||
|
||||
#next {}
|
||||
#next {
|
||||
}
|
||||
</style>
|
Loading…
x
Reference in New Issue
Block a user