├── .eslintignore
├── .gitignore
├── assets
├── iconfont.eot
├── iconfont.ttf
├── iconfont.woff
├── iconfont.css
├── iconfont.svg
└── iconfont.js
├── config.json
├── src
├── assets
│ ├── img
│ │ ├── main_bg.png
│ │ ├── search.png
│ │ └── view_bg.png
│ ├── iconFont
│ │ ├── iconfont.eot
│ │ ├── iconfont.ttf
│ │ ├── iconfont.woff
│ │ ├── demo.css
│ │ ├── demo_fontclass.html
│ │ └── iconfont.css
│ └── less
│ │ ├── UI.less
│ │ ├── header.less
│ │ └── rest.less
├── plugins
│ ├── README.md
│ └── Toast
│ │ ├── toast.js
│ │ └── toast.vue
├── components
│ ├── Page.vue
│ ├── textTitle.vue
│ ├── imgTitle.vue
│ ├── Paragraph.vue
│ ├── index.js
│ ├── footerComponent.vue
│ ├── HeaderComponent.vue
│ ├── passBanner.vue
│ ├── textLink.vue
│ ├── swipeBanner.vue
│ ├── TheSection.vue
│ ├── brandList.vue
│ ├── ordinaryProduct.vue
│ ├── startEffect.vue
│ ├── hotImage.vue
│ └── scrollActive.vue
├── viewComponents
│ ├── textTitle.vue
│ ├── imgTitle.vue
│ ├── Paragraph.vue
│ ├── TheSection.vue
│ ├── index.js
│ ├── passBanner.vue
│ ├── HeaderComponent.vue
│ ├── hotImage.vue
│ ├── textLink.vue
│ ├── swipeBanner.vue
│ ├── scrollActive.vue
│ ├── brandList.vue
│ ├── ordinaryProduct.vue
│ └── startEffect.vue
├── widgets
│ ├── siteTree.js
│ ├── util.js
│ └── widgetTree.js
├── layout
│ ├── Render.vue
│ ├── viewRender.vue
│ ├── leftModel.vue
│ └── configRight.vue
├── tpl
│ └── edit.html
├── server
│ ├── mock.js
│ ├── api.js
│ └── http.js
├── common
│ ├── jsonTree.vue
│ ├── scroll.vue
│ └── hotDrag.vue
├── edit.js
├── view.js
├── view.vue
├── store.js
└── edit.vue
├── .editorconfig
├── .github
└── workflows
│ └── nodejs.yml
├── .babelrc
├── mock
├── getpool.json
└── getConfig.json
├── LICENSE
├── README.md
├── package.json
└── webpack.config.js
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 | package-lock.json
5 |
--------------------------------------------------------------------------------
/assets/iconfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ithack/vueCMS/HEAD/assets/iconfont.eot
--------------------------------------------------------------------------------
/assets/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ithack/vueCMS/HEAD/assets/iconfont.ttf
--------------------------------------------------------------------------------
/assets/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ithack/vueCMS/HEAD/assets/iconfont.woff
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "version":"0.0.3",
4 | "jsLink":["vendor.js","build.js","view.js"]
5 | }
6 |
--------------------------------------------------------------------------------
/src/assets/img/main_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ithack/vueCMS/HEAD/src/assets/img/main_bg.png
--------------------------------------------------------------------------------
/src/assets/img/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ithack/vueCMS/HEAD/src/assets/img/search.png
--------------------------------------------------------------------------------
/src/assets/img/view_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ithack/vueCMS/HEAD/src/assets/img/view_bg.png
--------------------------------------------------------------------------------
/src/assets/iconFont/iconfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ithack/vueCMS/HEAD/src/assets/iconFont/iconfont.eot
--------------------------------------------------------------------------------
/src/assets/iconFont/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ithack/vueCMS/HEAD/src/assets/iconFont/iconfont.ttf
--------------------------------------------------------------------------------
/src/assets/iconFont/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ithack/vueCMS/HEAD/src/assets/iconFont/iconfont.woff
--------------------------------------------------------------------------------
/src/assets/less/UI.less:
--------------------------------------------------------------------------------
1 | .but{
2 | background-color:#fff;
3 | border-radius:5px;
4 | color:#333;
5 | &:hover{
6 | background-color:#5E9EF3;
7 | color:#fff;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 |
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | trim_trailing_whitespace = true
8 | insert_final_newline = true
9 | indent_style = space
10 | indent_size = 2
11 |
12 | [Makefile]
13 | indent_style = tab
14 |
--------------------------------------------------------------------------------
/src/plugins/README.md:
--------------------------------------------------------------------------------
1 | **plugins 插件文件**
2 |
3 | 创建一些关于toast等公用性较强的插件到vue实例用,目前所有类似功能全部用elemetUI或mintUi,暂时没有用到此文件;
4 |
5 | toast用法:
6 | ```$xslt
7 | //入口文件引入toast
8 | import Toast from './plugins/toast.js';
9 | import Vue from 'vue'
10 |
11 | Vue.use(Toast)
12 |
13 | //组件中直接调用
14 | this.$toast('toast测试内容')
15 |
16 | ```
17 |
--------------------------------------------------------------------------------
/src/components/Page.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
23 |
24 |
--------------------------------------------------------------------------------
/src/components/textTitle.vue:
--------------------------------------------------------------------------------
1 |
2 | {{node.other.title}}
3 |
4 |
5 |
17 |
18 |
21 |
--------------------------------------------------------------------------------
/src/viewComponents/textTitle.vue:
--------------------------------------------------------------------------------
1 |
2 | {{node.other.title}}
3 |
4 |
5 |
17 |
18 |
21 |
--------------------------------------------------------------------------------
/src/components/imgTitle.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
23 |
--------------------------------------------------------------------------------
/src/viewComponents/imgTitle.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
23 |
--------------------------------------------------------------------------------
/src/widgets/siteTree.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 2018/5/16
3 | * Created by yangkai9
4 | */
5 | let siteTree = {
6 | "type": "page",
7 | "name": "页面",
8 | "index": 0,
9 | "config": [{
10 | "key": "pid",
11 | "value": "123456789",
12 | "text": "组件id",
13 | "type": "text"
14 | }, {
15 | "style": "padding",
16 | "value": ["0px", "0px", "0px", "0px"],
17 | "text": "外边距",
18 | "type": "css"
19 | }, {
20 | "style": "backgroundColor",
21 | "value": "#fff",
22 | "text": "背景色",
23 | "type": "color"
24 | }],
25 | "children": []
26 | }
27 | export default siteTree
28 |
--------------------------------------------------------------------------------
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | name: Cms
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: ubuntu-latest
9 |
10 | strategy:
11 | matrix:
12 | node-version: [8.x, 10.x, 12.x]
13 |
14 | steps:
15 | - uses: actions/checkout@v1
16 | - name: Use Node.js ${{ matrix.node-version }}
17 | uses: actions/setup-node@v1
18 | with:
19 | node-version: ${{ matrix.node-version }}
20 | - name: npm install, build, and test
21 | run: |
22 | npm ci
23 | npm run build --if-present
24 | npm run serve
25 | env:
26 | CI: true
27 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "targets": {
5 | "safari": 7,
6 | "firefox": 52,
7 | "chrome": 42,
8 | "edge": 10
9 | },
10 | "exclude": [
11 | "transform-regenerator"
12 | ]
13 | }]
14 | ],
15 | "plugins": [
16 | [
17 | "component",
18 | {
19 | "libraryName": "element-ui",
20 | "styleLibraryName": "theme-chalk"
21 | }
22 | ],"syntax-dynamic-import",
23 | "transform-object-rest-spread","transform-runtime", "babel-plugin-transform-regenerator", "babel-plugin-transform-es2015-modules-commonjs"
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/mock/getpool.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "list": [
4 | {
5 | "imgurl": "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3141886839,1073302871&fm=26&gp=0.jpg",
6 | "skuid": "123456",
7 | "name": "测试数据标题名字"
8 | },
9 | {
10 | "imgurl": "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=238640327,3002157289&fm=200&gp=0.jpg",
11 | "skuid": "2",
12 | "name": "测试数据美女1"
13 | },
14 | {
15 | "imgurl": "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=254618362,2906926008&fm=200&gp=0.jpg",
16 | "skuid": "3",
17 | "name": "测试数据美女2"
18 | }
19 | ]
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/Paragraph.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{other.title}}
4 |
333
5 |
6 |
提交
7 |
8 |
9 |
10 |
31 |
32 |
40 |
41 |
--------------------------------------------------------------------------------
/src/viewComponents/Paragraph.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{other.title}}
4 |
333
5 |
6 |
提交
7 |
8 |
9 |
10 |
31 |
32 |
40 |
41 |
--------------------------------------------------------------------------------
/src/viewComponents/TheSection.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
30 |
31 |
37 |
--------------------------------------------------------------------------------
/src/assets/less/header.less:
--------------------------------------------------------------------------------
1 |
2 | header{
3 | height:60px;background-color:#fff;width:100%;border-bottom:1px solid #ccc;position:absolute;top:0;left:0;padding:0 12px;box-sizing:border-box;overflow:hidden;
4 | .header_left{display:inline-block;}
5 | //.el-switch{margin:20px 10px;}
6 | .el-switch__label *{line-height:20px;}
7 | .header_but{display:inline-block;width:100px;height:28px;border-radius:4px;font-size:14px;line-height:28px;margin:15px 0;text-align:center;}
8 | .but_blue{background:#5E9EF3;color:#fff;}
9 | & span{float:left;cursor:pointer;}
10 | .header_right{
11 | display:inline-block;float:right;
12 | &>span{margin:15px 6px;}
13 | }
14 | }
15 | .a_but{
16 | background:#5E9EF3;color:#fff;
17 | &:hover{
18 | border:1px solid #ccc;color:#333;background-color:#fff;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/layout/Render.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
30 |
--------------------------------------------------------------------------------
/src/layout/viewRender.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
31 |
--------------------------------------------------------------------------------
/src/viewComponents/index.js:
--------------------------------------------------------------------------------
1 | // 导入JSON 树中所涉及的所有节点
2 | import Page from './../components/Page.vue' //组件模版用
3 | // import Paragraph from './Paragraph'
4 | import TheSection from './TheSection'
5 | // import footerComponent from './footerComponent'
6 | export default {
7 | // Paragraph,
8 | TheSection,
9 | HeaderComponent:() => import('./HeaderComponent'),
10 | scrollActive:()=>import('./scrollActive'),//锚点导航
11 | // footerComponent,
12 | textTitle:()=>import('./textTitle'),
13 | imgTitle:()=>import('./imgTitle'),
14 | swipeBanner:()=>import('./swipeBanner'),
15 | ordinaryProduct:()=>import('./ordinaryProduct'),//普通商品
16 | hotImage:()=>import('./hotImage'),//图片热区
17 | passBanner:()=>import('./passBanner'),//通栏广告
18 | textLink:()=>import('./textLink'),//文字链
19 | brandList:()=>import('./brandList'),//品牌列表
20 | startEffect:()=>import('./startEffect'),//启动动效
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/index.js:
--------------------------------------------------------------------------------
1 | // 导入JSON 树中所涉及的所有节点
2 | import Page from './../components/Page.vue' //组件模版用
3 | // import TheSection from './../components/TheSection.vue' //楼层模版
4 | import Paragraph from './../components/Paragraph.vue'
5 | import TheSection from './TheSection'
6 | import footerComponent from './footerComponent.vue'
7 | export default {
8 | Paragraph,
9 | TheSection,
10 | HeaderComponent:() => import('./HeaderComponent'),
11 | scrollActive:()=>import('./scrollActive'),//锚点导航
12 | footerComponent,
13 | textTitle:()=>import('./textTitle'),
14 | imgTitle:()=>import('./imgTitle'),
15 | swipeBanner:()=>import('./swipeBanner'),
16 | ordinaryProduct:()=>import('./ordinaryProduct'),//普通商品
17 | hotImage:()=>import('./hotImage'),//图片热区
18 | passBanner:()=>import('./passBanner'),//通栏广告
19 | textLink:() =>import('./textLink'),//文字链
20 | brandList:() =>import('./brandList'),//品牌列表
21 | startEffect:() =>import('./startEffect'),//启动动效
22 | }
23 |
--------------------------------------------------------------------------------
/src/tpl/edit.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 移动端
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
27 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/components/footerComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 首页
5 |
6 |
7 | 活动
8 |
9 |
10 | 购物车
11 |
12 |
13 | 我的
14 |
15 |
16 |
17 |
18 |
39 |
40 |
48 |
--------------------------------------------------------------------------------
/src/plugins/Toast/toast.js:
--------------------------------------------------------------------------------
1 | import toast from './toast.vue'
2 | let Toast={};
3 | Toast.install=(Vue,option={})=>{
4 | const ToastTem=Vue.extend(toast);
5 | let removeDom = event => {
6 | if (event.target.parentNode.childNodes.length > 1) {
7 | event.target.parentNode.removeChild(event.target)
8 | } else {
9 | event.target.parentNode.parentNode.removeChild(event.target.parentNode)
10 | }
11 | }
12 | ToastTem.prototype.close=function(){
13 | this.visible=false;
14 | this.$el.addEventListener('transitionend',removeDom)
15 | }
16 | Vue.prototype.$toast=(option)=>{
17 | var instance = new ToastTem().$mount(document.createElement('div'));
18 | let duration = option.duration || option.duration || 2500;
19 | instance.message = typeof option==='string'? option :option.message;
20 | instance.position=option.position|| 'middle-bottom'
21 | document.body.appendChild(instance.$el);
22 | setTimeout(function () {
23 | instance.close()
24 | }, duration)
25 | }
26 | }
27 | export default Toast
28 |
--------------------------------------------------------------------------------
/src/server/mock.js:
--------------------------------------------------------------------------------
1 | /*import Mock from 'mockjs'
2 | Mock.mock('http://config.json', 'get', [
3 | {
4 | key: 'pid',
5 | value: '123456789',
6 | text: '组件id',
7 | type: 'text'
8 | },
9 | {
10 | style: 'width',
11 | value: 'auto',
12 | text: '宽',
13 | type: 'css'
14 | },
15 |
16 | {
17 | style: 'margin',
18 | value: ['0px','0px','0px','0px'],
19 | text: '内边距',
20 | type: 'css'
21 | },
22 | {
23 | style: 'padding',
24 | value: ['0px','0px','0px','0px'],
25 | text: '外边距',
26 | type: 'css'
27 | },
28 | {
29 | style: 'backgroundColor',
30 | value: '#fff',
31 | text: '背景色',
32 | type: 'color'
33 | },
34 | {
35 | style: 'backgroundImage',
36 | value: '',
37 | text: '背景图',
38 | key:'img',
39 | type: 'css'
40 | },
41 | {
42 | type: 'text',
43 | value: '测试文字',
44 | key: 'title',
45 | text: '测试'
46 | },
47 | {
48 | type: 'attr',
49 | value: '123456',
50 | key: 'kid',
51 | text: '数据ID'
52 | }
53 | ])*//**
54 | * 2018/5/18
55 | * Created by yangkai9
56 | */
57 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 tanghejun
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/common/jsonTree.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
40 |
41 |
44 |
--------------------------------------------------------------------------------
/src/viewComponents/passBanner.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
42 |
43 |
49 |
50 |
--------------------------------------------------------------------------------
/src/components/HeaderComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 返回
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
38 |
39 |
44 |
45 |
--------------------------------------------------------------------------------
/src/edit.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill'
2 | import Vue from 'vue'
3 | import { Upload,MessageBox,Button,Input,Select,Option,Form,FormItem,Dialog,Row,Switch,Tree} from 'element-ui'
4 | import {Toast} from 'mint-ui'
5 | import Lazyload from 'vue-lazyload'
6 | import App from './edit.vue'
7 | import store from './store'
8 | import axios from './server/http'
9 | import 'element-ui/lib/theme-chalk/index.css'
10 | import 'mint-ui/lib/style.css'
11 | Vue.component(Button.name,Button);
12 | Vue.component(Select.name,Select);
13 | Vue.component(Option.name,Option);
14 | Vue.component(Input.name,Input);
15 | Vue.component(Row.name,Row);
16 | Vue.component(Form.name,Form);
17 | Vue.component(FormItem.name,FormItem);
18 | Vue.component(Dialog.name,Dialog);
19 | Vue.component(Upload.name, Upload)
20 | Vue.component(Switch.name, Switch)
21 | Vue.component(Tree.name, Tree)
22 | Vue.component(MessageBox.name, MessageBox)
23 | const app = new Vue({
24 | store,
25 | render: h => h(App)
26 | })
27 | Vue.prototype.$http=axios
28 | Vue.prototype.$msgbox = MessageBox
29 | Vue.prototype.$alert = MessageBox.alert
30 | Vue.prototype.$confirm = MessageBox.confirm
31 | Vue.prototype.$toast = Toast
32 | Vue.use(Upload)
33 | // Vue.use(Scrollactive);
34 | //懒加载配置
35 | Vue.use(Lazyload, {
36 | error: '',
37 | loading: '',
38 | })
39 | // config配置项筛选器
40 | app.$mount('#app')
41 |
--------------------------------------------------------------------------------
/src/components/passBanner.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 |
6 |
7 |
47 |
48 |
54 |
55 |
--------------------------------------------------------------------------------
/src/plugins/Toast/toast.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{message}}
4 |
5 |
6 |
7 |
19 |
20 |
64 |
--------------------------------------------------------------------------------
/mock/getConfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "code": 0,
3 | "data": {
4 | "id": 2,
5 | "name": "楼层模型",
6 | "type_id": 1,
7 | "props": [
8 | {
9 | "id": 10,
10 | "title": "楼层ID",
11 | "name": "pool_id",
12 | "remark": "",
13 | "val_type": 1,
14 | "ui_type": 1,
15 | "is_must": 1,
16 | "options": [],
17 | "default_val": "2"
18 | },
19 | {
20 | "id": 8,
21 | "title": "外边距",
22 | "name": "margin",
23 | "remark": "css",
24 | "val_type": 1,
25 | "ui_type": 1,
26 | "is_must": 1,
27 | "options": [],
28 | "default_val": "0 0 10px 0"
29 | },
30 | {
31 | "id": 103,
32 | "title": "内间距",
33 | "name": "padding",
34 | "remark": "css",
35 | "val_type": 1,
36 | "ui_type": 1,
37 | "is_must": 0,
38 | "options": [],
39 | "default_val": "0 0 0 0"
40 | },
41 | {
42 | "id": 9,
43 | "title": "背景色",
44 | "name": "backgroundColor",
45 | "remark": "css",
46 | "val_type": 1,
47 | "ui_type": 6,
48 | "is_must": 1,
49 | "options": [],
50 | "default_val": "#ccc"
51 | },
52 | {
53 | "id": 59,
54 | "title": "背景图",
55 | "name": "backgroundImage",
56 | "remark": "css",
57 | "val_type": 1,
58 | "ui_type": 7,
59 | "is_must": 0,
60 | "options": [],
61 | "default_val": ""
62 | }
63 | ]
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/view.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill'
2 | import Vue from 'vue'
3 | import {Toast} from 'mint-ui'
4 | import Lazyload from 'vue-lazyload'
5 | import App from './view.vue'
6 | import store from './store'
7 | import axios from './server/http'
8 | import 'mint-ui/lib/style.css'
9 | import {getHtmlDocName,getQueryUrl} from '~/widgets/util'
10 | // import Scrollactive from 'vue-scrollactive'
11 | const app = new Vue({
12 | store,
13 | render: h => h(App)
14 | })
15 | Vue.prototype.$http=axios
16 | Vue.prototype.$toast = Toast
17 | // Vue.use(Scrollactive);
18 | // 懒加载配置
19 | Vue.use(Lazyload, {
20 | error: '',
21 | loading: '',
22 | })
23 | // config配置项筛选器
24 | // 埋点
25 | Vue.directive('$log', {
26 | inserted: function (el, binding,vnode){
27 | var getUrlId=getHtmlDocName().split('-');
28 | $(el).attr('taglog',vnode.data.directives[0].value)
29 | el.addEventListener('click', () => {
30 | let floorEl=$(el).closest('.floor'),
31 | floorId=floorEl.attr('floorid'),
32 | floorName=floorEl.attr('floor-index'),
33 | // appid=getUrlId[0]?getUrlId[0]:'0',
34 | // pageid=getUrlId[1]?getUrlId[1]:'0',
35 | // 预览页埋点方法
36 | appid=getQueryUrl('app_id')||'0',
37 | pageid=getQueryUrl('page_id')||0,
38 | logString=appid+'|'+pageid+'|'+floorId+'|'+$(el).attr('taglog');
39 | logString=Math.floor(Math.random()*2+1)+'|'+appid+'|' +pageid+'|'+floorId+'|楼层'+floorName+'|'+$(el).attr('taglog');
40 | console.log('拼接后入参:'+logString)
41 | log('esite', 'esite_h5',logString)
42 |
43 | })
44 | }
45 | })
46 | app.$mount('#app')
47 |
--------------------------------------------------------------------------------
/src/viewComponents/HeaderComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 返回
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
50 |
51 |
56 |
57 |
--------------------------------------------------------------------------------
/src/widgets/util.js:
--------------------------------------------------------------------------------
1 | let NODE_ENV=process.env.NODE_ENV;
2 | // 获取cookie
3 | export function getCookie(name) {
4 | var arr, reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)')
5 | if ( arr = document.cookie.match(reg))
6 | return (arr[2])
7 | else
8 | return null
9 | }
10 |
11 | // 设置cookie,增加到vue实例方便全局调用
12 | export function setCookie (c_name, value, expiredays) {
13 | var exdate = new Date()
14 | exdate.setDate(exdate.getDate() + expiredays)
15 | document.cookie = c_name + '=' + escape(value) + ((expiredays == null) ? '' : ';expires=' + exdate.toGMTString())
16 | };
17 |
18 | //删除cookie
19 | export function delCookie (name) {
20 | var exp = new Date()
21 | exp.setTime(exp.getTime() - 1)
22 | var cval = getCookie(name)
23 | if (cval != null)
24 | document.cookie = name + '=' + cval + ';expires=' + exp.toGMTString()
25 | };
26 | // 获取url 参数
27 | export function getQueryUrl (variable) {
28 | var query = window.location.search.substring(1)
29 | var vars = query.split('&');
30 | for (var i = 0;i < vars.length;i++) {
31 | var pair = vars[i].split('=')
32 | if (pair[0] === variable) { return pair[1] }
33 | }
34 | return false
35 | }
36 |
37 | export function getHtmlDocName() {
38 | var str = window.location.href;
39 | str = str.substring(str.lastIndexOf('/') + 1);
40 | str = str.substring(0, str.lastIndexOf('.'));
41 | return str
42 | }
43 |
44 | export function link () {
45 | let url
46 | if (NODE_ENV === 'development'){
47 | url = {
48 | domain: '//kevin.com',
49 | mItem: '//kevin.com'// 普通商品详情
50 | }
51 | } else {
52 | url = {
53 | domain: '',
54 | mItem: '//kevin.com'// 普通商品详情
55 | }
56 | }
57 | return url
58 | }
59 |
--------------------------------------------------------------------------------
/src/viewComponents/hotImage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 |
6 |
7 |
8 |
44 |
45 |
61 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | vue_cms-x
2 | ====
3 | 可视化拖拽系统
4 | #20190516 更新
5 |
6 | 之前只是简单的删除了公司的一些代码,并没有细看,issues和私下有人说跑不起来,今天抽出几分钟吧主要的两个接口MOCK到本地,并实现`npm run dev` 跑起来!
7 |
8 | 这里还要说一下,整个拖拽可视化过程都需要后端接口返回组件的样式和数据,这次只是今天加了一个楼层的配置模拟接口!
9 |
10 | 这个项目提交的github主要是提供一种VUE实现拖拽生成页面的开发思路,有很多不完美的地方,大家可以指正,开发这个项目时我也是第一次做这个场景的项目开发,并没有类似场景的开发经验,所以如果又其他更有更好的开发思路和方案欢迎交流沟通,不限框架!我当时在选型时考虑的是React和Vue的,之所以 选择Vue是因为相对熟练,毕竟从Vue1.x就在玩了,并且相对于React的单向数据流,Vue的双向数据绑定更能轻松实现场景中实时配置,可视化区域实时更新!如上是简单的选型考虑!至于实现方案我相信一定还有其他更好的方案,欢迎类似场景需求同行交流经验
11 |
12 | #20180814更新
13 |
14 | 1.加入组件code split优化
15 |
16 | 2.项目目录出入口多页面打包完成,拆分view和edit两个页面,功能单一性;
17 |
18 | view只负责渲染组件用户浏览页面组件的加载
19 |
20 | edit加载更多UI和JS插件等
21 |
22 | view和edit拆分有助于后期开发的可观和操作性
23 |
24 | 3.埋点的加入
25 |
26 | ##使用说明
27 | ```
28 | npm install
29 |
30 | npm run dev //本地运行 访问可视化编辑访问edit.html,显示效果访问view.html
31 |
32 | npm run pre //预发打包
33 |
34 | npm run build
35 |
36 | ```
37 | componnet ====>编辑可视化组件
38 |
39 | viewComponents ====> 用户访问页面查看组件
40 |
41 | layout ====> 可视化编辑结构组件
42 |
43 | server ====> 所有相关请求接口文件配置
44 |
45 | widgets ===> 组件列表编辑配置
46 |
47 | plugins ===> 开发vue插件用,目前项目中用到的弹框等都是elementUI那一套,并没有自己开发,只写了个toast的例子在里边
48 |
49 |
50 | 组件开发步骤:
51 |
52 | 1。src/components里创建vue文件,同时在index.js里创建异步组件方法例`ordinaryProduct:()=>import('./ordinaryProduct')`
53 |
54 | 2。widgets-->widgets.js配置相关组件信息
55 |
56 | 由于项目中设计到公司的一些域名,可能直接跑无法运行;
57 |
58 | clone后要修改个文件:server中api文件中的createObject接口,这个接口是在拖拽后从后端请求组件配置接口,接口格式已经放到easy mock中;或者直接改掉store中getDefaultConfig方法,自己把组件配置写在本地一个文件中,这样拖拽时就可以看到效果
59 |
60 | 整个可视化项目中心都在store和render文件里,viewRender只是clone了一下并删掉了一些view时没用的功能;
61 |
62 | 核心:vuedraggable 和 vue的component组件,一切都围绕这两块做的
63 |
64 | 分享整个可视化项目主要是给大家提供一个思路,(项目中用到了elementUI的一些上传,按钮,弹框的UI,所以打包后vendor比较大,也没有把view和edit单独打包公用插件)代码有瑕疵的地方还望指出,理想情况下如果创建一套这样可视化拖拽系统,其实应该加入node,虽然这一套可视化加入了异步加载组件,但如果用户访问我们搭建好的页面时还是需要加载js后才会出现页面,这各部分如果有node加入的话,用SSR效率和可用性更加完美,毕竟我们搭建的页面时给用户看的;
65 |
66 | 欢迎大神指导意见
67 |
68 | 整个项目从搭建开始都是作者一人在搞,项目近,任务重,请轻喷!!!
69 |
70 | 原创不易,多多支持;
71 |
72 | **TODOS**
73 |
74 | copy 编辑配置有问题
75 |
76 | 整体结构目录优化,重灾区top.vue,util文件夹,edit.js等文件调整和文件内部拆分颗粒
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/src/view.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
35 |
36 |
84 |
--------------------------------------------------------------------------------
/src/assets/less/rest.less:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 | article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary {
6 | display: block;
7 | }
8 | html {
9 | font-size: 12px;
10 | font-family: 'Microsoft Yahei','Helvetica Neue', Helvetica, STHeiTi, Arial, sans-serif;
11 | }
12 | body{
13 | height: 100%; overflow-x: hidden; -webkit-overflow-scrolling: touch;max-width: 750px;margin:0 auto
14 | }
15 | audio, canvas, progress, video { display: inline-block; vertical-align: baseline; }
16 | img {
17 | border: none;
18 | vertical-align: middle;
19 | }
20 | a {
21 | text-decoration: none;
22 | outline: none;
23 | /*设置的tap A标签的时候出现的黑色高亮*/
24 | -webkit-tap-highlight-color: transparent;
25 | }
26 | a:active { outline: 0; }
27 | .clearfix {
28 | zoom: 1;
29 | }
30 | ul{list-style: none;}
31 | .clearfix:before,
32 | .clearfix:after {
33 | content: '';
34 | display: table;
35 | }
36 | .clearfix:after {
37 | clear: both;
38 | }
39 | em {
40 | font-style: normal;
41 | }
42 | input {
43 | outline: none;
44 | }
45 | input[type="text"],
46 | input[type="tel"] {
47 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
48 | user-select: text;
49 | }
50 | /* 去除iphone ipad 设备默认按钮样式 */
51 | input[type="button"], input[type="submit"], input[type="reset"] {
52 | //-webkit-appearance: none;
53 | border-radius: 0;
54 | }
55 | input::-webkit-outer-spin-button,
56 | input::-webkit-inner-spin-button {
57 | //-webkit-appearance: none !important;
58 | margin: 0;
59 | }
60 | input::-moz-placeholder, textarea::-moz-placeholder { color: #cccccc; }
61 | input:-ms-input-placeholder, textarea:-ms-input-placeholder { color: #cccccc; }
62 | input::-webkit-input-placeholder, textarea::-webkit-input-placeholder { color: #cccccc; }
63 | image[lazy=loading] {
64 | width: 40px;
65 | height: 300px;
66 | margin: auto;
67 | }
68 | /* 滚动槽 */
69 | ::-webkit-scrollbar {
70 | width: 0px;
71 | height: 0px;position:absolute;
72 | }
73 | ::-webkit-scrollbar-track {
74 | border-radius: 3px;
75 | background: rgba(0,0,0,0.0);
76 | }
77 | /* 滚动条滑块 */
78 | ::-webkit-scrollbar-thumb {
79 | border-radius: 3px;
80 | background: rgba(0,0,0,0);
81 | }
82 | @fontBase: 75;
83 | @import "../iconFont/iconfont.css";
84 |
--------------------------------------------------------------------------------
/src/components/textLink.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
67 |
68 |
84 |
85 |
--------------------------------------------------------------------------------
/src/viewComponents/textLink.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
66 |
67 |
85 |
86 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "CMSX",
3 | "version": "2.0.0",
4 | "description": "可视化拖拽",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "cross-env NODE_ENV=development webpack-dev-server --port 8080",
8 | "pre": "cross-env NODE_ENV=prefat webpack",
9 | "build": "cross-env NODE_ENV=production webpack",
10 | "lint": "eslint ."
11 | },
12 | "keywords": [
13 | "vuejs"
14 | ],
15 | "license": "MIT",
16 | "bugs": {},
17 | "devDependencies": {
18 | "babel-core": "^6.26.0",
19 | "babel-loader": "^7.1.2",
20 | "babel-plugin-component": "^1.1.1",
21 | "babel-plugin-import": "^1.7.0",
22 | "babel-plugin-module-resolver": "^3.0.0",
23 | "babel-plugin-syntax-dynamic-import": "^6.18.0",
24 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
25 | "babel-plugin-transform-runtime": "^6.23.0",
26 | "babel-preset-env": "^1.6.1",
27 | "bezier-easing": "^2.1.0",
28 | "clean-webpack-plugin": "^0.1.19",
29 | "cross-env": "^5.2.0",
30 | "css-loader": "^0.28.7",
31 | "eslint": "^4.10.0",
32 | "eslint-config-standard": "^10.2.1",
33 | "eslint-plugin-import": "^2.8.0",
34 | "eslint-plugin-node": "^5.2.1",
35 | "eslint-plugin-promise": "^3.6.0",
36 | "eslint-plugin-standard": "^3.0.1",
37 | "express": "^4.16.2",
38 | "file-loader": "^1.1.5",
39 | "html-webpack-plugin": "^2.30.1",
40 | "html-webpack-template": "^6.0.2",
41 | "postcss-cssnext": "^3.0.2",
42 | "postcss-fontpath": "^1.0.0",
43 | "postcss-import": "^11.0.0",
44 | "postcss-mixins": "^6.2.0",
45 | "style-loader": "^0.19.1",
46 | "url-loader": "^0.6.2",
47 | "vue-lazyload": "^1.2.6",
48 | "vue-loader": "^13.5.0",
49 | "vue-pop-colorpicker": "^1.0.2",
50 | "vue-style-loader": "^3.0.3",
51 | "vue-template-compiler": "^2.5.3",
52 | "webpack": "^3.8.1",
53 | "webpack-dev-server": "^2.9.4",
54 | "webpack-hot-middleware": "^2.20.0",
55 | "webpack-parallel-uglify-plugin": "^1.1.0"
56 | },
57 | "dependencies": {
58 | "axios": "^0.18.0",
59 | "babel-polyfill": "^6.26.0",
60 | "extract-text-webpack-plugin": "^3.0.2",
61 | "jquery": "^1.11.3",
62 | "element-ui": "^2.4.6",
63 | "less": "^3.0.4",
64 | "less-loader": "^4.1.0",
65 | "mint-ui": "^2.2.13",
66 | "vue": "^2.5.3",
67 | "vuedraggable": "^2.16.0",
68 | "vuex": "^3.0.1"
69 | },
70 | "eslintConfig": {
71 | "extends": [
72 | "standard"
73 | ]
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/viewComponents/swipeBanner.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{item.name}}
7 |
8 |
9 |
10 |
11 |
12 |
71 |
72 |
84 |
85 |
--------------------------------------------------------------------------------
/src/components/swipeBanner.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{item.name}}
6 |
7 |
8 |
9 |
10 |
79 |
80 |
92 |
93 |
--------------------------------------------------------------------------------
/src/components/TheSection.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
82 |
83 |
89 |
--------------------------------------------------------------------------------
/src/server/api.js:
--------------------------------------------------------------------------------
1 | import http from "./http";
2 | let NODE_ENV = process.env.NODE_ENV;
3 | // 其他接口请修改此配置
4 | let host_api = NODE_ENV !== "production" ? "//cms.kevin.com" : "";
5 |
6 | let api = {
7 | // createObject: "//easy-mock.com/mock/5b5ac6ca87a58d3c7572a60b/api/getConfig", // 根据模型id生成配置项
8 | // getPool: "//easy-mock.com/mock/5b5ac6ca87a58d3c7572a60b/api/getpool", // 池数据
9 | createObject: "/api/getConfig", // 根据模型id生成配置项
10 | getPool: "/api/getpool",
11 | savePage: host_api + "/app/gui/ajaxSavePage", // 保存草稿
12 | publish: host_api + "/app/gui/ajaxPublish", // 发布
13 | preview: host_api + "/app/gui/ajaxPreview", // 预览
14 | getCategory: host_api + "/common/cate/getCatesByFid", // 获取分类列表
15 | createTem: host_api + "/app/pagetemplate/create", // 创建页面模板
16 | getTemType: host_api + "/app/pagetemplate/getType", // 获取模板品类列表
17 | getAllList: host_api + "/app/pagetemplate/getAll", // 页面模板列表
18 | modelUse: host_api + "/app/pagetemplate/choose", // 使用模版
19 | modelDel: host_api + "/app/pagetemplate/delete" // 删除模版
20 | };
21 |
22 | /**
23 | * 获取组件默认配置
24 | * @param params
25 | * @returns {*}
26 | */
27 | export const getConfig = params => {
28 | return http.oGet(api.createObject, params);
29 | };
30 | /**
31 | * 获取池数据
32 | * @param params
33 | */
34 | export const poolList = params => {
35 | return http.jsonp(api.getPool, params);
36 | };
37 | /**
38 | * 保存草稿
39 | * @param params
40 | * @returns {AxiosPromise}
41 | */
42 | export const savePage = params => {
43 | return http.post(api.savePage, params);
44 | };
45 | /**
46 | * 发布页面
47 | * @param params
48 | * @returns {AxiosPromise}
49 | */
50 | export const publish = params => {
51 | return http.post(api.publish, params);
52 | };
53 | /**
54 | * 预览
55 | * @param params
56 | * @returns {AxiosPromise}
57 | */
58 | export const preview = params => {
59 | return http.post(api.preview, params);
60 | };
61 | /**
62 | * 获取类目
63 | * @param params
64 | */
65 | export const getCategory = params => {
66 | return http.oGet(api.getCategory, params);
67 | };
68 | /**
69 | * 创建模版
70 | * @param params
71 | */
72 | export const createTem = params => {
73 | return http.post(api.createTem, params);
74 | };
75 | /**
76 | * 获取类型
77 | * @param params
78 | */
79 | export const getTemType = params => {
80 | return http.oGet(api.getTemType, params);
81 | };
82 | /**
83 | * 页面模版列表
84 | * @param params
85 | */
86 | export const getAllList = params => {
87 | return http.oGet(api.getAllList, params);
88 | };
89 | /**
90 | * 使用模版
91 | * @param params
92 | * @returns {AxiosPromise}
93 | */
94 | export const modelUse = params => {
95 | return http.post(api.modelUse, params);
96 | };
97 | export const modelDel = params => {
98 | return http.post(api.modelDel, params);
99 | };
100 |
--------------------------------------------------------------------------------
/src/viewComponents/scrollActive.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
54 |
55 |
86 |
--------------------------------------------------------------------------------
/src/server/http.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import {Toast} from 'mint-ui'
3 | //http.js
4 | //设置请求baseURL
5 | // axios.defaults.baseURL = '/app'
6 | //设置默认请求头
7 | axios.defaults.headers = {
8 | "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
9 | 'Accept': 'application/json',
10 | }
11 | axios.defaults.timeout = 10000
12 | axios.defaults.withCredentials=true
13 | //添加请求拦截器
14 | axios.interceptors.request.use(config => {
15 | //在发送请求之前做某事,比如说 设置loading动画显示
16 | const { url } = config
17 | config.url = url + ".json"
18 | if(config.data&&!config.data.cancelLoad){
19 | $('#loading').show()
20 | }
21 | return config
22 | }, error => {
23 | //请求错误时做些事
24 | return Promise.reject(error)
25 | })
26 |
27 | //添加响应拦截器
28 | axios.interceptors.response.use(res => {
29 | //对响应数据做些事,比如说把loading动画关掉
30 | $('#loading').hide()
31 | if (res.status && res.status != 200) {
32 | Toast("接口错误");
33 | return;
34 | }
35 | return res.data
36 | }, error => {
37 | //请求错误时做些事
38 | console.log(error)
39 | $('#loading').hide()
40 | if (error.response&&(error.response.status == 504||error.response.status == 404)) {
41 | Toast('服务器被吃了⊙﹏⊙∥');
42 | } else {
43 | Toast(error);
44 | }
45 | return Promise.reject(error)
46 | })
47 |
48 | //如果不想要这个拦截器也简单,可以删除拦截器
49 | //axios.interceptors.request.eject(myInterceptor)
50 | // POST发送请求前处理入参的数据为:formData 形式
51 | axios.defaults.transformRequest = [function (data) {
52 | let newData = ''
53 | for (let k in data) {
54 | newData += encodeURIComponent(k) + '=' + encodeURIComponent(data[k]) + '&'
55 | }
56 | return newData
57 | }]
58 | axios.jsonp=(url,params)=>{
59 | // 判断url是否存在以及是否为字符串
60 | if(!url || typeof url !== 'string') throw new Error('必须传入字符串类型的url地址');
61 | let param=function(data){
62 | let url = ''
63 | for (var k in data) {
64 | let value = data[k] !== undefined ? data[k] : ''
65 | url += '&' + k + '=' + encodeURIComponent(value)
66 | }
67 | return url ? url.substring(1) : ''
68 | };
69 | url += (url.indexOf('?') < 0 ? '?' : '&') + param(params)
70 | return new Promise((resolve,reject) => {
71 | // 处理返回的结果
72 | var oDate=new Date().getTime();
73 | window['jsonCallBack'+oDate]= (result) => {
74 | resolve(result)
75 | }
76 | // 在页面创建script标签,并将src设置为请求地址,取回数据之后移除script标签
77 | let JSONP = document.createElement("script");
78 | JSONP.type = "text/javascript";
79 | JSONP.src = `${url}&callback=jsonCallBack${oDate}`;
80 | document.getElementsByTagName("head")[0].appendChild(JSONP);
81 | setTimeout(() => {
82 | document.getElementsByTagName("head")[0].removeChild(JSONP)
83 | },500)
84 | })
85 | }
86 | axios.oGet=(url,params)=>{
87 | // return axios.get(url,{"params":params})
88 | // if(process.env.NODE_ENV!=="production"){
89 | // return axios.jsonp(url+'?format=jsonp',params)
90 | // }else{
91 | return axios.get(url,{"params":params})
92 | // }
93 | }
94 | //导出使用
95 | export default axios
96 |
--------------------------------------------------------------------------------
/src/components/brandList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
85 |
86 |
115 |
116 |
--------------------------------------------------------------------------------
/src/components/ordinaryProduct.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 | {{item.name}}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
61 |
62 |
101 |
102 |
--------------------------------------------------------------------------------
/src/viewComponents/brandList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
92 |
93 |
122 |
123 |
--------------------------------------------------------------------------------
/src/widgets/widgetTree.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 2018/5/16
3 | * Created by kevin
4 | */
5 | // 线上
6 | let pro=[{
7 | text:"页面楼层",
8 | icon: 'icon-yemianlouceng',
9 | attrId:1,
10 | list:[{
11 | name: '楼层容器',
12 | icon: 'icon-loucengrongqi',
13 | model_id: 2,
14 | w:'floor',
15 | placeholder: {
16 | type: 'the-section',
17 | children: []
18 | }
19 | }]
20 | },{
21 | text:"布局容器",
22 | icon:'icon-bujurongqi',
23 | attrId:1,
24 | list:[{
25 | name: "文字title",
26 | icon: 'icon-dingbugudingdaohang',
27 | model_id: 3,
28 | placeholder: {
29 | type: 'text-title'
30 | }
31 | },{
32 | name: "图片title",
33 | icon: 'icon-dingbugudingdaohang',
34 | model_id: 4,
35 | placeholder: {
36 | type: 'img-title'
37 | }
38 | }]
39 | },{
40 | text:"导航类",
41 | icon:'icon-daohang',
42 | attrId:1,
43 | list:[{
44 | name: "header组件",
45 | icon: 'icon-dingbugudingdaohang',
46 | model_id: 5,
47 | placeholder: {
48 | type: 'header-component'
49 | }
50 | }]
51 | },{
52 | text:"图文广告",
53 | icon:'icon-tuwen',
54 | attrId:1,
55 | list:[{
56 | name: '通栏广告',
57 | icon: 'icon-tonglanguanggao',
58 | model_id: 8,
59 | placeholder: {
60 | type: 'pass-banner',
61 | }
62 | },{
63 | name: '品牌列表',
64 | icon: 'icon-pinpailiebiao',
65 | isClose:false,
66 | model_id: 14,
67 | placeholder: {
68 | type: 'brand-list',
69 | }
70 | }]
71 | },{
72 | text:"商品类",
73 | icon:'icon-shangpin',
74 | attrId:1,
75 | list:[{
76 | name: '普通商品',
77 | icon: 'icon-shangpin',
78 | model_id: 6,
79 | placeholder: {
80 | type: 'ordinary-product'
81 | }
82 | }]
83 | },{
84 | text:"活动类",
85 | icon:'icon-huodong',
86 | attrId:1,
87 | list:[]
88 | },{
89 | text:"基本类",
90 | icon:'icon-tongyonglei',
91 | attrId:1,
92 | list:[{
93 | name: '图片热区',
94 | icon: 'icon-tupianrequ',
95 | model_id: 7,
96 | placeholder: {
97 | type: 'hot-image',
98 | }
99 | },{
100 | name: '轮播图',
101 | icon: 'icon-lunboyangshi',
102 | model_id: 9,
103 | placeholder: {
104 | type: 'swipe-banner',
105 | }
106 | },{
107 | name: "楼层锚点",
108 | icon: 'icon-loucengmaodian',
109 | model_id: 10,
110 | w:'floor',
111 | placeholder: {
112 | type: 'scroll-active',
113 | saveConfig:[]
114 | }
115 | }]
116 | },{
117 | text:"其他类",
118 | icon: 'icon-qita',
119 | attrId:1,
120 | list:[{
121 | name: "文字链",
122 | icon: 'icon-wenzilian',
123 | model_id: 12,
124 | isClose: false,//提示暂未开发
125 | placeholder: {
126 | type: 'text-link',
127 | saveConfig:[]
128 | }
129 | },{
130 | name: "启动动效",
131 | icon: 'icon-qidongdongxiao',
132 | model_id: 13,
133 | isClose:false,// 提示暂未开发
134 | w: 'floor', // 配置floor后可拖拽至楼层级别
135 | placeholder: {
136 | type: 'start-effect',
137 | saveConfig:[]
138 | }
139 | }]
140 | },{
141 | text:"楼层导航",
142 | icon: 'icon-qita',
143 | attrId:2
144 | }]
145 | let tabTree;
146 | console.log(process.env.NODE_ENV)
147 | /*if(process.env.NODE_ENV=="development"){
148 | tabTree=dev
149 | }else if(process.env.NODE_ENV=="prefat"){
150 | tabTree=pre
151 | }else{
152 | tabTree=pro
153 | }*/
154 | //直接生产cmsx建模型
155 | export default pro
156 |
--------------------------------------------------------------------------------
/src/viewComponents/ordinaryProduct.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 | {{item.name}}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
65 |
66 |
105 |
106 |
--------------------------------------------------------------------------------
/assets/iconfont.css:
--------------------------------------------------------------------------------
1 |
2 | @font-face {font-family: "iconfont";
3 | src: url('iconfont.eot?t=1510759602811'); /* IE9*/
4 | src: url('iconfont.eot?t=1510759602811#iefix') format('embedded-opentype'), /* IE6-IE8 */
5 | url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
6 | url('iconfont.ttf?t=1510759602811') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
7 | url('iconfont.svg?t=1510759602811#iconfont') format('svg'); /* iOS 4.1- */
8 | }
9 |
10 | .iconfont {
11 | font-family:"iconfont" !important;
12 | font-size:16px;
13 | font-style:normal;
14 | -webkit-font-smoothing: antialiased;
15 | -moz-osx-font-smoothing: grayscale;
16 | }
17 |
18 | .icon-lego:before { content: "\e639"; }
19 |
20 | .icon-legoblock:before { content: "\e847"; }
21 |
22 | .icon-page1:before { content: "\e613"; }
23 |
24 | .icon-Lego:before { content: "\ea10"; }
25 |
26 | .icon-Lego1:before { content: "\ec93"; }
27 |
28 |
--------------------------------------------------------------------------------
/src/store.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 |
4 | import oneSite from './widgets/siteTree'
5 | import tabTree from './widgets/widgetTree'
6 | const htmlCon = window.htmlConfig
7 | import { getQueryUrl } from '~/widgets/util'
8 | import {getConfig} from './server/api'
9 | Vue.use(Vuex)
10 | const store = new Vuex.Store({
11 | state: {
12 | pid: 1000,
13 | configShow:false,
14 | page_id: getQueryUrl('page_id'),
15 | htmlCon,
16 | currentConfig:null,
17 | site: oneSite,
18 | tabTree:tabTree,
19 | widgets: []
20 | },
21 |
22 | mutations: {
23 | assignState (state, obj) {
24 | Object.assign(state, obj)
25 | },
26 | setWidget({widgets},arr){
27 | // widgets.length=0;
28 | widgets.splice(0,widgets.length)
29 | arr.map(item=>{widgets.push(item)});
30 | },
31 | sortWidget (state, { array, oldIndex, newIndex }) {
32 | console.log("storeSort")
33 | let target = array[oldIndex]
34 | array.splice(oldIndex, 1)
35 | array.splice(newIndex, 0, target)
36 | },
37 | copyWidget (state,{array, oldIndex, newIndex}){
38 | console.log("copyEl",oldIndex,newIndex)
39 | store.commit('incrementGid')
40 | //let el=array[oldIndex] 浅拷贝有问题
41 | let el= JSON.parse(JSON.stringify(array[oldIndex]));
42 | el.id=state.pid;
43 | array.splice(-1,0,el)
44 | // store.commit('setConfig',{oldIndex:newIndex,currDom:el})
45 | },
46 | addWidget ({widgets, pid, site}, { section, widgetType, newIndex, config }) {
47 | console.log("addWidget:"+newIndex);
48 | const widget = widgets.find(widget => widget.placeholder.type === widgetType);
49 | let styl={},other={};
50 | config&&(config.map(item=>{
51 | if(item.remark === 'css'){
52 | styl[item.name] = item.default_val
53 | }else{
54 | other[item.name] = item.default_val
55 | }
56 | }))
57 | // store.commit('incrementGid')
58 | let obj={ ...widget.placeholder, config,styl,other, id: pid ,name:widget.name}
59 | if (widget.w=='floor') {
60 | // section.splice(newIndex,1);
61 | section.splice(newIndex, 0, obj)
62 | section[newIndex].children = []
63 | store.commit('setConfig',{oldIndex:newIndex,currDom:site})
64 | return false
65 | }
66 | section.splice(newIndex,0,obj);
67 | },
68 | delCurrDom ({site}, {section, oldIndex}) {
69 | store.commit('setConfig', { oldIndex: -1, currDom: {} })
70 | section.splice(oldIndex, 1)
71 | store.commit('changeShow',false)
72 | },
73 | setConfig (stat, {oldIndex, currDom}) {
74 | console.log("setConfig")
75 | stat.currentConfig = null
76 | oldIndex >= 0 && (currDom.index = oldIndex)
77 | stat.currentConfig = {...currDom}
78 | console.log({...currDom})
79 | store.commit('changeShow',true)
80 | console.log(currDom)
81 | },
82 | changeShow(sta,val){
83 | console.log("show")
84 | sta.configShow=val
85 | },
86 | incrementGid (state) {
87 | console.log("addPid")
88 | state.pid++;
89 | }
90 | },
91 | actions: {
92 | async getSite ({ commit }) {
93 | const site =await window.config&&window.config.type?window.config:oneSite
94 | commit('assignState', { site })
95 | // commit('assignState', { currentPage: site.children[0] })
96 | },
97 | setSite({commit},site){
98 | commit('assignState',{site})
99 | },
100 | getDefaultConfig({commit},{section,widgetType,newIndex,model_id}){
101 | getConfig({"model_id":model_id}).then(res=>{
102 | commit('addWidget',{section,widgetType,newIndex,config:res.data['props']})
103 | })
104 | }
105 | }
106 | })
107 |
108 | export default store
109 |
--------------------------------------------------------------------------------
/src/viewComponents/startEffect.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 跳转{{mTime}}秒
6 |
7 |
8 | 跳转{{mTime}}秒
9 |
10 |
11 | {{mTime}}秒
12 |
13 |
![]()
14 |
15 |
16 |
17 |
18 |
85 |
86 |
141 |
142 |
--------------------------------------------------------------------------------
/src/components/startEffect.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 跳转{{mTime}}秒
6 |
7 |
8 | 跳转{{mTime}}秒
9 |
10 |
11 | {{mTime}}秒
12 |
13 |
![]()
14 |
15 |
16 |
17 |
18 |
83 |
84 |
139 |
140 |
--------------------------------------------------------------------------------
/src/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

加载中……
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
105 |
106 |
155 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const webpack = require('webpack')
3 | const HtmlWebpackPlugin = require('html-webpack-plugin')
4 | // 引包:删除(旧的打包文件)dist目录
5 | const CleanWebpackPlugin = require('clean-webpack-plugin')
6 | var config = require('./config.json')
7 | let isDev = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'prefat' ? 'dev' : 'pro'
8 | let proPlugins = []
9 | if (isDev !== 'dev') {
10 | proPlugins.push(
11 | new webpack.optimize.UglifyJsPlugin({
12 | // 最紧凑的输出
13 | beautify: false,
14 | // 删除所有的注释
15 | comments: false,
16 | compress: {
17 | // 在UglifyJs删除没有用到的代码时不输出警告
18 | warnings: false,
19 | // 删除所有的 `console` 语句
20 | // 还可以兼容ie浏览器
21 | drop_console: true,
22 | // 内嵌定义了但是只用到一次的变量
23 | collapse_vars: true,
24 | // 提取出出现多次但是没有定义成变量去引用的静态值
25 | reduce_vars: true
26 | }
27 | }),
28 | new CleanWebpackPlugin(path.resolve('./dist/', config.version))// build命令清空dist下配置的当前版本文件
29 | )
30 | }
31 | module.exports = {
32 | entry: {
33 | vendor: ["vue", "vuex", "vuedraggable", "mint-ui", "element-ui", "axios"],
34 | build: ["babel-polyfill", path.resolve(__dirname, "./src/edit.js")],
35 | view: [path.resolve(__dirname, "./src/view.js")]
36 | },
37 | output: {
38 | path: path.resolve("./dist/", config.version),
39 | filename: "[name].js",
40 | chunkFilename: "chunk[id].js?[chunkhash]",
41 | publicPath: "/"
42 | },
43 | devtool: "inline-source-map",
44 | devServer: {
45 | host: "0.0.0.0",
46 | port: 8080,
47 | https: false,
48 | hotOnly: true,
49 | disableHostCheck: true,
50 | proxy: {
51 | "/api": {
52 | target: "http://localhost:8080",
53 | changeOrigin: true,
54 | pathRewrite: {
55 | "^/api": "/mock"
56 | }
57 | }
58 | },
59 | // contentBase: "./dist",
60 | compress: true,
61 | hot: true,
62 | disableHostCheck: true,
63 | inline: true
64 | },
65 | plugins: [
66 | new webpack.optimize.CommonsChunkPlugin("vendor"),
67 | new HtmlWebpackPlugin({
68 | filename: "edit.html",
69 | inject: "body",
70 | template: "./src/tpl/edit.html",
71 | title: "cmsx",
72 | appMountId: "app",
73 | excludeChunks: ["view"],
74 | chunksSortMode: function(chunk1, chunk2) {
75 | var order = ["vendor", "build"];
76 | var order1 = order.indexOf(chunk1.names[0]);
77 | var order2 = order.indexOf(chunk2.names[0]);
78 | return order1 - order2;
79 | },
80 | minify: {
81 | // 打包后压缩
82 | removeComments: true, // 打包后删除注释
83 | collapseWhitespace: true // 打包后删除空格
84 | },
85 | mobile: true
86 | }),
87 | new HtmlWebpackPlugin({
88 | filename: "view.html",
89 | inject: "body",
90 | template: "./src/tpl/view.html",
91 | title: "cmsx",
92 | appMountId: "app",
93 | excludeChunks: ["build"],
94 | chunksSortMode: function(chunk1, chunk2) {
95 | var order = ["vendor", "view"];
96 | var order1 = order.indexOf(chunk1.names[0]);
97 | var order2 = order.indexOf(chunk2.names[0]);
98 | return order1 - order2;
99 | },
100 | minify: {
101 | // 打包后压缩
102 | removeComments: true, // 打包后删除注释
103 | collapseWhitespace: true // 打包后删除空格
104 | },
105 | mobile: true
106 | }),
107 | new webpack.DefinePlugin({
108 | "process.env": {
109 | NODE_ENV: JSON.stringify(process.env.NODE_ENV)
110 | }
111 | }),
112 | ...proPlugins,
113 | new webpack.NamedModulesPlugin(),
114 | new webpack.HotModuleReplacementPlugin()
115 | ],
116 | module: {
117 | rules: [
118 | {
119 | test: /\.vue$/,
120 | loader: "vue-loader",
121 | options: {
122 | postcss: [require("postcss-cssnext")()]
123 | }
124 | },
125 | {
126 | test: /\.js$/,
127 | loader: "babel-loader",
128 | exclude: /node_modules/
129 | },
130 | {
131 | test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/,
132 | loader: "url-loader",
133 | options: {
134 | limit: 10000
135 | }
136 | },
137 | {
138 | test: /\.less$/,
139 | use: ["style-loader", "css-loader", "less-loader"],
140 | exclude: /node_modules/
141 | },
142 | {
143 | test: /\.css$/,
144 | loader: [
145 | "vue-style-loader",
146 | "style-loader",
147 | "css-loader",
148 | "less-loader"
149 | ]
150 | },
151 | {
152 | // 图片加载器,雷同file-loader,更适合图片,可以将较小的图片转成base64,减少http请求
153 | // 如下配置,将小于8192byte的图片转成base64码
154 | test: /\.(png|jpg|gif)$/,
155 | loader: "url-loader?limit=8192&name=[name].[ext]?[hash]"
156 | }
157 | ]
158 | },
159 | resolve: {
160 | extensions: [".js", ".vue"],
161 | alias: {
162 | "~": path.resolve(__dirname, "./src")
163 | }
164 | }
165 | };
166 |
--------------------------------------------------------------------------------
/src/components/hotImage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 | {{index}}
6 |
7 |
编辑
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | 新增热区
19 |
20 |
24 |
25 |
26 |
27 |
28 |
140 |
141 |
157 |
--------------------------------------------------------------------------------
/src/components/scrollActive.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 | 编辑
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | +锚点
23 |
24 |
28 |
29 |
30 |
31 |
32 |
117 |
118 |
150 |
--------------------------------------------------------------------------------
/src/layout/leftModel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 组件库
5 |
6 |
7 |
26 |
27 |
28 |
29 |
30 |
100 |
101 |
170 |
--------------------------------------------------------------------------------
/src/assets/iconFont/demo.css:
--------------------------------------------------------------------------------
1 | *{margin: 0;padding: 0;list-style: none;}
2 | /*
3 | KISSY CSS Reset
4 | 理念:1. reset 的目的不是清除浏览器的默认样式,这仅是部分工作。清除和重置是紧密不可分的。
5 | 2. reset 的目的不是让默认样式在所有浏览器下一致,而是减少默认样式有可能带来的问题。
6 | 3. reset 期望提供一套普适通用的基础样式。但没有银弹,推荐根据具体需求,裁剪和修改后再使用。
7 | 特色:1. 适应中文;2. 基于最新主流浏览器。
8 | 维护:玉伯, 正淳
9 | */
10 |
11 | /** 清除内外边距 **/
12 | body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */
13 | dl, dt, dd, ul, ol, li, /* list elements 列表元素 */
14 | pre, /* text formatting elements 文本格式元素 */
15 | form, fieldset, legend, button, input, textarea, /* form elements 表单元素 */
16 | th, td /* table elements 表格元素 */ {
17 | margin: 0;
18 | padding: 0;
19 | }
20 |
21 | /** 设置默认字体 **/
22 | body,
23 | button, input, select, textarea /* for ie */ {
24 | font: 12px/1.5 tahoma, arial, \5b8b\4f53, sans-serif;
25 | }
26 | h1, h2, h3, h4, h5, h6 { font-size: 100%; }
27 | address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */
28 | code, kbd, pre, samp { font-family: courier new, courier, monospace; } /* 统一等宽字体 */
29 | small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */
30 |
31 | /** 重置列表元素 **/
32 | ul, ol { list-style: none; }
33 |
34 | /** 重置文本格式元素 **/
35 | a { text-decoration: none; }
36 | a:hover { text-decoration: underline; }
37 |
38 |
39 | /** 重置表单元素 **/
40 | legend { color: #000; } /* for ie6 */
41 | fieldset, img { border: 0; } /* img 搭车:让链接里的 img 无边框 */
42 | button, input, select, textarea { font-size: 100%; } /* 使得表单元素在 ie 下能继承字体大小 */
43 | /* 注:optgroup 无法扶正 */
44 |
45 | /** 重置表格元素 **/
46 | table { border-collapse: collapse; border-spacing: 0; }
47 |
48 | /* 清除浮动 */
49 | .ks-clear:after, .clear:after {
50 | content: '\20';
51 | display: block;
52 | height: 0;
53 | clear: both;
54 | }
55 | .ks-clear, .clear {
56 | *zoom: 1;
57 | }
58 |
59 | .main {
60 | padding: 30px 100px;
61 | width: 960px;
62 | margin: 0 auto;
63 | }
64 | .main h1{font-size:36px; color:#333; text-align:left;margin-bottom:30px; border-bottom: 1px solid #eee;}
65 |
66 | .helps{margin-top:40px;}
67 | .helps pre{
68 | padding:20px;
69 | margin:10px 0;
70 | border:solid 1px #e7e1cd;
71 | background-color: #fffdef;
72 | overflow: auto;
73 | }
74 |
75 | .icon_lists{
76 | width: 100% !important;
77 |
78 | }
79 |
80 | .icon_lists li{
81 | float:left;
82 | width: 100px;
83 | height:180px;
84 | text-align: center;
85 | list-style: none !important;
86 | }
87 | .icon_lists .icon{
88 | font-size: 42px;
89 | line-height: 100px;
90 | margin: 10px 0;
91 | color:#333;
92 | -webkit-transition: font-size 0.25s ease-out 0s;
93 | -moz-transition: font-size 0.25s ease-out 0s;
94 | transition: font-size 0.25s ease-out 0s;
95 |
96 | }
97 | .icon_lists .icon:hover{
98 | font-size: 100px;
99 | }
100 |
101 |
102 |
103 | .markdown {
104 | color: #666;
105 | font-size: 14px;
106 | line-height: 1.8;
107 | }
108 |
109 | .highlight {
110 | line-height: 1.5;
111 | }
112 |
113 | .markdown img {
114 | vertical-align: middle;
115 | max-width: 100%;
116 | }
117 |
118 | .markdown h1 {
119 | color: #404040;
120 | font-weight: 500;
121 | line-height: 40px;
122 | margin-bottom: 24px;
123 | }
124 |
125 | .markdown h2,
126 | .markdown h3,
127 | .markdown h4,
128 | .markdown h5,
129 | .markdown h6 {
130 | color: #404040;
131 | margin: 1.6em 0 0.6em 0;
132 | font-weight: 500;
133 | clear: both;
134 | }
135 |
136 | .markdown h1 {
137 | font-size: 28px;
138 | }
139 |
140 | .markdown h2 {
141 | font-size: 22px;
142 | }
143 |
144 | .markdown h3 {
145 | font-size: 16px;
146 | }
147 |
148 | .markdown h4 {
149 | font-size: 14px;
150 | }
151 |
152 | .markdown h5 {
153 | font-size: 12px;
154 | }
155 |
156 | .markdown h6 {
157 | font-size: 12px;
158 | }
159 |
160 | .markdown hr {
161 | height: 1px;
162 | border: 0;
163 | background: #e9e9e9;
164 | margin: 16px 0;
165 | clear: both;
166 | }
167 |
168 | .markdown p,
169 | .markdown pre {
170 | margin: 1em 0;
171 | }
172 |
173 | .markdown > p,
174 | .markdown > blockquote,
175 | .markdown > .highlight,
176 | .markdown > ol,
177 | .markdown > ul {
178 | width: 80%;
179 | }
180 |
181 | .markdown ul > li {
182 | list-style: circle;
183 | }
184 |
185 | .markdown > ul li,
186 | .markdown blockquote ul > li {
187 | margin-left: 20px;
188 | padding-left: 4px;
189 | }
190 |
191 | .markdown > ul li p,
192 | .markdown > ol li p {
193 | margin: 0.6em 0;
194 | }
195 |
196 | .markdown ol > li {
197 | list-style: decimal;
198 | }
199 |
200 | .markdown > ol li,
201 | .markdown blockquote ol > li {
202 | margin-left: 20px;
203 | padding-left: 4px;
204 | }
205 |
206 | .markdown code {
207 | margin: 0 3px;
208 | padding: 0 5px;
209 | background: #eee;
210 | border-radius: 3px;
211 | }
212 |
213 | .markdown pre {
214 | border-radius: 6px;
215 | background: #f7f7f7;
216 | padding: 20px;
217 | }
218 |
219 | .markdown pre code {
220 | border: none;
221 | background: #f7f7f7;
222 | margin: 0;
223 | }
224 |
225 | .markdown strong,
226 | .markdown b {
227 | font-weight: 600;
228 | }
229 |
230 | .markdown > table {
231 | border-collapse: collapse;
232 | border-spacing: 0px;
233 | empty-cells: show;
234 | border: 1px solid #e9e9e9;
235 | width: 95%;
236 | margin-bottom: 24px;
237 | }
238 |
239 | .markdown > table th {
240 | white-space: nowrap;
241 | color: #333;
242 | font-weight: 600;
243 |
244 | }
245 |
246 | .markdown > table th,
247 | .markdown > table td {
248 | border: 1px solid #e9e9e9;
249 | padding: 8px 16px;
250 | text-align: left;
251 | }
252 |
253 | .markdown > table th {
254 | background: #F7F7F7;
255 | }
256 |
257 | .markdown blockquote {
258 | font-size: 90%;
259 | color: #999;
260 | border-left: 4px solid #e9e9e9;
261 | padding-left: 0.8em;
262 | margin: 1em 0;
263 | font-style: italic;
264 | }
265 |
266 | .markdown blockquote p {
267 | margin: 0;
268 | }
269 |
270 | .markdown .anchor {
271 | opacity: 0;
272 | transition: opacity 0.3s ease;
273 | margin-left: 8px;
274 | }
275 |
276 | .markdown .waiting {
277 | color: #ccc;
278 | }
279 |
280 | .markdown h1:hover .anchor,
281 | .markdown h2:hover .anchor,
282 | .markdown h3:hover .anchor,
283 | .markdown h4:hover .anchor,
284 | .markdown h5:hover .anchor,
285 | .markdown h6:hover .anchor {
286 | opacity: 1;
287 | display: inline-block;
288 | }
289 |
290 | .markdown > br,
291 | .markdown > p > br {
292 | clear: both;
293 | }
294 |
295 |
296 | .hljs {
297 | display: block;
298 | background: white;
299 | padding: 0.5em;
300 | color: #333333;
301 | overflow-x: auto;
302 | }
303 |
304 | .hljs-comment,
305 | .hljs-meta {
306 | color: #969896;
307 | }
308 |
309 | .hljs-string,
310 | .hljs-variable,
311 | .hljs-template-variable,
312 | .hljs-strong,
313 | .hljs-emphasis,
314 | .hljs-quote {
315 | color: #df5000;
316 | }
317 |
318 | .hljs-keyword,
319 | .hljs-selector-tag,
320 | .hljs-type {
321 | color: #a71d5d;
322 | }
323 |
324 | .hljs-literal,
325 | .hljs-symbol,
326 | .hljs-bullet,
327 | .hljs-attribute {
328 | color: #0086b3;
329 | }
330 |
331 | .hljs-section,
332 | .hljs-name {
333 | color: #63a35c;
334 | }
335 |
336 | .hljs-tag {
337 | color: #333333;
338 | }
339 |
340 | .hljs-title,
341 | .hljs-attr,
342 | .hljs-selector-id,
343 | .hljs-selector-class,
344 | .hljs-selector-attr,
345 | .hljs-selector-pseudo {
346 | color: #795da3;
347 | }
348 |
349 | .hljs-addition {
350 | color: #55a532;
351 | background-color: #eaffea;
352 | }
353 |
354 | .hljs-deletion {
355 | color: #bd2c00;
356 | background-color: #ffecec;
357 | }
358 |
359 | .hljs-link {
360 | text-decoration: underline;
361 | }
362 |
363 | pre{
364 | background: #fff;
365 | }
366 |
367 |
368 |
369 |
370 |
371 |
--------------------------------------------------------------------------------
/src/common/scroll.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
236 |
242 |
--------------------------------------------------------------------------------
/src/assets/iconFont/demo_fontclass.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | IconFont
7 |
8 |
9 |
10 |
11 |
12 |
IconFont 图标
13 |
238 |
239 |
font-class引用
240 |
241 |
242 |
font-class是unicode使用方式的一种变种,主要是解决unicode书写不直观,语意不明确的问题。
243 |
与unicode使用方式相比,具有如下特点:
244 |
245 | - 兼容性良好,支持ie8+,及所有现代浏览器。
246 | - 相比于unicode语意明确,书写更直观。可以很容易分辨这个icon是什么。
247 | - 因为使用class来定义图标,所以当要替换图标时,只需要修改class里面的unicode引用。
248 | - 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
249 |
250 |
使用步骤如下:
251 |
第一步:引入项目下面生成的fontclass代码:
252 |
253 |
254 |
255 |
第二步:挑选相应图标并获取类名,应用于页面:
256 |
<i class="iconfont icon-xxx"></i>
257 |
258 | "iconfont"是你项目下的font-family。可以通过编辑项目查看,默认是"iconfont"。
259 |
260 |
261 |
262 |
263 |
--------------------------------------------------------------------------------
/src/assets/iconFont/iconfont.css:
--------------------------------------------------------------------------------
1 |
2 | @font-face {font-family: "iconfont";
3 | src: url('iconfont.eot?t=1534755961395'); /* IE9*/
4 | src: url('iconfont.eot?t=1534755961395#iefix') format('embedded-opentype'), /* IE6-IE8 */
5 | url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
6 | url('iconfont.ttf?t=1534755961395') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
7 | url('iconfont.svg?t=1534755961395#iconfont') format('svg'); /* iOS 4.1- */
8 | }
9 |
10 | .iconfont {
11 | font-family:"iconfont" !important;
12 | font-size:16px;
13 | font-style:normal;
14 | -webkit-font-smoothing: antialiased;
15 | -moz-osx-font-smoothing: grayscale;
16 | }
17 |
18 | .icon-gouwuche:before { content: "\e64c"; }
19 |
20 | .icon-duigou:before { content: "\e632"; }
21 |
22 | .icon-shezhi:before { content: "\e64b"; }
23 |
24 | .icon-tanhao:before { content: "\e793"; }
25 |
26 | .icon-search:before { content: "\e6a4"; }
27 |
28 | .icon-wenhao:before { content: "\e630"; }
29 |
30 | .icon-dingbugudingdaohang:before { content: "\e602"; }
31 |
32 | .icon-bujurongqi:before { content: "\e603"; }
33 |
34 | .icon-baocun:before { content: "\e604"; }
35 |
36 | .icon-daohang:before { content: "\e605"; }
37 |
38 | .icon-buyulan:before { content: "\e606"; }
39 |
40 | .icon-fuzhi:before { content: "\e607"; }
41 |
42 | .icon-huodong:before { content: "\e608"; }
43 |
44 | .icon-putongshangpin:before { content: "\e609"; }
45 |
46 | .icon-qidongdongxiao:before { content: "\e60a"; }
47 |
48 | .icon-shanchu:before { content: "\e60b"; }
49 |
50 | .icon-qita:before { content: "\e60c"; }
51 |
52 | .icon-jiben:before { content: "\e60d"; }
53 |
54 | .icon-shangpin:before { content: "\e60e"; }
55 |
56 | .icon-shangyi:before { content: "\e60f"; }
57 |
58 | .icon-tongyonglei:before { content: "\e610"; }
59 |
60 | .icon-toupiaolei:before { content: "\e611"; }
61 |
62 | .icon-loucengrongqi:before { content: "\e612"; }
63 |
64 | .icon-xiayi:before { content: "\e613"; }
65 |
66 | .icon-tuwen:before { content: "\e614"; }
67 |
68 | .icon-zhankai:before { content: "\e615"; }
69 |
70 | .icon-yemianlouceng:before { content: "\e616"; }
71 |
72 | .icon-yulan:before { content: "\e617"; }
73 |
74 | .icon-tosatcuowu:before { content: "\e618"; }
75 |
76 | .icon-daojishi:before { content: "\e619"; }
77 |
78 | .icon-loucengmaodian:before { content: "\e61a"; }
79 |
80 | .icon-qidongdongxiao1:before { content: "\e61b"; }
81 |
82 | .icon-tonglanguanggao:before { content: "\e61c"; }
83 |
84 | .icon-tupianrequ:before { content: "\e61d"; }
85 |
86 | .icon-lunboyangshi:before { content: "\e61e"; }
87 |
88 | .icon-pinpailiebiao:before { content: "\e61f"; }
89 |
90 | .icon-wenzilian:before { content: "\e620"; }
91 |
92 |
--------------------------------------------------------------------------------
/assets/iconfont.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
49 |
--------------------------------------------------------------------------------
/src/layout/configRight.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 | -
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
![]()
30 |
31 |
32 |
33 |
34 |
44 |
45 |
46 |
47 | 建议上传jpg/png文件,且不超过500kb;
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
58 |
59 |
60 |
61 |
62 |
63 | {{sItem.name}}
64 |
65 |
66 |
67 |
68 |
69 |
71 | {{check.name}}
72 |
73 |
74 |
75 |
76 |
77 |
78 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | 请将图片的宽与组件宽保持一致,才会正常展示哦!
91 |
92 |
93 |
94 |
95 | 请将图片的高与组件高保持一致,才会正常展示哦!
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
277 |
343 |
344 |
--------------------------------------------------------------------------------
/assets/iconfont.js:
--------------------------------------------------------------------------------
1 | (function(window){var svgSprite='';var script=function(){var scripts=document.getElementsByTagName("script");return scripts[scripts.length-1]}();var shouldInjectCss=script.getAttribute("data-injectcss");var ready=function(fn){if(document.addEventListener){if(~["complete","loaded","interactive"].indexOf(document.readyState)){setTimeout(fn,0)}else{var loadFn=function(){document.removeEventListener("DOMContentLoaded",loadFn,false);fn()};document.addEventListener("DOMContentLoaded",loadFn,false)}}else if(document.attachEvent){IEContentLoaded(window,fn)}function IEContentLoaded(w,fn){var d=w.document,done=false,init=function(){if(!done){done=true;fn()}};var polling=function(){try{d.documentElement.doScroll("left")}catch(e){setTimeout(polling,50);return}init()};polling();d.onreadystatechange=function(){if(d.readyState=="complete"){d.onreadystatechange=null;init()}}}};var before=function(el,target){target.parentNode.insertBefore(el,target)};var prepend=function(el,target){if(target.firstChild){before(el,target.firstChild)}else{target.appendChild(el)}};function appendSvg(){var div,svg;div=document.createElement("div");div.innerHTML=svgSprite;svgSprite=null;svg=div.getElementsByTagName("svg")[0];if(svg){svg.setAttribute("aria-hidden","true");svg.style.position="absolute";svg.style.width=0;svg.style.height=0;svg.style.overflow="hidden";prepend(svg,document.body)}}if(shouldInjectCss&&!window.__iconfont__svg__cssinject__){window.__iconfont__svg__cssinject__=true;try{document.write("")}catch(e){console&&console.log(e)}}ready(appendSvg)})(window)
--------------------------------------------------------------------------------
/src/common/hotDrag.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
312 |
313 |
411 |
--------------------------------------------------------------------------------