diff --git a/public/index.html b/public/index.html index 3c3eac3..5ba1dd0 100644 --- a/public/index.html +++ b/public/index.html @@ -139,7 +139,7 @@ top: 0; width: 51%; height: 100%; - background: #49a9ee; + background: #051314; /* Old browsers */ z-index: 1000; -webkit-transform: translateX(0); @@ -249,9 +249,6 @@ <div id="loader"></div> <div class="loader-section section-left"></div> <div class="loader-section section-right"></div> - <div class="load_title">正在加载 核素监测数据自动处理与交互分析系统,请耐心等待 - - </div> </div> </div> diff --git a/src/api/manage.js b/src/api/manage.js index 45153ed..5ce1de7 100644 --- a/src/api/manage.js +++ b/src/api/manage.js @@ -152,8 +152,8 @@ export function downFile(url,parameter, method='get'){ * @param parameter * @returns {*} */ -export function downloadFile(url, fileName, parameter) { - return downFile(url, parameter).then((data) => { +export function downloadFile(url, fileName, parameter, method) { + return downFile(url, parameter, method).then((data) => { if (!data || data.size === 0) { Vue.prototype['$message'].warning('文件下载失败') return diff --git a/src/assets/images/login/bg.jpg b/src/assets/images/login/bg.jpg new file mode 100644 index 0000000..1b84ff5 Binary files /dev/null and b/src/assets/images/login/bg.jpg differ diff --git a/src/assets/images/login/login-btn-active.png b/src/assets/images/login/login-btn-active.png new file mode 100644 index 0000000..2b81eb3 Binary files /dev/null and b/src/assets/images/login/login-btn-active.png differ diff --git a/src/assets/images/login/login-btn.png b/src/assets/images/login/login-btn.png new file mode 100644 index 0000000..64dc2c4 Binary files /dev/null and b/src/assets/images/login/login-btn.png differ diff --git a/src/assets/images/login/logo.png b/src/assets/images/login/logo.png new file mode 100644 index 0000000..f577b6b Binary files /dev/null and b/src/assets/images/login/logo.png differ diff --git a/src/assets/images/login/pwd-bg.png b/src/assets/images/login/pwd-bg.png new file mode 100644 index 0000000..324d1c9 Binary files /dev/null and b/src/assets/images/login/pwd-bg.png differ diff --git a/src/assets/images/login/username-bg.png b/src/assets/images/login/username-bg.png new file mode 100644 index 0000000..1f8a8e0 Binary files /dev/null and b/src/assets/images/login/username-bg.png differ diff --git a/src/assets/images/login/validate-bg.png b/src/assets/images/login/validate-bg.png new file mode 100644 index 0000000..774b365 Binary files /dev/null and b/src/assets/images/login/validate-bg.png differ diff --git a/src/components/SearchForm/index.vue b/src/components/SearchForm/index.vue index 20fd1a0..17bde55 100644 --- a/src/components/SearchForm/index.vue +++ b/src/components/SearchForm/index.vue @@ -1,6 +1,6 @@ <template> <div class="search-form"> - <a-form-model ref="form" :model="formModel" v-bind="$attrs" @keyup.enter.native="onSearch"> + <a-form-model ref="form" :colon="false" :model="formModel" v-bind="$attrs" @keyup.enter.native="onSearch"> <a-row v-if="type == 'single-line'" :gutter="20" style="margin-right: 0 !important;"> <a-col class="search-form-item" @@ -101,6 +101,13 @@ export default { } .ant-form-item-label { flex-shrink: 0; + margin-right: 10px; + label { + font-size: 16px; + &::after { + display: none; + } + } } .ant-form-item-control-wrapper { width: 100%; diff --git a/src/components/TreeWithLine/index.vue b/src/components/TreeWithLine/index.vue index f79f0ae..24412db 100644 --- a/src/components/TreeWithLine/index.vue +++ b/src/components/TreeWithLine/index.vue @@ -1,6 +1,6 @@ <template> <div class="tree-with-line"> - <a-tree v-bind="$attrs" :defaultExpandedKeys="defaultExpandedKeys" :selected-keys="selectedKeys" @select="onSelect"> + <a-tree v-bind="$attrs" :selected-keys="selectedKeys" :expandedKeys="expandedKeys" @select="onSelect" @expand="onExpand"> <template slot="switcherIcon"> <div></div> </template> @@ -13,7 +13,7 @@ export default { selectedKeys: { type: Array }, - defaultExpandedKeys: { + expandedKeys: { type: Array } }, @@ -23,6 +23,9 @@ export default { this.$emit('update:selectedKeys', selectedKeys) this.$emit('select') } + }, + onExpand(expandedKeys) { + this.$emit('update:expandedKeys', expandedKeys) } } } diff --git a/src/components/page/GlobalLayout.vue b/src/components/page/GlobalLayout.vue index 36395a5..7505b0c 100644 --- a/src/components/page/GlobalLayout.vue +++ b/src/components/page/GlobalLayout.vue @@ -680,7 +680,8 @@ margin-right: 10px; height: 30px; line-height: 30px; - padding: 0 15px; + padding: 0 16px; + letter-spacing: 2px; position: relative; > a { color: #c9f6f6; diff --git a/src/mixins/JeecgListMixin.js b/src/mixins/JeecgListMixin.js index 71d4873..4993894 100644 --- a/src/mixins/JeecgListMixin.js +++ b/src/mixins/JeecgListMixin.js @@ -23,7 +23,7 @@ export const JeecgListMixin = { pageSizeOptions: ['10', '20', '30'], showTotal: (total, range) => { const { current, pageSize } = this.ipagination - return `共 ${total} 条记录 第 ${current} / ${Math.ceil(total / pageSize)} 页` + return `Total ${total} items Page ${current} / ${Math.ceil(total / pageSize)}` }, showQuickJumper: true, showSizeChanger: true, @@ -228,12 +228,12 @@ export const JeecgListMixin = { }, handleEdit: function (record) { this.$refs.modalForm.edit(record); - this.$refs.modalForm.title = "编辑"; + this.$refs.modalForm.title = "Edit"; this.$refs.modalForm.disableSubmit = false; }, handleAdd: function () { this.$refs.modalForm.add(); - this.$refs.modalForm.title = "新增"; + this.$refs.modalForm.title = "Add"; this.$refs.modalForm.disableSubmit = false; }, handleTableChange(pagination, filters, sorter) { @@ -262,7 +262,7 @@ export const JeecgListMixin = { }, handleDetail:function(record){ this.$refs.modalForm.edit(record); - this.$refs.modalForm.title="详情"; + this.$refs.modalForm.title="Detail"; this.$refs.modalForm.disableSubmit = true; }, /* 导出 */ diff --git a/src/views/logManage/index.vue b/src/views/logManage/index.vue index 706000d..9e552a4 100644 --- a/src/views/logManage/index.vue +++ b/src/views/logManage/index.vue @@ -17,9 +17,18 @@ </template> <!-- 标题结束 --> <!-- 内容 --> - <tree-with-line :treeData="treeData" :selected-keys.sync="selectedKeys" :expanded-keys.sync="expandedKeys" @select="onSelect"> </tree-with-line> + <a-spin :spinning="isGettingTreeData" style="min-height: 200px"> + <tree-with-line + :treeData="treeData" + :selected-keys.sync="selectedKeys" + :expanded-keys.sync="expandedKeys" + @select="onSelect" + > + </tree-with-line> + </a-spin> <!-- 内容结束 --> </a-card> + <!-- 日志列表 --> <div class="log-list"> <custom-table size="middle" @@ -27,10 +36,10 @@ :columns="columns" :list="dataSource" :pagination="false" - :loading="loading" + :loading="isGettingTreeData || loading" :can-select="false" @change="handleTableChange" - :scroll="{ y: 'calc(100vh - 365px)' }" + :scroll="{ y: 'calc(100vh - 175px)' }" > <template slot="operate" slot-scope="{ record }"> <a-space :size="20"> @@ -45,37 +54,42 @@ </template> </custom-table> </div> - + <!-- 日志列表结束 --> <custom-modal title="Log" v-model="visible" :show-footer="false"> - 这里是Log内容 + <a-spin :spinning="isGettingDetail" style="min-height: 100px"> + {{ logInfo }} + </a-spin> </custom-modal> </div> </template> <script> import { JeecgListMixin } from '@/mixins/JeecgListMixin' import TreeWithLine from '@/components/TreeWithLine/index.vue' -import { downloadFile, getAction } from '../../api/manage' -import TreeJson from './tree.json' +import { downloadFile, getAction, postAction } from '../../api/manage' const columns = [ { - title: 'Name', + title: 'NAME', align: 'center', - dataIndex: 'name' + width: 320, + dataIndex: 'fileName' }, { - title: 'date', + title: 'DATE', align: 'center', - dataIndex: 'date' + width: 200, + dataIndex: 'fileDate' }, { - title: 'size', + title: 'SIZE', align: 'center', - dataIndex: 'size' + width: 220, + dataIndex: 'fileSize' }, { - title: 'Operate', + title: 'OPERATE', align: 'center', + width: 200, scopedSlots: { customRender: 'operate' } @@ -92,22 +106,17 @@ export default { return { disableMixinCreated: true, url: { - list: '/test' + list: '/logManage/findFiles' }, isGettingTreeData: false, // 正在获取左侧树信息 treeData: [], selectedKeys: [], expandedKeys: [], - dataSource: [ - { - id: 1, - name: 'DEX33_002-20220512_0723_S_FULL_9011.9.log', - date: '2022-05-13', - size: '105KB', - fileName: 'test.txt' - } - ], - visible: false + dataSource: [], + + visible: false, + isGettingDetail: false, + logInfo: '' } }, created() { @@ -117,17 +126,15 @@ export default { async getTreeData() { try { this.isGettingTreeData = true - const res = await getAction('/logManage/findFtpFolders') - console.log('%c [ res ]-159', 'font-size:13px; background:pink; color:#bf2c9f;', res) - } catch (error) { - console.error(error) - this.$message.error('Get Tree Data Failed') - this.treeData = this.buildTreeData(TreeJson) - console.log('%c [ this.treeData ]-125', 'font-size:13px; background:pink; color:#bf2c9f;', this.treeData) + const res = await getAction('/logManage/findFtpFolders', { workPath: 'log' }) + this.treeData = this.buildTreeData(res) const firstNode = this.treeData[0] this.selectedKeys = [firstNode.key] this.expandedKeys = [firstNode.key] this.onSelect() + } catch (error) { + console.error(error) + this.$message.error('Get Tree Data Failed') } finally { this.isGettingTreeData = false } @@ -152,15 +159,60 @@ export default { return tree }, onSelect() { - this.queryParam.query = this.selectedKeys[0] + this.queryParam.path = this.selectedKeys[0] this.loadData() }, - onOperate(record) { - console.log('%c [ ]-147', 'font-size:13px; background:pink; color:#bf2c9f;', record) - this.visible = true + + loadData(arg) { + if (!this.url.list) { + this.$message.error('请设置url.list属性!') + return + } + //加载数据 若传入参数1则加载第一页的内容 + if (arg === 1) { + this.ipagination.current = 1 + } + this.onClearSelected() + + var params = this.getQueryParams() //查询条件 + this.loading = true + getAction(this.url.list, params) + .then(res => { + this.dataSource = res + }) + .finally(() => { + this.loading = false + }) }, - onDownload({ fileName }) { - downloadFile('/logManage/downloadFile', fileName, { fileName }) + + async onOperate({ fileName, filePath, fileSize }) { + if (parseFloat(fileSize) == 0) { + this.$message.warn('This Log Is Empty') + return + } + this.visible = true + const formData = new FormData() + formData.append('fileName', fileName) + formData.append('localPath', filePath) + try { + this.isGettingDetail = true + const res = await postAction('/logManage/downloadFile', formData) + this.logInfo = res + } catch (error) { + console.error(error) + } finally { + this.isGettingDetail = false + } + }, + onDownload({ fileName, filePath, fileSize }) { + if (parseFloat(fileSize) == 0) { + this.$message.warn('This Log Is Empty') + return + } + const formData = new FormData() + formData.append('fileName', fileName) + formData.append('localPath', filePath) + downloadFile('/logManage/downloadFile', fileName, formData, 'post') } } } diff --git a/src/views/user/Login.vue b/src/views/user/Login.vue index d7b07d9..29a5581 100644 --- a/src/views/user/Login.vue +++ b/src/views/user/Login.vue @@ -1,205 +1,308 @@ <template> - <div class="main"> - <a-form-model class="user-layout-login" @keyup.enter.native="handleSubmit"> - <a-tabs :activeKey="customActiveKey" :tabBarStyle="{ textAlign: 'center', borderBottom: 'unset' }" @change="handleTabClick"> - <a-tab-pane key="tab1" tab="账号密码登录"> - <login-account ref="alogin" @validateFail="validateFail" @success="requestSuccess" @fail="requestFailed"></login-account> - </a-tab-pane> + <div class="login-page"> + <div class="login-form"> + <div class="logo"> + <img src="@/assets/images/login/logo.png" alt="" /> + </div> + <a-form-model layout="vertical" ref="formRef" :model="model" :rules="rules" @keyup.enter.native="handleSubmit"> + <a-form-model-item class="username" label="Username" prop="username"> + <a-input v-model="model.username"></a-input> + </a-form-model-item> + <a-form-model-item class="password" label="Password" prop="password"> + <a-input type="password" v-model="model.password"></a-input> + </a-form-model-item> + <!-- 验证码 --> - <a-tab-pane key="tab2" tab="手机号登录"> - <login-phone ref="plogin" @validateFail="validateFail" @success="requestSuccess" @fail="requestFailed"></login-phone> - </a-tab-pane> - </a-tabs> + <a-form-model-item class="validate-code" label="Captcha" prop="inputCode"> + <a-input v-model="model.inputCode"> </a-input> + <div class="validate-image"> + <img v-if="requestCodeSuccess" :src="randCodeImage" @click="handleChangeCheckCode" /> + <img v-else src="@/assets/checkcode.png" @click="handleChangeCheckCode" /> + </div> + </a-form-model-item> - <a-form-model-item> - <a-checkbox @change="handleRememberMeChange" default-checked>自动登录</a-checkbox> - </a-form-model-item> - - <a-form-item style="margin-top:24px"> - <a-button size="large" type="primary" htmlType="submit" class="login-button" :loading="loginBtn" @click.stop.prevent="handleSubmit" :disabled="loginBtn">确定 - </a-button> - </a-form-item> - - </a-form-model> - <login-select-tenant ref="loginSelect" @success="loginSelectOk"></login-select-tenant> + <!-- 验证码结束 --> + <!-- 记住密码 --> + <div class="remember-pwd"> + <a-checkbox v-model="model.rememberPwd">Remember password</a-checkbox> + </div> + <!-- 记住密码结束 --> + <a-button class="login-button" :loading="isSubmitting" @click="handleSubmit"> SIGN IN </a-button> + </a-form-model> + </div> </div> </template> <script> import Vue from 'vue' -import { ACCESS_TOKEN, ENCRYPTED_STRING } from '@/store/mutation-types' -import ThirdLogin from './third/ThirdLogin' -import LoginSelectTenant from './LoginSelectTenant' -import TwoStepCaptcha from '@/components/tools/TwoStepCaptcha' -import { getEncryptedString } from '@/utils/encryption/aesEncrypt' +import { ACCESS_TOKEN } from '@/store/mutation-types' import { timeFix } from '@/utils/util' - -import LoginAccount from './LoginAccount' -import LoginPhone from './LoginPhone' +import { getAction } from '@/api/manage' +import { mapActions } from 'vuex' export default { - components: { - LoginSelectTenant, - TwoStepCaptcha, - ThirdLogin, - LoginAccount, - LoginPhone - }, - data () { - return { - customActiveKey: 'tab1', - rememberMe: true, - loginBtn: false, - requiredTwoStepCaptcha: false, - stepCaptchaVisible: false, - encryptedString:{ - key:"", - iv:"", - }, - } - }, - created() { - Vue.ls.remove(ACCESS_TOKEN) - this.getRouterData(); - this.rememberMe = true - }, - methods:{ - handleTabClick(key){ - this.customActiveKey = key + data() { + return { + isSubmitting: false, + randCodeImage: '', + requestCodeSuccess: false, + model: { + username: '', + password: '', + inputCode: '', + rememberPwd: true }, - handleRememberMeChange(e){ - this.rememberMe = e.target.checked + rules: { + username: [{ required: true, message: 'Username Required' }], + password: [ + { + required: true, + message: 'Password Required' + }, + ], + inputCode: [ + { + required: true, + message: 'Captchar Required', + }, + ], }, - /**跳转到登录页面的参数-账号获取*/ - getRouterData(){ - this.$nextTick(() => { - let temp = this.$route.params.username || this.$route.query.username || '' - if (temp) { - this.$refs.alogin.acceptUsername(temp) + currdatetime: '', + } + }, + created() { + Vue.ls.remove(ACCESS_TOKEN) + this.getRouterData() + this.handleChangeCheckCode() + }, + methods: { + ...mapActions(['Login']), + + /**跳转到登录页面的参数-账号获取*/ + getRouterData() { + this.$nextTick(() => { + let temp = this.$route.params.username || this.$route.query.username || '' + if (temp) { + this.$refs.alogin.acceptUsername(temp) + } + }) + }, + + /**刷新验证码*/ + handleChangeCheckCode() { + this.currdatetime = new Date().getTime() + this.model.inputCode = '' + getAction(`/sys/randomImage/${this.currdatetime}`) + .then((res) => { + if (res.success) { + this.randCodeImage = res.result + this.requestCodeSuccess = true + } else { + this.$message.error(res.message) + this.requestCodeSuccess = false } }) - }, - - //登录 - handleSubmit () { - this.loginBtn = true; - if (this.customActiveKey === 'tab1') { - // 使用账户密码登录 - this.$refs.alogin.handleLogin(this.rememberMe) - } else { - //手机号码登录 - this.$refs.plogin.handleLogin(this.rememberMe) - } - }, - // 校验失败 - validateFail(){ - this.loginBtn = false; - }, - // 登录后台成功 - requestSuccess(loginResult){ - this.$refs.loginSelect.show(loginResult) - }, - //登录后台失败 - requestFailed (err) { - let description = ((err.response || {}).data || {}).message || err.message || "请求出现错误,请稍后再试" - this.$notification[ 'error' ]({ - message: '登录失败', - description: description, - duration: 4, - }); - //账户密码登录错误后更新验证码 - if(this.customActiveKey === 'tab1' && description.indexOf('密码错误')>0){ - this.$refs.alogin.handleChangeCheckCode() - } - this.loginBtn = false; - }, - loginSelectOk(){ - this.loginSuccess() - }, - //登录成功 - loginSuccess () { - this.$router.push({ path: "/station-operation" }).catch(()=>{ - console.log('登录跳转首页出错,这个错误从哪里来的') + .catch(() => { + this.requestCodeSuccess = false }) - this.$notification.success({ - message: '欢迎', - description: `${timeFix()},欢迎回来`, - }); - }, + }, - stepCaptchaSuccess () { - this.loginSuccess() - }, - stepCaptchaCancel () { - this.Logout().then(() => { - this.loginBtn = false - this.stepCaptchaVisible = false - }) - }, - //获取密码加密规则 - getEncrypte(){ - var encryptedString = Vue.ls.get(ENCRYPTED_STRING); - if(encryptedString == null){ - getEncryptedString().then((data) => { - this.encryptedString = data - }); - }else{ - this.encryptedString = encryptedString; - } + //登录 + async handleSubmit() { + if (this.isSubmitting) { + return } + try { + await this.$refs.formRef.validate() + try { + const loginParams = { + username: this.model.username, + password: this.model.password, + captcha: this.model.inputCode, + checkKey: this.currdatetime, + } + this.isSubmitting = true + const res = await this.Login(loginParams) + this.loginSuccess() + } catch (error) { + if (error && error.code === 412) { + this.handleChangeCheckCode() + } + this.requestFailed(error) + } + } catch (error) { + console.error(error) + } + }, - } + //登录失败 + requestFailed(err) { + let description = ((err.response || {}).data || {}).message || err.message || 'Request Error' + this.$notification['error']({ + message: 'Login Failed', + description: description, + duration: 4, + }) + //账户密码登录错误后更新验证码 + this.handleChangeCheckCode() + this.isSubmitting = false + }, - } + //登录成功 + loginSuccess() { + this.$router.push({ path: '/station-operation' }).catch(() => { + console.log('登录跳转首页出错,这个错误从哪里来的') + }) + this.$notification.success({ + message: 'Welcome', + description: `${timeFix()},Welcome Back`, + }) + }, + }, +} </script> <style lang="less" scoped> - .user-layout-login { - label { - font-size: 14px; - } - .getCaptcha { - display: block; - width: 100%; - height: 40px; +.login-page { + height: 100%; + background: url(~@/assets/images/login/bg.jpg) center no-repeat; + background-size: cover; + + .login-form { + position: fixed; + top: 50%; + right: 295px; + transform: translateY(-50%); + + .logo { + img { + width: 578px; + height: 233px; + } } - .forge-password { - font-size: 14px; - } + .ant-form { + margin-right: 24px; + float: right; - button.login-button { - padding: 0 15px; - font-size: 16px; - height: 40px; - width: 100%; - } + &-item { + margin-bottom: 20px !important; + ::v-deep { + .ant-form-item-label { + line-height: 17px; + label { + font-size: 22px; + color: #fff; + padding-left: 6px; + &::before { + display: none; + } + } + } - .user-login-other { - text-align: left; - margin-top: 24px; - line-height: 22px; + .ant-form-explain { + position: absolute; + right: 0; + top: -36px; + font-size: 18px; + } - .item-icon { - font-size: 24px; - color: rgba(0,0,0,.2); - margin-left: 16px; - vertical-align: middle; - cursor: pointer; - transition: color .3s; + .ant-form-item-children { + width: 444px; + height: 60px; + .ant-input { + padding-left: 70px; + padding-right: 15px; + height: 100%; + font-size: 26px; + background-color: transparent !important; + border: none; + } + } + } - &:hover { - color: #1890ff; + &.username { + ::v-deep { + .ant-form-item-children { + background: url(~@/assets/images/login/username-bg.png) center no-repeat; + background-size: contain; + } + } + } + + &.password { + ::v-deep { + .ant-form-item-children { + background: url(~@/assets/images/login/pwd-bg.png) center no-repeat; + background-size: contain; + } + } + } + + &.validate-code { + width: 444px; + ::v-deep { + .ant-form-item-children { + display: flex; + justify-content: space-between; + + .ant-input { + width: 294px; + background: url(~@/assets/images/login/validate-bg.png) center no-repeat; + background-size: contain; + } + + .validate-image { + width: 135px; + height: 60px; + + img { + width: 100%; + height: 100%; + } + } + } + } } } - .register { - float: right; + .remember-pwd { + user-select: none; + margin-top: -20px; + margin-left: 5px; + .ant-checkbox-wrapper { + color: #6ebad0; + } + } + + .login-button { + width: 444px; + height: 76px; + margin-top: 44px; + background: url(~@/assets/images/login/login-btn.png) center no-repeat; + border: 0; + padding-bottom: 15px; + ::v-deep { + .anticon-loading { + font-size: 22px; + } + span { + font-family: MicrogrammaD-MediExte; + font-size: 22px; + font-weight: bold; + color: #fff; + text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.61); + } + } + &:focus, + &.ant-btn-loading { + background-image: url(~@/assets/images/login/login-btn-active.png); + } + &::before, + &::after { + display: none; + } } } } -</style> -<style> - .valid-error .ant-select-selection__placeholder{ - color: #f5222d; - } +} </style> \ No newline at end of file