This commit is contained in:
2022-03-21 12:44:51 +08:00
commit 521d9581ae
215 changed files with 34114 additions and 0 deletions

6
.babelrc Normal file
View File

@@ -0,0 +1,6 @@
{
"presets": [
"@vue/app"
],
"plugins": ["@babel/plugin-syntax-dynamic-import"]
}

9
.editorconfig Normal file
View File

@@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

0
.eslintignore Normal file
View File

21
.eslintrc.js Normal file
View File

@@ -0,0 +1,21 @@
module.exports = {
root: true,
'extends': [
'plugin:vue/essential',
'@vue/standard'
],
rules: {
// allow async-await
'generator-star-spacing': 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'vue/no-parsing-error': [2, {
'x-invalid-end-tag': false
}],
'no-undef': 'off',
'camelcase': 'off'
},
parserOptions: {
parser: 'babel-eslint'
}
}

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.idea
node_modules

5
.postcssrc.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {}
}
}

5
.travis.yml Normal file
View File

@@ -0,0 +1,5 @@
language: node_js
node_js: stable
script: npm run lint
notifications:
email: false

0
README.md Normal file
View File

3
cypress.json Normal file
View File

@@ -0,0 +1,3 @@
{
"pluginsFile": "tests/e2e/plugins/index.js"
}

20527
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

83
package.json Normal file
View File

@@ -0,0 +1,83 @@
{
"name": "iview-admin",
"version": "2.0.0",
"author": "Lison<lison16new@163.com>",
"private": false,
"scripts": {
"dev": "vue-cli-service serve --open",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e"
},
"dependencies": {
"axios": "^0.18.0",
"babel-polyfill": "^6.26.0",
"clipboard": "^2.0.0",
"codemirror": "^5.38.0",
"cookiejar": "^2.1.2",
"countup": "^1.8.2",
"cropperjs": "^1.2.2",
"dayjs": "^1.7.7",
"echarts": "^4.0.4",
"html2canvas": "^1.0.0-alpha.12",
"iview": "^3.2.2",
"iview-area": "^1.5.17",
"js-cookie": "^2.2.0",
"js-md5": "^0.7.3",
"moment": "^2.24.0",
"quill-image-resize-module": "^3.0.0",
"simplemde": "^1.11.2",
"sortablejs": "^1.7.0",
"tree-table-vue": "^1.1.0",
"v-org-tree": "^1.0.6",
"vue": "^2.5.10",
"vue-circleprogressbar": "^1.3.0",
"vue-codemirror": "^4.0.6",
"vue-cookies": "^1.6.1",
"vue-cropper": "^0.4.9",
"vue-i18n": "^7.8.0",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.0.7",
"vuedraggable": "^2.16.0",
"vuex": "^3.0.1",
"wangeditor": "^3.1.1",
"xlsx": "^0.13.3"
},
"devDependencies": {
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@vue/cli-plugin-babel": "^3.0.1",
"@vue/cli-plugin-eslint": "^3.0.1",
"@vue/cli-plugin-unit-mocha": "^3.0.1",
"@vue/cli-service": "^3.0.1",
"@vue/eslint-config-standard": "^3.0.0-beta.10",
"@vue/test-utils": "^1.0.0-beta.10",
"chai": "^4.1.2",
"eslint-plugin-cypress": "^2.0.1",
"less": "^2.7.3",
"less-loader": "^4.0.5",
"lint-staged": "^6.0.0",
"mockjs": "^1.0.1-beta3",
"node-sass": "^4.13.0",
"sass-loader": "^8.0.0",
"vue-template-compiler": "^2.5.13"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.js": [
"vue-cli-service lint",
"git add"
],
"*.vue": [
"vue-cli-service lint",
"git add"
]
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

17
public/index.html Normal file
View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<title></title>
</head>
<body>
<noscript>
<strong>We're sorry but iview-admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

162
src/App.vue Normal file
View File

@@ -0,0 +1,162 @@
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style lang="less">
.size{
width: 100%;
height: 100%;
}
html,body{
.size;
overflow: hidden;
margin: 0;
padding: 0;
}
#app {
.size;
}
#app .edit_container, #app .quill-editor {
height: inherit!important;
}
//iview组件样式修改
#app {
.ivu-layout {
background: none;
}
.ivu-modal-body {
margin-top: 120px;
}
.ivu-layout-header {
height: 70px;
line-height: 80px;
background: none;
}
.ivu-form-item {
margin-top: 10px;
margin-bottom: 18px;
}
.ivu-form-item:nth-last-child(1) {
margin-bottom: 0;
}
.ivu-form-item:nth-child(1) {
margin-top: 0;
}
.ivu-input, .ivu-input-number-input {
height: 40px !important;
font-size: 14px !important;
color: #000 !important;
}
.ivu-input-with-prefix {
padding-left: 45px !important;
}
.ivu-checkbox-wrapper {
font-size: 14px !important;
}
.ivu-spin-large .ivu-spin-dot {
margin: 0 auto;
margin-top: 200px;
margin-bottom: 250px;
}
}
//页面间公共样式
#product-setting, #homePageSetting, #homePageSettingH5 {
.subtitle {
color: #b2b2b2;
}
.title {
font-size: 18px;
font-weight: 600;
}
.flexbox {
display: flex;
// justify-content: space-between;
.flexLeft {
width: 460px;
margin-right: 60px;
}
.flexRight {
width: 460px;
}
}
}
.setting-section {
// width: 800px;
padding: 25px;
background:#fff;
.section-header {
display: flex;
align-items: baseline;
justify-content: space-between;
}
.section-content {
margin-top: 15px;
// img {
// width: 120px;
// height: 120px;
// margin: 3px;
// object-fit: cover;
// }
}
.prefix {
line-height: 40px;
padding-left: 8px;
color: rgb(121, 131, 153);
}
.tips {
font-size:12px;
color: #8787af;
margin-top: 15px;
}
.label {
padding-top: 12px;
padding-bottom: 3px;
position: relative;
top: 0;
}
}
.setting-section:nth-child(n+2) {
margin-top: 20px;
}
.header.setting-section {
padding: 6px 12px;
background: #6686cb;
text-align: right;
position: relative;
margin-bottom: 10px;
margin-top: -6px;
.ivu-btn-small {
width: 60px;
height: 25px;
margin-left: 6px;
}
.ivu-btn-small:nth-child(1) {
margin-right: 6px;
}
.head_title {
color: #fff;
position: absolute;
font-size: 16px;
top: 5px;
left: 14px;
}
}
</style>

89
src/api/account.js Normal file
View File

@@ -0,0 +1,89 @@
import axios from '@/libs/api.request'
// export const GetConfigAppFrontHome = () => {
// return axios.request({
// method: 'get',
// url: '?r=AjaxApiMallConfig/GetConfigAppFrontHome'
// })
// }
export const Register = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.User.Register',
data
})
}
export const Login = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.User.UserLogin',
data
})
}
// 获取当前登录用户自己的个人信息
export const GetAccountInfo = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.User.Profile',
data
})
}
// 修改个人信息
export const SetAccountInfo = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.User.UpdateProfile',
data
})
}
// 获取最近登录
// 修改密码
export const ResetPwd = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.User.AlterPass',
data
})
}
// 获取用户信息
export const GetMyPermission = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Permission.GetMyPermission',
data
})
}
// 获取第三方绑定信息
export const AuthorizationBindResult = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.UserBind.AuthorizationBindResult',
data
})
}
// 读取第三方配置
export const AuthorizationConfig = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Authorization_Authorization.AuthorizationConfig',
data
})
}
// 解除绑定
export const AuthorizationUnBind = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.UserBind.AuthorizationUnBind',
data
})
}

8
src/api/app.js Normal file
View File

@@ -0,0 +1,8 @@
import axios from '@/libs/api.request'
// export const GetConfigAppFrontHome = () => {
// return axios.request({
// method: 'get',
// url: '?r=AjaxApiMallConfig/GetConfigAppFrontHome'
// })
// }

71
src/api/application.js Normal file
View File

@@ -0,0 +1,71 @@
/* export function indexGetIndexData (data) {
return axios.request({
url: 'api/admin.php?s=Admin.Index.GetIndexData',
method: 'post',
data
})
} */
import axios from '@/libs/api.request'
// 应用管理列表
export const GetAppList = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Apps.GetAppList',
data
})
}
// 添加新应用
export const AddApp = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Apps.AddApp',
data
})
}
// 根据app_key查找应用
export const GetAppInfo = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Apps.GetMyAppInfo',
data
})
}
// 编辑应用
export const EditApp = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Apps.EditMyApp',
data
})
}
// 注销应用
export const CancelApp = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Apps.CancelApp',
data
})
}
// 获取下拉应用列表
export const GetAppDropdownList = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Apps.GetAppDropdownList',
data
})
}
// 获取全部接口及权限列表
export const GetAllAppApis = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Rights.GetAllAppApis',
data
})
}

22
src/api/data.js Normal file
View File

@@ -0,0 +1,22 @@
import axios from '@/libs/api.request'
// export const GetConfigAppFrontHome = () => {
// return axios.request({
// method: 'get',
// url: '?r=AjaxApiMallConfig/GetConfigAppFrontHome'
// })
// }
export const GetSiteData = () => {
return axios.request({
method: 'get',
url: 'platform.php?s=Platform.Site.Index'
})
}
export const UploadFile = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.File.Upload',
data
})
}

18
src/api/home.js Normal file
View File

@@ -0,0 +1,18 @@
import axios from '@/libs/api.request'
// 获取首页数据
export const GetIndexData = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Index_Index.GetIndexData',
data
})
}
// 获取接口数据
export const GetDataFlow = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Index_Index.GetDataFlow',
data
})
}

79
src/api/order.js Normal file
View File

@@ -0,0 +1,79 @@
import axios from '@/libs/api.request'
// export const GetConfigAppFrontHome = () => {
// return axios.request({
// method: 'get',
// url: '?r=AjaxApiMallConfig/GetConfigAppFrontHome'
// })
// }
export const GetSiteData = () => {
return axios.request({
method: 'get',
url: 'platform.php?s=Platform.Site.Index'
})
}
// 创建订单
export const CreateOrder = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Mall_Mall.CreateOrder',
data
})
}
// 准备下单
export const PreviewOrder = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Mall_Mall.PreviewOrder',
data
})
}
// 在线支付
export const PreviewPay = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Mall_Mall.PreviewPay',
data
})
}
// 开始支付
export const StartPay = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Mall_Mall.StartPay',
data
})
}
// 支付成功
export const PaySuccess = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Mall_Mall.PaySuccess',
data
})
}
// 获取我的订单列表
export const GetMyOrderList = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Mall_Mall.GetMyOrderList',
data
})
}
// 获取我的流量套餐
export const GetMyFlowList = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Mall_Mall.GetMyFlowList',
data
})
}
// 前台组合套餐列表
export const GetProductMoreList = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.Mall_Mall.GetProductMoreList',
data
})
}

64
src/api/workorder.js Normal file
View File

@@ -0,0 +1,64 @@
import axios from '@/libs/api.request'
// 获取工单列表
export const LstWorkOrder = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.WorkOrder_WorkOrder.LstWorkOrder',
data
})
}
// 新增工单
export const AddWorkOrder = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.WorkOrder_WorkOrder.AddWorkOrder',
data
})
}
// 模块列表
export const GetModuleLst = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.WorkOrder_WorkOrder.GetModuleLst',
data
})
}
// 工单详情
export const DetailWorkOrder = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.WorkOrder_WorkOrder.DetailWorkOrder',
data
})
}
// 更新工单信息
export const UpdateChatRecodeWorkOrder = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.WorkOrder_WorkOrder.UpdateChatRecodeWorkOrder',
data
})
}
// 上图
export const UploadImg = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.File.Upload',
data
})
}
// 获取上传类型UploadType
export const UploadType = (data) => {
return axios.request({
method: 'post',
url: 'platform.php?s=Platform.File.UploadType',
data
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

View File

@@ -0,0 +1,37 @@
@font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1541579316141'); /* IE9*/
src: url('iconfont.eot?t=1541579316141#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAiEAAsAAAAADmgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFY8eUnXY21hcAAAAYAAAACjAAACLi+YJuBnbHlmAAACJAAABAgAAAcg4dRWHmhlYWQAAAYsAAAAMQAAADYTL8piaGhlYQAABmAAAAAgAAAAJAfdA4xobXR4AAAGgAAAABQAAAAsLAD//2xvY2EAAAaUAAAAGAAAABgImgpGbWF4cAAABqwAAAAfAAAAIAEcAG5uYW1lAAAGzAAAAUUAAAJtPlT+fXBvc3QAAAgUAAAAbgAAAI54roygeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2BkYWCcwMDKwMHUyXSGgYGhH0IzvmYwYuRgYGBiYGVmwAoC0lxTGByeMTx/ytzwv4EhhrmBoRkozAiSAwDuUwzMeJzlkUEKwkAMRd/YabXFhQvxFF6qPYPrUujGY7jyIr1JoZNjtMnEhag3MOEN5MMk8D9QAoVyVSKEJwGrh6oh6wVN1iM3nc+cVImJVKdOehlklElmWdYVstp+ql8VdIv15a1NLW0zFXsO7Kjz3erH/3+rY37vr6kxnx1LKNWOJZlaxxJNnWOpSu+ot8jgqMvI6KjfyOSo88jsaAbI4tBsig89rQB4nLVUTWwbRRSeNzO767i2g7N/FP9s7MRrE5ON4/V6rSZyU0PiINSSNImES4IUoapWz6hEiqiMBDQqEojkAkiFStyKRC+9VSoFCeUEyqESVUAqEkcu3OAQb3hrJxAXwSGI3X0/szPz5vvm2x0i7O/vf8IJe5VkSJnUyUtklRBQJE1VIjRtUafkmk6pSu2ipleh4+xikkKxSksWTUeo8m8NoagpYtoslTmxrLl37z64e33esuJjU8P5Wd262LxoPVnPZ06Pxfe+C0YjkhSJygPhQCA8ABPOykwuN7NyuRvgUnAgLEnhATkaCQQiUe/7XKUyV6nQz+t2o7l66+rs7NVbq82GXTdrdjxjRGU5amTids2bUDMFtzCsqsMYMqr3IDY6OT05GjsI8Exv/6CSkOWEQigh+y3clxY5QVTcEZFIGtHLxDUJs6WsHR1y9SFKdr1HggCp3V1ICYL36OOpVmvKN9bC1u6R3vZ0qwWtVovgJfqOfUvfIYxIWL+fyETHNVJqSkIT1JTjW8ZWh3yDJDz0ctvsyt51etvrg9/QHhqGlzMM+vbmizPnDWPLMNbW19e7tffvsBzL99aWEfBRY46t+tbe3PypXv/IMDYN43WsQBe9HL2NC33RuxABrPsG+xH3o4bVRE2KgCRqulbWNf8W/UYVHM129aKra24VshZkq+CWD/Oy6Xt8cGYEthgHVlVliCfynAlqjo6oysTKlYUAD4docMI5/1ZioN+GwZNBcTwWUmTdBUqhTwX29QebXzF4An4JJMzwfMl+WQ01+IlQZVR4yhie53ycA16pOI/ODiYNGK4MChdCgXNnX5gIJXPCSYnf2OF850aQ+zJIyOs+u8+mMO8jQdwtg1TIWVRjKAnFcslMi8KfGUPoSUCergUyUk77dMyS69Ms6tijKZKYwUGKbpfdzu+iYeZYAHMFiOVi+MD7h9mb99qC0L7X8c+XatMfTj97KZ5IxJt/pd43tYYQKEjAnXMOB6kQEBrwg+LPjindAPOHNdC3q3ait0I3/ZIunZEARLNYNEUA6czSP3N/7j9wz6ZESdX0VNl1zGNS/szbQaQSIGk4DtVPcZf8AgXpf9A2OyTit5s2syZmand46bhEe2WtodLHkvaoqtTXuXN2/c42WADP9HGfbUcUW7JgqHss4xHtlMys679FqUomdP9VJBQBdnlPABBubpuNwqnmQj6/0HwNQzKxDUJFgKiXurBG6dqFjmeBzsvtRPJgGIZThYa5fdOvsReOticPh6JHHXxsv7ItJpOniYPYsmZ/x0QD/o5P105DeQwF6MH33ogoLi+KQp7zpY3HQV5bFMURzheXeds7gpP+jKNXljjHuYvXHke7cdCxLLZf6YX7B63UcCV4nGNgZGBgAOKAN2ZR8fw2Xxm4WRhA4AbHYRMY/f///1oWBuYGIJeDgQkkCgAvWgs2AAAAeJxjYGRgYG7438AQw8Lw/z8DAwsDA1AEBXADAHXiBHJ4nGNhYGBgYfj/nwVM48cATwECKwAAAAAAjAC6AOgBFAGAAf4CbgLqAzgDkHicY2BkYGDgZkhiYGcAASYg5gJCBob/YD4DABOmAYsAeJxlj01OwzAQhV/6B6QSqqhgh+QFYgEo/RGrblhUavdddN+mTpsqiSPHrdQDcB6OwAk4AtyAO/BIJ5s2lsffvHljTwDc4Acejt8t95E9XDI7cg0XuBeuU38QbpBfhJto41W4Rf1N2MczpsJtdGF5g9e4YvaEd2EPHXwI13CNT+E69S/hBvlbuIk7/Aq30PHqwj7mXle4jUcv9sdWL5xeqeVBxaHJIpM5v4KZXu+Sha3S6pxrW8QmU4OgX0lTnWlb3VPs10PnIhVZk6oJqzpJjMqt2erQBRvn8lGvF4kehCblWGP+tsYCjnEFhSUOjDFCGGSIyujoO1Vm9K+xQ8Jee1Y9zed0WxTU/3OFAQL0z1xTurLSeTpPgT1fG1J1dCtuy56UNJFezUkSskJe1rZUQuoBNmVXjhF6XNGJPyhnSP8ACVpuyAAAAHicbYhdDoIwEAb3a6k/YIIX8VArWewmdJFWJOnpJTG+OQ+TzJCjLy39p4ODR4OAA4444YwWHS7U3IVzn6Voldtb8ksHnvohrlqjjmw1rmzXsvdT7fEbblnCmOfNfJIYStJJfGIL27yb6AOCGR89AAA=') format('woff'),
url('iconfont.ttf?t=1541579316141') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('iconfont.svg?t=1541579316141#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family:"iconfont" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-bear:before { content: "\e600"; }
.icon-resize-vertical:before { content: "\e7c3"; }
.icon-chuizhifanzhuan:before { content: "\e661"; }
.icon-shuipingfanzhuan:before { content: "\e662"; }
.icon-qq:before { content: "\e609"; }
.icon-frown:before { content: "\e77e"; }
.icon-meh:before { content: "\e780"; }
.icon-smile:before { content: "\e783"; }
.icon-man:before { content: "\e7e2"; }
.icon-woman:before { content: "\e7e5"; }

Binary file not shown.

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
<font-face
font-family="iconfont"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="bear" unicode="&#58880;" d="M1024 683.008q0-70.656-46.08-121.856 46.08-89.088 46.08-193.536 0-96.256-39.936-181.248t-109.568-147.968-162.816-99.328-199.68-36.352-199.68 36.352-162.304 99.328-109.568 147.968-40.448 181.248q0 104.448 46.08 193.536-46.08 51.2-46.08 121.856 0 37.888 13.824 71.168t37.376 58.368 55.808 39.424 68.096 14.336q43.008 0 78.848-18.432t59.392-50.176q46.08 17.408 96.256 26.624t102.4 9.216 102.4-9.216 96.256-26.624q24.576 31.744 59.904 50.176t78.336 18.432q36.864 0 68.608-14.336t55.296-39.424 37.376-58.368 13.824-71.168zM205.824 268.288q10.24 0 18.944 10.24t15.36 28.672 10.24 42.496 3.584 51.712-3.584 51.712-10.24 41.984-15.36 28.16-18.944 10.24q-9.216 0-17.92-10.24t-15.36-28.16-10.752-41.984-4.096-51.712 4.096-51.712 10.752-42.496 15.36-28.672 17.92-10.24zM512-31.744000000000028q53.248 0 99.84 13.312t81.408 35.84 54.784 52.736 19.968 65.024q0 33.792-19.968 64t-54.784 52.736-81.408 35.84-99.84 13.312-99.84-13.312-81.408-35.84-54.784-52.736-19.968-64q0-34.816 19.968-65.024t54.784-52.736 81.408-35.84 99.84-13.312zM818.176 268.288q10.24 0 18.944 10.24t15.36 28.672 10.24 42.496 3.584 51.712-3.584 51.712-10.24 41.984-15.36 28.16-18.944 10.24q-9.216 0-17.92-10.24t-15.36-28.16-10.752-41.984-4.096-51.712 4.096-51.712 10.752-42.496 15.36-28.672 17.92-10.24zM512 235.51999999999998q39.936 0 68.096-9.728t28.16-24.064-28.16-24.064-68.096-9.728-68.096 9.728-28.16 24.064 28.16 24.064 68.096 9.728z" horiz-adv-x="1024" />
<glyph glyph-name="resize-vertical" unicode="&#59331;" d="M512 896C229.248 896 0 666.752 0 384s229.248-512 512-512 512 229.248 512 512S794.752 896 512 896zM576 192l64 0-128-128-128 128 64 0L448 576l-64 0 128 128 128-128-64 0L576 192z" horiz-adv-x="1024" />
<glyph glyph-name="chuizhifanzhuan" unicode="&#58977;" d="M286.01856 645.08416l472.4224 0 0-146.2784-472.4224 0 0 146.2784ZM87.19872 420.37248l885.80096 0 0-70.87104-885.80096 0 0 70.87104ZM773.55008 268.05248l0-31.0016L270.6688 237.05088l0 31.0016L773.55008 268.05248zM773.55008 121.4208l0-31.0016L270.6688 90.4192l0 31.0016L773.55008 121.4208zM742.54848 240.75776l31.0016 0 0-123.04896-31.0016 0L742.54848 240.75776zM270.70464 240.57856l31.0016 0 0-123.04896-31.0016 0L270.70464 240.57856z" horiz-adv-x="1024" />
<glyph glyph-name="shuipingfanzhuan" unicode="&#58978;" d="M252.76928 596.096l146.2784 0 0-472.42752-146.2784 0 0 472.42752ZM477.48096 810.65472l70.87104 0 0-885.80608-70.87104 0 0 885.80608ZM629.80096 611.2l31.0016 0 0-502.88128-31.0016 0L629.80096 611.2zM776.42752 611.2l31.0016 0 0-502.88128-31.0016 0L776.42752 611.2zM657.09056 580.1984l0 31.0016 123.04896 0 0-31.0016L657.09056 580.1984zM657.27488 108.35456l0 31.0016 123.04896 0 0-31.0016L657.27488 108.35456z" horiz-adv-x="1024" />
<glyph glyph-name="qq" unicode="&#58889;" d="M147.372058 491.394284c-5.28997-13.909921 2.431986-22.698872 0-75.732573-0.682996-14.25092-62.165649-78.762555-86.569511-145.791177-24.192863-66.517625-27.519845-135.978232 9.811944-163.285078 37.419789-27.305846 72.191593 90.879487 76.757567 73.685584 1.961989-7.509958 4.436975-15.317914 7.423958-23.338868a331.945126 331.945126 0 0 1 61.140655-101.162429c5.929967-6.783962-36.009797-19.199892-61.140655-61.99365-25.173858-42.751759 7.209959-120.49032 132.223254-120.49032 161.27909 0 197.288886 56.70368 200.574868 56.447681 12.031932-0.895995 12.841928 0 25.599855 0 15.572912 0 9.129948-1.279993 23.593867 0 7.807956 0.682996 86.186514-67.839617 194.686901-56.447681 184.873956 19.45589 156.586116 81.40754 142.079198 120.48932-15.103915 40.83277-68.692612 59.946662-66.303626 62.549647 44.28775 48.938724 51.285711 79.018554 66.346626 123.9463 6.143965 18.473896 49.066723-101.674426 82.089537-73.685584 13.781922 11.690934 41.301767 60.24566 13.781922 163.285078-27.519845 102.996419-80.767544 126.505286-79.615551 145.791177 2.389987 40.191773 1.023994 68.436614-1.023994 75.732573-9.812945 35.4128-30.378829 27.604844-30.378829 35.4128C858.450044 730.752933 705.10691 896 515.966978 896s-342.398067-165.289067-342.398068-369.192916c0-16.169909-14.378919-4.223976-26.154852-35.4128z" horiz-adv-x="1024" />
<glyph glyph-name="frown" unicode="&#59262;" d="M336 475m-48 0a48 48 0 1 1 96 0 48 48 0 1 1-96 0ZM688 475m-48 0a48 48 0 1 1 96 0 48 48 0 1 1-96 0ZM512 832C264.6 832 64 631.4 64 384s200.6-448 448-448 448 200.6 448 448S759.4 832 512 832z m263-711c-34.2-34.2-74-61-118.3-79.8C611 21.8 562.3 12 512 12c-50.3 0-99 9.8-144.8 29.2-44.3 18.7-84.1 45.6-118.3 79.8-34.2 34.2-61 74-79.8 118.3C149.8 285 140 333.7 140 384s9.8 99 29.2 144.8c18.7 44.3 45.6 84.1 79.8 118.3 34.2 34.2 74 61 118.3 79.8C413 746.2 461.7 756 512 756c50.3 0 99-9.8 144.8-29.2 44.3-18.7 84.1-45.6 118.3-79.8 34.2-34.2 61-74 79.8-118.3C874.2 483 884 434.3 884 384s-9.8-99-29.2-144.8c-18.7-44.3-45.6-84.1-79.8-118.2zM512 363c-85.5 0-155.6-67.3-160-151.6-0.2-4.6 3.4-8.4 8-8.4h48.1c4.2 0 7.8 3.2 8.1 7.4C420 259.9 461.5 299 512 299s92.1-39.1 95.8-88.6c0.3-4.2 3.9-7.4 8.1-7.4H664c4.6 0 8.2 3.8 8 8.4-4.4 84.3-74.5 151.6-160 151.6z" horiz-adv-x="1024" />
<glyph glyph-name="meh" unicode="&#59264;" d="M336 475m-48 0a48 48 0 1 1 96 0 48 48 0 1 1-96 0ZM688 475m-48 0a48 48 0 1 1 96 0 48 48 0 1 1-96 0ZM512 832C264.6 832 64 631.4 64 384s200.6-448 448-448 448 200.6 448 448S759.4 832 512 832z m263-711c-34.2-34.2-74-61-118.3-79.8C611 21.8 562.3 12 512 12c-50.3 0-99 9.8-144.8 29.2-44.3 18.7-84.1 45.6-118.3 79.8-34.2 34.2-61 74-79.8 118.3C149.8 285 140 333.7 140 384s9.8 99 29.2 144.8c18.7 44.3 45.6 84.1 79.8 118.3 34.2 34.2 74 61 118.3 79.8C413 746.2 461.7 756 512 756c50.3 0 99-9.8 144.8-29.2 44.3-18.7 84.1-45.6 118.3-79.8 34.2-34.2 61-74 79.8-118.3C874.2 483 884 434.3 884 384s-9.8-99-29.2-144.8c-18.7-44.3-45.6-84.1-79.8-118.2zM664 331H360c-4.4 0-8-3.6-8-8v-48c0-4.4 3.6-8 8-8h304c4.4 0 8 3.6 8 8v48c0 4.4-3.6 8-8 8z" horiz-adv-x="1024" />
<glyph glyph-name="smile" unicode="&#59267;" d="M336 475m-48 0a48 48 0 1 1 96 0 48 48 0 1 1-96 0ZM688 475m-48 0a48 48 0 1 1 96 0 48 48 0 1 1-96 0ZM512 832C264.6 832 64 631.4 64 384s200.6-448 448-448 448 200.6 448 448S759.4 832 512 832z m263-711c-34.2-34.2-74-61-118.3-79.8C611 21.8 562.3 12 512 12c-50.3 0-99 9.8-144.8 29.2-44.3 18.7-84.1 45.6-118.3 79.8-34.2 34.2-61 74-79.8 118.3C149.8 285 140 333.7 140 384s9.8 99 29.2 144.8c18.7 44.3 45.6 84.1 79.8 118.3 34.2 34.2 74 61 118.3 79.8C413 746.2 461.7 756 512 756c50.3 0 99-9.8 144.8-29.2 44.3-18.7 84.1-45.6 118.3-79.8 34.2-34.2 61-74 79.8-118.3C874.2 483 884 434.3 884 384s-9.8-99-29.2-144.8c-18.7-44.3-45.6-84.1-79.8-118.2zM664 363h-48.1c-4.2 0-7.8-3.2-8.1-7.4C604 306.1 562.5 267 512 267s-92.1 39.1-95.8 88.6c-0.3 4.2-3.9 7.4-8.1 7.4H360c-4.6 0-8.2-3.8-8-8.4 4.4-84.3 74.5-151.6 160-151.6s155.6 67.3 160 151.6c0.2 4.6-3.4 8.4-8 8.4z" horiz-adv-x="1024" />
<glyph glyph-name="man" unicode="&#59362;" d="M874 776H622c-3.3 0-6-2.7-6-6v-56c0-3.3 2.7-6 6-6h160.4L583.1 508.7c-50 38.5-111 59.3-175.1 59.3-76.9 0-149.3-30-203.6-84.4S120 356.9 120 280s30-149.3 84.4-203.6C258.7 22 331.1-8 408-8s149.3 30 203.6 84.4C666 130.7 696 203.1 696 280c0 64.1-20.8 124.9-59.2 174.9L836 654.1V494c0-3.3 2.7-6 6-6h56c3.3 0 6 2.7 6 6V746c0 16.5-13.5 30-30 30zM408 68c-116.9 0-212 95.1-212 212s95.1 212 212 212 212-95.1 212-212-95.1-212-212-212z" horiz-adv-x="1024" />
<glyph glyph-name="woman" unicode="&#59365;" d="M909.7 739.4l-42.2 42.2c-3.1 3.1-8.2 3.1-11.3 0L764 689.4l-84.2 84.2c-3.1 3.1-8.2 3.1-11.3 0l-42.1-42.1c-3.1-3.1-3.1-8.1 0-11.3l84.2-84.2-135.5-135.3c-50 38.5-111 59.3-175.1 59.3-76.9 0-149.3-30-203.6-84.4S112 348.9 112 272s30-149.3 84.4-203.6C250.7 14 323.1-16 400-16s149.3 30 203.6 84.4C658 122.7 688 195.1 688 272c0 64.2-20.9 125.1-59.3 175.1l135.4 135.4 84.2-84.2c3.1-3.1 8.2-3.1 11.3 0l42.1 42.1c3.1 3.1 3.1 8.1 0 11.3l-84.2 84.2 92.2 92.2c3.1 3.1 3.1 8.2 0 11.3zM400 60c-116.9 0-212 95.1-212 212s95.1 212 212 212 212-95.1 212-212-95.1-212-212-212z" horiz-adv-x="1024" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
src/assets/images/cash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1547543883733" class="icon" style="" viewBox="0 0 1272 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16831" xmlns:xlink="http://www.w3.org/1999/xlink" width="496.875" height="400"><defs><style type="text/css"></style></defs><path d="M729.64116345 165.27693991L634.32650881 90.125l-99.5625 78.52693991-5.17887981 4.16056009 104.74137981 83.50215546 105.09051682-83.50215546-9.77586218-7.53556009z m361.21228445 291.47198236l-456.78879245 360.19396555-456.49784537-359.99030128L110.125 511.12715547l523.93965546 413.11745671 524.23060335-413.35021555-67.44181091-54.14547436z m-456.78879245 29.21120673L385.4784479 290.00646554 318.06573237 344.12284454l315.96982771 249.16810336 316.28987101-249.40086136-67.41271555-54.14547436-248.84806008 196.21551682z" fill="#006cff" p-id="16832"></path></svg>

After

Width:  |  Height:  |  Size: 955 B

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1547543874130" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16498" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400"><defs><style type="text/css"></style></defs><path d="M511.8 0.6C229.2 0.6 0.1 229.7 0.1 512.3S229.2 1024 511.8 1024s511.7-229.1 511.7-511.7S794.4 0.6 511.8 0.6z m264.9 375.3c-0.1 0.1-0.1 0.2-0.2 0.3h0.2c-9 14.3-21.2 28.8-34.2 39.2-5.2 4.2-10.5 8.3-15.7 12.5v0.5c0.3 22.9-0.3 44.9-4.7 64.2-25.2 113.1-91.9 189.9-197.4 222.8-37.9 11.8-99.1 16.7-142.6 5.9-21.5-5.4-41-11.4-59.3-19.3-10.2-4.5-19.6-9.3-28.5-14.7l-8.8-5.3h0.5l-0.5-0.3c9.8 0.2 21.3 2.9 32.2 1.2 9.8-1.6 19.6-1.2 28.7-3.2 22.7-5 43-11.6 60.4-21.8 8.3-4.8 20.9-10.6 27-17.6-11.2 0.2-21.4-2.4-29.7-5.4-32.6-11.5-51.6-32.7-63.9-64.4h0.1c0-0.1-0.1-0.2-0.1-0.3 9.7 1.1 37.3 3.5 44.6-1.7-12.3-0.8-24.1-7.9-32.5-13.2-26.2-16.4-47.6-43.9-47.4-86.2v-0.3c3.5 1.7 6.9 3.3 10.4 4.9 6.6 2.8 13.3 4.3 21.1 5.9 3.1 0.7 9.3 2.4 13.2 1.4-5.1-5.8-13.2-9.7-18.4-16-14.7-18.3-28.7-45.3-25.2-77.4 0.5-4.7 1.3-9.4 2.6-14.3 2.5-9.7 6.5-18.3 10.8-26.2 0.2 0.1 0.4 0.2 0.5 0.3 2 4.2 6.4 7.2 9.1 10.6 8.6 10.7 19.2 20.3 30 28.7 36.7 28.7 69.9 46.4 123.1 59.5 13.5 3.3 29 5.9 45.1 5.9-1.9-5.8-2.7-13-2.7-20.5 0-9.7 1.3-19.6 3.3-26.8 9-32.1 28.5-55.2 57-67.6 6.9-3 14.4-5.2 22.4-6.9 4.1-0.6 8.2-1.1 12.3-1.6 39-0.7 59.8 13.5 79.6 31.6 16.8-1.4 38.7-10.8 51.6-17.4l12.6-6.9c0 0.1-0.1 0.3-0.1 0.4l0.1-0.1c-7.3 19.9-17.4 35.5-32.7 47.3-3.1 2.4-6.3 5.6-10 7.4 21.5-0.4 39.3-10 56.1-15.4v0.3z" fill="#2EB1EB" p-id="16499"></path><path d="M719.7 391.1s0.1 0 0.1-0.1c0 0-0.1 0-0.1 0.1zM726.8 428.4v-0.5 0.5zM336.4 479.9c3.3 0.7 9.9 2.7 13.8 1.2h-0.5l-0.1-0.1c-3.9 1-10.1-0.7-13.2-1.4-7.8-1.6-14.5-3.1-21.1-5.9-3.5-1.6-6.9-3.2-10.4-4.9v0.3c3.4 1.6 6.9 3.2 10.4 4.9 6.6 2.8 13.3 4.3 21.1 5.9zM719.6 391.4v0.2c21.9-0.2 39.8-10.1 56.9-15.4 0.1-0.1 0.1-0.2 0.2-0.3v-0.3c-16.9 5.3-34.6 14.9-56.1 15.4-0.4 0.1-0.7 0.3-1 0.4zM584.8 337.5c6.9-3 14.4-5.1 22.4-6.9 4.1-0.6 8.2-1 12.3-1.6 39-0.7 59.8 13.5 79.6 31.6 16.8-1.4 38.7-10.8 51.6-17.4 4.2-2.3 8.3-4.5 12.5-6.8 0-0.1 0.1-0.3 0.1-0.4l-12.6 6.9c-12.9 6.6-34.8 16-51.6 17.4-19.8-18.1-40.6-32.3-79.6-31.6-4.1 0.5-8.2 1-12.3 1.6-8 1.7-15.5 3.9-22.4 6.9-28.5 12.4-48 35.5-57 67.6-2 7.2-3.4 17.2-3.3 26.8 0-9.6 1.3-19.4 3.3-26.5 9-32.1 28.5-55.2 57-67.6zM385.2 568.5h-0.4c-7.3 5.2-34.9 2.8-44.6 1.7 0 0.1 0.1 0.2 0.1 0.3 10 1.1 38.2 3.6 44.9-2zM319.4 347.4c0.1 0.1 0.3 0.1 0.5 0.3 2 4.1 6.3 7.1 9.1 10.6 8.6 10.6 19.2 20.2 30 28.7 36.8 28.7 69.9 46.4 123.1 59.5 13.5 3.3 29.1 5.9 45.2 5.9 0-0.1-0.1-0.2-0.1-0.3-16.1 0-31.6-2.6-45.1-5.9-53.2-13.1-86.4-30.8-123.1-59.5-10.8-8.4-21.4-18-30-28.7-2.7-3.4-7.1-6.4-9.1-10.6-0.1-0.1-0.3-0.2-0.5-0.3-4.3 7.9-8.3 16.5-10.8 26.2-1.3 4.9-2.1 9.6-2.6 14.3 0.5-4.6 1.3-9.2 2.6-14 2.5-9.7 6.5-18.3 10.8-26.2zM317.7 683.2c9.9-1.6 19.6-1.2 28.7-3.2 22.8-5 43-11.6 60.4-21.8 8.4-4.9 21.3-10.8 27.3-17.9h-0.3c-6.1 7-18.7 12.8-27 17.6-17.4 10.2-37.7 16.8-60.4 21.8-9.1 2-18.9 1.6-28.7 3.2-10.9 1.7-22.4-1-32.2-1.2l0.5 0.3c9.7 0.4 21 2.9 31.7 1.2z" fill="#FFFFFF" p-id="16500"></path></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1547543863835" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16165" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400"><defs><style type="text/css"></style></defs><path d="M512 1024C229.236364 1024 0 794.763636 0 512S229.236364 0 512 0s512 229.236364 512 512-229.236364 512-512 512z m-129.861818-756.48s-36.212364 2.094545-48.989091 24.482909c-12.8 22.365091-54.318545 137.378909-54.318546 137.378909s13.847273 6.376727 37.28291-10.658909c23.435636-17.035636 30.882909-46.848 30.882909-46.848l42.589091-2.117818 1.070545 121.390545s-73.495273-1.070545-88.413091 0c-14.894545 1.047273-23.412364 40.448-23.412364 40.448h111.825455s-9.588364 67.095273-38.353455 116.084364c-28.741818 48.989091-83.060364 87.319273-83.060363 87.319273s39.424 15.965091 77.730909-6.4c38.353455-22.341818 66.629818-120.692364 66.629818-120.692364l89.925818 110.056727s8.192-52.386909-1.466182-67.188363c-9.658182-14.778182-62.208-74.286545-62.208-74.286546l-22.946909 20.247273 16.337455-65.117091h97.954909s0-38.353455-19.153455-40.494545c-19.176727-2.094545-78.801455 0-78.801454 0V371.898182h88.389818s-1.070545-39.400727-18.106182-39.400727h-143.755636l22.341818-64.954182z m169.984 61.184v358.562909h36.002909l13.102545 45.009455 63.348364-45.009455h89.064727V328.704h-201.518545z" fill="#0f84fd" p-id="16166"></path><path d="M594.781091 368.64h117.899636v277.876364h-41.890909l-53.364363 40.261818-11.636364-40.261818h-11.008V368.64z" fill="#0f84fd" p-id="16167"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src/assets/images/left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
src/assets/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/assets/images/money.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
src/assets/images/right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,156 @@
<template>
<div class="percentloop">
<div class="circle-left">
<div ref="leftcontent"></div>
</div>
<div class="circle-right">
<div ref="rightcontent"></div>
</div>
<div class="number">
{{ percent }} %
</div>
</div>
</template>
<script>
export default {
props: {
percentNum: {
type: [String, Number],
default: 0
},
speed: { // 建议取值为0-3
type: [String, Number],
default: 1
}
},
data () {
return {
percent: 0,
initDeg: 0,
timeId: null,
animationing: false
}
},
methods: {
transformToDeg (percent) {
let deg = 0
if (percent >= 100) {
deg = 360
} else {
deg = parseInt(360 * percent / 100)
}
return deg
},
transformToPercent (deg) {
let percent = 0
if (deg >= 360) {
percent = 100
} else {
percent = parseInt(100 * deg / 360)
}
return percent
},
rotateLeft (deg) { // 大于180时执行的动画
this.$refs.leftcontent.style.transform = 'rotate(' + (deg - 180) + 'deg)'
},
rotateRight (deg) { // 小于180时执行的动画
this.$refs.rightcontent.style.transform = 'rotate(' + deg + 'deg)'
},
goRotate (deg) {
this.animationing = true
this.timeId = setInterval(() => {
if (deg > this.initDeg) { // 递增动画
this.initDeg += Number(this.speed)
if (this.initDeg >= 180) {
this.rotateLeft(this.initDeg)
this.rotateRight(180) // 为避免前后两次传入的百分比转换为度数后的值不为步距的整数,可能出现的左右转动不到位的情况。
} else {
this.rotateRight(this.initDeg)
}
} else { // 递减动画
this.initDeg -= Number(this.speed)
if (this.initDeg >= 180) {
this.rotateLeft(this.initDeg)
} else {
this.rotateLeft(180) // 为避免前后两次传入的百分比转换为度数后的值不为步距的整数,可能出现的左右转动不到位的情况。
this.rotateRight(this.initDeg)
}
}
this.percent = this.transformToPercent(this.initDeg) // 百分比数据滚动动画
const remainer = Number(deg) - this.initDeg
if (Math.abs(remainer) < this.speed) {
this.initDeg += remainer
if (this.initDeg > 180) {
this.rotateLeft(deg)
} else {
this.rotateRight(deg)
}
this.animationFinished()
}
}, 10)
},
animationFinished () {
this.percent = this.percentNum // 百分比数据滚动动画
this.animationing = false
clearInterval(this.timeId)
this.$emit('animationFinished') // 动画完成的回调
}
},
created () {
this.goRotate(this.transformToDeg(this.percentNum))
},
watch: {
'percentNum': function (val) {
if (this.animationing) return
this.goRotate(this.transformToDeg(val))
}
}
}
</script>
<style scoped lang="scss">
.percentloop {
position: relative;
width: 100%;
height: 100%;
border-radius: 50%;
overflow: hidden;
.circle-left, .circle-right {
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 100%;
background-color: red;
overflow: hidden;
&>div {
width: 100%;
height: 100%;
background-color: #8a8a8a;
transform-origin: right center;
/*transition: all .5s linear;*/
}
}
.circle-right {
left: 50%;
&>div {
transform-origin: left center;
}
}
.number {
position: absolute;
top: 9%;
bottom: 9%;
left: 9%;
right: 9%;
background-color: #fff;
border-radius: 50%;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
color: #000;
}
}
</style>

View File

@@ -0,0 +1,284 @@
<template>
<div>
<Modal
id="assets-libs"
class="img-lib"
v-model="showLibs"
title="素材库"
width='1055px'
@on-ok="ok"
@on-cancel="cancel">
<CheckboxGroup v-if="this.fileList.length" v-model="selected" @on-change="checkboxChange" class="assets-collection" >
<item-card
:class="['assets-collection-item', {'selected':is_selected(item)}]"
v-for="item in fileList"
:key="item.id"
:fileData="item"
@del_item="delImg">
</item-card>
</CheckboxGroup>
<div v-else class="empty-libs">
<Icon type="md-images" />
<p>素材库内容目前还是空的</p>
</div>
<div class="flexbox" slot="footer">
<div class="pagination">
<Page :page-size-opts="pageSizeOpts" :page-size="20" :total="total" show-sizer @on-page-size-change='changeSize' @on-change='changePage'/>
</div>
<div class="buttons">
<Upload
:action="uploadApi"
:format="['jpg','jpeg','png']"
:max-size="2048"
:before-upload="handleUpload"
:on-format-error="handleFormatError"
:on-exceeded-size="handleMaxSize"
:on-success="uploadSuccess"
>
<Button :loading="loadingStatus" size="large"><Icon type="ios-cloud-upload-outline" />&nbsp;&nbsp;上传图片&nbsp;</Button>
</Upload>
<Button type="primary" size="large" @click="ok">确定选择</Button>
</div>
</div>
</Modal>
</div>
</template>
<script>
import { GetImgList, DocsRecordDelete } from '@/api/data'
import ItemCard from './item-card.vue'
export default {
components: {
ItemCard
},
name: 'assets-libs',
props: {
// 可选,最大选择数量
maxSelected: {
type: Number,
default: 1
},
uploadApi: {
type: String,
required: true
}
},
data () {
return {
showLibs: false,
total: 0,
fileList: [],
fileName: '', // 查询名字
fileType: '', // 文件类型
currentOrder: 'desc', // 升序降序
page: 1, // 分页
perpage: 20,
orderType: '降序', // 下拉框默认,
selected: [],
pageSizeOpts: [20, 30, 40],
loadingStatus: false,
bindName: '' // 可传入绑定的字段再emit事件时带出
}
},
computed: {
},
methods: {
is_selected (item) {
let is_selected = this.selected.findIndex((value) => {
return value === item.file_url
})
if (is_selected >= 0) {
return true
}
return false
},
_initOption () { // 筛选条件初始化
let file_name = this.fileName
let file_type = this.fileType
let order_type = this.currentOrder
let page = this.page
let perpage = this.perpage
// post 参数为空的时候不加入
let data = { order_type, page, perpage }
if (file_name) {
data.file_name = file_name
}
if (file_type) {
data.file_name = file_type
}
return data
},
_reset () {
let {
fileName,
fileType,
currentOrder,
page,
perpage,
orderType,
bindName,
selected
} = this.$options.data()
const originData = {
fileName,
fileType,
currentOrder,
page,
perpage,
orderType,
bindName,
selected
}
Object.assign(this.$data, originData)
this.getImgs()
},
checkboxChange (value) {
if (this.maxSelected === 1 && this.selected.length > 1) {
this.selected.shift()
} else if (this.selected.length > this.maxSelected) {
this.selected.pop()
this.$Message.info(`当前选项不得超过${this.maxSelected}个。`)
}
},
show (bindName) {
if (bindName) {
this.bindName = bindName
}
this.showLibs = true
},
hide () {
this._reset()
this.showLibs = false
},
delImg (id) {
DocsRecordDelete({ id }).then(res => {
this.getImgs()
this.$Message.success('图片已删除。')
})
},
ok () {
if (this.bindName) {
let params = {
bindName: this.bindName,
value: this.selected
}
this.$emit('selected', params)
} else {
this.$emit('selected', this.selected)
}
this.hide()
},
cancel () {
this._reset()
},
getImgs () {
let data = this._initOption()
const formdata = new FormData()
// formdata.append('access_token', this.token)
if (data.file_name) {
formdata.append('file_name', data.file_name)
}
if (data.file_type) {
formdata.append('sort', data.orderType)
}
formdata.append('by', data.order_type)
formdata.append('page', this.page)
formdata.append('perpage', this.perpage)
GetImgList(formdata).then(res => {
if (res.code === 0) {
this.total = res.totalCount
this.fileList = res.recordList
} else {
this.$Message.error(res.msg)
}
})
},
changeSize (size) {
this.perpage = size
this.getImgs()
},
changePage (page) {
this.page = page
this.getImgs()
},
handleUpload (file) {
this.loadingStatus = true
},
handleFormatError (file) {
this.$Message.warning({
content: '请上传正确的图片格式文件。'
})
this.loadingStatus = false
},
handleMaxSize (file) {
this.$Message.warning({
content: '请将上传的图片控制在2M以内。'
})
this.loadingStatus = false
},
uploadSuccess (response, file, fileList) {
this.loadingStatus = false
this.getImgs()
}
},
created () {
this.getImgs()
}
}
</script>
<style lang="less">
.selected {
box-shadow: rgb(217, 233, 247) 1px 1px 6px 2px;
}
.assets-collection {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.ivu-modal{
top: 20px;
height: 80%;
}
.img-lib {
.ivu-modal-body {
overflow-y: scroll;
height: 560px;
padding-top: 0;
}
.ivu-modal-footer .flexbox {
display: flex;
justify-content: space-between;
.buttons {
display: flex;
.ivu-btn-large {
height: 36px;
margin-left: 10px;
}
}
.ivu-upload-list {
display: none !important;
}
}
}
.empty-libs {
width: 250px;
margin: 0 auto;
margin-top: 20px;
font-size: 250px;
color: #7485a9;
p {
font-size: 14px;
font-weight: 600;
text-align: center;
}
}
</style>

View File

@@ -0,0 +1,221 @@
<template>
<div class="item-card">
<div class="hover-card">
<div class="img-container">
<img :src="file_logo" alt="">
</div>
<div class="item-headline" :title="fileData.file_name" @click="showPic">
<p class="item-name">{{fileData.file_name}}</p><Icon class="item-delet" @click.stop="del_item(fileData.id)" type="md-close" />
</div>
</div>
<Checkbox :label="fileData.file_url" ></Checkbox>
<div v-show="false" class="item-info">
<!-- <span>{{fileData.file_type}}</span> -->
<span style="margin-right: 15px;">大小<span>{{fileSize}}</span></span>
<span>上传于<span>{{fileAddTime}}</span></span>
</div>
<Input v-show="false" v-model="fileData.file_url" readonly>
<a href="javascript:void(0);" class="copyButton" v-clipboard="copyLink" slot="append">复制</a>
</Input>
</div>
</template>
<script>
import { DelFile } from '@/api/data'
import { getToken } from '@/libs/util'
export default {
props: {
fileData: {
type: Object
}
},
methods: {
showPic () {
window.open(this.fileData.file_url, '_blank')
},
del_item (id) {
this.$Modal.confirm({
title: '提示',
content: '<p>是否确定删除?</p>',
className: 'vertical-center-modal',
onOk: () => {
this.$emit('delItem', id)
},
onCancel: () => {
return false
}
})
}
},
computed: {
fileSize () {
let size = this.fileData.file_size / 1024
if (size > 1024) {
size = size / 1024
size = Math.floor(size * 100) / 100 + 'MB'
} else {
size = Math.floor(size * 100) / 100 + 'KB'
}
return size
},
fileAddTime () {
let data_time = this.fileData.add_time
let time = data_time.slice(0, 10)
return time
},
copyLink () {
return {
value: this.fileData.file_url,
success: (e) => {
this.$Message.success('复制成功')
},
error: () => {
this.$Message.error('复制失败')
}
}
},
file_logo () {
// todo 扩展其他文件的logo 使用swtich方式
if (/\.(jpe?g|png|gif)$/i.test(this.fileData.file_url)) {
return this.fileData.file_url
} else if (/\.(xlsx?)$/i.test(this.fileData.file_url)) {
let logo = require('@/assets/icons/file-icon/xls_logo.jpg')
return logo
} else if (/\.(docx?)$/i.test(this.fileData.file_url)) {
let logo = require('@/assets/icons/file-icon/doc_logo.jpg')
return logo
} else if (/\.(pptx?)$/i.test(this.fileData.file_url)) {
let logo = require('@/assets/icons/file-icon/ppt_logo.jpg')
return logo
} else if (/\.(html)$/i.test(this.fileData.file_url)) {
let logo = require('@/assets/icons/file-icon/html_logo.jpg')
return logo
} else {
let logo = require('@/assets/icons/file-icon/others_logo.jpg')
return logo
}
}
}
}
</script>
<style lang="less" scoped>
.item-card {
width: 170px;
font-size: 14px;
display: flex;
flex-flow: column;
justify-content: space-between;
margin-top: 15px;
padding-bottom: 25px;
position: relative;
margin: 5px 15px;
label {
position: absolute;
top: 3px;
right: -3px;
}
.hover-card {
border-radius: 3px;
}
.img-container {
width: 100%;
height: 168px;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.item-headline {
display: flex;
justify-content: space-between;
cursor: pointer;
position: absolute;
bottom: 0px;
width:170px;
background: #fff;
padding: 2px 3px 3px;
.item-name {
font-weight: 600;
color: #57a3f3;
overflow: hidden;
text-overflow:ellipsis;
white-space:nowrap;
width: 280px;
font-size: 12px;
}
.item-delet {
display: none;
padding-right: 5px;
padding-top: 5px;
color: #fff;
}
}
.item-info {
display: flex;
justify-content: start;
color: #838383;
margin: 5px 0;
font-size: 12px;
}
.copyButton {
color: #515a6e;
}
.copyButton:hover {
color: #57a3f3;
}
}
.item-card:hover {
box-shadow: rgb(223, 223, 223) 1px 1px 6px 2px;
.item-headline {
background: rgb(25, 92, 146);
}
.item-name {
color: #fff;
}
.item-delet {
display: inline-block;
}
.item-delet:hover {
display: inline-block;
color: rgb(255, 60, 0);
}
}
.ivu-modal-wrap .ivu-modal {
margin-top: 200px;
}
.ivu-checkbox:nth-child(1) {
display: none;
}
.assets-collection label /deep/ span:nth-child(2) {
display: none;
}
.assets-collection label /deep/ .ivu-checkbox-inner {
border: 2px solid #41a0ff82;
height: 17px;
width: 17px;
box-shadow: #cdd2ff 0px 0px 5px 0px;
}
.ivu-checkbox-inner:after {
left: 5px!important;
}
</style>

View File

@@ -0,0 +1,58 @@
<template>
<div ref="dom" class="charts chart-bar"></div>
</template>
<script>
import echarts from 'echarts'
import tdTheme from './theme.json'
import { on, off } from '@/libs/tools'
echarts.registerTheme('tdTheme', tdTheme)
export default {
name: 'ChartBar',
props: {
value: Object,
text: String,
subtext: String
},
data () {
return {
dom: null
}
},
methods: {
resize () {
this.dom.resize()
}
},
mounted () {
this.$nextTick(() => {
let xAxisData = Object.keys(this.value)
let seriesData = Object.values(this.value)
let option = {
title: {
text: this.text,
subtext: this.subtext,
x: 'center'
},
xAxis: {
type: 'category',
data: xAxisData
},
yAxis: {
type: 'value'
},
series: [{
data: seriesData,
type: 'bar'
}]
}
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
this.dom.setOption(option)
on(window, 'resize', this.resize)
})
},
beforeDestroy () {
off(window, 'resize', this.resize)
}
}
</script>

View File

@@ -0,0 +1,3 @@
import ChartPie from './pie.vue'
import ChartBar from './bar.vue'
export { ChartPie, ChartBar }

View File

@@ -0,0 +1,70 @@
<template>
<div ref="dom" class="charts chart-pie"></div>
</template>
<script>
import echarts from 'echarts'
import tdTheme from './theme.json'
import { on, off } from '@/libs/tools'
echarts.registerTheme('tdTheme', tdTheme)
export default {
name: 'ChartPie',
props: {
value: Array,
text: String,
subtext: String
},
data () {
return {
dom: null
}
},
methods: {
resize () {
this.dom.resize()
}
},
mounted () {
this.$nextTick(() => {
let legend = this.value.map(_ => _.name)
let option = {
title: {
text: this.text,
subtext: this.subtext,
x: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 'left',
data: legend
},
series: [
{
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
data: this.value,
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
}
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
this.dom.setOption(option)
on(window, 'resize', this.resize)
})
},
beforeDestroy () {
off(window, 'resize', this.resize)
}
}
</script>

View File

@@ -0,0 +1,491 @@
{
"color": [
"#2d8cf0",
"#19be6b",
"#ff9900",
"#E46CBB",
"#9A66E4",
"#ed3f14"
],
"backgroundColor": "rgba(0,0,0,0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#516b91"
},
"subtextStyle": {
"color": "#93b7e3"
}
},
"line": {
"itemStyle": {
"normal": {
"borderWidth": "2"
}
},
"lineStyle": {
"normal": {
"width": "2"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true
},
"radar": {
"itemStyle": {
"normal": {
"borderWidth": "2"
}
},
"lineStyle": {
"normal": {
"width": "2"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true
},
"bar": {
"itemStyle": {
"normal": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
},
"emphasis": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
}
}
},
"pie": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"scatter": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"boxplot": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"parallel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"sankey": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"funnel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"gauge": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"candlestick": {
"itemStyle": {
"normal": {
"color": "#edafda",
"color0": "transparent",
"borderColor": "#d680bc",
"borderColor0": "#8fd3e8",
"borderWidth": "2"
}
}
},
"graph": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"lineStyle": {
"normal": {
"width": 1,
"color": "#aaa"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true,
"color": [
"#2d8cf0",
"#19be6b",
"#f5ae4a",
"#9189d5",
"#56cae2",
"#cbb0e3"
],
"label": {
"normal": {
"textStyle": {
"color": "#eee"
}
}
}
},
"map": {
"itemStyle": {
"normal": {
"areaColor": "#f3f3f3",
"borderColor": "#516b91",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(165,231,240,1)",
"borderColor": "#516b91",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#000"
}
},
"emphasis": {
"textStyle": {
"color": "rgb(81,107,145)"
}
}
}
},
"geo": {
"itemStyle": {
"normal": {
"areaColor": "#f3f3f3",
"borderColor": "#516b91",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(165,231,240,1)",
"borderColor": "#516b91",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#000"
}
},
"emphasis": {
"textStyle": {
"color": "rgb(81,107,145)"
}
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"toolbox": {
"iconStyle": {
"normal": {
"borderColor": "#999"
},
"emphasis": {
"borderColor": "#666"
}
}
},
"legend": {
"textStyle": {
"color": "#999999"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "#ccc",
"width": 1
},
"crossStyle": {
"color": "#ccc",
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"color": "#8fd3e8",
"width": 1
},
"itemStyle": {
"normal": {
"color": "#8fd3e8",
"borderWidth": 1
},
"emphasis": {
"color": "#8fd3e8"
}
},
"controlStyle": {
"normal": {
"color": "#8fd3e8",
"borderColor": "#8fd3e8",
"borderWidth": 0.5
},
"emphasis": {
"color": "#8fd3e8",
"borderColor": "#8fd3e8",
"borderWidth": 0.5
}
},
"checkpointStyle": {
"color": "#8fd3e8",
"borderColor": "rgba(138,124,168,0.37)"
},
"label": {
"normal": {
"textStyle": {
"color": "#8fd3e8"
}
},
"emphasis": {
"textStyle": {
"color": "#8fd3e8"
}
}
}
},
"visualMap": {
"color": [
"#516b91",
"#59c4e6",
"#a5e7f0"
]
},
"dataZoom": {
"backgroundColor": "rgba(0,0,0,0)",
"dataBackgroundColor": "rgba(255,255,255,0.3)",
"fillerColor": "rgba(167,183,204,0.4)",
"handleColor": "#a7b7cc",
"handleSize": "100%",
"textStyle": {
"color": "#333"
}
},
"markPoint": {
"label": {
"normal": {
"textStyle": {
"color": "#eee"
}
},
"emphasis": {
"textStyle": {
"color": "#eee"
}
}
}
}
}

View File

@@ -0,0 +1,42 @@
<template>
<component :is="iconType" :type="iconName" :color="iconColor" :size="iconSize"/>
</template>
<script>
import Icons from '_c/icons'
export default {
name: 'CommonIcon',
components: { Icons },
props: {
type: {
type: String,
required: true
},
color: String,
size: Number
},
computed: {
iconType () {
return this.type.indexOf('_') === 0 ? 'Icons' : 'Icon'
},
iconName () {
return this.iconType === 'Icons' ? this.getCustomIconName(this.type) : this.type
},
iconSize () {
return this.size || (this.iconType === 'Icons' ? 12 : undefined)
},
iconColor () {
return this.color || ''
}
},
methods: {
getCustomIconName (iconName) {
return iconName.slice(1)
}
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,2 @@
import CommonIcon from './common-icon.vue'
export default CommonIcon

View File

@@ -0,0 +1,8 @@
.no-select{
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

View File

@@ -0,0 +1,3 @@
export const showTitle = (item, vm) => {
return vm.$config.useI18n ? vm.$t(item.name) : ((item.meta && item.meta.title) || item.name)
}

View File

@@ -0,0 +1,174 @@
<template>
<div class="count-to-wrapper">
<slot name="left"/>
<p class="content-outer"><span :class="['count-to-count-text', countClass]" :id="counterId">{{ init }}</span><i :class="['count-to-unit-text', unitClass]">{{ unitText }}</i></p>
<slot name="right"/>
</div>
</template>
<script>
import CountUp from 'countup'
import './index.less'
export default {
name: 'CountTo',
props: {
init: {
type: Number,
default: 0
},
/**
* @description 起始值,即动画开始前显示的数值
*/
startVal: {
type: Number,
default: 0
},
/**
* @description 结束值,即动画结束后显示的数值
*/
end: {
type: Number,
required: true
},
/**
* @description 保留几位小数
*/
decimals: {
type: Number,
default: 0
},
/**
* @description 分隔整数和小数的符号,默认是小数点
*/
decimal: {
type: String,
default: '.'
},
/**
* @description 动画持续的时间,单位是秒
*/
duration: {
type: Number,
default: 2
},
/**
* @description 动画延迟开始的时间,单位是秒
*/
delay: {
type: Number,
default: 0
},
/**
* @description 是否禁用easing动画效果
*/
uneasing: {
type: Boolean,
default: false
},
/**
* @description 是否使用分组,分组后每三位会用一个符号分隔
*/
usegroup: {
type: Boolean,
default: false
},
/**
* @description 用于分组(usegroup)的符号
*/
separator: {
type: String,
default: ','
},
/**
* @description 是否简化显示设为true后会使用unit单位来做相关省略
*/
simplify: {
type: Boolean,
default: false
},
/**
* @description 自定义单位,如[3, 'K+'], [6, 'M+']即大于3位数小于6位数的用k+来做省略
* 1000即显示为1K+
*/
unit: {
type: Array,
default () {
return [[3, 'K+'], [6, 'M+'], [9, 'B+']]
}
},
countClass: {
type: String,
default: ''
},
unitClass: {
type: String,
default: ''
}
},
data () {
return {
counter: null,
unitText: ''
}
},
computed: {
counterId () {
return `count_to_${this._uid}`
}
},
methods: {
getHandleVal (val, len) {
return {
endVal: parseInt(val / Math.pow(10, this.unit[len - 1][0])),
unitText: this.unit[len - 1][1]
}
},
transformValue (val) {
let len = this.unit.length
let res = {
endVal: 0,
unitText: ''
}
if (val < Math.pow(10, this.unit[0][0])) res.endVal = val
else {
for (let i = 1; i < len; i++) {
if (val >= Math.pow(10, this.unit[i - 1][0]) && val < Math.pow(10, this.unit[i][0])) res = this.getHandleVal(val, i)
}
}
if (val > Math.pow(10, this.unit[len - 1][0])) res = this.getHandleVal(val, len)
return res
},
getValue (val) {
let res = 0
if (this.simplify) {
let { endVal, unitText } = this.transformValue(val)
this.unitText = unitText
res = endVal
} else {
res = val
}
return res
}
},
mounted () {
this.$nextTick(() => {
let endVal = this.getValue(this.end)
this.counter = new CountUp(this.counterId, this.startVal, endVal, this.decimals, this.duration, {
useEasing: !this.uneasing,
useGrouping: this.useGroup,
separator: this.separator,
decimal: this.decimal
})
setTimeout(() => {
if (!this.counter.error) this.counter.start()
}, this.delay)
})
},
watch: {
end (newVal) {
let endVal = this.getValue(newVal)
this.counter.update(endVal)
}
}
}
</script>

View File

@@ -0,0 +1,2 @@
import countTo from './count-to.vue'
export default countTo

View File

@@ -0,0 +1,10 @@
@prefix: ~"count-to";
.@{prefix}-wrapper{
.content-outer{
display: inline-block;
.@{prefix}-unit-text{
font-style: normal;
}
}
}

View File

@@ -0,0 +1,2 @@
import Cropper from './index.vue'
export default Cropper

View File

@@ -0,0 +1,45 @@
.bg{
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")
}
.cropper-wrapper{
min-height: 500px;
display: flex;
justify-content: center;
flex-flow: column;
align-items: center;
.cropper-box {
display: flex;
justify-content: center;
margin-top: 20px;
}
.img-box{
margin: 0 auto;
height: 540px;
width: 960px;
border: 1px solid #ebebeb;
display: inline-block;
.bg;
img{
max-width: 100%;
display: block;
}
}
.button-box{
padding: 10px 0 0;
margin-bottom: 25px;
button {
margin: 0 5px;
}
}
.file_logo{
.file_name{
text-align: center;
padding-bottom: 15px;
}
}
.underline {
display: flex;
}
}

View File

@@ -0,0 +1,180 @@
<template>
<div class="cropper-wrapper">
<!-- 上传图片时出现cropper -->
<div class="cropper-box" v-show="isImage == 1">
<div class="img-box">
<img class="cropper-image" :id="imgId">
</div>
</div>
<div class="button-box">
<div v-show="isImage == 1">
<Button type="primary" @click="rotate">
<Icon type="md-refresh" :size="18"/>
</Button>
<Button type="primary" @click="scale('X')">
<Icon custom="iconfont icon-shuipingfanzhuan" :size="18"/>
</Button>
<Button type="primary" @click="scale('Y')">
<Icon custom="iconfont icon-chuizhifanzhuan" :size="18"/>
</Button>
<Button type="primary" @click="startCrop">
<Icon type="md-crop" :size="18"/>
</Button>
<Button type="primary" @click="cancelCrop">
{{$t('use_origin_size')}}}
</Button>
</div>
</div>
<!-- 其他文件时出现文件类型图片 -->
<div class="file_logo" v-show="isImage == 2">
<img :src="fileLogo">
<div class="file_name">{{fileName}}</div>
</div>
<div class="underline">
<Upload
type="drag"
:before-upload="beforeUpload"
action="image/upload"
v-show="!insideSrc">
<div style="padding: 30px 180px">
<Icon type="ios-cloud-upload" size="52" style="color: #ffa000"></Icon>
<p>{{$t('select_or_drag_img')}}</p>
</div>
</Upload>
<Upload action="image/upload" :before-upload="beforeUpload" v-show="insideSrc">
<Button icon="ios-cloud-upload-outline" style="width: 150px;">{{$t('reupload')}}</Button>
</Upload>
<Button style="width: 150px;margin-left: 10px;height: 31.9px" type="primary" @click="comfirm" v-show="insideSrc">{{ cropButtonText }}</Button>
</div>
</div>
</template>
<script>
import Cropper from 'cropperjs'
import './index.less'
import 'cropperjs/dist/cropper.min.css'
export default {
name: 'Cropper',
props: {
cropButtonText: {
type: String,
default: '确定'
}
},
data () {
return {
cropper: null,
fileSize: 0,
updataFile: {},
insideSrc: '', // 文件内容
infoFile: '', // 文件信息
fileName: '',
fileType: '',
isImage: '', // 0表示无文件 1表示文件为图片 2表示其他类型文件
fileLogo: ''
}
},
computed: {
imgId () {
return `cropper${this._uid}`
}
},
watch: {
insideSrc (src) {
this.replace(src)
}
},
methods: {
beforeUpload (file) {
// 使用html5的fileReader将图片转换成base64编码
// var fileSize = 0
this.updataFile = file
this.fileSize = file.size
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = (event) => {
this.insideSrc = event.srcElement.result
this.fileName = file.name
this.fileType = file.type
}
this.fileName = file.name
this.fileType = file.type
// 判断文件类型是否为图片 0无 1为图片 2其他类型文件
if (/\.(jpe?g|png|gif)$/i.test(file.name)) {
this.isImage = 1
} else if (/\.(xlsx?)$/i.test(file.name)) {
this.isImage = 2
this.fileLogo = require('@/assets/icons/file-icon/xls_logo.jpg')
} else if (/\.(docx?)$/i.test(file.name)) {
this.isImage = 2
this.fileLogo = require('@/assets/icons/file-icon/doc_logo.jpg')
} else if (/\.(pptx?)$/i.test(file.name)) {
this.isImage = 2
this.fileLogo = require('@/assets/icons/file-icon/ppt_logo.jpg')
} else if (/\.(html)$/i.test(file.name)) {
this.isImage = 2
this.fileLogo = require('@/assets/icons/file-icon/html_logo.jpg')
} else {
this.isImage = 2
this.fileLogo = require('@/assets/icons/file-icon/others_logo.jpg')
}
return false
},
replace (src) {
this.cropper.replace(src)
this.insideSrc = src
},
rotate () {
this.cropper.rotate(90)
},
scale (d) {
this.cropper[`scale${d}`](-this.cropper.getData()[`scale${d}`])
},
move (...argu) {
this.cropper.move(...argu)
},
startCrop () {
this.cropper.crop()
},
cancelCrop () {
this.cropper.clear()
},
comfirm () {
// let dataUrl = this.insideSrc
let dataUrl
if (this.isImage === 1) {
dataUrl = this.cropper.getCroppedCanvas().toDataURL()
} else if (this.isImage === 2) {
dataUrl = this.insideSrc
}
let name = this.fileName
let type = this.fileType
let fileSize = this.fileSize
let updataFile = this.updataFile
let fileData = {
fileSize,
updataFile,
dataUrl,
name,
type
}
this.$emit('transmitInfo', fileData)
this.insideSrc = ''
this.isImage = 0
}
},
mounted () {
this.$nextTick(() => {
let dom = document.getElementById(this.imgId)
this.cropper = new Cropper(dom, {
checkCrossOrigin: true,
autoCrop: false
})
})
}
}
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -0,0 +1,18 @@
<template>
<div :class="`${prefix}-move-trigger`">
<div :class="`${prefix}-move-trigger-point`">
<i></i><i></i><i></i><i></i><i></i>
</div>
</div>
</template>
<script>
import Mixin from './mixin'
export default {
name: 'DragDrawerTrigger',
mixins: [Mixin]
}
</script>
<style>
</style>

View File

@@ -0,0 +1,156 @@
<template>
<Drawer ref="drawerWrapper"
:value="value"
@input="handleInput"
:width="width"
:class-name="outerClasses"
v-bind="$attrs"
v-on="$listeners">
<!-- 所有插槽内容显示在这里 -->
<template v-for="(slots, slotsName) in $slots">
<template v-if="slotsName !== 'default'">
<render-dom v-for="(render, index) in slots"
:key="`b_drawer_${slotsName}_${index}`"
:render="() => render"
:slot="slotsName">
</render-dom>
</template>
<template v-else>
<div :class="`${prefix}-body-wrapper`"
:key="`b_drawer_${slotsName}`">
<render-dom v-for="(render, index) in slots"
:key="`b_drawer_${slotsName}_${index}`"
:render="() => render"
:slot="slotsName">
</render-dom>
</div>
</template>
</template>
<!-- 所有插槽内容显示在这里 -->
<div v-if="draggable"
:style="triggerStyle"
:class="`${prefix}-trigger-wrapper`"
@mousedown="handleTriggerMousedown">
<slot name="trigger">
<drag-drawer-trigger></drag-drawer-trigger>
</slot>
</div>
<div v-if="$slots.footer"
:class="`${prefix}-footer`">
<slot name="footer"></slot>
</div>
</Drawer>
</template>
<script>
import RenderDom from '@/libs/render-dom'
import DragDrawerTrigger from './drag-drawer-trigger.vue'
import Mixin from './mixin'
import { on, off } from '@/libs/tools'
import './index.less'
export default {
name: 'BDrawer',
components: {
RenderDom,
DragDrawerTrigger
},
mixins: [Mixin],
props: {
value: {
type: Boolean,
default: false
},
width: {
type: [String, Number],
default: 256
},
// 是否可拖动修改宽度
draggable: {
type: Boolean,
default: false
},
// 最小拖动宽度
minWidth: {
type: [String, Number],
default: 256
}
},
data () {
return {
canMove: false,
wrapperWidth: 0,
wrapperLeft: 0
}
},
computed: {
outerClasses () {
const classesArray = [
`${this.prefix}-wrapper`,
this.canMove ? 'no-select pointer-events-none' : ''
]
return classesArray.join(' ')
},
placement () {
return this.$attrs.placement
},
innerWidth () {
const width = this.width
return width <= 100 ? (this.wrapperWidth * width) / 100 : width
},
triggerStyle () {
return {
[this.placement]: `${this.innerWidth}px`,
position: this.$attrs.inner ? 'absolute' : 'fixed'
}
}
},
methods: {
handleInput (status) {
this.$emit('input', status)
},
handleTriggerMousedown (event) {
this.canMove = true
this.$emit('on-resize-start')
// 防止鼠标选中抽屉中文字造成拖动trigger触发浏览器原生拖动行为
window.getSelection().removeAllRanges()
},
handleMousemove (event) {
if (!this.canMove) return
// 更新容器宽度和距离左侧页面距离如果是window则距左侧距离为0
this.setWrapperWidth()
const left = event.pageX - this.wrapperLeft
// 如果抽屉方向为右边宽度计算需用容器宽度减去left
let width = this.placement === 'right' ? this.wrapperWidth - left : left
// 限定做小宽度
width = Math.max(width, parseFloat(this.minWidth))
event.atMin = width === parseFloat(this.minWidth)
// 如果当前width不大于100视为百分比
if (width <= 100) width = (width / this.wrapperWidth) * 100
this.$emit('update:width', parseInt(width))
this.$emit('on-resize', event)
},
handleMouseup (event) {
this.canMove = false
this.$emit('on-resize-end')
},
setWrapperWidth () {
const {
width,
left
} = this.$refs.drawerWrapper.$el.getBoundingClientRect()
this.wrapperWidth = width
this.wrapperLeft = left
}
},
mounted () {
on(document, 'mousemove', this.handleMousemove)
on(document, 'mouseup', this.handleMouseup)
this.setWrapperWidth()
},
beforeDestroy () {
off(document, 'mousemove', this.handleMousemove)
off(document, 'mouseup', this.handleMouseup)
}
}
</script>

View File

@@ -0,0 +1,2 @@
import DragDrawer from './drag-drawer.vue'
export default DragDrawer

View File

@@ -0,0 +1,70 @@
@prefix: ~"drag-drawer";
@drag-drawer-trigger-height: 100px;
@drag-drawer-trigger-width: 8px;
.@{prefix}-wrapper{
&.no-select{
user-select: none;
}
&.pointer-events-none{
pointer-events: none;
& .@{prefix}-trigger-wrapper{
pointer-events: all;
}
}
.ivu-drawer{
&-header{
overflow: hidden !important;
box-sizing: border-box;
}
&-body{
padding: 0;
overflow: visible;
position: static;
display: flex;
flex-direction: column;
}
}
.@{prefix}-body-wrapper{
width: 100%;
height: 100%;
padding: 16px;
overflow: auto;
}
.@{prefix}-trigger-wrapper{
top: 0;
height: 100%;
width: 0;
.@{prefix}-move-trigger{
position: absolute;
top: 50%;
height: @drag-drawer-trigger-height;
width: @drag-drawer-trigger-width;
background: rgb(243, 243, 243);
transform: translate(-50%, -50%);
border-radius: ~"4px / 6px";
box-shadow: 0 0 1px 1px rgba(0, 0, 0, .2);
line-height: @drag-drawer-trigger-height;
cursor: col-resize;
&-point{
display: inline-block;
width: 50%;
transform: translateX(50%);
i{
display: block;
border-bottom: 1px solid rgb(192, 192, 192);
padding-bottom: 2px;
}
}
}
}
.@{prefix}-footer{
flex-grow: 1;
width: 100%;
bottom: 0;
left: 0;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
background: #fff;
}
}

View File

@@ -0,0 +1,7 @@
export default {
data () {
return {
prefix: 'drag-drawer'
}
}
}

View File

@@ -0,0 +1,92 @@
<template>
<div class="drag-list-wrapper">
<div class="drag-list-con con1">
<slot name="left-title"></slot>
<draggable class="drop-box1" :class="dropConClass.left" :options="options" :value="list1" @input="handleListChange($event, 'left')" @end="handleEnd($event, 'left')">
<div class="drag-list-item" v-for="(itemLeft, index) in list1" :key="`drag_li1_${index}`">
<slot name="left" :itemLeft="itemLeft">{{ itemLeft }}</slot>
</div>
</draggable>
</div>
<div class="drag-list-con con2">
<slot name="right-title"></slot>
<draggable class="drop-box2" :class="dropConClass.right" :options="options" :value="list2" @input="handleListChange($event, 'right')" @end="handleEnd($event, 'right')">
<div class="drag-list-item" v-for="(itemRight, index) in list2" :key="`drag_li2_${index}`">
<slot name="right" :itemRight="itemRight">{{ itemRight }}</slot>
</div>
</draggable>
</div>
</div>
</template>
<script>
import draggable from 'vuedraggable'
export default {
name: 'DragList',
components: {
draggable
},
props: {
list1: {
type: Array,
required: true
},
list2: {
type: Array,
default: () => []
},
dropConClass: {
type: Object,
default: () => ({})
}
},
data () {
return {
options: { group: 'drag_list' }
}
},
methods: {
handleListChange (value, type) {
if (type === 'left') this.$emit('update:list1', value)
else this.$emit('update:list2', value)
},
handleEnd (event, type) {
const srcClassName = (event.srcElement || event.target).classList[0]
const targetClassName = event.to.classList[0]
let src = ''
let target = ''
if (srcClassName === targetClassName) {
if (type === 'left') {
src = 'left'
target = 'left'
} else {
src = 'right'
target = 'right'
}
} else {
if (type === 'left') {
src = 'left'
target = 'right'
} else {
src = 'right'
target = 'left'
}
}
this.$emit('on-change', {
src: src,
target: target,
oldIndex: event.oldIndex,
newIndex: event.newIndex
})
}
}
}
</script>
<style lang="less">
.drag-list-wrapper{
height: 100%;
.drag-list-con{
width: 50%;
float: left;
}
}
</style>

View File

@@ -0,0 +1,2 @@
import DragList from './drag-list.vue'
export default DragList

View File

@@ -0,0 +1,75 @@
<template>
<div class="editor-wrapper">
<div :id="editorId"></div>
</div>
</template>
<script>
import Editor from 'wangeditor'
import 'wangeditor/release/wangEditor.min.css'
import { oneOf } from '@/libs/tools'
export default {
name: 'Editor',
props: {
value: {
type: String,
default: ''
},
/**
* 绑定的值的类型, enum: ['html', 'text']
*/
valueType: {
type: String,
default: 'html',
validator: (val) => {
return oneOf(val, ['html', 'text'])
}
},
/**
* @description 设置change事件触发时间间隔
*/
changeInterval: {
type: Number,
default: 200
},
/**
* @description 是否开启本地存储
*/
cache: {
type: Boolean,
default: true
}
},
computed: {
editorId () {
return `editor${this._uid}`
}
},
methods: {
setHtml (val) {
this.editor.txt.html(val)
}
},
mounted () {
this.editor = new Editor(`#${this.editorId}`)
this.editor.customConfig.onchange = (html) => {
let text = this.editor.txt.text()
if (this.cache) localStorage.editorCache = html
this.$emit('input', this.valueType === 'html' ? html : text)
this.$emit('on-change', html, text)
}
this.editor.customConfig.onchangeTimeout = this.changeInterval
// create这个方法一定要在所有配置项之后调用
this.editor.create()
// 如果本地有存储加载本地存储内容
let html = this.value || localStorage.editorCache
if (html) this.editor.txt.html(html)
}
}
</script>
<style lang="less">
.editor-wrapper *{
z-index: 100 !important;
}
</style>

View File

@@ -0,0 +1,2 @@
import Editor from './editor.vue'
export default Editor

View File

@@ -0,0 +1,35 @@
<template>
<i :class="`iconfont icon-${type}`" :style="styles"></i>
</template>
<script>
export default {
name: 'Icons',
props: {
type: {
type: String,
required: true
},
color: {
type: String,
default: '#5c6b77'
},
size: {
type: Number,
default: 16
}
},
computed: {
styles () {
return {
fontSize: `${this.size}px`,
color: this.color
}
}
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,2 @@
import Icons from './icons.vue'
export default Icons

View File

@@ -0,0 +1,2 @@
import InforCard from './infor-card.vue'
export default InforCard

View File

@@ -0,0 +1,94 @@
<template>
<Card :shadow="shadow" class="info-card-wrapper" :padding="0">
<div class="content-con">
<div class="left-area" :style="{width: leftWidth}">
<common-icon class="icon" :type="icon" :size="iconSize" :color="color"/>
</div>
<div class="right-area" :style="{width: rightWidth}">
<div>
<slot></slot>
</div>
</div>
</div>
</Card>
</template>
<script>
import CommonIcon from '_c/common-icon'
export default {
name: 'InforCard',
components: {
CommonIcon
},
props: {
left: {
type: Number,
default: 45
},
color: {
type: String,
default: '#2d8cf0'
},
icon: {
type: String,
default: ''
},
iconSize: {
type: Number,
default: 20
},
shadow: {
type: Boolean,
default: false
}
},
computed: {
leftWidth () {
return `${this.left}%`
},
rightWidth () {
return `${100 - this.left}%`
}
}
}
</script>
<style lang="less">
.common{
float: left;
height: 100%;
display: table;
text-align: center;
}
.size{
width: 100%;
height: 100%;
}
.middle-center{
display: table-cell;
vertical-align: middle;
}
.info-card-wrapper{
.size;
overflow: hidden;
.ivu-card-body{
.size;
}
.content-con{
.size;
position: relative;
.left-area{
.common;
& > .icon{
.middle-center;
}
}
.right-area{
.common;
& > div{
.middle-center;
}
}
}
}
</style>

View File

@@ -0,0 +1,2 @@
import LoginForm from './login-form.vue'
export default LoginForm

View File

@@ -0,0 +1,204 @@
<template>
<Form class="login-form" ref="loginForm" :model="form" :rules="rules" @keydown.enter.native="handleSubmit">
<FormItem prop="username">
<Input v-model="form.username" :placeholder="$t('developer_account_tips')">
<span slot="prepend">
<Icon :size="16" type="ios-person"></Icon>
</span>
</Input>
</FormItem>
<FormItem prop="password">
<Input type="password" v-model="form.password" :placeholder="$t('developer_pwd_tips')">
<span slot="prepend">
<Icon :size="14" type="md-lock"></Icon>
</span>
</Input>
</FormItem>
<FormItem v-if="logincaptcha">
<div style="display: flex;align-items: center;">
<Input clearable style="width:310px;margin-right:10px" v-model="form.verification" :placeholder="$t('input_captcha_case_sensitive')">
<span slot="prepend">
<Icon :size="14" type="md-barcode"></Icon>
</span>
</Input>
<img style="height:40px;" :src="codeImg" @click="changeSrc" alt="">
</div>
</FormItem>
<FormItem>
<div class="flexbox">
<Checkbox class="label" @on-change="toggle">{{$t('keep_login')}}</Checkbox>
<router-link v-if="canRegister" :to="{path:'/register'}">{{$t('login_tips')}}&gt;&gt;</router-link>
</div>
<Button class="flexbox-btn" @click="handleSubmit" type="primary" long>{{$t('login')}}</Button>
</FormItem>
<div class="thirdParty_login" v-if="isShowThirdParty">
<div class="title-line">
<div class="line"></div>
<div class="text">第三方登录</div>
<div class="line"></div>
</div>
<div class="select-list">
<a @click="thirdpartyLogin" :href="item.callback_url" target="_blank" v-for="(item,index) in thirdPartyList" :key="index">
<img :src="item.icon" alt="" srcset="">
<div class="text">{{item.desc}}</div>
</a>
</div>
</div>
</Form>
</template>
<script>
import config from '@/config'
import { AuthorizationConfig } from '@/api/account'
const { cookieExpires_long, cookieExpires_short } = config
export default {
name: 'LoginForm',
props: {
logincaptcha: {
type: Boolean
}
// usernameRules: {
// type: Array,
// default: () => {
// return [
// // { required: true, message: this.$i18n.tc('account_empty'), trigger: 'blur' }
// { required: true, message: '账号不得为空', trigger: 'blur' }
// ]
// }
// },
// passwordRules: {
// type: Array,
// default: () => {
// return [
// // { required: true, message: this.$t('developer_pwd_tips'), trigger: 'blur' }
// { required: true, message: '密码不得为空', trigger: 'blur' }
// ]
// }
// }
},
data () {
return {
codeImg: '/api/platform.php?service=Platform.Captcha.Create',
form: {
username: '',
password: '',
verification: ''
},
cookiesExp: 1,
usernameRules: [
{ required: true, message: this.$i18n.tc('account_empty'), trigger: 'blur' }
// { required: true, message: '账号不得为空', trigger: 'blur' }
],
passwordRules: [
{ required: true, message: this.$t('developer_pwd_tips'), trigger: 'blur' }
// { required: true, message: '密码不得为空', trigger: 'blur' }
],
isShowThirdParty: false,
thirdPartyList: []
}
},
created () {
// console.log('i18n', this.$t('welcome'))
this.thirdpartyLogin()
},
computed: {
rules () {
return {
username: this.usernameRules,
password: this.passwordRules
}
},
canRegister () {
return this.$store.state.user.is_dev_register
}
},
methods: {
thirdpartyLogin () {
let _this = this
AuthorizationConfig().then(res => {
if (res.ret == 200) {
_this.isShowThirdParty = true
_this.thirdPartyList = res.data.quick_login
}
})
},
handleSubmit () {
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.$emit('on-success-valid', {
username: this.form.username,
password: this.form.password,
captcha: this.form.verification,
cookiesExp: this.cookiesExp
})
}
})
},
toggle (value) {
this.cookiesExp = value ? cookieExpires_long : cookieExpires_short
},
changeSrc () {
let timestamp = Date.parse(new Date())
this.codeImg = '/api/platform.php?service=Platform.Captcha.Create&t=' + timestamp
}
}
}
</script>
<style lang="less" scope>
.login-form {
.flexbox {
margin-top: 10px;
width: 400px;
display: flex;
flex-flow: row;
justify-content: space-between;
&-btn {
width: 100%;
height: 40px;
}
}
.thirdParty_login {
.title-line {
display: flex;
align-items: center;
margin-bottom: 10px;
.line {
flex:1;
background: #ECECEC;
height: 1px;
}
.text {
color: #666;
padding: 0 15px;
}
}
.select-list {
display: flex;
justify-content: center;
a {
margin: 0 40px;
line-height: 1;
display: flex;
min-width: 60px;
flex-flow: column;
align-items: center;
img {
width: 24px;
height: 24px;
margin-bottom: 8px;
}
.text {
color: #666 !important;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,2 @@
import ABackTop from './index.vue'
export default ABackTop

View File

@@ -0,0 +1,97 @@
<!--
* @Description:
* @Author: Wang Minjie
* @Date: 2020-01-04 11:48:55
* @LastEditTime: 2020-01-10 16:16:02
* @LastEditors: Wang Minjie
-->
<template>
<div :class="classes" :style="styles" @click="back">
<slot>
<div :class="innerClasses">
<i class="ivu-icon ivu-icon-ios-arrow-up"></i>
</div>
</slot>
</div>
</template>
<script>
import { scrollTo } from '@/libs/util'
import { on, off } from '@/libs/tools'
const prefixCls = 'ivu-back-top'
export default {
name: 'ABackTop',
props: {
height: {
type: Number,
default: 400
},
bottom: {
type: Number,
default: 30
},
right: {
type: Number,
default: 30
},
duration: {
type: Number,
default: 1000
},
container: {
type: null,
default: window
}
},
data () {
return {
backTop: false
}
},
mounted () {
// window.addEventListener('scroll', this.handleScroll, false)
// window.addEventListener('resize', this.handleScroll, false)
on(this.containerEle, 'scroll', this.handleScroll)
on(this.containerEle, 'resize', this.handleScroll)
},
beforeDestroy () {
// window.removeEventListener('scroll', this.handleScroll, false)
// window.removeEventListener('resize', this.handleScroll, false)
off(this.containerEle, 'scroll', this.handleScroll)
off(this.containerEle, 'resize', this.handleScroll)
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-show`]: this.backTop
}
]
},
styles () {
return {
bottom: `${this.bottom}px`,
right: `${this.right}px`
}
},
innerClasses () {
return `${prefixCls}-inner`
},
containerEle () {
return this.container === window ? window : document.querySelector(this.container)
}
},
methods: {
handleScroll () {
this.backTop = this.containerEle.scrollTop >= this.height
},
back () {
let target = typeof this.container === 'string' ? this.containerEle : (document.documentElement || document.body)
const sTop = target.scrollTop
scrollTo(this.containerEle, sTop, 0, this.duration)
this.$emit('on-click')
}
}
}
</script>

View File

@@ -0,0 +1,49 @@
<template>
<div class="error-store">
<Badge dot :count="countComputed">
<Button type="text" @click="openErrorLoggerPage">
<Icon :size="20" type="ios-bug"/>
</Button>
</Badge>
</div>
</template>
<script>
export default {
name: 'ErrorStore',
props: {
count: {
type: Number,
default: 0
},
hasRead: {
type: Boolean,
default: false
}
},
computed: {
countComputed () {
return this.hasRead ? 0 : this.count
}
},
methods: {
openErrorLoggerPage () {
this.$router.push({
name: 'error_logger_page'
})
}
}
}
</script>
<style lang="less">
.error-store{
margin-right: 12px;
.ivu-badge-dot{
top: 20px;
}
.ivu-btn.ivu-btn-text{
padding: 5px 1px 6px;
}
}
</style>

View File

@@ -0,0 +1,2 @@
import ErrorStore from './error-store.vue'
export default ErrorStore

View File

@@ -0,0 +1,83 @@
<template>
<div v-if="showFullScreenBtn" class="full-screen-btn-con">
<Tooltip :content="value ? $t('exit_fullscreen') : $t('fullscreen')" placement="bottom">
<Icon @click.native="handleChange" :type="value ? 'md-contract' : 'md-expand'" :size="23"></Icon>
</Tooltip>
</div>
</template>
<script>
export default {
name: 'Fullscreen',
computed: {
showFullScreenBtn () {
return window.navigator.userAgent.indexOf('MSIE') < 0
}
},
props: {
value: {
type: Boolean,
default: false
}
},
methods: {
handleFullscreen () {
let main = document.body
if (this.value) {
if (document.exitFullscreen) {
document.exitFullscreen()
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen()
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen()
} else if (document.msExitFullscreen) {
document.msExitFullscreen()
}
} else {
if (main.requestFullscreen) {
main.requestFullscreen()
} else if (main.mozRequestFullScreen) {
main.mozRequestFullScreen()
} else if (main.webkitRequestFullScreen) {
main.webkitRequestFullScreen()
} else if (main.msRequestFullscreen) {
main.msRequestFullscreen()
}
}
},
handleChange () {
this.handleFullscreen()
}
},
mounted () {
let isFullscreen = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen
isFullscreen = !!isFullscreen
document.addEventListener('fullscreenchange', () => {
this.$emit('input', !this.value)
this.$emit('on-change', !this.value)
})
document.addEventListener('mozfullscreenchange', () => {
this.$emit('input', !this.value)
this.$emit('on-change', !this.value)
})
document.addEventListener('webkitfullscreenchange', () => {
this.$emit('input', !this.value)
this.$emit('on-change', !this.value)
})
document.addEventListener('msfullscreenchange', () => {
this.$emit('input', !this.value)
this.$emit('on-change', !this.value)
})
this.$emit('input', isFullscreen)
}
}
</script>
<style lang="less">
.full-screen-btn-con .ivu-tooltip-rel{
line-height: 30px;
i{
cursor: pointer;
}
}
</style>

View File

@@ -0,0 +1,2 @@
import Fullscreen from './fullscreen.vue'
export default Fullscreen

Some files were not shown because too many files have changed in this diff Show More