@ -0,0 +1,14 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = false
|
||||
@ -0,0 +1,8 @@
|
||||
NODE_ENV = production
|
||||
|
||||
# just a flag
|
||||
ENV = 'staging'
|
||||
|
||||
# base api
|
||||
VUE_APP_BASE_API = '/stage-api'
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
build/*.js
|
||||
src/assets
|
||||
public
|
||||
dist
|
||||
@ -0,0 +1,198 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint',
|
||||
sourceType: 'module'
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true,
|
||||
},
|
||||
extends: ['plugin:vue/recommended', 'eslint:recommended'],
|
||||
|
||||
// add your custom rules here
|
||||
//it is base on https://github.com/vuejs/eslint-config-vue
|
||||
rules: {
|
||||
"vue/max-attributes-per-line": [2, {
|
||||
"singleline": 10,
|
||||
"multiline": {
|
||||
"max": 1,
|
||||
"allowFirstLine": false
|
||||
}
|
||||
}],
|
||||
"vue/singleline-html-element-content-newline": "off",
|
||||
"vue/multiline-html-element-content-newline":"off",
|
||||
"vue/name-property-casing": ["error", "PascalCase"],
|
||||
"vue/no-v-html": "off",
|
||||
'accessor-pairs': 2,
|
||||
'arrow-spacing': [2, {
|
||||
'before': true,
|
||||
'after': true
|
||||
}],
|
||||
'block-spacing': [2, 'always'],
|
||||
'brace-style': [2, '1tbs', {
|
||||
'allowSingleLine': true
|
||||
}],
|
||||
'camelcase': [0, {
|
||||
'properties': 'always'
|
||||
}],
|
||||
'comma-dangle': [2, 'never'],
|
||||
'comma-spacing': [2, {
|
||||
'before': false,
|
||||
'after': true
|
||||
}],
|
||||
'comma-style': [2, 'last'],
|
||||
'constructor-super': 2,
|
||||
'curly': [2, 'multi-line'],
|
||||
'dot-location': [2, 'property'],
|
||||
'eol-last': 2,
|
||||
'eqeqeq': ["error", "always", {"null": "ignore"}],
|
||||
'generator-star-spacing': [2, {
|
||||
'before': true,
|
||||
'after': true
|
||||
}],
|
||||
'handle-callback-err': [2, '^(err|error)$'],
|
||||
'indent': [2, 2, {
|
||||
'SwitchCase': 1
|
||||
}],
|
||||
'jsx-quotes': [2, 'prefer-single'],
|
||||
'key-spacing': [2, {
|
||||
'beforeColon': false,
|
||||
'afterColon': true
|
||||
}],
|
||||
'keyword-spacing': [2, {
|
||||
'before': true,
|
||||
'after': true
|
||||
}],
|
||||
'new-cap': [2, {
|
||||
'newIsCap': true,
|
||||
'capIsNew': false
|
||||
}],
|
||||
'new-parens': 2,
|
||||
'no-array-constructor': 2,
|
||||
'no-caller': 2,
|
||||
'no-console': 'off',
|
||||
'no-class-assign': 2,
|
||||
'no-cond-assign': 2,
|
||||
'no-const-assign': 2,
|
||||
'no-control-regex': 0,
|
||||
'no-delete-var': 2,
|
||||
'no-dupe-args': 2,
|
||||
'no-dupe-class-members': 2,
|
||||
'no-dupe-keys': 2,
|
||||
'no-duplicate-case': 2,
|
||||
'no-empty-character-class': 2,
|
||||
'no-empty-pattern': 2,
|
||||
'no-eval': 2,
|
||||
'no-ex-assign': 2,
|
||||
'no-extend-native': 2,
|
||||
'no-extra-bind': 2,
|
||||
'no-extra-boolean-cast': 2,
|
||||
'no-extra-parens': [2, 'functions'],
|
||||
'no-fallthrough': 2,
|
||||
'no-floating-decimal': 2,
|
||||
'no-func-assign': 2,
|
||||
'no-implied-eval': 2,
|
||||
'no-inner-declarations': [2, 'functions'],
|
||||
'no-invalid-regexp': 2,
|
||||
'no-irregular-whitespace': 2,
|
||||
'no-iterator': 2,
|
||||
'no-label-var': 2,
|
||||
'no-labels': [2, {
|
||||
'allowLoop': false,
|
||||
'allowSwitch': false
|
||||
}],
|
||||
'no-lone-blocks': 2,
|
||||
'no-mixed-spaces-and-tabs': 2,
|
||||
'no-multi-spaces': 2,
|
||||
'no-multi-str': 2,
|
||||
'no-multiple-empty-lines': [2, {
|
||||
'max': 1
|
||||
}],
|
||||
'no-native-reassign': 2,
|
||||
'no-negated-in-lhs': 2,
|
||||
'no-new-object': 2,
|
||||
'no-new-require': 2,
|
||||
'no-new-symbol': 2,
|
||||
'no-new-wrappers': 2,
|
||||
'no-obj-calls': 2,
|
||||
'no-octal': 2,
|
||||
'no-octal-escape': 2,
|
||||
'no-path-concat': 2,
|
||||
'no-proto': 2,
|
||||
'no-redeclare': 2,
|
||||
'no-regex-spaces': 2,
|
||||
'no-return-assign': [2, 'except-parens'],
|
||||
'no-self-assign': 2,
|
||||
'no-self-compare': 2,
|
||||
'no-sequences': 2,
|
||||
'no-shadow-restricted-names': 2,
|
||||
'no-spaced-func': 2,
|
||||
'no-sparse-arrays': 2,
|
||||
'no-this-before-super': 2,
|
||||
'no-throw-literal': 2,
|
||||
'no-trailing-spaces': 2,
|
||||
'no-undef': 2,
|
||||
'no-undef-init': 2,
|
||||
'no-unexpected-multiline': 2,
|
||||
'no-unmodified-loop-condition': 2,
|
||||
'no-unneeded-ternary': [2, {
|
||||
'defaultAssignment': false
|
||||
}],
|
||||
'no-unreachable': 2,
|
||||
'no-unsafe-finally': 2,
|
||||
'no-unused-vars': [2, {
|
||||
'vars': 'all',
|
||||
'args': 'none'
|
||||
}],
|
||||
'no-useless-call': 2,
|
||||
'no-useless-computed-key': 2,
|
||||
'no-useless-constructor': 2,
|
||||
'no-useless-escape': 0,
|
||||
'no-whitespace-before-property': 2,
|
||||
'no-with': 2,
|
||||
'one-var': [2, {
|
||||
'initialized': 'never'
|
||||
}],
|
||||
'operator-linebreak': [2, 'after', {
|
||||
'overrides': {
|
||||
'?': 'before',
|
||||
':': 'before'
|
||||
}
|
||||
}],
|
||||
'padded-blocks': [2, 'never'],
|
||||
'quotes': [2, 'single', {
|
||||
'avoidEscape': true,
|
||||
'allowTemplateLiterals': true
|
||||
}],
|
||||
'semi': [2, 'never'],
|
||||
'semi-spacing': [2, {
|
||||
'before': false,
|
||||
'after': true
|
||||
}],
|
||||
'space-before-blocks': [2, 'always'],
|
||||
'space-before-function-paren': [2, 'never'],
|
||||
'space-in-parens': [2, 'never'],
|
||||
'space-infix-ops': 2,
|
||||
'space-unary-ops': [2, {
|
||||
'words': true,
|
||||
'nonwords': false
|
||||
}],
|
||||
'spaced-comment': [2, 'always', {
|
||||
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
|
||||
}],
|
||||
'template-curly-spacing': [2, 'never'],
|
||||
'use-isnan': 2,
|
||||
'valid-typeof': 2,
|
||||
'wrap-iife': [2, 'any'],
|
||||
'yield-star-spacing': [2, 'both'],
|
||||
'yoda': [2, 'never'],
|
||||
'prefer-const': 2,
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
|
||||
'object-curly-spacing': [2, 'always', {
|
||||
objectsInObjects: false
|
||||
}],
|
||||
'array-bracket-spacing': [2, 'never']
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
dist/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
package-lock.json
|
||||
tests/**/coverage/
|
||||
|
||||
.env.development
|
||||
.env.production
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017-present PanJiaChen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -0,0 +1,91 @@
|
||||
# vue-admin-template
|
||||
|
||||
English | [简体中文](./README-zh.md)
|
||||
|
||||
> A minimal vue admin template with Element UI & axios & iconfont & permission control & lint
|
||||
|
||||
**Live demo:** http://panjiachen.github.io/vue-admin-template
|
||||
|
||||
|
||||
**The current version is `v4.0+` build on `vue-cli`. If you want to use the old version , you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0), it does not rely on `vue-cli`**
|
||||
|
||||
## Build Setup
|
||||
|
||||
|
||||
```bash
|
||||
# clone the project
|
||||
git clone https://github.com/PanJiaChen/vue-admin-template.git
|
||||
|
||||
# enter the project directory
|
||||
cd vue-admin-template
|
||||
|
||||
# install dependency
|
||||
npm install
|
||||
|
||||
# develop
|
||||
npm run dev
|
||||
```
|
||||
|
||||
This will automatically open http://localhost:9528
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
# build for test environment
|
||||
npm run build:stage
|
||||
|
||||
# build for production environment
|
||||
npm run build:prod
|
||||
```
|
||||
|
||||
## Advanced
|
||||
|
||||
```bash
|
||||
# preview the release environment effect
|
||||
npm run preview
|
||||
|
||||
# preview the release environment effect + static resource analysis
|
||||
npm run preview -- --report
|
||||
|
||||
# code format check
|
||||
npm run lint
|
||||
|
||||
# code format check and auto fix
|
||||
npm run lint -- --fix
|
||||
```
|
||||
|
||||
Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information
|
||||
|
||||
## Demo
|
||||
|
||||

|
||||
|
||||
## Extra
|
||||
|
||||
If you want router permission && generate menu by user roles , you can use this branch [permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
|
||||
|
||||
For `typescript` version, you can use [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
|
||||
|
||||
## Related Project
|
||||
|
||||
- [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
|
||||
|
||||
- [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
||||
|
||||
- [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template)
|
||||
|
||||
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
|
||||
|
||||
## Browsers support
|
||||
|
||||
Modern browsers and Internet Explorer 10+.
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||
| --------- | --------- | --------- | --------- |
|
||||
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license.
|
||||
|
||||
Copyright (c) 2017-present PanJiaChen
|
||||
@ -0,0 +1,14 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
],
|
||||
'env': {
|
||||
'development': {
|
||||
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
|
||||
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
|
||||
// https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
|
||||
'plugins': ['dynamic-import-node']
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
const { run } = require('runjs')
|
||||
const chalk = require('chalk')
|
||||
const config = require('../vue.config.js')
|
||||
const rawArgv = process.argv.slice(2)
|
||||
const args = rawArgv.join(' ')
|
||||
|
||||
if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
|
||||
const report = rawArgv.includes('--report')
|
||||
|
||||
run(`vue-cli-service build ${args}`)
|
||||
|
||||
const port = 9526
|
||||
const publicPath = config.publicPath
|
||||
|
||||
var connect = require('connect')
|
||||
var serveStatic = require('serve-static')
|
||||
const app = connect()
|
||||
|
||||
app.use(
|
||||
publicPath,
|
||||
serveStatic('./dist', {
|
||||
index: ['index.html', '/']
|
||||
})
|
||||
)
|
||||
|
||||
app.listen(port, function () {
|
||||
console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
|
||||
if (report) {
|
||||
console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`))
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
run(`vue-cli-service build ${args}`)
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
|
||||
transform: {
|
||||
'^.+\\.vue$': 'vue-jest',
|
||||
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
|
||||
'jest-transform-stub',
|
||||
'^.+\\.jsx?$': 'babel-jest'
|
||||
},
|
||||
moduleNameMapper: {
|
||||
'^@/(.*)$': '<rootDir>/src/$1'
|
||||
},
|
||||
snapshotSerializers: ['jest-serializer-vue'],
|
||||
testMatch: [
|
||||
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
|
||||
],
|
||||
collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
|
||||
coverageDirectory: '<rootDir>/tests/unit/coverage',
|
||||
// 'collectCoverage': true,
|
||||
'coverageReporters': [
|
||||
'lcov',
|
||||
'text-summary'
|
||||
],
|
||||
testURL: 'http://localhost/'
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
const Mock = require('mockjs')
|
||||
const { param2Obj } = require('./utils')
|
||||
|
||||
const user = require('./user')
|
||||
const table = require('./table')
|
||||
|
||||
const mocks = [
|
||||
...user,
|
||||
...table
|
||||
]
|
||||
|
||||
// for front mock
|
||||
// please use it cautiously, it will redefine XMLHttpRequest,
|
||||
// which will cause many of your third-party libraries to be invalidated(like progress event).
|
||||
function mockXHR() {
|
||||
// mock patch
|
||||
// https://github.com/nuysoft/Mock/issues/300
|
||||
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
|
||||
Mock.XHR.prototype.send = function() {
|
||||
if (this.custom.xhr) {
|
||||
this.custom.xhr.withCredentials = this.withCredentials || false
|
||||
|
||||
if (this.responseType) {
|
||||
this.custom.xhr.responseType = this.responseType
|
||||
}
|
||||
}
|
||||
this.proxy_send(...arguments)
|
||||
}
|
||||
|
||||
function XHR2ExpressReqWrap(respond) {
|
||||
return function(options) {
|
||||
let result = null
|
||||
if (respond instanceof Function) {
|
||||
const { body, type, url } = options
|
||||
// https://expressjs.com/en/4x/api.html#req
|
||||
result = respond({
|
||||
method: type,
|
||||
body: JSON.parse(body),
|
||||
query: param2Obj(url)
|
||||
})
|
||||
} else {
|
||||
result = respond
|
||||
}
|
||||
return Mock.mock(result)
|
||||
}
|
||||
}
|
||||
|
||||
for (const i of mocks) {
|
||||
Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
mocks,
|
||||
mockXHR
|
||||
}
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
const chokidar = require('chokidar')
|
||||
const bodyParser = require('body-parser')
|
||||
const chalk = require('chalk')
|
||||
const path = require('path')
|
||||
const Mock = require('mockjs')
|
||||
|
||||
const mockDir = path.join(process.cwd(), 'mock')
|
||||
|
||||
function registerRoutes(app) {
|
||||
let mockLastIndex
|
||||
const { mocks } = require('./index.js')
|
||||
const mocksForServer = mocks.map(route => {
|
||||
return responseFake(route.url, route.type, route.response)
|
||||
})
|
||||
for (const mock of mocksForServer) {
|
||||
app[mock.type](mock.url, mock.response)
|
||||
mockLastIndex = app._router.stack.length
|
||||
}
|
||||
const mockRoutesLength = Object.keys(mocksForServer).length
|
||||
return {
|
||||
mockRoutesLength: mockRoutesLength,
|
||||
mockStartIndex: mockLastIndex - mockRoutesLength
|
||||
}
|
||||
}
|
||||
|
||||
function unregisterRoutes() {
|
||||
Object.keys(require.cache).forEach(i => {
|
||||
if (i.includes(mockDir)) {
|
||||
delete require.cache[require.resolve(i)]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// for mock server
|
||||
const responseFake = (url, type, respond) => {
|
||||
return {
|
||||
url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
|
||||
type: type || 'get',
|
||||
response(req, res) {
|
||||
console.log('request invoke:' + req.path)
|
||||
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = app => {
|
||||
// parse app.body
|
||||
// https://expressjs.com/en/4x/api.html#req.body
|
||||
app.use(bodyParser.json())
|
||||
app.use(bodyParser.urlencoded({
|
||||
extended: true
|
||||
}))
|
||||
|
||||
const mockRoutes = registerRoutes(app)
|
||||
var mockRoutesLength = mockRoutes.mockRoutesLength
|
||||
var mockStartIndex = mockRoutes.mockStartIndex
|
||||
|
||||
// watch files, hot reload mock server
|
||||
chokidar.watch(mockDir, {
|
||||
ignored: /mock-server/,
|
||||
ignoreInitial: true
|
||||
}).on('all', (event, path) => {
|
||||
if (event === 'change' || event === 'add') {
|
||||
try {
|
||||
// remove mock routes stack
|
||||
app._router.stack.splice(mockStartIndex, mockRoutesLength)
|
||||
|
||||
// clear routes cache
|
||||
unregisterRoutes()
|
||||
|
||||
const mockRoutes = registerRoutes(app)
|
||||
mockRoutesLength = mockRoutes.mockRoutesLength
|
||||
mockStartIndex = mockRoutes.mockStartIndex
|
||||
|
||||
console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
|
||||
} catch (error) {
|
||||
console.log(chalk.redBright(error))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
const Mock = require('mockjs')
|
||||
|
||||
const data = Mock.mock({
|
||||
'items|30': [{
|
||||
id: '@id',
|
||||
title: '@sentence(10, 20)',
|
||||
'status|1': ['published', 'draft', 'deleted'],
|
||||
author: 'name',
|
||||
display_time: '@datetime',
|
||||
pageviews: '@integer(300, 5000)'
|
||||
}]
|
||||
})
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
url: '/vue-admin-template/table/list',
|
||||
type: 'get',
|
||||
response: config => {
|
||||
const items = data.items
|
||||
return {
|
||||
code: 20000,
|
||||
data: {
|
||||
total: items.length,
|
||||
items: items
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,84 @@
|
||||
|
||||
const tokens = {
|
||||
admin: {
|
||||
token: 'admin-token'
|
||||
},
|
||||
editor: {
|
||||
token: 'editor-token'
|
||||
}
|
||||
}
|
||||
|
||||
const users = {
|
||||
'admin-token': {
|
||||
roles: ['admin'],
|
||||
introduction: 'I am a super administrator',
|
||||
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
|
||||
name: 'Super Admin'
|
||||
},
|
||||
'editor-token': {
|
||||
roles: ['editor'],
|
||||
introduction: 'I am an editor',
|
||||
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
|
||||
name: 'Normal Editor'
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = [
|
||||
// user login
|
||||
{
|
||||
url: '/vue-admin-template/user/login',
|
||||
type: 'post',
|
||||
response: config => {
|
||||
const { username } = config.body
|
||||
const token = tokens[username]
|
||||
|
||||
// mock error
|
||||
if (!token) {
|
||||
return {
|
||||
code: 60204,
|
||||
message: 'Account and password are incorrect.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
code: 20000,
|
||||
data: token
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// get user info
|
||||
{
|
||||
url: '/vue-admin-template/user/info\.*',
|
||||
type: 'get',
|
||||
response: config => {
|
||||
const { token } = config.query
|
||||
const info = users[token]
|
||||
|
||||
// mock error
|
||||
if (!info) {
|
||||
return {
|
||||
code: 50008,
|
||||
message: 'Login failed, unable to get user details.'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
code: 20000,
|
||||
data: info
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// user logout
|
||||
{
|
||||
url: '/vue-admin-template/user/logout',
|
||||
type: 'post',
|
||||
response: _ => {
|
||||
return {
|
||||
code: 20000,
|
||||
data: 'success'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @param {string} url
|
||||
* @returns {Object}
|
||||
*/
|
||||
function param2Obj(url) {
|
||||
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
|
||||
if (!search) {
|
||||
return {}
|
||||
}
|
||||
const obj = {}
|
||||
const searchArr = search.split('&')
|
||||
searchArr.forEach(v => {
|
||||
const index = v.indexOf('=')
|
||||
if (index !== -1) {
|
||||
const name = v.substring(0, index)
|
||||
const val = v.substring(index + 1, v.length)
|
||||
obj[name] = val
|
||||
}
|
||||
})
|
||||
return obj
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
param2Obj
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
{
|
||||
"name": "vue-admin-template",
|
||||
"version": "4.4.0",
|
||||
"description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
|
||||
"author": "Pan <panfree23@gmail.com>",
|
||||
"scripts": {
|
||||
"dev": "vue-cli-service serve",
|
||||
"build:prod": "vue-cli-service build",
|
||||
"build:stage": "vue-cli-service build --mode staging",
|
||||
"preview": "node build/index.js --preview",
|
||||
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
|
||||
"lint": "eslint --ext .js,.vue src",
|
||||
"test:unit": "jest --clearCache && vue-cli-service test:unit",
|
||||
"test:ci": "npm run lint && npm run test:unit"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "0.18.1",
|
||||
"core-js": "3.6.5",
|
||||
"echarts": "^4.9.0",
|
||||
"element-resize-detector": "^1.2.4",
|
||||
"element-ui": "2.13.2",
|
||||
"html2canvas": "^1.4.1",
|
||||
"js-cookie": "2.2.0",
|
||||
"less": "^3.13.1",
|
||||
"moment": "^2.29.4",
|
||||
"normalize.css": "7.0.0",
|
||||
"nprogress": "0.2.0",
|
||||
"path-to-regexp": "2.4.0",
|
||||
"print-js": "^1.6.0",
|
||||
"view-design": "^4.7.0",
|
||||
"vue": "2.6.10",
|
||||
"vue-grid-layout": "^2.4.0",
|
||||
"vue-router": "3.0.6",
|
||||
"vuex": "3.1.0",
|
||||
"vuex-persistedstate": "^4.1.0",
|
||||
"wangeditor": "^4.7.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "4.4.4",
|
||||
"@vue/cli-plugin-eslint": "4.4.4",
|
||||
"@vue/cli-plugin-unit-jest": "4.4.4",
|
||||
"@vue/cli-service": "4.4.4",
|
||||
"@vue/test-utils": "1.0.0-beta.29",
|
||||
"autoprefixer": "9.5.1",
|
||||
"babel-eslint": "^8.2.2",
|
||||
"babel-jest": "23.6.0",
|
||||
"babel-plugin-dynamic-import-node": "2.3.3",
|
||||
"chalk": "2.4.2",
|
||||
"connect": "3.6.6",
|
||||
"eslint": "6.7.2",
|
||||
"eslint-plugin-vue": "6.2.2",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"less-loader": "^5.0.0",
|
||||
"mockjs": "1.0.1-beta3",
|
||||
"runjs": "4.3.2",
|
||||
"sass": "1.26.8",
|
||||
"sass-loader": "8.0.2",
|
||||
"script-ext-html-webpack-plugin": "2.1.3",
|
||||
"serve-static": "1.13.2",
|
||||
"svg-sprite-loader": "4.1.3",
|
||||
"svgo": "1.2.2",
|
||||
"vue-template-compiler": "2.6.10"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=8.9",
|
||||
"npm": ">= 3.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
||||
|
||||
module.exports = {
|
||||
'plugins': {
|
||||
// to edit target browsers: use "browserslist" field in package.json
|
||||
'autoprefixer': {}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--清除浏览器中的缓存 -->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= webpackConfig.name %></title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= webpackConfig.name %> 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>
|
||||
@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import "./assets/css/common.less";
|
||||
export default {
|
||||
name: 'App'
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function index(params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/admin/plan_evaluate/index',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function show(params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/admin/plan_evaluate/show',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function save(data) {
|
||||
return request({
|
||||
method: 'post',
|
||||
url: '/api/admin/plan_evaluate/save',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function destroy(params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/admin/plan_evaluate/destroy',
|
||||
params
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function index(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/api/admin/target/index",
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function show(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/api/admin/target/show",
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function save(data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "/api/admin/target/save",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function destroy(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/api/admin/target/destroy",
|
||||
params
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
import request from '@/utils/request'
|
||||
import * as url from 'url'
|
||||
|
||||
export function index(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/api/admin/target_type/index",
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function show(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/api/admin/target_type/show",
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function save(data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "/api/admin/target_type/save",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function destroy(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/api/admin/target_type/destroy",
|
||||
params
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getBudget(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/plan/index',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function addBudget(data){
|
||||
return request({
|
||||
method:'post',
|
||||
url:'/api/admin/plan/store',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function delBudget(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/plan/destroy',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function editorBudget(data){
|
||||
return request({
|
||||
method:'post',
|
||||
url:'/api/admin/plan/save',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function detailBudget(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:"/api/admin/plan/show",
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function getProgress(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/plan/progress',
|
||||
params
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function index(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/api/admin/plan_target/index",
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function show(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/api/admin/plan_target/show",
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function save(data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "/api/admin/plan_target/save",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function destroy(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/api/admin/plan_target/destroy",
|
||||
params
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function index(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/api/admin/pre_plan/index",
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function show(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/api/admin/pre_plan/show",
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function save(data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "/api/admin/pre_plan/save",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function destroy(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/api/admin/pre_plan/destroy",
|
||||
params
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export function listCommondepartment(params) {
|
||||
return request({
|
||||
url: '/api/admin/other/admin-department-list',
|
||||
method: 'get',
|
||||
params:params
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function listCommonuser(params) {
|
||||
return request({
|
||||
url: '/api/admin/other/admin-user-list',
|
||||
method: 'get',
|
||||
params:params
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getContract(params,noloading = false){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/contract/index',
|
||||
params,
|
||||
noloading
|
||||
})
|
||||
}
|
||||
|
||||
export function addContrant(data){
|
||||
return request({
|
||||
method:"post",
|
||||
url:'/api/admin/contract/store',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function detailContract(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/contract/show',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function delContract(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/contract/destroy',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function editorContract(data){
|
||||
return request({
|
||||
method:'post',
|
||||
url:'/api/admin/contract/save',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function checkContractName(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/contract/check-name',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function updateStatus(params,noloading = true){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'api/admin/oa/update-contract',
|
||||
params,
|
||||
noloading
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function addContractSign(data){
|
||||
return request({
|
||||
method:'post',
|
||||
url:'/api/admin/sign_plan/store',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function getContractSign(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/sign_plan/index',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function delContractSign(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:"/api/admin/sign_plan/destroy",
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function detailContractSign(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/sign_plan/show',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function editorContractSign(data){
|
||||
return request({
|
||||
method:'post',
|
||||
url:"/api/admin/sign_plan/save",
|
||||
data
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getNotice(params,noLoading = false){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/notice/index',
|
||||
params,
|
||||
noLoading
|
||||
})
|
||||
}
|
||||
|
||||
export function getNotice2(params,noLoading = false){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/notice/index-v2',
|
||||
params,
|
||||
noLoading
|
||||
})
|
||||
}
|
||||
|
||||
export function readNotice(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/notice/has-read',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function statistic(params,noLoading = false){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/notice/statistic',
|
||||
params,
|
||||
noLoading
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function index (params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/admin/income/index',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function show (params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/admin/income/show',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function save (data) {
|
||||
return request({
|
||||
method: 'post',
|
||||
url: '/api/admin/income/save',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function destroy (params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/admin/income/destroy',
|
||||
params
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getOatoken(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/oa/get-oa-token',
|
||||
params
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
import request from "@/utils/request"
|
||||
export function getOutDetail({ tbname,out_caigou_id,out_contract_id,out_pay_id,out_zhaobiao_id }) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/index.php',
|
||||
requestBase: '/old',
|
||||
params: {
|
||||
s: "/Api/flowDetail",
|
||||
tbname,
|
||||
out_caigou_id,
|
||||
out_contract_id,
|
||||
out_pay_id,
|
||||
out_zhaobiao_id
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function httpCurl(params,noloading = true,s= '/Api/flowDetail',method='GET',url) {
|
||||
return request({
|
||||
method: 'post',
|
||||
url: '/api/admin/other/http-curl',
|
||||
data: {
|
||||
url: url || process.env.VUE_APP_OUT_OLD,
|
||||
method,
|
||||
params: {
|
||||
s,
|
||||
...params
|
||||
}
|
||||
},
|
||||
noloading
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getFundLog(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/fund_log/index',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function addFundLog(data){
|
||||
return request({
|
||||
method:'post',
|
||||
url:"/api/admin/fund_log/store",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function delFundLog(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/fund_log/destroy',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function detailFundLog(params){
|
||||
return request({
|
||||
method:'get',
|
||||
url:'/api/admin/fund_log/show',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function editorFundLog(data){
|
||||
return request({
|
||||
method:"post",
|
||||
url:"/api/admin/fund_log/save",
|
||||
data
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function save(data) {
|
||||
return request({
|
||||
url: '/api/admin/department/save',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function listdept() {
|
||||
return request({
|
||||
url: '/api/admin/department',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function listdeptNoAuth(params = {show_tree:1}){
|
||||
return request({
|
||||
url:'/api/admin/other/admin-department-list',
|
||||
method:'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function del(data) {
|
||||
return request({
|
||||
url: '/api/admin/department/delete',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function adminDepartmentList(data) {
|
||||
return request({
|
||||
url: '/api/admin/other/admin-department-list',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function save(data) {
|
||||
return request({
|
||||
url: '/api/admin/parameter/save',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function store(data) {
|
||||
return request({
|
||||
url: '/api/admin/parameter/store',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function getparameter(param) {
|
||||
return request({
|
||||
url: '/api/admin/parameter/show',
|
||||
method: 'get',
|
||||
params: param
|
||||
})
|
||||
}
|
||||
|
||||
export function listparameter(param) {
|
||||
return request({
|
||||
url: '/api/admin/parameter/index',
|
||||
method: 'get',
|
||||
params: param
|
||||
})
|
||||
}
|
||||
export function del(id) {
|
||||
return request({
|
||||
url: '/api/admin/parameter/delete',
|
||||
method: 'get',
|
||||
params: {
|
||||
id
|
||||
}
|
||||
})
|
||||
}
|
||||
export function delDetail(id) {
|
||||
return request({
|
||||
url: '/api/admin/parameter/detail-delete',
|
||||
method: 'get',
|
||||
params: {
|
||||
id
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
export function index(params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/admin/admin_expand/index',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function save(data) {
|
||||
return request({
|
||||
method: 'post',
|
||||
url: '/api/admin/admin_expand/save',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function show(params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/admin/admin_expand/show',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function destroy(params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/admin/admin_expand/destroy',
|
||||
params
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function index(data){
|
||||
return request({
|
||||
method:'post',
|
||||
url:'/api/admin/operate-log/index',
|
||||
data
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function save(data) {
|
||||
return request({
|
||||
url: '/api/admin/menu/save',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function listmenu() {
|
||||
return request({
|
||||
url: '/api/admin/menu',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
export function del(data) {
|
||||
return request({
|
||||
url: '/api/admin/menu/delete',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
import request from "@/utils/request";
|
||||
import store from '@/store';
|
||||
export function ossLogin(){
|
||||
return request({
|
||||
isLoading:false,
|
||||
method:'post',
|
||||
url:'/api/admin/auth/oss-login',
|
||||
data:{
|
||||
id:store.state.user.userId,
|
||||
username:store.state.user.username
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function setPermissions(data) {
|
||||
return request({
|
||||
url: '/api/admin/role/set-permissions',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function save(data) {
|
||||
return request({
|
||||
url: '/api/admin/role/save',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function list() {
|
||||
return request({
|
||||
url: '/api/admin/role',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
export function del(data) {
|
||||
return request({
|
||||
url: '/api/admin/role/delete',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function set(data) {
|
||||
return request({
|
||||
url: '/api/admin/admin/set-roles-many',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function save(data) {
|
||||
return request({
|
||||
url: '/api/admin/admin/save',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function listuser(params) {
|
||||
return request({
|
||||
url: '/api/admin/admin',
|
||||
method: 'get',
|
||||
params:params
|
||||
})
|
||||
}
|
||||
|
||||
export function del(data) {
|
||||
return request({
|
||||
url: '/api/admin/admin/delete',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function setRoles(data) {
|
||||
return request({
|
||||
url: '/api/admin/admin/set-roles',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function login(data) {
|
||||
return request({
|
||||
url: '/api/admin/auth/login',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function loginOss(data) {
|
||||
return request({
|
||||
url: '/api/admin/auth/oss-login',
|
||||
method: 'post',
|
||||
data,
|
||||
noloading:true
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function getInfo(token) {
|
||||
return request({
|
||||
url: '/api/admin/auth/me',
|
||||
method: 'post',
|
||||
params: { token }
|
||||
})
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
return request({
|
||||
url: '/api/admin/auth/logout',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function getAuthMenu(token) {
|
||||
return request({
|
||||
url: '/api/admin/auth/permissions',
|
||||
method: 'get',
|
||||
params: { token }
|
||||
})
|
||||
}
|
||||
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
@ -0,0 +1,83 @@
|
||||
|
||||
.layout-container {
|
||||
// border-top: 1px solid #eee;
|
||||
background: #eee;
|
||||
// padding: 15px;
|
||||
/* margin-bottom: 40px; */
|
||||
}
|
||||
// .animated {
|
||||
// -webkit-animation-duration: 1s;
|
||||
// animation-duration: 1s;
|
||||
// -webkit-animation-fill-mode: both;
|
||||
// animation-fill-mode: both;
|
||||
// }
|
||||
// .animated.infinite {
|
||||
// -webkit-animation-iteration-count: infinite;
|
||||
// animation-iteration-count: infinite;
|
||||
// }
|
||||
// .animated.hinge {
|
||||
// -webkit-animation-duration: 2s;
|
||||
// animation-duration: 2s;
|
||||
// }
|
||||
// .animated.bounceIn,
|
||||
// .animated.bounceOut,
|
||||
// .animated.flipOutX,
|
||||
// .animated.flipOutY {
|
||||
// -webkit-animation-duration: 0.75s;
|
||||
// animation-duration: 0.75s;
|
||||
// }
|
||||
// @-webkit-keyframes fadeInDown {
|
||||
// 0% {
|
||||
// opacity: 0;
|
||||
// -webkit-transform: translate3d(0, -100%, 0);
|
||||
// transform: translate3d(0, -100%, 0);
|
||||
// }
|
||||
// to {
|
||||
// opacity: 1;
|
||||
// -webkit-transform: none;
|
||||
// transform: none;
|
||||
// }
|
||||
// }
|
||||
// @keyframes fadeInDown {
|
||||
// 0% {
|
||||
// opacity: 0;
|
||||
// -webkit-transform: translate3d(0, -100%, 0);
|
||||
// transform: translate3d(0, -100%, 0);
|
||||
// }
|
||||
// to {
|
||||
// opacity: 1;
|
||||
// -webkit-transform: none;
|
||||
// transform: none;
|
||||
// }
|
||||
// }
|
||||
// .fadeInDown {
|
||||
// -webkit-animation-name: fadeInDown;
|
||||
// animation-name: fadeInDown;
|
||||
// }
|
||||
|
||||
// @-webkit-keyframes slideInDown {
|
||||
// 0% {
|
||||
// -webkit-transform: translate3d(0, -100%, 0);
|
||||
// transform: translate3d(0, -100%, 0);
|
||||
// visibility: visible;
|
||||
// }
|
||||
// to {
|
||||
// -webkit-transform: translateZ(0);
|
||||
// transform: translateZ(0);
|
||||
// }
|
||||
// }
|
||||
// @keyframes slideInDown {
|
||||
// 0% {
|
||||
// -webkit-transform: translate3d(0, -100%, 0);
|
||||
// transform: translate3d(0, -100%, 0);
|
||||
// visibility: visible;
|
||||
// }
|
||||
// to {
|
||||
// -webkit-transform: translateZ(0);
|
||||
// transform: translateZ(0);
|
||||
// }
|
||||
// }
|
||||
// .slideInDown {
|
||||
// -webkit-animation-name: slideInDown;
|
||||
// animation-name: slideInDown;
|
||||
// }
|
||||
@ -0,0 +1,226 @@
|
||||
.view-container{
|
||||
// padding: 15px;
|
||||
margin: 0px 20px;
|
||||
padding-bottom: 15px;
|
||||
background: white;
|
||||
.grid-search{
|
||||
padding-top:15px;
|
||||
//padding: 15px 15px 0 15px;
|
||||
}
|
||||
.grid-container,.grid-body{
|
||||
padding: 0 15px;
|
||||
}
|
||||
.view-header{
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
.fs-line{
|
||||
height: 10px;
|
||||
background: #eee;
|
||||
margin-top: -10px;
|
||||
margin-bottom: 11px;
|
||||
border-top: 1px solid #dadada;
|
||||
border-bottom: 1px solid #dadada;
|
||||
}
|
||||
}
|
||||
.view-header {
|
||||
height: 45px;
|
||||
position: relative;
|
||||
padding-bottom: 11px;
|
||||
display: flex;
|
||||
.search-line {
|
||||
width: 180px;
|
||||
}
|
||||
.search-line > div {
|
||||
margin-left: 5px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.search-line > div > div{
|
||||
width: 200px;
|
||||
text-align: left;
|
||||
}
|
||||
.search-line > div:first-child{
|
||||
flex: 1;
|
||||
}
|
||||
.search-line > div .ivu-select-dropdown{
|
||||
max-height: 300px;
|
||||
}
|
||||
// .btn-group > button {
|
||||
// text-align: right;
|
||||
// }
|
||||
.btn-group{
|
||||
white-space: nowrap;
|
||||
button {
|
||||
margin-left: 10px;
|
||||
// padding: 5px 16px;
|
||||
}
|
||||
.dropdown{
|
||||
height: 31px;
|
||||
padding-right: 9px;
|
||||
padding-left: 11px;
|
||||
border-top-right-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
}
|
||||
.r-dropdown{
|
||||
height: 31px;
|
||||
margin-left: 0px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
border-bottom-left-radius: 0px;
|
||||
border-left: 1px solid #eee;
|
||||
border-top-left-radius: 0;
|
||||
}
|
||||
}
|
||||
.btn-group .ivu-dropdown-item {
|
||||
text-align: left !important;
|
||||
}
|
||||
.btn-group .ivu-dropdown-item:not(:last-child) {
|
||||
border-bottom: 1px dotted #eee;
|
||||
}
|
||||
.desc-text {
|
||||
margin-top: 5px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 3px;
|
||||
font-size: 14px;
|
||||
color: #313131;
|
||||
white-space: nowrap;
|
||||
border-bottom: 2px solid #646565;
|
||||
}
|
||||
.desc-text .ivu-icon {
|
||||
font-size: 20px;
|
||||
bottom: 2px;
|
||||
position: relative;
|
||||
}
|
||||
.search-box {
|
||||
background: #fefefe;
|
||||
margin-top: 45px;
|
||||
border: 1px solid #ececec;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
left: 0;
|
||||
right: 0;
|
||||
// width: 100%;
|
||||
padding: 25px 40px;
|
||||
padding-bottom: 0;
|
||||
box-shadow: 0px 7px 18px -12px #bdc0bb;
|
||||
}
|
||||
.notice {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
top: 12px;
|
||||
flex: 1;
|
||||
left: 10px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.table-info-cell-title {
|
||||
background-color: #f5f5f5 !important;
|
||||
}
|
||||
.iview-com {
|
||||
background: #f3f3f3;
|
||||
> div.item{
|
||||
// margin-bottom: 10px;
|
||||
|
||||
margin-bottom: 12px;
|
||||
background: white;
|
||||
}
|
||||
> div.form-item{
|
||||
padding: 8px 16px 7px 16px;
|
||||
//box-shadow: 0 1px 7px rgb(199, 199, 199);
|
||||
}
|
||||
> div.table-item{
|
||||
padding: 0 10px;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
.v-text{
|
||||
line-height: 27px;
|
||||
}
|
||||
.form-text{
|
||||
position: relative;
|
||||
/* height: 38px; */
|
||||
/* line-height: 38px; */
|
||||
/* padding: 0 15px; */
|
||||
// border-bottom: 1px solid #e4e4e4;
|
||||
border-bottom: 1px solid #eee;
|
||||
/* border-radius: 2px 2px 0 0; */
|
||||
font-size: 14px;
|
||||
margin-bottom: 14px;
|
||||
.title{
|
||||
border-bottom: 2px solid #00BCD4;
|
||||
color: #009688;
|
||||
font-weight: bold;
|
||||
letter-spacing: 1px;
|
||||
// border-bottom-right-radius: 5px;
|
||||
// border-top-left-radius: 5px;
|
||||
padding: 6px 0;
|
||||
// background: #009688;
|
||||
// color: white;
|
||||
}
|
||||
.icon{
|
||||
color: #00BCD4;
|
||||
font-size: 19px;
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-closex {
|
||||
text-align: right;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
.form-closex button {
|
||||
margin-left: 10px;
|
||||
padding: 4px 13px;
|
||||
}
|
||||
// .grid-detail{
|
||||
// }
|
||||
.toolbar{
|
||||
padding: 3px 0px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
.title{
|
||||
line-height: 29px;
|
||||
border-bottom: none;
|
||||
font-size: 13px;
|
||||
font-weight: bolder;
|
||||
margin-bottom: 0;
|
||||
color: #5d5c5c;
|
||||
.icon{
|
||||
color: #009688;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
i{
|
||||
line-height: 29px;
|
||||
border-bottom: none;
|
||||
font-weight: bolder;
|
||||
margin-bottom: 0;
|
||||
color: #5d5c5c;
|
||||
position: relative;
|
||||
margin-top: -4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.btns{
|
||||
line-height: 28px;
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
margin-right: 12px;
|
||||
button{
|
||||
border: none;
|
||||
margin-left:15px;
|
||||
border: 0px;
|
||||
color: #009688;
|
||||
}
|
||||
button:hover{
|
||||
color: #FF9800;
|
||||
border-color: #FF9800;
|
||||
border: none;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
*{
|
||||
box-sizing:border-box;
|
||||
-moz-box-sizing:border-box; /* Firefox */
|
||||
-webkit-box-sizing:border-box; /* Safari */
|
||||
}
|
||||
.el-pager li{
|
||||
font-weight: 100;
|
||||
margin-right: 9px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 3px;
|
||||
min-width: 28px;
|
||||
}
|
||||
.el-pager li.active,.el-pager li:hover{
|
||||
background: #ed4014;
|
||||
color: white;
|
||||
}
|
||||
.el-pagination__editor.el-input .el-input__inner{
|
||||
height: 23px;
|
||||
}
|
||||
|
||||
|
||||
.animated {
|
||||
-webkit-animation-duration: 0.5s;
|
||||
animation-duration: 0.5s;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
@media (print), (prefers-reduced-motion) {
|
||||
.animated {
|
||||
-webkit-animation: unset !important;
|
||||
animation: unset !important;
|
||||
-webkit-transition: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeInDown {
|
||||
from {
|
||||
opacity: 1;
|
||||
-webkit-transform: translate3d(0, -100%, 0);
|
||||
transform: translate3d(0, -100%, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
-webkit-transform: translate3d(0, -100%, 0);
|
||||
transform: translate3d(0, -100%, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.fadeInDown {
|
||||
-webkit-animation-name: fadeInDown;
|
||||
animation-name: fadeInDown;
|
||||
}
|
||||
.ivu-message{
|
||||
z-index: 999999999 !important;
|
||||
}
|
||||
.ivu-form-item-content{
|
||||
text-align: left;
|
||||
}
|
||||
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
@ -0,0 +1,303 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div ref="lxHeader">
|
||||
<LxHeader icon="md-apps" :text="typeLabel[type]" style="margin-bottom: 10px; border: 0px; margin-top: 15px">
|
||||
<div slot="content" />
|
||||
<slot>
|
||||
<div>
|
||||
<Input v-model="listQuery.keyword" style="width: 200px; margin-right: 10px" placeholder="关键字搜索" />
|
||||
<Button type="primary" @click="handleFilter">查询</Button>
|
||||
</div>
|
||||
</slot>
|
||||
</LxHeader>
|
||||
</div>
|
||||
<div class="table-tree">
|
||||
<el-table :data="tableData" border default-expand-all class="v-table" style="width: 100%;margin-bottom: 20px;">
|
||||
<el-table-column type="index" label="序号" width="50" />
|
||||
<el-table-column label="项目名称" prop="name" width="400" />
|
||||
<el-table-column label="文档数量" prop="item_accepts_count" align="center" />
|
||||
<el-table-column label="编辑人" align="center">
|
||||
<template slot-scope="{row}"><span>{{ row.admin ? row.admin.name: '' }}</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最后编辑时间" width="160" prop="updated_at" align="center" />
|
||||
<el-table-column fixed="right" width="250" label="操作" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<Button type="primary" size="small" style="margin-left: 10px;" ghost @click="editList(row)">编辑</Button>
|
||||
<Button type="primary" size="small" style="margin-left: 10px;" ghost @click="showList(row)">查看</Button>
|
||||
<!-- <Button type="error" size="small" style="margin-left: 10px;" ghost @click="dialogFormVisible = true">删除</Button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.page_size" @pagination="getList" />
|
||||
</div>
|
||||
<el-dialog :title="'管理文件'" :visible.sync="dialogFormVisible" width="80%" @close="dialogClose">
|
||||
<div class="rightCol">
|
||||
<Button type="primary" @click="addRow" size="small" ghost>新增文件</Button>
|
||||
</div>
|
||||
<el-form ref="dataForm" :model="form" :rules="rules">
|
||||
<el-table border default-expand-all class="v-table" :data="form.list">
|
||||
<el-table-column label="文件名称" prop="name" width="400">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'list.' + scope.$index + '.name'" style="margin-top: 15px;margin-bottom: 17px;">
|
||||
<el-input v-model="scope.row.name" placeholder="文件名称" style="width:100%" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="获取时间" prop="date">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'list.' + scope.$index + '.date'" style="margin-top: 15px;margin-bottom: 17px;">
|
||||
<el-date-picker v-model="scope.row.date" type="date" placeholder="选择日期" value-format="yyyy-MM-dd" style="width: 100%;" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件名称" prop="upload_id">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'list.' + scope.$index + '.upload_id'" style="margin-top: 15px;margin-bottom: 17px;">
|
||||
<UploadFile v-if="dialogFormVisible" v-model="scope.row.upload_id" :file_name="scope.row.upload ? scope.row.upload.original_name : ''" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="150" label="操作" align="center">
|
||||
<template slot-scope="scope">
|
||||
<Button @click="save(scope.$index)" type="primary" size="small" ghost>保存</Button>
|
||||
<Button type="error" size="small" ghost @click="handleDelete(scope.row, scope.$index)">删除</Button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer"></div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :title="'查看文件'" :visible.sync="dialogTableVisible" width="80%">
|
||||
<el-table border default-expand-all class="v-table" :data="form.list">
|
||||
<el-table-column label="文件名称" prop="name" width="400">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.name}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="获取时间" prop="date">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.date}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件名称" prop="upload_id">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.upload ? scope.row.upload.original_name : ''}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template slot-scope="scope">
|
||||
<a v-if="scope.row.upload" :href="scope.row.upload.url" target="_blank">下载</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div slot="footer" class="dialog-footer"></div>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LxHeader from '@/components/LxHeader/index.vue'
|
||||
import UploadFile from '@/components/Upload/file.vue'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { contractIndex, index, show, destroy, store, save } from '../../api/accept.js'
|
||||
export default {
|
||||
name: 'Accept',
|
||||
components: {
|
||||
LxHeader, UploadFile, Pagination
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
typeLabel: {1: '结算审计资料', 2: '结算审计报告', 3: '归档管理', 4: '决算报告'},
|
||||
listQuery: {
|
||||
page: 1,
|
||||
page_size: 10
|
||||
},
|
||||
total: 0,
|
||||
tableData: [],
|
||||
rules: {
|
||||
list:[]
|
||||
},
|
||||
dialogFormVisible:false,
|
||||
dialogTableVisible: false,
|
||||
form: {
|
||||
id: undefined,
|
||||
contract_id: '',
|
||||
list: []
|
||||
},
|
||||
bcglXiangXiList: [],
|
||||
checkedDetail: [],
|
||||
formLabelWidth: '120px',
|
||||
search:''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.listQuery.type = this.type
|
||||
contractIndex(this.listQuery).then(response => {
|
||||
this.tableData = response.data
|
||||
this.total = response.total
|
||||
}).catch(error => {})
|
||||
},
|
||||
handleFilter() {
|
||||
this.listQuery.page = 1
|
||||
this.getList()
|
||||
},
|
||||
createRules(idx) {
|
||||
let ruleList = []
|
||||
for (let i = 0; i < this.form.list.length; i++) {
|
||||
let required = i == idx ? true : false
|
||||
ruleList.push({
|
||||
name: { required: required, message: '请输入文件名称', trigger: 'change' },
|
||||
date: { required: required, message: '请选择获取时间', trigger: 'change' },
|
||||
upload_id: { required: required, message: '请上传文件', trigger: 'change' },
|
||||
})
|
||||
}
|
||||
this.rules = {list: ruleList}
|
||||
},
|
||||
editList(row) {
|
||||
this.form.list = []
|
||||
index({contract_id: row.id, type: this.type, page_size: 9999, sort_name: 'id', sort_type: 'asc'}).then(r => {
|
||||
this.form.list = r.data
|
||||
this.form.contract_id = row.id
|
||||
if (r.data.length == 0) {
|
||||
this.addRow()
|
||||
}
|
||||
this.dialogFormVisible = true
|
||||
}).catch(error => {})
|
||||
},
|
||||
showList(row) {
|
||||
this.form.list = []
|
||||
index({contract_id: row.id, type: this.type, page_size: 9999, sort_name: 'id', sort_type: 'asc'}).then(r => {
|
||||
this.form.list = r.data
|
||||
this.dialogTableVisible = true
|
||||
}).catch(error => {})
|
||||
},
|
||||
addRow() {
|
||||
this.form.list.push({ name: '', date: '', upload_id: null, upload: {original_name: ''} })
|
||||
},
|
||||
save(idx) {
|
||||
this.createRules(idx)
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
this.$refs['dataForm'].validate()
|
||||
|
||||
let tempData = this.form.list[idx]
|
||||
tempData.contract_id = this.form.contract_id
|
||||
tempData.type = this.type
|
||||
if (tempData.name && tempData.date && tempData.upload_id) {
|
||||
if (tempData.id) {
|
||||
save(tempData).then(r => { this.saved() }).catch(error => {})
|
||||
} else {
|
||||
store(tempData).then(r => { this.saved() }).catch(error => {})
|
||||
}
|
||||
}
|
||||
},
|
||||
saved() {
|
||||
this.$message.success('保存成功')
|
||||
},
|
||||
handleDelete(row, index) {
|
||||
this.$confirm('确定要删除吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
if (!row.id) {
|
||||
this.form.list.splice(index, 1)
|
||||
return
|
||||
}
|
||||
destroy({ id: row.id }).then(response => {
|
||||
this.$message.success('删除成功')
|
||||
this.form.list.splice(index, 1)
|
||||
}).catch(error => {})
|
||||
}).catch(() => {})
|
||||
},
|
||||
dialogClose() {
|
||||
this.getList()
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
/deep/ .el-dialog__body{
|
||||
padding:8px 20px;
|
||||
}
|
||||
/deep/ .el-col-5{
|
||||
width:20%;
|
||||
}
|
||||
/deep/ .el-upload-list{
|
||||
float:left;
|
||||
line-height: 28px;
|
||||
margin-right:15px;
|
||||
}
|
||||
/deep/ .el-upload-list__item:first-child{
|
||||
margin-top:0;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.ivu-btn{
|
||||
margin-right:10px;
|
||||
}
|
||||
.table-tree{
|
||||
margin-top:10px;
|
||||
}
|
||||
.rightCol{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-left: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.v-text{
|
||||
padding:8px 0;
|
||||
border-bottom:1px solid #eee;
|
||||
margin-bottom:20px;
|
||||
.title{
|
||||
color: #338de3;
|
||||
}
|
||||
}
|
||||
.dataGroup{
|
||||
padding:10px 0;
|
||||
}
|
||||
.grid-content{
|
||||
border-radius:5px;
|
||||
text-align:center;
|
||||
background: #ffffff;
|
||||
padding:15px 0;
|
||||
p{
|
||||
line-height: 1.8;
|
||||
}
|
||||
p:first-child{
|
||||
font-weight:700;
|
||||
font-size:16px;
|
||||
}
|
||||
}
|
||||
.bg-org{
|
||||
border:2px solid #EF6C24;
|
||||
color:#EF6C24;
|
||||
}
|
||||
.bg-blue{
|
||||
border:2px solid #0800FF;
|
||||
color:#0800FF;
|
||||
}
|
||||
.bg-green{
|
||||
border:2px solid #0F9700;
|
||||
color:#0F9700;
|
||||
}
|
||||
.bg-black{
|
||||
border:2px solid #333;
|
||||
color:#333;
|
||||
}
|
||||
.bg-pink{
|
||||
border:2px solid #FF0000;
|
||||
color:#FF0000;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||
<transition-group name="breadcrumb">
|
||||
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
|
||||
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
|
||||
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
|
||||
</el-breadcrumb-item>
|
||||
</transition-group>
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import pathToRegexp from 'path-to-regexp'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
levelList: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.getBreadcrumb()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getBreadcrumb()
|
||||
},
|
||||
methods: {
|
||||
getBreadcrumb() {
|
||||
// only show routes with meta.title
|
||||
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
|
||||
const first = matched[0]
|
||||
|
||||
if (!this.isDashboard(first)) {
|
||||
matched = [{ path: '/dashboard', meta: { title: '系统首页' }}].concat(matched)
|
||||
}
|
||||
|
||||
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
||||
},
|
||||
isDashboard(route) {
|
||||
const name = route && route.name
|
||||
if (!name) {
|
||||
return false
|
||||
}
|
||||
return name.trim().toLocaleLowerCase() === '系统首页'.toLocaleLowerCase()
|
||||
},
|
||||
pathCompile(path) {
|
||||
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
|
||||
const { params } = this.$route
|
||||
var toPath = pathToRegexp.compile(path)
|
||||
return toPath(params)
|
||||
},
|
||||
handleLink(item) {
|
||||
const { redirect, path } = item
|
||||
if (redirect) {
|
||||
this.$router.push(redirect)
|
||||
return
|
||||
}
|
||||
this.$router.push(this.pathCompile(path))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-breadcrumb.el-breadcrumb {
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
margin-left: 8px;
|
||||
|
||||
.no-redirect {
|
||||
color: #97a8be;
|
||||
cursor: text;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,303 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div ref="lxHeader">
|
||||
<LxHeader icon="md-apps" :text="typeLabel[type]" style="margin-bottom: 10px; border: 0px; margin-top: 15px">
|
||||
<div slot="content" />
|
||||
<slot>
|
||||
<div>
|
||||
<Input v-model="listQuery.keyword" style="width: 200px; margin-right: 10px" placeholder="关键字搜索" />
|
||||
<Button type="primary" @click="handleFilter">查询</Button>
|
||||
</div>
|
||||
</slot>
|
||||
</LxHeader>
|
||||
</div>
|
||||
<div class="table-tree">
|
||||
<el-table :data="tableData" border default-expand-all class="v-table" style="width: 100%;margin-bottom: 20px;">
|
||||
<el-table-column type="index" label="序号" width="50" />
|
||||
<el-table-column label="项目名称" prop="name" width="400" />
|
||||
<el-table-column label="文档数量" prop="item_builds_count" align="center" />
|
||||
<el-table-column label="编辑人" align="center">
|
||||
<template slot-scope="{row}"><span>{{ row.admin ? row.admin.name: '' }}</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最后编辑时间" prop="updated_at" align="center" />
|
||||
<el-table-column fixed="right" width="250" label="操作" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<Button type="primary" size="small" style="margin-left: 10px;" ghost @click="editList(row)">编辑</Button>
|
||||
<Button type="primary" size="small" style="margin-left: 10px;" ghost @click="showList(row)">查看</Button>
|
||||
<!-- <Button type="error" size="small" style="margin-left: 10px;" ghost @click="dialogFormVisible = true">删除</Button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.page_size" @pagination="getList" />
|
||||
</div>
|
||||
<el-dialog :title="'管理文件'" :visible.sync="dialogFormVisible" width="80%" @close="dialogClose">
|
||||
<div class="rightCol">
|
||||
<Button type="primary" @click="addRow" size="small" ghost>新增文件</Button>
|
||||
</div>
|
||||
<el-form ref="dataForm" :model="form" :rules="rules">
|
||||
<el-table border default-expand-all class="v-table" :data="form.list">
|
||||
<el-table-column label="文件名称" prop="name" width="400">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'list.' + scope.$index + '.name'" style="margin-top: 15px;margin-bottom: 17px;">
|
||||
<el-input v-model="scope.row.name" placeholder="文件名称" style="width:100%" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="获取时间" prop="date">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'list.' + scope.$index + '.date'" style="margin-top: 15px;margin-bottom: 17px;">
|
||||
<el-date-picker v-model="scope.row.date" type="date" placeholder="选择日期" value-format="yyyy-MM-dd" style="width: 100%;" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件名称" prop="upload_id">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'list.' + scope.$index + '.upload_id'" style="margin-top: 15px;margin-bottom: 17px;">
|
||||
<UploadFile v-if="dialogFormVisible" v-model="scope.row.upload_id" :file_name="scope.row.upload ? scope.row.upload.original_name : ''" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="150" label="操作" align="center">
|
||||
<template slot-scope="scope">
|
||||
<Button @click="save(scope.$index)" type="primary" size="small" ghost>保存</Button>
|
||||
<Button type="error" size="small" ghost @click="handleDelete(scope.row, scope.$index)">删除</Button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer"></div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :title="'查看文件'" :visible.sync="dialogTableVisible" width="80%">
|
||||
<el-table border default-expand-all class="v-table" :data="form.list">
|
||||
<el-table-column label="文件名称" prop="name" width="400">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.name}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="获取时间" prop="date">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.date}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件名称" prop="upload_id">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.upload ? scope.row.upload.original_name : ''}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template slot-scope="scope">
|
||||
<a v-if="scope.row.upload" :href="scope.row.upload.url" target="_blank">下载</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div slot="footer" class="dialog-footer"></div>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LxHeader from '@/components/LxHeader/index.vue'
|
||||
import UploadFile from '@/components/Upload/file.vue'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { contractIndex, index, show, destroy, store, save } from '../../api/build.js'
|
||||
export default {
|
||||
name: 'BuildPage',
|
||||
components: {
|
||||
LxHeader, UploadFile, Pagination
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
typeLabel: {1: '合同文件管理', 2: '合同登记', 3: '履约验收'},
|
||||
listQuery: {
|
||||
page: 1,
|
||||
page_size: 10
|
||||
},
|
||||
total: 0,
|
||||
tableData: [],
|
||||
rules: {
|
||||
list:[]
|
||||
},
|
||||
dialogFormVisible:false,
|
||||
dialogTableVisible: false,
|
||||
form: {
|
||||
id: undefined,
|
||||
contract_id: '',
|
||||
list: []
|
||||
},
|
||||
bcglXiangXiList: [],
|
||||
checkedDetail: [],
|
||||
formLabelWidth: '120px',
|
||||
search:''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.listQuery.type = this.type
|
||||
contractIndex(this.listQuery).then(response => {
|
||||
this.tableData = response.data
|
||||
this.total = response.total
|
||||
}).catch(error => {})
|
||||
},
|
||||
handleFilter() {
|
||||
this.listQuery.page = 1
|
||||
this.getList()
|
||||
},
|
||||
createRules(idx) {
|
||||
let ruleList = []
|
||||
for (let i = 0; i < this.form.list.length; i++) {
|
||||
let required = i == idx ? true : false
|
||||
ruleList.push({
|
||||
name: { required: required, message: '请输入文件名称', trigger: 'change' },
|
||||
date: { required: required, message: '请选择获取时间', trigger: 'change' },
|
||||
upload_id: { required: required, message: '请上传文件', trigger: 'change' },
|
||||
})
|
||||
}
|
||||
this.rules = {list: ruleList}
|
||||
},
|
||||
editList(row) {
|
||||
this.form.list = []
|
||||
index({contract_id: row.id, type: this.type, page_size: 9999, sort_name: 'id', sort_type: 'asc'}).then(r => {
|
||||
this.form.list = r.data
|
||||
this.form.contract_id = row.id
|
||||
if (r.data.length == 0) {
|
||||
this.addRow()
|
||||
}
|
||||
this.dialogFormVisible = true
|
||||
}).catch(error => {})
|
||||
},
|
||||
showList(row) {
|
||||
this.form.list = []
|
||||
index({contract_id: row.id, type: this.type, page_size: 9999, sort_name: 'id', sort_type: 'asc'}).then(r => {
|
||||
this.form.list = r.data
|
||||
this.dialogTableVisible = true
|
||||
}).catch(error => {})
|
||||
},
|
||||
addRow() {
|
||||
this.form.list.push({ name: '', date: '', upload_id: null, upload: {original_name: ''} })
|
||||
},
|
||||
save(idx) {
|
||||
this.createRules(idx)
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
this.$refs['dataForm'].validate()
|
||||
|
||||
let tempData = this.form.list[idx]
|
||||
tempData.contract_id = this.form.contract_id
|
||||
tempData.type = this.type
|
||||
if (tempData.name && tempData.date && tempData.upload_id) {
|
||||
if (tempData.id) {
|
||||
save(tempData).then(r => { this.saved() }).catch(error => {})
|
||||
} else {
|
||||
store(tempData).then(r => { this.saved() }).catch(error => {})
|
||||
}
|
||||
}
|
||||
},
|
||||
saved() {
|
||||
this.$message.success('保存成功')
|
||||
},
|
||||
handleDelete(row, index) {
|
||||
this.$confirm('确定要删除吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
if (!row.id) {
|
||||
this.form.list.splice(index, 1)
|
||||
return
|
||||
}
|
||||
destroy({ id: row.id }).then(response => {
|
||||
this.$message.success('删除成功')
|
||||
this.form.list.splice(index, 1)
|
||||
}).catch(error => {})
|
||||
}).catch(() => {})
|
||||
},
|
||||
dialogClose() {
|
||||
this.getList()
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
/deep/ .el-dialog__body{
|
||||
padding:8px 20px;
|
||||
}
|
||||
/deep/ .el-col-5{
|
||||
width:20%;
|
||||
}
|
||||
/deep/ .el-upload-list{
|
||||
float:left;
|
||||
line-height: 28px;
|
||||
margin-right:15px;
|
||||
}
|
||||
/deep/ .el-upload-list__item:first-child{
|
||||
margin-top:0;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.ivu-btn{
|
||||
margin-right:10px;
|
||||
}
|
||||
.table-tree{
|
||||
margin-top:10px;
|
||||
}
|
||||
.rightCol{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-left: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.v-text{
|
||||
padding:8px 0;
|
||||
border-bottom:1px solid #eee;
|
||||
margin-bottom:20px;
|
||||
.title{
|
||||
color: #338de3;
|
||||
}
|
||||
}
|
||||
.dataGroup{
|
||||
padding:10px 0;
|
||||
}
|
||||
.grid-content{
|
||||
border-radius:5px;
|
||||
text-align:center;
|
||||
background: #ffffff;
|
||||
padding:15px 0;
|
||||
p{
|
||||
line-height: 1.8;
|
||||
}
|
||||
p:first-child{
|
||||
font-weight:700;
|
||||
font-size:16px;
|
||||
}
|
||||
}
|
||||
.bg-org{
|
||||
border:2px solid #EF6C24;
|
||||
color:#EF6C24;
|
||||
}
|
||||
.bg-blue{
|
||||
border:2px solid #0800FF;
|
||||
color:#0800FF;
|
||||
}
|
||||
.bg-green{
|
||||
border:2px solid #0F9700;
|
||||
color:#0F9700;
|
||||
}
|
||||
.bg-black{
|
||||
border:2px solid #333;
|
||||
color:#333;
|
||||
}
|
||||
.bg-pink{
|
||||
border:2px solid #FF0000;
|
||||
color:#FF0000;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,239 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div ref="lxHeader">
|
||||
<LxHeader icon="md-apps" :text="typeLabel[type]" style="margin-bottom: 10px; border: 0px; margin-top: 15px">
|
||||
<div slot="content" />
|
||||
<slot>
|
||||
<div>
|
||||
<!-- <Select v-model="listQuery.item_type" style="width:200px; margin-right: 10px" placeholder="项目属性">
|
||||
<Option v-for="(i, idx) in []" :key="idx" :value="i.id">{{ i.name }}</Option>
|
||||
</Select> -->
|
||||
<Input v-model="listQuery.keyword" style="width: 200px; margin-right: 10px" placeholder="关键字搜索" />
|
||||
<Button type="primary" @click="handleFilter">查询</Button>
|
||||
<Button type="primary" @click="handleUpdate(null)">新增</Button>
|
||||
</div>
|
||||
</slot>
|
||||
</LxHeader>
|
||||
</div>
|
||||
<div class="table-tree">
|
||||
<el-table :data="list" border default-expand-all class="v-table" style="width: 100%;margin-bottom: 20px;">
|
||||
<el-table-column type="index" label="序号" width="50" />
|
||||
<el-table-column label="项目名称" align="center">
|
||||
<template slot-scope="{row}"><span>{{ row.item ? row.item.name: '' }}</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="项目属性" align="center">
|
||||
<template slot-scope="{row}"><span>{{ row.item ? row.item.name: '' }}</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="文件名称" prop="name" align="center" />
|
||||
<el-table-column label="验收日期" prop="check_date" align="center" />
|
||||
<el-table-column label="附件" align="center">
|
||||
<template slot-scope="{row}"><a v-if="row.upload" :href="row.upload.url" target="_blank">{{ row.upload.original_name }}</a></template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" width="250" label="操作" align="center">
|
||||
<template slot-scope="{row, $index}">
|
||||
<Button type="error" size="small" style="margin-left: 10px;" ghost @click="handleDelete(row, $index)">删除</Button>
|
||||
<Button type="primary" size="small" style="margin-left: 10px;" ghost @click="handleUpdate(row)">编辑</Button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.page_size" @pagination="getList" />
|
||||
</div>
|
||||
<el-dialog :title="form.id ? '编辑项目' : '新增项目'" :visible.sync="dialogFormVisible" width="45%">
|
||||
<el-form ref="dataForm" :model="form" label-position="right" :label-width="formLabelWidth">
|
||||
<el-form-item label="项目名称" prop="name" :rules="{ required: true, message: '请输入项目名称', trigger: 'change' }">
|
||||
<el-select v-model="form.item_id" placeholder="请选择" style="width:100%">
|
||||
<el-option v-for="(i, idx) in itemList" :key="idx" :label="i.name" :value="i.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件名称" prop="name" :rules="{ required: true, message: '请输入文件名称', trigger: 'change' }">
|
||||
<el-input v-model="form.name" />
|
||||
</el-form-item>
|
||||
<el-form-item label="验收日期" prop="check_date" :rules="{ required: true, message: '请选择验收日期', trigger: 'change' }">
|
||||
<el-date-picker v-model="form.check_date" type="date" placeholder="选择日期" value-format="yyyy-MM-dd" style="width: 100%;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="附件" prop="upload_id" :rules="{ required: true, message: '请上传附件', trigger: 'change' }">
|
||||
<UploadFile v-if="dialogFormVisible" v-model="form.upload_id" :file_name="form.upload ? form.upload.original_name : ''" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="save">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LxHeader from '@/components/LxHeader/index.vue'
|
||||
import UploadFile from '@/components/Upload/file.vue'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { getList } from '../../api/item.js'
|
||||
import { itemIndex, index, show, destroy, store, save } from '../../api/end-check.js'
|
||||
export default {
|
||||
name: 'EndCheck',
|
||||
components: {
|
||||
LxHeader, UploadFile, Pagination
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
itemList: [],
|
||||
typeLabel: {1: '竣工验收', 2: '项目结算', 3: '项目决算'},
|
||||
list: [],
|
||||
total: 0,
|
||||
listQuery: {
|
||||
page: 1,
|
||||
page_size: 10
|
||||
},
|
||||
form: {
|
||||
id: undefined,
|
||||
upload_id: null,
|
||||
},
|
||||
dialogFormVisible:false,
|
||||
formLabelWidth: '120px',
|
||||
search:''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
getList({}).then(r => { this.itemList = r.list }).catch(error => {})
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.listQuery.type = this.type
|
||||
index(this.listQuery).then(response => {
|
||||
this.list = response.data
|
||||
this.total = response.total
|
||||
}).catch(error => {})
|
||||
},
|
||||
handleFilter() {
|
||||
this.listQuery.page = 1
|
||||
this.getList()
|
||||
},
|
||||
handleUpdate(row) {
|
||||
if (row) {
|
||||
show({id: row.id}).then(r => {
|
||||
this.form = r
|
||||
this.showDialog()
|
||||
}).catch(error => {})
|
||||
} else {
|
||||
this.form = { id: '' }
|
||||
this.showDialog()
|
||||
}
|
||||
},
|
||||
showDialog() {
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => { this.$refs['dataForm'].clearValidate() })
|
||||
},
|
||||
save() {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
const tempData = Object.assign({}, this.form)
|
||||
tempData.stage = this.type
|
||||
if (tempData.id) {
|
||||
save(tempData).then(r => { this.saved() }).catch(error => {})
|
||||
} else {
|
||||
store(tempData).then(r => { this.saved() }).catch(error => {})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
saved() {
|
||||
this.handleFilter()
|
||||
this.dialogFormVisible = false
|
||||
this.$message.success('保存成功')
|
||||
},
|
||||
handleDelete(row, index) {
|
||||
this.$confirm('确定要删除吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
destroy({id: row.id}).then(response => {
|
||||
this.$message.success('删除成功')
|
||||
this.getList()
|
||||
}).catch(error => {})
|
||||
}).catch(() => {});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
/deep/ .el-dialog__body{
|
||||
padding:8px 20px;
|
||||
}
|
||||
/deep/ .el-col-5{
|
||||
width:20%;
|
||||
}
|
||||
/deep/ .el-upload-list{
|
||||
float:left;
|
||||
line-height: 28px;
|
||||
margin-right:15px;
|
||||
}
|
||||
/deep/ .el-upload-list__item:first-child{
|
||||
margin-top:0;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.ivu-btn{
|
||||
margin-right:10px;
|
||||
}
|
||||
.table-tree{
|
||||
margin-top:10px;
|
||||
}
|
||||
.rightCol{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-left: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.v-text{
|
||||
padding:8px 0;
|
||||
border-bottom:1px solid #eee;
|
||||
margin-bottom:20px;
|
||||
.title{
|
||||
color: #338de3;
|
||||
}
|
||||
}
|
||||
.dataGroup{
|
||||
padding:10px 0;
|
||||
}
|
||||
.grid-content{
|
||||
border-radius:5px;
|
||||
text-align:center;
|
||||
background: #ffffff;
|
||||
padding:15px 0;
|
||||
p{
|
||||
line-height: 1.8;
|
||||
}
|
||||
p:first-child{
|
||||
font-weight:700;
|
||||
font-size:16px;
|
||||
}
|
||||
}
|
||||
.bg-org{
|
||||
border:2px solid #EF6C24;
|
||||
color:#EF6C24;
|
||||
}
|
||||
.bg-blue{
|
||||
border:2px solid #0800FF;
|
||||
color:#0800FF;
|
||||
}
|
||||
.bg-green{
|
||||
border:2px solid #0F9700;
|
||||
color:#0F9700;
|
||||
}
|
||||
.bg-black{
|
||||
border:2px solid #333;
|
||||
color:#333;
|
||||
}
|
||||
.bg-pink{
|
||||
border:2px solid #FF0000;
|
||||
color:#FF0000;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div style="padding: 0 15px;" @click="toggleClick">
|
||||
<svg :class="{'is-active-hamburger':isActive}" class="hamburger" viewBox="0 0 1024 1024"
|
||||
xmlns="http://www.w3.org/2000/svg" width="64" height="64">
|
||||
<path
|
||||
d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
|
||||
</svg>
|
||||
<transition name="fade">
|
||||
<span class="hamburgertxt" v-if="isActive">收起左边</span>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Hamburger',
|
||||
props: {
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleClick() {
|
||||
this.$emit('toggleClick')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hamburger {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.hamburgertxt {
|
||||
color: #606266;
|
||||
font-size: 16px;
|
||||
margin-left: 0.625rem;
|
||||
}
|
||||
|
||||
.hamburger.is-active-hamburger {
|
||||
transform: rotate(180deg);
|
||||
background-color: none !important;
|
||||
}
|
||||
|
||||
.fade-enter {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.fade-enter-active {
|
||||
transition: opacity .1s;
|
||||
}
|
||||
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.fade-leave-active {
|
||||
transition: opacity .1s;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,53 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'MenuItem',
|
||||
functional: true,
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
render(h, context) {
|
||||
const { icon, title } = context.props
|
||||
const vnodes = []
|
||||
|
||||
if (icon) {
|
||||
if (icon.includes('el-icon')) {
|
||||
vnodes.push(<i class={[icon, 'sub-el-icon']} />)
|
||||
}
|
||||
else if(icon.includes("viewicon")){
|
||||
let _icon=icon.split("/")[1];
|
||||
vnodes.push(<Icon type={_icon} class='sub-el-icon' size="18" />)
|
||||
}
|
||||
else if(icon.includes("iconfont")){
|
||||
let _icon=icon.split("/")[1]+" iconfont";
|
||||
vnodes.push(<Icon custom={_icon} class='sub-el-icon' size="18" />)
|
||||
}
|
||||
else {
|
||||
vnodes.push(<svg-icon icon-class={icon}/>)
|
||||
}
|
||||
}else {
|
||||
var _icon="el-icon-menu";
|
||||
vnodes.push(<i class={[_icon, 'sub-el-icon']} />)
|
||||
}
|
||||
|
||||
if (title) {
|
||||
vnodes.push(<span slot='title'>{(title)}</span>)
|
||||
}
|
||||
return vnodes
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sub-el-icon {
|
||||
color: currentColor;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div class="v-header">
|
||||
<div class="v-left-text">
|
||||
<item :icon="iconImg" />
|
||||
<span style="margin-left: 3px;">{{title}}</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
<!-- <div class="v-right-content">
|
||||
<slot></slot>
|
||||
</div> -->
|
||||
<div class="selerchcontent">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Item from './Item'
|
||||
export default {
|
||||
components: {
|
||||
Item
|
||||
},
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
default: "未定义名称"
|
||||
},
|
||||
custom:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
if(this.custom){
|
||||
return this.text;
|
||||
}else
|
||||
return this.$route.meta.title;
|
||||
},
|
||||
iconImg() {
|
||||
if(this.custom){
|
||||
return this.icon;
|
||||
}else
|
||||
return this.$route.meta.icon;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.v-header {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #dcdee2;
|
||||
flex-direction: column;
|
||||
|
||||
.v-left-text {
|
||||
margin-top: 3px;
|
||||
padding-bottom: 6px;
|
||||
// padding-top: 10px;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
color: #338de3;
|
||||
white-space: nowrap;
|
||||
border-bottom: 2px solid #338de3;
|
||||
|
||||
>span {
|
||||
position: relative;
|
||||
// top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
line-height: 25px;
|
||||
padding-left: 10px;
|
||||
padding: 6px 0 0 10px;
|
||||
}
|
||||
|
||||
.v-right-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.selerchcontent {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<div :class="{'hidden':hidden}" class="pagination-container">
|
||||
<el-pagination
|
||||
:background="background"
|
||||
:current-page.sync="currentPage"
|
||||
:page-size.sync="pageSize"
|
||||
:layout="layout"
|
||||
:page-sizes="pageSizes"
|
||||
:total="total"
|
||||
v-bind="$attrs"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { scrollTo } from '@/utils/scroll-to'
|
||||
|
||||
export default {
|
||||
name: 'Pagination',
|
||||
props: {
|
||||
total: {
|
||||
required: true,
|
||||
type: Number
|
||||
},
|
||||
page: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 20
|
||||
},
|
||||
pageSizes: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [10, 20, 30, 50]
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
type: String,
|
||||
default: 'total, prev, pager, next, jumper'
|
||||
},
|
||||
background: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
autoScroll: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
hidden: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentPage: {
|
||||
get() {
|
||||
return this.page
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:page', val)
|
||||
}
|
||||
},
|
||||
pageSize: {
|
||||
get() {
|
||||
return this.limit
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:limit', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSizeChange(val) {
|
||||
this.$emit('pagination', { page: this.currentPage, limit: val })
|
||||
if (this.autoScroll) {
|
||||
scrollTo(0, 800)
|
||||
}
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.$emit('pagination', { page: val, limit: this.pageSize })
|
||||
if (this.autoScroll) {
|
||||
scrollTo(0, 800)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.pagination-container {
|
||||
text-align:right;
|
||||
padding: 32px 16px;
|
||||
}
|
||||
.pagination-container.hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,303 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div ref="lxHeader">
|
||||
<LxHeader icon="md-apps" :text="typeLabel[type]" style="margin-bottom: 10px; border: 0px; margin-top: 15px">
|
||||
<div slot="content" />
|
||||
<slot>
|
||||
<div>
|
||||
<Input v-model="listQuery.keyword" style="width: 200px; margin-right: 10px" placeholder="关键字搜索" />
|
||||
<Button type="primary" @click="handleFilter">查询</Button>
|
||||
</div>
|
||||
</slot>
|
||||
</LxHeader>
|
||||
</div>
|
||||
<div class="table-tree">
|
||||
<el-table :data="tableData" border default-expand-all class="v-table" style="width: 100%;margin-bottom: 20px;">
|
||||
<el-table-column type="index" label="序号" width="50" />
|
||||
<el-table-column label="项目名称" prop="name" width="400" />
|
||||
<el-table-column label="文档数量" prop="prepares_count" align="center" />
|
||||
<el-table-column label="编辑人" align="center">
|
||||
<template slot-scope="{row}"><span>{{ row.admin ? row.admin.name: '' }}</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最后编辑时间" width="160" prop="updated_at" align="center" />
|
||||
<el-table-column fixed="right" width="250" label="操作" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<Button type="primary" size="small" style="margin-left: 10px;" ghost @click="editList(row)">编辑</Button>
|
||||
<Button type="primary" size="small" style="margin-left: 10px;" ghost @click="showList(row)">查看</Button>
|
||||
<!-- <Button type="error" size="small" style="margin-left: 10px;" ghost @click="dialogFormVisible = true">删除</Button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.page_size" @pagination="getList" />
|
||||
</div>
|
||||
<el-dialog :title="'管理文件'" :visible.sync="dialogFormVisible" width="80%" @close="dialogClose">
|
||||
<div class="rightCol">
|
||||
<Button type="primary" @click="addRow" size="small" ghost>新增文件</Button>
|
||||
</div>
|
||||
<el-form ref="dataForm" :model="form" :rules="rules">
|
||||
<el-table border default-expand-all class="v-table" :data="form.list">
|
||||
<el-table-column label="文件名称" prop="name" width="400">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'list.' + scope.$index + '.name'" style="margin-top: 15px;margin-bottom: 17px;">
|
||||
<el-input v-model="scope.row.name" placeholder="文件名称" style="width:100%" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="获取时间" prop="date">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'list.' + scope.$index + '.date'" style="margin-top: 15px;margin-bottom: 17px;">
|
||||
<el-date-picker v-model="scope.row.date" type="date" placeholder="选择日期" value-format="yyyy-MM-dd" style="width: 100%;" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件名称" prop="upload_id">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'list.' + scope.$index + '.upload_id'" style="margin-top: 15px;margin-bottom: 17px;">
|
||||
<UploadFile v-if="dialogFormVisible" v-model="scope.row.upload_id" :file_name="scope.row.upload ? scope.row.upload.original_name : ''" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="150" label="操作" align="center">
|
||||
<template slot-scope="scope">
|
||||
<Button @click="save(scope.$index)" type="primary" size="small" ghost>保存</Button>
|
||||
<Button type="error" size="small" ghost @click="handleDelete(scope.row, scope.$index)">删除</Button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer"></div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :title="'查看文件'" :visible.sync="dialogTableVisible" width="80%">
|
||||
<el-table border default-expand-all class="v-table" :data="form.list">
|
||||
<el-table-column label="文件名称" prop="name" width="400">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.name}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="获取时间" prop="date">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.date}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件名称" prop="upload_id">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.upload ? scope.row.upload.original_name : ''}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template slot-scope="scope">
|
||||
<a v-if="scope.row.upload" :href="scope.row.upload.url" target="_blank">下载</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div slot="footer" class="dialog-footer"></div>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LxHeader from '@/components/LxHeader/index.vue'
|
||||
import UploadFile from '@/components/Upload/file.vue'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { itemIndex, index, show, destroy, store, save } from '../../api/prepares.js'
|
||||
export default {
|
||||
name: 'Prepare',
|
||||
components: {
|
||||
LxHeader, UploadFile, Pagination
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
typeLabel: {1: '立项阶段', 2: '可研阶段', 3: '初设阶段', 4: '概算', 5: '预算', 6: '其他'},
|
||||
listQuery: {
|
||||
page: 1,
|
||||
page_size: 10
|
||||
},
|
||||
total: 0,
|
||||
tableData: [],
|
||||
rules: {
|
||||
list:[]
|
||||
},
|
||||
dialogFormVisible:false,
|
||||
dialogTableVisible: false,
|
||||
form: {
|
||||
id: undefined,
|
||||
item_id: '',
|
||||
list: []
|
||||
},
|
||||
bcglXiangXiList: [],
|
||||
checkedDetail: [],
|
||||
formLabelWidth: '120px',
|
||||
search:''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.listQuery.type = this.type
|
||||
itemIndex(this.listQuery).then(response => {
|
||||
this.tableData = response.data
|
||||
this.total = response.total
|
||||
}).catch(error => {})
|
||||
},
|
||||
handleFilter() {
|
||||
this.listQuery.page = 1
|
||||
this.getList()
|
||||
},
|
||||
createRules(idx) {
|
||||
let ruleList = []
|
||||
for (let i = 0; i < this.form.list.length; i++) {
|
||||
let required = i == idx ? true : false
|
||||
ruleList.push({
|
||||
name: { required: required, message: '请输入文件名称', trigger: 'change' },
|
||||
date: { required: required, message: '请选择获取时间', trigger: 'change' },
|
||||
upload_id: { required: required, message: '请上传文件', trigger: 'change' },
|
||||
})
|
||||
}
|
||||
this.rules = {list: ruleList}
|
||||
},
|
||||
editList(row) {
|
||||
this.form.list = []
|
||||
index({item_id: row.id, type: this.type, page_size: 9999, sort_name: 'id', sort_type: 'asc'}).then(r => {
|
||||
this.form.list = r.data
|
||||
this.form.item_id = row.id
|
||||
if (r.data.length == 0) {
|
||||
this.addRow()
|
||||
}
|
||||
this.dialogFormVisible = true
|
||||
}).catch(error => {})
|
||||
},
|
||||
showList(row) {
|
||||
this.form.list = []
|
||||
index({item_id: row.id, type: this.type, page_size: 9999, sort_name: 'id', sort_type: 'asc'}).then(r => {
|
||||
this.form.list = r.data
|
||||
this.dialogTableVisible = true
|
||||
}).catch(error => {})
|
||||
},
|
||||
addRow() {
|
||||
this.form.list.push({ name: '', date: '', upload_id: null, upload: {original_name: ''} })
|
||||
},
|
||||
save(idx) {
|
||||
this.createRules(idx)
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
this.$refs['dataForm'].validate()
|
||||
|
||||
let tempData = this.form.list[idx]
|
||||
tempData.item_id = this.form.item_id
|
||||
tempData.type = this.type
|
||||
if (tempData.name && tempData.date && tempData.upload_id) {
|
||||
if (tempData.id) {
|
||||
save(tempData).then(r => { this.saved() }).catch(error => {})
|
||||
} else {
|
||||
store(tempData).then(r => { this.saved() }).catch(error => {})
|
||||
}
|
||||
}
|
||||
},
|
||||
saved() {
|
||||
this.$message.success('保存成功')
|
||||
},
|
||||
handleDelete(row, index) {
|
||||
this.$confirm('确定要删除吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
if (!row.id) {
|
||||
this.form.list.splice(index, 1)
|
||||
return
|
||||
}
|
||||
destroy({ id: row.id }).then(response => {
|
||||
this.$message.success('删除成功')
|
||||
this.form.list.splice(index, 1)
|
||||
}).catch(error => {})
|
||||
}).catch(() => {})
|
||||
},
|
||||
dialogClose() {
|
||||
this.getList()
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
/deep/ .el-dialog__body{
|
||||
padding:8px 20px;
|
||||
}
|
||||
/deep/ .el-col-5{
|
||||
width:20%;
|
||||
}
|
||||
/deep/ .el-upload-list{
|
||||
float:left;
|
||||
line-height: 28px;
|
||||
margin-right:15px;
|
||||
}
|
||||
/deep/ .el-upload-list__item:first-child{
|
||||
margin-top:0;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.ivu-btn{
|
||||
margin-right:10px;
|
||||
}
|
||||
.table-tree{
|
||||
margin-top:10px;
|
||||
}
|
||||
.rightCol{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-left: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.v-text{
|
||||
padding:8px 0;
|
||||
border-bottom:1px solid #eee;
|
||||
margin-bottom:20px;
|
||||
.title{
|
||||
color: #338de3;
|
||||
}
|
||||
}
|
||||
.dataGroup{
|
||||
padding:10px 0;
|
||||
}
|
||||
.grid-content{
|
||||
border-radius:5px;
|
||||
text-align:center;
|
||||
background: #ffffff;
|
||||
padding:15px 0;
|
||||
p{
|
||||
line-height: 1.8;
|
||||
}
|
||||
p:first-child{
|
||||
font-weight:700;
|
||||
font-size:16px;
|
||||
}
|
||||
}
|
||||
.bg-org{
|
||||
border:2px solid #EF6C24;
|
||||
color:#EF6C24;
|
||||
}
|
||||
.bg-blue{
|
||||
border:2px solid #0800FF;
|
||||
color:#0800FF;
|
||||
}
|
||||
.bg-green{
|
||||
border:2px solid #0F9700;
|
||||
color:#0F9700;
|
||||
}
|
||||
.bg-black{
|
||||
border:2px solid #333;
|
||||
color:#333;
|
||||
}
|
||||
.bg-pink{
|
||||
border:2px solid #FF0000;
|
||||
color:#FF0000;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
|
||||
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
|
||||
<use :xlink:href="iconName" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
|
||||
import { isExternal } from '@/utils/validate'
|
||||
|
||||
export default {
|
||||
name: 'SvgIcon',
|
||||
props: {
|
||||
iconClass: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isExternal() {
|
||||
return isExternal(this.iconClass)
|
||||
},
|
||||
iconName() {
|
||||
return `#icon-${this.iconClass}`
|
||||
},
|
||||
svgClass() {
|
||||
if (this.className) {
|
||||
return 'svg-icon ' + this.className
|
||||
} else {
|
||||
return 'svg-icon'
|
||||
}
|
||||
},
|
||||
styleExternalIcon() {
|
||||
return {
|
||||
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
|
||||
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.svg-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.svg-external-icon {
|
||||
background-color: currentColor;
|
||||
mask-size: cover!important;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
:action="uploadUrl"
|
||||
:before-upload="beforeFileUpload"
|
||||
:on-remove="picDel"
|
||||
:on-success="picSuccess"
|
||||
:headers="headers"
|
||||
:limit="1"
|
||||
:file-list="file_list">
|
||||
<el-button size="small" type="primary" v-if="!value">{{loading ? '上传中...' : '点击上传'}}</el-button>
|
||||
</el-upload>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from '@/utils/auth'
|
||||
export default {
|
||||
name: 'UploadFile',
|
||||
props: {
|
||||
value: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
file_name: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
headers: {},
|
||||
uploadUrl: process.env.VUE_APP_BASE_API + '/api/admin/upload-file',
|
||||
loading: false,
|
||||
picUrl: '',
|
||||
picDialog: false,
|
||||
file_list: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.headers = {Authorization: "Bearer " + getToken()}
|
||||
this.file_list = this.value ? [{name: this.file_name, url: this.value.toString()}] : []
|
||||
},
|
||||
methods: {
|
||||
beforeFileUpload(file) {
|
||||
this.loading = true
|
||||
return true
|
||||
},
|
||||
picSuccess: function (res, file, fileList) {
|
||||
this.loading = false
|
||||
if (res.errcode) {
|
||||
alert(res.errmsg)
|
||||
return
|
||||
}
|
||||
fileList[fileList.length - 1].url = res.id.toString();
|
||||
this.$emit('input', res.id)
|
||||
},
|
||||
picDel: function(file, fileList) {
|
||||
this.$emit('input', null)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.upload-demo {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,312 @@
|
||||
<script>
|
||||
export default {
|
||||
props:{
|
||||
type:{
|
||||
type:String,
|
||||
default:"normal"
|
||||
//"normal" "form"
|
||||
},
|
||||
width:{
|
||||
type:Number,
|
||||
default:55
|
||||
},
|
||||
isShow:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
title:{
|
||||
type:String,
|
||||
default: ''
|
||||
},
|
||||
form:{
|
||||
type:Object,
|
||||
default:()=>{
|
||||
return {}
|
||||
}
|
||||
},
|
||||
rules:{
|
||||
type:Object,
|
||||
default:()=>{
|
||||
return {}
|
||||
}
|
||||
},
|
||||
okText:{
|
||||
type:String
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
footerRender(){
|
||||
if(this.type === 'form'){
|
||||
return (
|
||||
<div>
|
||||
<Button ghost type="primary" on-click={this.reset}>重置</Button>
|
||||
<Button type="primary" on-click={this.submit}>{this.okText || '确定'}</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if(this.type === 'normal'){
|
||||
return (
|
||||
<div>
|
||||
<Button ghost type="primary" on-click={()=>{this.$emit('update:isShow',false)}}>取消</Button>
|
||||
<Button type="primary" on-click={()=>{this.$emit('on-ok')}}>{this.okText || '确定'}</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
showChange(e){
|
||||
this.$emit('update:isShow',e)
|
||||
},
|
||||
validate(){
|
||||
return new Promise((resolve,reject)=>{
|
||||
this.$refs['elForm'].validate().then(res=>{
|
||||
if(res){
|
||||
resolve(res)
|
||||
}else{
|
||||
reject(res)
|
||||
}
|
||||
}).catch(err=>{
|
||||
reject(err)
|
||||
this.$Message.warning({
|
||||
content:'请填写完整信息',
|
||||
duration:1
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
reset(){
|
||||
this.$emit('reset')
|
||||
if(this.type === 'normal'){
|
||||
return
|
||||
}
|
||||
this.$refs['elForm'].resetFields()
|
||||
},
|
||||
submit(){
|
||||
if(this.type === 'normal'){
|
||||
return
|
||||
}
|
||||
this.$refs['elForm'].validate().then(res=>{
|
||||
if(res)this.$emit('submit')
|
||||
}).catch(err=>{
|
||||
this.$Message.warning({
|
||||
content:'请填写完整信息',
|
||||
duration:1
|
||||
})
|
||||
})
|
||||
},
|
||||
okClick(){
|
||||
this.$emit('on-ok')
|
||||
},
|
||||
clearValidate(){
|
||||
this.$refs['elForm'].clearValidate()
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
isShow(val){
|
||||
if(!val && this.type === 'form'){
|
||||
this.reset()
|
||||
}
|
||||
}
|
||||
},
|
||||
render(h) {
|
||||
/*
|
||||
type='form' slot:
|
||||
extraFormTop
|
||||
extraFormBottom
|
||||
{表单名}
|
||||
type='normal' slot:
|
||||
normalContent
|
||||
footer slot:
|
||||
footerContent
|
||||
*/
|
||||
const {okText,okClick,footerRender,width,type,$scopedSlots,rules,form,showChange,isShow,title} = this
|
||||
return (
|
||||
<Modal
|
||||
ok-text={okText}
|
||||
class-name={'vertical-center-modal'}
|
||||
width={width}
|
||||
title={title}
|
||||
value={isShow}
|
||||
on={{['on-visible-change']:showChange,['on-ok']:okClick}}
|
||||
scopedSlots={{
|
||||
default(){
|
||||
if(type === "form"){
|
||||
let formItems = []
|
||||
for(let key in form){
|
||||
if(form.hasOwnProperty(key) && $scopedSlots[key]){
|
||||
formItems.push(
|
||||
<el-form-item
|
||||
prop={key}>
|
||||
{eval(`{$scopedSlots.${key} ? $scopedSlots.${key}() : ''}`)}
|
||||
</el-form-item>
|
||||
)
|
||||
}
|
||||
}
|
||||
return (
|
||||
<el-form
|
||||
style={title.length === 0 ? {'margin-top':'32px'} : {}}
|
||||
ref="elForm"
|
||||
props={{
|
||||
model:form,
|
||||
rules
|
||||
}}>
|
||||
|
||||
{$scopedSlots.extraFormTop ? $scopedSlots.extraFormTop() : ''}
|
||||
|
||||
<div
|
||||
style={
|
||||
{
|
||||
'display':'flex',
|
||||
'align-items':'center',
|
||||
'flex-wrap':'wrap',
|
||||
'min-width':'380px'
|
||||
}
|
||||
}>
|
||||
{
|
||||
formItems.map(item=>{
|
||||
return item
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
{$scopedSlots.extraFormBottom ? $scopedSlots.extraFormBottom() : ''}
|
||||
</el-form>
|
||||
)
|
||||
}else{
|
||||
return (
|
||||
<div
|
||||
style={title.length === 0 ? {'margin-top':'32px'} : {}}>
|
||||
{$scopedSlots.default ? $scopedSlots.default() : ''}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
header(){
|
||||
if($scopedSlots.headerContent){
|
||||
return $scopedSlots.headerContent()
|
||||
}
|
||||
},
|
||||
footer(){
|
||||
{
|
||||
if(type === 'form' || type === 'normal') return ($scopedSlots.footerContent ? $scopedSlots.footerContent() : footerRender())
|
||||
}
|
||||
}
|
||||
}}>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.xy-table-item-label{
|
||||
width: 140px;
|
||||
text-align: right;
|
||||
}
|
||||
.xy-table-item-min{
|
||||
position: relative;
|
||||
&::after{
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
content:'(分钟)'
|
||||
}
|
||||
::v-deep .el-input__clear{
|
||||
position: relative;
|
||||
right: 46px;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
.xy-table-item-price{
|
||||
position: relative;
|
||||
&::after{
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
content:'(元)'
|
||||
}
|
||||
::v-deep .el-input__clear{
|
||||
padding: 0 6px;
|
||||
position: relative;
|
||||
right: 30px;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
.xy-table-item-price-wan{
|
||||
position: relative;
|
||||
&::after{
|
||||
padding: 0 6px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
content:'(万元)'
|
||||
}
|
||||
::v-deep .el-input__clear{
|
||||
position: relative;
|
||||
right: 46px;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
.xy-table-item-price-percent{
|
||||
position: relative;
|
||||
&::after{
|
||||
padding: 0 6px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
content:'%'
|
||||
}
|
||||
::v-deep .el-input__clear{
|
||||
position: relative;
|
||||
right: 46px;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.vertical-center-modal{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.ivu-modal{
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
.ivu-modal-body{
|
||||
max-height: 65vh !important;
|
||||
min-height: 300px;
|
||||
overflow: scroll;
|
||||
|
||||
}
|
||||
.xy-table-item{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
padding-right: 80px;
|
||||
&-label{
|
||||
|
||||
padding: 0 20px;
|
||||
}
|
||||
&-content{
|
||||
|
||||
}
|
||||
}
|
||||
.el-form-item{
|
||||
flex-shrink: 0;
|
||||
flex-basis: 50%;
|
||||
}
|
||||
.el-form-item__error{
|
||||
white-space: nowrap;
|
||||
word-break: keep-all !important;
|
||||
top: 100% !important;
|
||||
left: calc(100% - 80px) !important;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -0,0 +1,225 @@
|
||||
<script>
|
||||
export default {
|
||||
props:{
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShowSelector:false,
|
||||
width:300,
|
||||
left:0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initStyle(){
|
||||
const header = document.querySelector('.v-header').getBoundingClientRect()
|
||||
this.width = header.width
|
||||
const select = document.querySelector('.xy-selectors').getBoundingClientRect()
|
||||
this.left = select.left - header.left
|
||||
|
||||
this.$forceUpdate()
|
||||
},
|
||||
|
||||
showSelector(){
|
||||
this.isShowSelector =! this.isShowSelector
|
||||
},
|
||||
renderAdd(){
|
||||
return (<Button
|
||||
class="xy-selectors-btn__item"
|
||||
type='primary'
|
||||
on={{
|
||||
['click']:()=>this.$emit('add')
|
||||
}}>
|
||||
新增
|
||||
</Button>)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initStyle()
|
||||
|
||||
window.onresize = this.initStyle
|
||||
},
|
||||
destroyed() {
|
||||
window.onresize = null
|
||||
},
|
||||
render(h) {
|
||||
let {isShowSelector,showSelector,$scopedSlots} = this
|
||||
|
||||
return (
|
||||
<div class="xy-selectors">
|
||||
<div v-show={isShowSelector} style={{'width':'100vw','height':'100vh','position':'fixed','top':0,'left':0,'z-index':1}} on={{['click']:()=>this.isShowSelector = false}}></div>
|
||||
<Button
|
||||
icon='md-arrow-dropdown'
|
||||
ghost={isShowSelector}
|
||||
class={isShowSelector ? 'xy-selectors-btn__item xy-selectors-btn__select xy-selectors-btn-active__select' : 'xy-selectors-btn__item xy-selectors-btn__select"'}
|
||||
type='primary'
|
||||
on={{
|
||||
['click']:() => showSelector()
|
||||
}}>
|
||||
高级搜索
|
||||
</Button>
|
||||
|
||||
<transition
|
||||
enter-active-class="scale-enter"
|
||||
leave-to-class="scale-leave">
|
||||
<div class="xy-selectors-card" style={{'width':`${this.width}px`,'left':`-${this.left}px`}} v-show={isShowSelector}>
|
||||
<Icon
|
||||
type="md-close"
|
||||
size={24}
|
||||
class="xy-selectors-card__close"
|
||||
on={{['click']:()=> {
|
||||
this.isShowSelector = false
|
||||
}}}/>
|
||||
<div class="xy-selectors-card-content">
|
||||
{$scopedSlots?.selected ? $scopedSlots?.selected() : ''}
|
||||
{$scopedSlots?.default ? $scopedSlots?.default() : ''}
|
||||
</div>
|
||||
<div class="xy-selectors-card-btn">
|
||||
<Button
|
||||
class="xy-selectors-card-btn__item"
|
||||
type="primary"
|
||||
ghost={true}
|
||||
on={{['click']:()=>{this.$emit('reset')}}}>重置</Button>
|
||||
<Button
|
||||
class="xy-selectors-card-btn__item"
|
||||
type="primary"
|
||||
on={{['click']:()=>{
|
||||
this.$emit('search')
|
||||
this.isShowSelector = false
|
||||
}}}>搜索</Button>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
.xy-selectors{
|
||||
|
||||
&__item{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
padding: 8px 20px;
|
||||
|
||||
&--name{
|
||||
width: 100px;
|
||||
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="scss">
|
||||
@import "../../styles/variables";
|
||||
.xy-selectors{
|
||||
|
||||
position: relative;
|
||||
&-btn{
|
||||
//display: flex;
|
||||
//justify-content: flex-start;
|
||||
//align-items: center;
|
||||
&__item{
|
||||
|
||||
//margin-right: 10px;
|
||||
}
|
||||
&__select{
|
||||
|
||||
}
|
||||
&-active__select{
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom: none;
|
||||
box-shadow: 0 2px 10px 1px $primaryColor;
|
||||
|
||||
position: relative;
|
||||
&::after{
|
||||
content:'';
|
||||
height: 12px;
|
||||
background: linear-gradient(to top,rgba(235,238,244,0.98) 40%,#0000 80%,#0000);
|
||||
|
||||
z-index: 5;
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-card{
|
||||
//width: 100%;
|
||||
background: rgba(239,242,250,0.95);
|
||||
border-radius: 0 4px 4px 4px;
|
||||
border: $primaryColor solid 1px;
|
||||
box-shadow: 0 4px 10px 1px $primaryColor;
|
||||
|
||||
z-index: 4;
|
||||
position: absolute;
|
||||
&__close{
|
||||
cursor: pointer;
|
||||
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 14px;
|
||||
}
|
||||
&-content{
|
||||
min-height: 50px;
|
||||
max-height: 400px;
|
||||
overflow: scroll;
|
||||
|
||||
padding: 36px 0 44px 8px;
|
||||
&::-webkit-scrollbar-thumb{
|
||||
background: $primaryColor;
|
||||
}
|
||||
}
|
||||
&-btn{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
background: rgba(239,242,250,0.95);
|
||||
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
&__item{
|
||||
width: 120px;
|
||||
|
||||
margin: 10px 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scale-enter{
|
||||
transform-origin: 0 0%;
|
||||
animation: scale-enter 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
||||
}
|
||||
@keyframes scale-enter {
|
||||
from{
|
||||
transform: scaleY(0);
|
||||
opacity: 0;
|
||||
}
|
||||
to{
|
||||
transform: scaleY(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.scale-leave{
|
||||
transform-origin: 0 0%;
|
||||
animation: scale-leave 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
||||
}
|
||||
@keyframes scale-leave {
|
||||
from{
|
||||
transform: scaleY(1);
|
||||
opacity: 1;
|
||||
}
|
||||
to{
|
||||
transform: scaleY(0);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,350 @@
|
||||
<script>
|
||||
export default {
|
||||
props:{
|
||||
height:{
|
||||
type:Number
|
||||
},
|
||||
list:{
|
||||
type:Array,
|
||||
default:()=> []
|
||||
},
|
||||
tableItem:{
|
||||
type:Array,
|
||||
default:()=> []
|
||||
},
|
||||
indent:{
|
||||
type:Number,
|
||||
default:18
|
||||
},
|
||||
expandRowKeys:{
|
||||
type: Array,
|
||||
default: ()=>[]
|
||||
},
|
||||
rowKey:{
|
||||
type:[String,Function],
|
||||
default:'id'
|
||||
},
|
||||
cellStyle:{
|
||||
type:Function,
|
||||
default:()=>{}
|
||||
},
|
||||
rowStyle:{
|
||||
type:Function,
|
||||
default:()=>{}
|
||||
},
|
||||
headerRowStyle:{
|
||||
type:Function,
|
||||
default:()=>{}
|
||||
},
|
||||
headerCellStyle:{
|
||||
type:Function,
|
||||
default:()=>{}
|
||||
},
|
||||
defaultExpandAll:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
},
|
||||
showIndex:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
},
|
||||
showHeader:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
},
|
||||
showSummary:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
summaryMethod:{
|
||||
type:Function
|
||||
},
|
||||
objectSpanMethod:{
|
||||
type:Function
|
||||
},
|
||||
treeProps:{
|
||||
type:Object,
|
||||
default:()=> {
|
||||
return { children: 'children', hasChildren: 'hasChildren' }
|
||||
}
|
||||
},
|
||||
tableStyle:{
|
||||
type:Object,
|
||||
default:()=>{
|
||||
return { width: '100%', marginBottom: "20px"}
|
||||
}
|
||||
},
|
||||
|
||||
btnWidth:{
|
||||
type:Number,
|
||||
default:190
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tableHeight: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initLoad() {
|
||||
var that = this;
|
||||
var clientHeight = document.documentElement.clientHeight
|
||||
var lxHeader_height = 96.5; //查询 头部
|
||||
var paginationHeight = 37; //分页的高度
|
||||
var topHeight = 50; //页面 头部
|
||||
let tableHeight = clientHeight - lxHeader_height - topHeight - paginationHeight - 20;
|
||||
that.tableHeight = tableHeight;
|
||||
},
|
||||
deleteClick(row){
|
||||
this.$emit('delete',row)
|
||||
},
|
||||
editorClick(row){
|
||||
this.$emit('editor',row)
|
||||
},
|
||||
selectClick(selection, row){
|
||||
this.$emit('select',selection, row)
|
||||
},
|
||||
rowClick(selection, row){
|
||||
this.$emit('rowClick',selection, row)
|
||||
},
|
||||
cellClick(row, column, cell){
|
||||
this.$emit('cellClick',row, column, cell)
|
||||
},
|
||||
selectAllClick(selection){
|
||||
this.$emit('select-all',selection)
|
||||
},
|
||||
selectChange(selection){
|
||||
this.$emit('selection-change',selection)
|
||||
},
|
||||
createIndexRow(){
|
||||
return <el-table-column type="index" align="center" fixed="left"></el-table-column>
|
||||
},
|
||||
toggleRowSelection(row){
|
||||
this.$nextTick(()=>{
|
||||
this.$refs.table.toggleRowSelection(row);
|
||||
})
|
||||
},
|
||||
clearSelection(){
|
||||
this.$refs.table.clearSelection();
|
||||
},
|
||||
toggleAllSelection(){
|
||||
this.$refs.table.toggleAllSelection()
|
||||
},
|
||||
doLayout() {
|
||||
this.$refs['table'].doLayout();
|
||||
},
|
||||
toggleRowExpansion(row,expanded){
|
||||
this.$refs['table'].toggleRowExpansion(row,expanded)
|
||||
},
|
||||
getSelection(){
|
||||
return this.$refs.table?.store?.states?.selection ?? []
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.initLoad()
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
render(h) {
|
||||
let {rowKey,expandRowKeys,selectChange,selectAllClick,summaryMethod,cellClick,btnWidth,selectClick,height,createIndexRow,tableStyle,treeProps,showSummary,showHeader,$scopedSlots,showIndex,defaultExpandAll,headerCellStyle,headerRowStyle,rowStyle,cellStyle,indent,tableHeight,tableItem,list,deleteClick,editorClick,rowClick,objectSpanMethod} = this
|
||||
return (
|
||||
<div className="table-tree" style={{ 'position': 'relative' }}>
|
||||
{tableItem && tableItem.length > 0 ?
|
||||
(<el-table
|
||||
ref="table"
|
||||
size="small"
|
||||
span-method={objectSpanMethod}
|
||||
show-summary={showSummary}
|
||||
show-header={showHeader}
|
||||
summary-method={summaryMethod}
|
||||
header-row-style={headerRowStyle}
|
||||
header-cell-style={headerCellStyle}
|
||||
row-style={rowStyle}
|
||||
cell-style={cellStyle}
|
||||
indent={indent}
|
||||
data={list}
|
||||
expand-row-keys={expandRowKeys}
|
||||
height={height ?? tableHeight}
|
||||
className="v-table"
|
||||
style={tableStyle}
|
||||
row-key={rowKey}
|
||||
border={true}
|
||||
default-expand-all={defaultExpandAll}
|
||||
tree-props={treeProps}
|
||||
fit={true}
|
||||
on={{
|
||||
['select']: selectClick,
|
||||
['cell-click']: cellClick,
|
||||
['select-all']: selectAllClick,
|
||||
['selection-change']: selectChange,
|
||||
['expand-change']: (row, expanded) => this.$emit('expand-change', { row, expanded })
|
||||
}}
|
||||
>
|
||||
<el-table-column
|
||||
fixed='left'
|
||||
align='center'
|
||||
width='60'
|
||||
type='index'
|
||||
>
|
||||
</el-table-column>
|
||||
{
|
||||
tableItem.map((item, index) => {
|
||||
//自定义表格内容
|
||||
if (item.customFn) {
|
||||
return (
|
||||
<el-table-column
|
||||
fixed={item.fixed ?? false}
|
||||
render-header={item.renderHeader ?? undefined}
|
||||
align={item.align ?? 'center'}
|
||||
sortable={item.sortable ?? false}
|
||||
width={item.width ?? 'auto'}
|
||||
min-width={item.minWidth ?? item.width}
|
||||
header-align={item.headerAlign ?? 'center'}
|
||||
label={item.label}
|
||||
prop={item.prop}
|
||||
scopedSlots={{
|
||||
default(scope) {
|
||||
return item.customFn(scope.row, scope)
|
||||
}
|
||||
}}
|
||||
>
|
||||
</el-table-column>
|
||||
)
|
||||
} else if (item.multiHd) {
|
||||
//二级表头结构表格内容
|
||||
return (
|
||||
<el-table-column
|
||||
render-header={item.renderHeader ?? undefined}
|
||||
header-align={item.headerAlign ?? 'center'}
|
||||
label={item.label}
|
||||
>
|
||||
{item.multiHd.map((item1, index1) => {
|
||||
if (item1.customFn) {
|
||||
return (
|
||||
<el-table-column
|
||||
render-header={item1.renderHeader ?? undefined}
|
||||
align={item1.align ?? 'center'}
|
||||
header-align={item1.headerAlign ?? 'center'}
|
||||
label={item1.label}
|
||||
width={item1.width ?? 'auto'}
|
||||
min-width={item1.minWidth ?? item1.width}
|
||||
sortable={item1.sortable ?? false}
|
||||
prop={`${item.Fprop ? item.Fprop + '.' : ''}${item1.prop}`}
|
||||
scopedSlots={{
|
||||
default(scope) {
|
||||
return item1.customFn(scope.row)
|
||||
}
|
||||
}}
|
||||
>
|
||||
</el-table-column>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<el-table-column
|
||||
render-header={item1.renderHeader ?? undefined}
|
||||
fixed={item1.fixed ?? false}
|
||||
align={item1.align ?? 'center'}
|
||||
header-align={item1.headerAlign ?? 'center'}
|
||||
prop={`${item.Fprop ? item.Fprop + '.' : ''}${item1.prop}`}
|
||||
label={item1.label}
|
||||
width={item1.width ?? 'auto'}
|
||||
min-width={item1.minWidth ?? item1.width}
|
||||
sortable={item1.sortable ?? false}
|
||||
type={item1.type ?? ''}
|
||||
formatter={item1.formatter}
|
||||
>
|
||||
</el-table-column>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</el-table-column>
|
||||
)
|
||||
} else {
|
||||
//默认内容
|
||||
return (
|
||||
<el-table-column
|
||||
render-header={item.renderHeader ?? undefined}
|
||||
fixed={item.fixed ?? false}
|
||||
formatter={item.formatter}
|
||||
width={item.width ?? 'auto'}
|
||||
min-width={item.minWidth ?? item.width}
|
||||
header-align={item.headerAlign ?? 'center'}
|
||||
align={item.align ?? 'center'}
|
||||
label={item.label}
|
||||
prop={item.prop}
|
||||
sortable={item.sortable ?? false}
|
||||
type={item.type}
|
||||
reserve-selection={item.reserveSelection}
|
||||
selectable={item.selectable}
|
||||
scopedSlots={item.type === 'expand' ? {
|
||||
default(props) {
|
||||
return item.expandFn(props)
|
||||
}
|
||||
} : ''}
|
||||
>
|
||||
</el-table-column>
|
||||
)
|
||||
}
|
||||
})}
|
||||
|
||||
{
|
||||
$scopedSlots.btns ? $scopedSlots.btns() :
|
||||
(<el-table-column
|
||||
fixed="right"
|
||||
label="操作"
|
||||
width={btnWidth}
|
||||
header-align="center"
|
||||
scopedSlots={{
|
||||
default(scope) {
|
||||
return (
|
||||
<div>
|
||||
<Poptip
|
||||
transfer={true}
|
||||
confirm
|
||||
title="确认要删除吗"
|
||||
on={{ ['on-ok']: () => deleteClick(scope.row) }}
|
||||
>
|
||||
<i-button
|
||||
type="error"
|
||||
size="small"
|
||||
style="margin-left: 10px;"
|
||||
ghost
|
||||
>删除
|
||||
</i-button>
|
||||
</Poptip>
|
||||
|
||||
<i-button
|
||||
type="primary"
|
||||
size="small"
|
||||
style="margin-left: 10px;"
|
||||
ghost
|
||||
onClick={() => editorClick(scope.row)}
|
||||
>编辑
|
||||
</i-button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}}
|
||||
>
|
||||
</el-table-column>)
|
||||
}
|
||||
</el-table>)
|
||||
:
|
||||
<el-table height={height ?? tableHeight}/>}
|
||||
|
||||
<el-backtop
|
||||
target=".el-table__body-wrapper"
|
||||
visibility-height={120}
|
||||
bottom={100}
|
||||
right={36}
|
||||
>
|
||||
</el-backtop>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
@ -0,0 +1,556 @@
|
||||
<template>
|
||||
<div class="kindeditor">
|
||||
<div>
|
||||
<VolBox
|
||||
icon="ios-chatbubbles"
|
||||
:model.sync="uploadModel"
|
||||
title="图片上传"
|
||||
:height="180"
|
||||
:width="520"
|
||||
:padding="15"
|
||||
>
|
||||
<VolUpload
|
||||
style="text-align: center; border: 1px dotted #FF9800;padding: 20px;"
|
||||
:autoUpload="false"
|
||||
:multiple="true"
|
||||
:url="UploadImgUrl"
|
||||
:max-file="uploadCount"
|
||||
:img="true"
|
||||
:upload-after="uploadAfter"
|
||||
:upload-before="uploadBefore"
|
||||
></VolUpload>
|
||||
</VolBox>
|
||||
</div>
|
||||
<!-- <Button type="info" @click="appendContent()">插入内容</Button> -->
|
||||
<textarea :height="height" :width="width" :id="id" name="content" v-model="outContent"></textarea>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import "@/../static/kindeditor/themes/default/default.css";
|
||||
import "@/../static/kindeditor/kindeditor-all-min.js";
|
||||
// import "@/../static/kindeditor/kindeditor-all.js";
|
||||
import "@/../static/kindeditor/lang/zh-CN.js";
|
||||
let $this;
|
||||
export default {
|
||||
components: {
|
||||
VolBox: () => import("@/components/basic/VolBox.vue"),
|
||||
VolUpload: () => import("@/components/basic/VolUpload.vue")
|
||||
},
|
||||
name: "kindeditor",
|
||||
data() {
|
||||
return {
|
||||
uploadModel: false,
|
||||
id: "vue-kind" + ~~(Math.random() * 1000),
|
||||
editor: null,
|
||||
outContent: this.content
|
||||
};
|
||||
},
|
||||
props: {
|
||||
UploadImgUrl: {
|
||||
//上传图片的url
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
upload:{ //上传方法
|
||||
type:Function,
|
||||
default:(file)=>{
|
||||
|
||||
}
|
||||
},
|
||||
uploadCount: {
|
||||
//最多可以上传(图片)的数量
|
||||
type: Number,
|
||||
default: 3
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
// id: {
|
||||
// type: String,
|
||||
// required: true
|
||||
// },
|
||||
width: {
|
||||
type: String,
|
||||
default: "100%"
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: "500px"
|
||||
},
|
||||
minWidth: {
|
||||
type: Number,
|
||||
default: 650
|
||||
},
|
||||
minHeight: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
items: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return [
|
||||
"source",
|
||||
"|",
|
||||
"undo",
|
||||
"redo",
|
||||
"|",
|
||||
"preview",
|
||||
"print",
|
||||
"template",
|
||||
"code",
|
||||
"cut",
|
||||
"copy",
|
||||
"paste",
|
||||
"plainpaste",
|
||||
"wordpaste",
|
||||
"|",
|
||||
"justifyleft",
|
||||
"justifycenter",
|
||||
"justifyright",
|
||||
"justifyfull",
|
||||
"insertorderedlist",
|
||||
"insertunorderedlist",
|
||||
"indent",
|
||||
"outdent",
|
||||
"subscript",
|
||||
"superscript",
|
||||
"clearhtml",
|
||||
"quickformat",
|
||||
"selectall",
|
||||
"|",
|
||||
"fullscreen",
|
||||
"/",
|
||||
"formatblock",
|
||||
"fontname",
|
||||
"fontsize",
|
||||
"|",
|
||||
"forecolor",
|
||||
"hilitecolor",
|
||||
"bold",
|
||||
"italic",
|
||||
"underline",
|
||||
"strikethrough",
|
||||
"lineheight",
|
||||
"removeformat",
|
||||
"|",
|
||||
// "image",
|
||||
// "multiimage",
|
||||
// "flash",
|
||||
// "media",
|
||||
// "insertfile",
|
||||
"table",
|
||||
"hr",
|
||||
"emoticons",
|
||||
"baidumap",
|
||||
"pagebreak",
|
||||
"anchor",
|
||||
"link",
|
||||
"unlink",
|
||||
"|",
|
||||
"vue-img"
|
||||
// "about"
|
||||
];
|
||||
}
|
||||
},
|
||||
noDisableItems: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return ["source", "fullscreen"];
|
||||
}
|
||||
},
|
||||
filterMode: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
htmlTags: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return {
|
||||
font: ["color", "size", "face", ".background-color"],
|
||||
span: ["style"],
|
||||
div: ["class", "align", "style"],
|
||||
table: [
|
||||
"class",
|
||||
"border",
|
||||
"cellspacing",
|
||||
"cellpadding",
|
||||
"width",
|
||||
"height",
|
||||
"align",
|
||||
"style"
|
||||
],
|
||||
"td,th": [
|
||||
"class",
|
||||
"align",
|
||||
"valign",
|
||||
"width",
|
||||
"height",
|
||||
"colspan",
|
||||
"rowspan",
|
||||
"bgcolor",
|
||||
"style"
|
||||
],
|
||||
a: ["class", "href", "target", "name", "style"],
|
||||
embed: [
|
||||
"src",
|
||||
"width",
|
||||
"height",
|
||||
"type",
|
||||
"loop",
|
||||
"autostart",
|
||||
"quality",
|
||||
"style",
|
||||
"align",
|
||||
"allowscriptaccess",
|
||||
"/"
|
||||
],
|
||||
img: [
|
||||
"src",
|
||||
"width",
|
||||
"height",
|
||||
"border",
|
||||
"alt",
|
||||
"title",
|
||||
"align",
|
||||
"style",
|
||||
"/"
|
||||
],
|
||||
hr: ["class", "/"],
|
||||
br: ["/"],
|
||||
"p,ol,ul,li,blockquote,h1,h2,h3,h4,h5,h6": ["align", "style"],
|
||||
"tbody,tr,strong,b,sub,sup,em,i,u,strike": []
|
||||
};
|
||||
}
|
||||
},
|
||||
wellFormatMode: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
resizeType: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
themeType: {
|
||||
type: String,
|
||||
default: "default"
|
||||
},
|
||||
langType: {
|
||||
type: String,
|
||||
default: "zh-CN"
|
||||
},
|
||||
designMode: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
fullscreenMode: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
basePath: {
|
||||
type: String
|
||||
},
|
||||
themesPath: {
|
||||
type: String
|
||||
},
|
||||
pluginsPath: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
langPath: {
|
||||
type: String
|
||||
},
|
||||
minChangeSize: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
loadStyleMode: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
urlType: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
newlineTag: {
|
||||
type: String,
|
||||
default: "p"
|
||||
},
|
||||
pasteType: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
dialogAlignType: {
|
||||
type: String,
|
||||
default: "page"
|
||||
},
|
||||
shadowMode: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
zIndex: {
|
||||
type: Number,
|
||||
default: 811213
|
||||
},
|
||||
useContextmenu: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
syncType: {
|
||||
type: String,
|
||||
default: "form"
|
||||
},
|
||||
indentChar: {
|
||||
type: String,
|
||||
default: "\t"
|
||||
},
|
||||
cssPath: {
|
||||
type: [String, Array]
|
||||
},
|
||||
cssData: {
|
||||
type: String
|
||||
},
|
||||
bodyClass: {
|
||||
type: String,
|
||||
default: "ke-content"
|
||||
},
|
||||
colorTable: {
|
||||
type: Array
|
||||
},
|
||||
afterCreate: {
|
||||
type: Function
|
||||
},
|
||||
afterChange: {
|
||||
type: Function
|
||||
},
|
||||
afterTab: {
|
||||
type: Function
|
||||
},
|
||||
afterFocus: {
|
||||
type: Function
|
||||
},
|
||||
afterBlur: {
|
||||
type: Function
|
||||
},
|
||||
afterUpload: {
|
||||
type: Function
|
||||
},
|
||||
uploadJson: {
|
||||
type: String
|
||||
},
|
||||
fileManagerJson: {
|
||||
type: Function
|
||||
},
|
||||
allowPreviewEmoticons: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
allowImageUpload: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
allowFlashUpload: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
allowMediaUpload: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
allowFileUpload: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
allowFileManager: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
fontSizeTable: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return ["9px", "10px", "12px", "14px", "16px", "18px", "24px", "32px"];
|
||||
}
|
||||
},
|
||||
imageTabIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
formatUploadUrl: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
fullscreenShortcut: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
extraFileUploadParams: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
filePostName: {
|
||||
type: String,
|
||||
default: "imgFile"
|
||||
},
|
||||
fillDescAfterUploadImage: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
afterSelectFile: {
|
||||
type: Function
|
||||
},
|
||||
pagebreakHtml: {
|
||||
type: String,
|
||||
default: "<hr style=”page-break-after: always;” class=”ke-pagebreak” />"
|
||||
},
|
||||
allowImageRemote: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
autoHeightMode: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
fixToolBar: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
tabIndex: {
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
content(val) {
|
||||
this.editor && val !== this.outContent && this.editor.html(val);
|
||||
},
|
||||
outContent(val) {
|
||||
this.$emit("update:content", val);
|
||||
this.$emit("on-content-change", val);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
uploadBefore(files) {
|
||||
//上传前,建议上传至第三方进行存储
|
||||
return true;
|
||||
},
|
||||
uploadAfter(result, files) {
|
||||
if (!result.status) {
|
||||
return;
|
||||
}
|
||||
let urls = files.map(x => {
|
||||
return (
|
||||
`<img class="editor-img" src="` +
|
||||
(this.http.ipAddress + result.data + x.name) +
|
||||
`"/>`
|
||||
);
|
||||
});
|
||||
this.editor.insertHtml(urls.join(","));
|
||||
this.uploadModel = false;
|
||||
},
|
||||
getContent() {
|
||||
return this.outContent;
|
||||
},
|
||||
setContent(content) {
|
||||
//设置内容
|
||||
this.outContent = content || "";
|
||||
this.editor.html(this.outContent);
|
||||
},
|
||||
appendContent(htmlContent) {
|
||||
//kindEditor中当前光标的位置插入内容
|
||||
var startOffset = this.editor.cmd.range.startOffset;
|
||||
this.editor.insertHtml(htmlContent);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
$this = this;
|
||||
KindEditor.plugin("vue-img", function(K) {
|
||||
var editor = this,
|
||||
name = "vue-img";
|
||||
// 点击图标时执行
|
||||
editor.clickToolbar(name, function() {
|
||||
$this.uploadModel = true;
|
||||
});
|
||||
});
|
||||
KindEditor.lang({
|
||||
"vue-img": "上传图片"
|
||||
});
|
||||
var _this = this;
|
||||
_this.editor = window.KindEditor.create("#" + this.id, {
|
||||
width: _this.width,
|
||||
height: _this.height,
|
||||
minWidth: _this.minWidth,
|
||||
minHeight: _this.minHeight,
|
||||
items: _this.items,
|
||||
noDisableItems: _this.noDisableItems,
|
||||
filterMode: _this.filterMode,
|
||||
htmlTags: _this.htmlTags,
|
||||
wellFormatMode: _this.wellFormatMode,
|
||||
resizeType: _this.resizeType,
|
||||
themeType: _this.themeType,
|
||||
langType: _this.langType,
|
||||
designMode: _this.designMode,
|
||||
fullscreenMode: _this.fullscreenMode,
|
||||
basePath: _this.basePath,
|
||||
themesPath: _this.cssPath,
|
||||
pluginsPath: 'static/kindeditor/plugins/', // _this.pluginsPath,
|
||||
langPath: _this.langPath,
|
||||
minChangeSize: _this.minChangeSize,
|
||||
loadStyleMode: _this.loadStyleMode,
|
||||
urlType: _this.urlType,
|
||||
newlineTag: _this.newlineTag,
|
||||
pasteType: _this.pasteType,
|
||||
dialogAlignType: _this.dialogAlignType,
|
||||
shadowMode: _this.shadowMode,
|
||||
zIndex: _this.zIndex,
|
||||
useContextmenu: _this.useContextmenu,
|
||||
syncType: _this.syncType,
|
||||
indentChar: _this.indentChar,
|
||||
cssPath: _this.cssPath,
|
||||
cssData: _this.cssData,
|
||||
bodyClass: _this.bodyClass,
|
||||
colorTable: _this.colorTable,
|
||||
afterCreate: _this.afterCreate,
|
||||
afterChange: function() {
|
||||
_this.afterChange;
|
||||
_this.outContent = this.html();
|
||||
},
|
||||
afterTab: _this.afterTab,
|
||||
afterFocus: _this.afterFocus,
|
||||
afterBlur: _this.afterBlur,
|
||||
afterUpload: _this.afterUpload,
|
||||
uploadJson: _this.uploadJson,
|
||||
fileManagerJson: _this.fileManagerJson,
|
||||
allowPreviewEmoticons: _this.allowPreviewEmoticons,
|
||||
allowImageUpload: _this.allowImageUpload,
|
||||
allowFlashUpload: _this.allowFlashUpload,
|
||||
allowMediaUpload: _this.allowMediaUpload,
|
||||
allowFileUpload: _this.allowFileUpload,
|
||||
allowFileManager: _this.allowFileManager,
|
||||
fontSizeTable: _this.fontSizeTable,
|
||||
imageTabIndex: _this.imageTabIndex,
|
||||
formatUploadUrl: _this.formatUploadUrl,
|
||||
fullscreenShortcut: _this.fullscreenShortcut,
|
||||
extraFileUploadParams: _this.extraFileUploadParams,
|
||||
filePostName: _this.filePostName,
|
||||
fillDescAfterUploadImage: _this.fillDescAfterUploadImage,
|
||||
afterSelectFile: _this.afterSelectFile,
|
||||
pagebreakHtml: _this.pagebreakHtml,
|
||||
allowImageRemote: _this.allowImageRemote,
|
||||
autoHeightMode: _this.autoHeightMode,
|
||||
fixToolBar: _this.fixToolBar,
|
||||
tabIndex: _this.tabIndex
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.ke-icon-vue-img {
|
||||
background-image: url(/../static/kindeditor/themes/default/default.png);
|
||||
background-position: 0px -496px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,9 @@
|
||||
import Vue from 'vue'
|
||||
import SvgIcon from '@/components/SvgIcon'// svg component
|
||||
|
||||
// register globally
|
||||
Vue.component('svg-icon', SvgIcon)
|
||||
|
||||
const req = require.context('./svg', false, /\.svg$/)
|
||||
const requireAll = requireContext => requireContext.keys().map(requireContext)
|
||||
requireAll(req)
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 497 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 944 B |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 285 B |
|
After Width: | Height: | Size: 821 B |
|
After Width: | Height: | Size: 623 B |
|
After Width: | Height: | Size: 597 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 440 B |
@ -0,0 +1,22 @@
|
||||
# replace default config
|
||||
|
||||
# multipass: true
|
||||
# full: true
|
||||
|
||||
plugins:
|
||||
|
||||
# - name
|
||||
#
|
||||
# or:
|
||||
# - name: false
|
||||
# - name: true
|
||||
#
|
||||
# or:
|
||||
# - name:
|
||||
# param1: 1
|
||||
# param2: 2
|
||||
|
||||
- removeAttrs:
|
||||
attrs:
|
||||
- 'fill'
|
||||
- 'fill-rule'
|
||||
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<section class="app-main">
|
||||
|
||||
<breadcrumb class="breadcrumb-container" />
|
||||
<transition name="fade-transform" mode="out-in">
|
||||
<router-view :key="key" />
|
||||
</transition>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Breadcrumb from '@/components/Breadcrumb'
|
||||
export default {
|
||||
components: {
|
||||
Breadcrumb
|
||||
},
|
||||
name: 'AppMain',
|
||||
computed: {
|
||||
key() {
|
||||
return this.$route.path
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.app-main {
|
||||
/*50 = navbar */
|
||||
min-height: calc(100vh - 30px);
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.fixed-header+.app-main {
|
||||
padding-top: 50px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
// fix css style bug in open el-dialog
|
||||
.el-popup-parent--hidden {
|
||||
.fixed-header {
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
.breadcrumb-container {
|
||||
margin-left: 20px !important;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div class="navbar">
|
||||
<a href="javascript:;" class="btn-quit">退出</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapGetters
|
||||
} from 'vuex'
|
||||
import Breadcrumb from '@/components/Breadcrumb'
|
||||
import Hamburger from '@/components/Hamburger'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Breadcrumb,
|
||||
Hamburger
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'sidebar',
|
||||
'avatar'
|
||||
])
|
||||
},
|
||||
methods: {
|
||||
toggleSideBar() {
|
||||
this.$store.dispatch('app/toggleSideBar')
|
||||
},
|
||||
async logout() {
|
||||
await this.$store.dispatch('user/logout')
|
||||
this.$router.push(`/login?redirect=${this.$route.fullPath}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.navbar {
|
||||
height: 30px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
//background: #fff;
|
||||
|
||||
background: #338de3;
|
||||
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
|
||||
color: #FFFFFF;
|
||||
line-height: 30px;
|
||||
|
||||
.hamburger-container {
|
||||
line-height: 46px;
|
||||
height: 100%;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
transition: background .3s;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, .025)
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb-container {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.right-menu {
|
||||
float: right;
|
||||
height: 100%;
|
||||
line-height: 50px;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.right-menu-item {
|
||||
display: inline-block;
|
||||
padding: 0 8px;
|
||||
height: 100%;
|
||||
font-size: 18px;
|
||||
color: #5a5e66;
|
||||
vertical-align: text-bottom;
|
||||
|
||||
&.hover-effect {
|
||||
cursor: pointer;
|
||||
transition: background .3s;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, .025)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
margin-right: 30px;
|
||||
|
||||
.avatar-wrapper {
|
||||
margin-top: 5px;
|
||||
position: relative;
|
||||
|
||||
.user-avatar {
|
||||
cursor: pointer;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.el-icon-caret-bottom {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: -20px;
|
||||
top: 25px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,26 @@
|
||||
export default {
|
||||
computed: {
|
||||
device() {
|
||||
return this.$store.state.app.device
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// In order to fix the click on menu on the ios device will trigger the mouseleave bug
|
||||
// https://github.com/PanJiaChen/vue-element-admin/issues/1135
|
||||
this.fixBugIniOS()
|
||||
},
|
||||
methods: {
|
||||
fixBugIniOS() {
|
||||
const $subMenu = this.$refs.subMenu
|
||||
if ($subMenu) {
|
||||
const handleMouseleave = $subMenu.handleMouseleave
|
||||
$subMenu.handleMouseleave = (e) => {
|
||||
if (this.device === 'mobile') {
|
||||
return
|
||||
}
|
||||
handleMouseleave(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'MenuItem',
|
||||
functional: true,
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
render(h, context) {
|
||||
const { icon, title } = context.props
|
||||
const vnodes = []
|
||||
|
||||
if (icon) {
|
||||
if (icon.includes('el-icon')) {
|
||||
vnodes.push(<i class={[icon, 'sub-el-icon']} />)
|
||||
}
|
||||
else if(icon.includes("viewicon")){
|
||||
let _icon=icon.split("/")[1];
|
||||
vnodes.push(<Icon type={_icon} class='sub-el-icon' size="18" />)
|
||||
}
|
||||
else if(icon.includes("iconfont")){
|
||||
let _icon=icon.split("/")[1]+" iconfont";
|
||||
vnodes.push(<Icon custom={_icon} class='sub-el-icon' size="18" />)
|
||||
}
|
||||
else {
|
||||
vnodes.push(<svg-icon icon-class={icon}/>)
|
||||
}
|
||||
}else {
|
||||
var _icon="el-icon-menu";
|
||||
vnodes.push(<i class={[_icon, 'sub-el-icon']} />)
|
||||
}
|
||||
|
||||
if (title) {
|
||||
vnodes.push(<span slot='title'>{(title)}</span>)
|
||||
}
|
||||
return vnodes
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sub-el-icon {
|
||||
color: currentColor;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<component :is="type" v-bind="linkProps(to)">
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isExternal } from '@/utils/validate'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
to: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isExternal() {
|
||||
return isExternal(this.to)
|
||||
},
|
||||
type() {
|
||||
if (this.isExternal) {
|
||||
return 'a'
|
||||
}
|
||||
return 'router-link'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
linkProps(to) {
|
||||
if (this.isExternal) {
|
||||
return {
|
||||
href: to,
|
||||
target: '_blank',
|
||||
rel: 'noopener'
|
||||
}
|
||||
}
|
||||
return {
|
||||
to: to
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||