Parcourir la source

完成网站管理

YANGPENG il y a 3 ans
Parent
commit
d138afc44f

+ 1 - 1
_web/.env.development

@ -1,6 +1,6 @@
NODE_ENV=development
VUE_APP_PREVIEW=true
VUE_APP_API_BASE_URL=http://ehr.yihu.com/zjxltest
VUE_APP_API_BASE_URL=http://ehr.yihu.com/zjxl
VUE_APP_IMG_UPLOAD_URL=http://120.41.253.95:3000
VUE_APP_IMG_SERVICE_URL=http://172.26.0.110:8888/
assetsPublicPath='/zjxlBackstage'

+ 5 - 2
_web/src/core/lazy_lib/components_use.js

@ -8,6 +8,7 @@
import Vue from 'vue'
import {
  ConfigProvider,
  Cascader,
  Layout,
  Input,
  InputNumber,
@ -52,7 +53,8 @@ import {
  Empty,
  PageHeader,
  Descriptions,
  Result
  Result,
  pagination
} from 'ant-design-vue'
// import VueCropper from 'vue-cropper'
@ -69,6 +71,7 @@ Vue.use(Card)
Vue.use(Form)
Vue.use(Row)
Vue.use(Col)
Vue.use(Cascader)
Vue.use(Modal)
Vue.use(Table)
Vue.use(Tabs)
@ -93,7 +96,7 @@ Vue.use(Upload)
Vue.use(Progress)
Vue.use(Skeleton)
Vue.use(Popconfirm)
// Vue.use(VueCropper)
Vue.use(pagination)
Vue.use(notification)
Vue.use(TreeSelect)
Vue.use(Tree)

+ 3 - 0
_web/src/views/gwSystem/indexClassifyDict.vue

@ -115,6 +115,9 @@
        })
      }
    },
    mounted(){
        // console.log('this',this.typeList)
    },
    methods: {
      statusFilter (status) {
        const values = this.statusDictTypeDropDown.filter(item => item.code === status)

+ 267 - 0
_web/src/views/system/article/addForm.vue

@ -0,0 +1,267 @@
<template>
  <a-modal
    title="新增应用"
    :width="900"
    :visible="visible"
    :confirmLoading="confirmLoading"
    @ok="handleSubmit"
    @cancel="handleCancel"
  >
    <a-spin :spinning="confirmLoading">
      <a-form :form="form">
        <a-form-item
          label="所属菜单"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-cascader class="cascader" :options="options" placeholder="请选择" v-decorator="['name', {rules: [{required: true, message: '请选择所属菜单!'}]}]"/>
        </a-form-item>
        <a-form-item
          label="标题"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="请输入标题" v-decorator="['code', {rules: [{required: true, message: '请输入标题!'}]}]" />
        </a-form-item>
        <a-form-item label="发布时间"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback>
            <a-date-picker
                v-decorator="['date-time-picker']"
                show-time
                format="YYYY-MM-DD HH:mm:ss"
            />
        </a-form-item>
        <a-form-item
          label="简介"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="" />
        </a-form-item>
        <a-form-item
          label="封面"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-upload
            name="avatar"
            list-type="picture-card"
            class="avatar-uploader"
            :show-upload-list="false"
            action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
            :before-upload="beforeUpload"
            @change="handleChange"
          >
            <img v-if="imageUrl" :src="imageUrl" alt="avatar" />
            <div v-else>
            <a-icon :type="loading ? 'loading' : 'plus'" />
            </div>
          </a-upload>
        </a-form-item>
        <a-form-item
          label="视频"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-upload
            name="avatar"
            list-type="picture-card"
            class="avatar-uploader"
            :show-upload-list="false"
            action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
            :before-upload="beforeUpload"
            @change="handleChange"
          >
            <img v-if="imageUrl" :src="imageUrl" alt="avatar" />
            <div v-else>
            <a-icon :type="loading ? 'loading' : 'plus'" />
            </div>
          </a-upload>
        </a-form-item>
        <a-form-item
          label="内容"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <div ref="demo" style="height:500px">
              <p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
          </div>
        </a-form-item>
      </a-form>
      
    </a-spin>
  </a-modal>
</template>
<script>
    import { sysAppAdd } from '@/api/modular/system/appManage'
    import E from 'wangeditor'
    function getBase64(img, callback) {
        const reader = new FileReader();
        reader.addEventListener('load', () => callback(reader.result));
        reader.readAsDataURL(img);
    }
  export default {
    data () {
      return {
        labelCol: {
          xs: { span: 24 },
          sm: { span: 5 }
        },
        wrapperCol: {
          xs: { span: 24 },
          sm: { span: 15 }
        },
        visible: false,
        confirmLoading: false,
        form: this.$form.createForm(this),
        options: [
            {
                value: 'zhejiang',
                label: 'Zhejiang',
                children: [
                    {
                        value: 'hangzhou',
                        label: 'Hangzhou',
                        children: [
                            {
                                value: 'xihu',
                                label: 'West Lake'
                            }
                        ]
                    }
                ]
            },
            {
                value: 'chongqin',
                label: 'chongqin',
                children: [
                    {
                    value: 'yubei',
                    label: 'yubei',
                    children: [
                        {
                        value: 'xihus',
                        label: 'West Lakes'
                        }
                    ]
                    }
                ]
            },
            {
                value: 'jiangxi',
                label: 'jiangxi',
                children: [
                    {
                    value: 'ganzhou',
                    label: 'ganzhou',
                    children: [
                        {
                        value: 'huichang',
                        label: 'huichang'
                        }
                    ]
                    }
                ]
            }
        ],
        loading: false,
        imageUrl: '',
        editor:null,
      }
    },
    mounted(){
        this.demo()
    },
    methods: {
        demo(){
            console.log('E',E)
            this.editor = new E(this.$refs.demo)
            this.editor.config.height = 500
            this.editor.create()
        },
      // 初始化方法
      add () {
        this.visible = true
        this.form.getFieldDecorator('active', { initialValue: 'N' })
      },
      handleSubmit () {
        const { form: { validateFields } } = this
        this.confirmLoading = true
        validateFields((errors, values) => {
          if (!errors) {
            sysAppAdd(values).then((res) => {
              this.confirmLoading = false
              if (res.success) {
                this.$message.success('新增成功')
                this.handleCancel()
                this.$emit('ok', values)
              } else {
                this.$message.error('新增失败:' + res.message)
              }
            }).finally((res) => {
              this.confirmLoading = false
            })
          } else {
            this.confirmLoading = false
          }
        })
      },
      handleCancel () {
        this.form.resetFields()
        this.visible = false
      },
      handleChange(info) {
      if (info.file.status === 'uploading') {
        this.loading = true;
        return;
      }
      if (info.file.status === 'done') {
        // Get this url from response in real world.
        getBase64(info.file.originFileObj, imageUrl => {
          this.imageUrl = imageUrl;
          this.loading = false;
        });
      }
    },
    beforeUpload(file) {
      const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
      if (!isJpgOrPng) {
        this.$message.error('You can only upload JPG file!');
      }
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isLt2M) {
        this.$message.error('Image must smaller than 2MB!');
      }
      return isJpgOrPng && isLt2M;
    },
    }
  }
</script>
<style lang="less">
    .avatar-uploader > .ant-upload {
  width: 128px;
  height: 128px;
}
.ant-upload-select-picture-card i {
  font-size: 32px;
  color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  color: #666;
}
</style>

+ 0 - 0
_web/src/views/system/article/article.vue


+ 343 - 0
_web/src/views/system/article/index.vue

@ -0,0 +1,343 @@
<template>
    <div class="article">
        <div class="article-header">
            <div class="articleinit">
                <div class="articleinit-text">所属单位</div>
                <a-cascader class="cascader" :options="options" placeholder="请选择" />
            </div>
            <div class="articletitle">
                <div class="articletitle-text">文章标题</div>
                <a-input class="input" v-mode="title" placeholder="文章标题" />
            </div>
            <div class="query">搜索</div>
            <div class="query add" @click="$refs.addForm.add()">新增</div>
        </div>
        <a-table
        class="table"
          :columns="columns"
          :pagination='false'
          :data-source="data"
          bordered
          tableLayout="fixed">
            <span slot="operation" slot-scope="">
                <a @click="editor">编辑</a>
                <a-divider type="vertical" />
                <a @click="articleDelect">删除</a>
            </span>
        </a-table>
        <a-pagination
         class="pagination"
          :total="data.length"
          show-size-changer
          show-quick-jumper
          @change="pageChange"
          @showSizeChange="showChange" />
        <add-form ref="addForm" />
    </div>
</template>
<script>
    import { STable } from '@/components'
    import addForm from './addForm'
    const columns = [
        {
            dataIndex: 'key',
            width: 70,
            align: 'center',
            title: '序号',
            key: 'key',
            scopedSlots: { customRender: 'key' }
        },
        {
            title: '一级菜单',
            dataIndex: 'oneMenu',
            align: 'center',
            key: 'oneMenu'
        },
        {
            title: '二级菜单',
            align: 'center',
            dataIndex: 'twoMenu',
            key: 'twoMenu'
        },
        {
            title: '文章标题',
            align: 'center',
            key: 'title',
            dataIndex: 'title',
            scopedSlots: { customRender: 'title' }
        },
        {
            title: '审核状态',
            align: 'center',
            key: 'audit',
            dataIndex: 'audit',
            scopedSlots: { customRender: 'audit' }
        },
        {
            title: '审核时间',
            align: 'center',
            dataIndex: 'auditDate',
            key: 'auditDate'
        },
        {
            title: '审核意见',
            align: 'center',
            dataIndex: 'auditOpinion',
            key: 'auditOpinion'
        },
        {
            title: '发布状态',
            align: 'center',
            dataIndex: 'release',
            key: 'release'
        },
        {
            title: '发布时间',
            align: 'center',
            dataIndex: 'releaseDate',
            key: 'releaseDate'
        },
        {
            title: '操作',
            dataIndex: 'operation',
            align: 'center',
            key: 'operation',
            scopedSlots: { customRender: 'operation' },
            slots: { title: 'operation' }
        }
    ]
    const data = [
        {
            key: '1',
            serial: 'John',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '2',
            serial: 'John',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '3',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '4',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '5',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '6',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '7',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        }
    ]
  export default {
    components: {
      STable,
      addForm
    },
    data () {
      return {
        title: '',
        selectedRowKeys: [],
        options: [
            {
                value: 'zhejiang',
                label: 'Zhejiang',
                children: [
                    {
                        value: 'hangzhou',
                        label: 'Hangzhou',
                        children: [
                            {
                                value: 'xihu',
                                label: 'West Lake'
                            }
                        ]
                    }
                ]
            },
            {
                value: 'chongqin',
                label: 'chongqin',
                children: [
                    {
                    value: 'yubei',
                    label: 'yubei',
                    children: [
                        {
                        value: 'xihus',
                        label: 'West Lakes'
                        }
                    ]
                    }
                ]
            },
            {
                value: 'jiangxi',
                label: 'jiangxi',
                children: [
                    {
                    value: 'ganzhou',
                    label: 'ganzhou',
                    children: [
                        {
                        value: 'huichang',
                        label: 'huichang'
                        }
                    ]
                    }
                ]
            }
        ],
        columns,
        data,
        pageSize: ['10', '20', '30', '40']
      }
    },
    created () {},
    methods: {
      onChange (selectedRowKeys, selectedRows) {
        this.selectedRowKeys = selectedRowKeys
        this.selectedRows = selectedRows
      },
      pageChange (value, page) {
        console.log('pageChange', value)
        console.log('pageChange', page)
      },
      showChange (value, page) {
        console.log('showChange', value)
        console.log('showChange', page)
      },
      editor () {
        console.log('bianji')
      },
      articleDelect () {
        console.log('删除')
      }
    }
  }
</script>
<style lang="less">
    .ant-cascader-menu{
        height:auto;
    }
    .article-header{
        width:100%;
        // height:40px;
        margin-bottom:30px;
        .articleinit{
            display:inline-block;
            .articleinit-text{
                line-height:32px;
                display:inline-block;
                margin-right:10px;
            }
            .cascader{
                // height:40px;
            }
            .ant-input{
                // height:40px;
            }
        }
        .articletitle{
            width:300px;
            margin-left:20px;
            display:inline-block;
            .articletitle-text{
                display:inline-block;
                margin-right:10px;
            }
            .input{
                width:200px;
            }
            .ant-input{
                // height:40px;
            }
        }
        .query{
            display:inline-block;
            vertical-align: top;
            height:32px;
            width:60px;
            background:#40a9ff;
            line-height:32px;
            color:#fff;
            text-align:center;
            cursor: pointer;
            border:1px solid #40a9ff;
            border-radius:5px;
        }
        .add{
            margin-left:20px;
        }
    }
    .table{
        margin-bottom:20px;
    }
    .pagination{
        float:right;
    }
</style>

+ 1 - 0
_web/src/views/system/druid/index.vue

@ -0,0 +1 @@

+ 248 - 0
_web/src/views/system/employees/addForm.vue

@ -0,0 +1,248 @@
<template>
  <a-modal
    class="modal"
    title="员工管理"
    :width="600"
    okText="保存"
    cancelText='关闭'
    :visible="visible"
    :confirmLoading="confirmLoading"
    @ok="handleSubmit"
    @cancel="handleCancel"
  >
    <a-spin :spinning="confirmLoading">
      <a-form :form="form">
        <a-form-item
          label="姓名"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="请输入姓名" v-decorator="['code', {rules: [{required: true, message: '请输入员工姓名!'}]}]" />
        </a-form-item>
        <a-form-item
          label="性别"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-select
                label-in-value
                :default-value="{ key: 'choose' }"
                @change="handleChange"
                placeholder="请选择性别"
                v-decorator="['name', {rules: [{required: true, message: '请选择性别!'}]}]"
            >
                <a-select-option value="jack">男</a-select-option>
                <a-select-option value="lucy">女</a-select-option>
            </a-select>
        </a-form-item>
        <a-form-item
          label="手机号"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="请输入手机号" v-decorator="['tel', {rules: [{required: true, message: '请输入员工手机号!'}]}]" />
        </a-form-item>
        <a-form-item
          label="身份证号"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="请输入身份证号" v-decorator="['card', {rules: [{required: true, message: '请输入身份证号!'}]}]" />
        </a-form-item>
        <a-form-item
          label="部门"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="请输入部门" v-decorator="['department', {rules: [{required: true, message: '请输入员工部门!'}]}]" />
        </a-form-item>
      </a-form>
      <div class="reset">重置密码</div>
    </a-spin>
  </a-modal>
</template>
<script>
    import { sysAppAdd } from '@/api/modular/system/appManage'
    import E from 'wangeditor'
    function getBase64(img, callback) {
        const reader = new FileReader();
        reader.addEventListener('load', () => callback(reader.result));
        reader.readAsDataURL(img);
    }
  export default {
    data () {
      return {
        labelCol: {
          xs: { span: 24 },
          sm: { span: 5 }
        },
        wrapperCol: {
          xs: { span: 24 },
          sm: { span: 15 }
        },
        visible: false,
        confirmLoading: false,
        form: this.$form.createForm(this),
        options: [
            {
                value: 'zhejiang',
                label: 'Zhejiang',
                children: [
                    {
                        value: 'hangzhou',
                        label: 'Hangzhou',
                        children: [
                            {
                                value: 'xihu',
                                label: 'West Lake'
                            }
                        ]
                    }
                ]
            },
            {
                value: 'chongqin',
                label: 'chongqin',
                children: [
                    {
                    value: 'yubei',
                    label: 'yubei',
                    children: [
                        {
                        value: 'xihus',
                        label: 'West Lakes'
                        }
                    ]
                    }
                ]
            },
            {
                value: 'jiangxi',
                label: 'jiangxi',
                children: [
                    {
                    value: 'ganzhou',
                    label: 'ganzhou',
                    children: [
                        {
                        value: 'huichang',
                        label: 'huichang'
                        }
                    ]
                    }
                ]
            }
        ],
        loading: false,
        imageUrl: '',
        editor:null,
      }
    },
    mounted(){
        this.demo()
    },
    methods: {
        handleChange(){
        },
      // 初始化方法
      add () {
        this.visible = true
        this.form.getFieldDecorator('active', { initialValue: 'N' })
      },
      handleSubmit () {
        const { form: { validateFields } } = this
        this.confirmLoading = true
        validateFields((errors, values) => {
          if (!errors) {
            sysAppAdd(values).then((res) => {
              this.confirmLoading = false
              if (res.success) {
                this.$message.success('新增成功')
                this.handleCancel()
                this.$emit('ok', values)
              } else {
                this.$message.error('新增失败:' + res.message)
              }
            }).finally((res) => {
              this.confirmLoading = false
            })
          } else {
            this.confirmLoading = false
          }
        })
      },
      handleCancel () {
        this.form.resetFields()
        this.visible = false
      },
      handleChange(info) {
      if (info.file.status === 'uploading') {
        this.loading = true;
        return;
      }
      if (info.file.status === 'done') {
        // Get this url from response in real world.
        getBase64(info.file.originFileObj, imageUrl => {
          this.imageUrl = imageUrl;
          this.loading = false;
        });
      }
    },
    beforeUpload(file) {
      const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
      if (!isJpgOrPng) {
        this.$message.error('You can only upload JPG file!');
      }
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isLt2M) {
        this.$message.error('Image must smaller than 2MB!');
      }
      return isJpgOrPng && isLt2M;
    },
    }
  }
</script>
<style lang="less">
    .avatar-uploader > .ant-upload {
  width: 128px;
  height: 128px;
}
.ant-upload-select-picture-card i {
  font-size: 32px;
  color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  color: #666;
}
.modal{
    position:relative;
}
.reset{
    width:80px;
    height:32px;
    line-height:32px;
    text-align:center;
    border:1px solid #ccc;
    cursor: pointer;
    position:absolute;
    top:355px;
    right:140px;
    &:hover{
        border:1px solid #10aef9;
        color:#10aef9;
    }
}
</style>

+ 310 - 0
_web/src/views/system/employees/index.vue

@ -0,0 +1,310 @@
<template>
    <div class="employees">
        <div class="article-header">
            <div class="articletitle">
                <div class="articletitle-text">员工姓名</div>
                <a-input class="input" v-mode="title" placeholder="请输入姓名" />
            </div>
            <div class="articletitle">
                <div class="articletitle-text">员工手机号</div>
                <a-input class="input" v-mode="title" placeholder="请输入手机号" />
            </div>
            <div class="articletitle">
                <div class="articletitle-text">员工部门</div>
                <a-input class="input" v-mode="title" placeholder="请输入部门" />
            </div>
            <div class="query">查询</div>
            <div class="query add" @click="$refs.addForm.add()">新增</div>
        </div>
        <a-table
        class="table"
          :columns="columns"
          :pagination='false'
          :data-source="data"
          bordered
          tableLayout="fixed">
            <span slot="operation" slot-scope="">
                <a @click="editor">编辑</a>
                <a-divider type="vertical" />
                <a @click="articleDelect">重置密码</a>
                <a-divider type="vertical" />
                <a @click="articleDelect" style="color:red">删除</a>
            </span>
        </a-table>
        <a-pagination
         class="pagination"
          :total="data.length"
          show-size-changer
          show-quick-jumper
          @change="pageChange"
          @showSizeChange="showChange" />
        <add-form ref="addForm" />
    </div>
</template>
<script>
    import { STable } from '@/components'
    import addForm from './addForm'
    const columns = [
        {
            dataIndex: 'key',
            width: 70,
            align: 'center',
            title: '序号',
            key: 'key',
            scopedSlots: { customRender: 'key' }
        },
        {
            title: '姓名',
            dataIndex: 'oneMenu',
            align: 'center',
            key: 'oneMenu'
        },
        {
            title: '手机号',
            align: 'center',
            dataIndex: 'twoMenu',
            key: 'twoMenu'
        },
        {
            title: '身份证',
            align: 'center',
            key: 'title',
            dataIndex: 'title',
            scopedSlots: { customRender: 'title' }
        },
        {
            title: '部门',
            align: 'center',
            key: 'audit',
            dataIndex: 'audit',
            scopedSlots: { customRender: 'audit' }
        },
        {
            title: '操作',
            dataIndex: 'operation',
            align: 'center',
            key: 'operation',
            scopedSlots: { customRender: 'operation' },
            slots: { title: 'operation' }
        }
    ]
    const data = [
        {
            key: '1',
            serial: 'John',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '2',
            serial: 'John',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '3',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '4',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '5',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '6',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '7',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        }
    ]
  export default {
    components: {
      STable,
      addForm
    },
    data () {
      return {
        title: '',
        selectedRowKeys: [],
        options: [
            {
                value: 'zhejiang',
                label: 'Zhejiang',
                children: [
                    {
                        value: 'hangzhou',
                        label: 'Hangzhou',
                        children: [
                            {
                                value: 'xihu',
                                label: 'West Lake'
                            }
                        ]
                    }
                ]
            },
            {
                value: 'chongqin',
                label: 'chongqin',
                children: [
                    {
                    value: 'yubei',
                    label: 'yubei',
                    children: [
                        {
                        value: 'xihus',
                        label: 'West Lakes'
                        }
                    ]
                    }
                ]
            },
            {
                value: 'jiangxi',
                label: 'jiangxi',
                children: [
                    {
                    value: 'ganzhou',
                    label: 'ganzhou',
                    children: [
                        {
                        value: 'huichang',
                        label: 'huichang'
                        }
                    ]
                    }
                ]
            }
        ],
        columns,
        data,
        pageSize: ['10', '20', '30', '40']
      }
    },
    created () {},
    methods: {
      onChange (selectedRowKeys, selectedRows) {
        this.selectedRowKeys = selectedRowKeys
        this.selectedRows = selectedRows
      },
      pageChange (value, page) {
        console.log('pageChange', value)
        console.log('pageChange', page)
      },
      showChange (value, page) {
        console.log('showChange', value)
        console.log('showChange', page)
      },
      editor () {
        console.log('bianji')
      },
      articleDelect () {
        console.log('删除')
      }
    }
  }
</script>
<style lang="less">
    .ant-cascader-menu{
        height:auto;
    }
    .article-header{
        width:100%;
        margin-bottom:30px;
        .articletitle{
            width:300px;
            margin-left:20px;
            display:inline-block;
            .articletitle-text{
                display:inline-block;
                margin-right:10px;
            }
            .input{
                width:200px;
            }
            .ant-input{
                // height:40px;
            }
        }
        .query{
            display:inline-block;
            vertical-align: top;
            height:32px;
            width:60px;
            background:#40a9ff;
            line-height:32px;
            color:#fff;
            text-align:center;
            cursor: pointer;
            border:1px solid #40a9ff;
            border-radius:5px;
        }
        .add{
            margin-left:20px;
        }
    }
    .table{
        margin-bottom:20px;
    }
    .pagination{
        float:right;
    }
</style>

+ 265 - 0
_web/src/views/system/homePage/addForm.vue

@ -0,0 +1,265 @@
<template>
  <a-modal
    class="modal"
    title="荣誉"
    :width="600"
    okText="保存"
    cancelText='关闭'
    :visible="visible"
    :confirmLoading="confirmLoading"
    @ok="handleSubmit"
    @cancel="handleCancel"
  >
    <a-spin :spinning="confirmLoading">
      <a-form :form="form">
        <a-form-item
          label="banner名称"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="请输入名称" v-decorator="['code', {rules: [{required: true, message: '请输入名称!'}]}]" />
        </a-form-item>
        <a-form-item
          label="图像"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-upload
            name="avatar"
            list-type="picture-card"
            class="avatar-uploader"
            :show-upload-list="false"
            action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
            :before-upload="beforeUpload"
            @change="handleChange"
            v-decorator="['code', {rules: [{required: true, message: '请上传图片!'}]}]"
          >
            <img v-if="imageUrl" :src="imageUrl" alt="avatar" />
            <div v-else>
                <a-icon :type="loading ? 'loading' : 'plus'" />
                <div class="ant-upload-text">上传图片</div>
            </div>
          </a-upload>
        </a-form-item>
        <a-form-item
          label="链接"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="请输入链接" v-decorator="['code', {rules: [{required: true, message: '请输入链接!'}]}]" />
        </a-form-item>
        <a-form-item
          label="排序"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="请输入排序" v-decorator="['code', {rules: [{required: true, message: '请输入排序!'}]}]" />
        </a-form-item>
        <a-form-item
          label="是否生效"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-select
                label-in-value
                :default-value="{ key: 'choose' }"
                @change="handleChange"
                placeholder="请选择"
                v-decorator="['name', {rules: [{required: true, message: '请选择是否生效!'}]}]"
            >
                <a-select-option value="jack">是</a-select-option>
                <a-select-option value="lucy">否</a-select-option>
            </a-select>
        </a-form-item>
      </a-form>
    </a-spin>
  </a-modal>
</template>
<script>
    import { sysAppAdd } from '@/api/modular/system/appManage'
    import E from 'wangeditor'
    function getBase64(img, callback) {
        const reader = new FileReader();
        reader.addEventListener('load', () => callback(reader.result));
        reader.readAsDataURL(img);
    }
  export default {
    data () {
      return {
        labelCol: {
          xs: { span: 24 },
          sm: { span: 5 }
        },
        wrapperCol: {
          xs: { span: 24 },
          sm: { span: 15 }
        },
        visible: false,
        confirmLoading: false,
        form: this.$form.createForm(this),
        options: [
            {
                value: 'zhejiang',
                label: 'Zhejiang',
                children: [
                    {
                        value: 'hangzhou',
                        label: 'Hangzhou',
                        children: [
                            {
                                value: 'xihu',
                                label: 'West Lake'
                            }
                        ]
                    }
                ]
            },
            {
                value: 'chongqin',
                label: 'chongqin',
                children: [
                    {
                    value: 'yubei',
                    label: 'yubei',
                    children: [
                        {
                        value: 'xihus',
                        label: 'West Lakes'
                        }
                    ]
                    }
                ]
            },
            {
                value: 'jiangxi',
                label: 'jiangxi',
                children: [
                    {
                    value: 'ganzhou',
                    label: 'ganzhou',
                    children: [
                        {
                        value: 'huichang',
                        label: 'huichang'
                        }
                    ]
                    }
                ]
            }
        ],
        loading: false,
        imageUrl: '',
        editor:null,
      }
    },
    mounted(){
        this.demo()
    },
    methods: {
        demo(){
            console.log('E',E)
            this.editor = new E(this.$refs.demo)
            this.editor.config.height = 500
            this.editor.create()
        },
      // 初始化方法
      add () {
        this.visible = true
        this.form.getFieldDecorator('active', { initialValue: 'N' })
      },
      handleSubmit () {
        const { form: { validateFields } } = this
        this.confirmLoading = true
        validateFields((errors, values) => {
          if (!errors) {
            sysAppAdd(values).then((res) => {
              this.confirmLoading = false
              if (res.success) {
                this.$message.success('新增成功')
                this.handleCancel()
                this.$emit('ok', values)
              } else {
                this.$message.error('新增失败:' + res.message)
              }
            }).finally((res) => {
              this.confirmLoading = false
            })
          } else {
            this.confirmLoading = false
          }
        })
      },
      handleCancel () {
        this.form.resetFields()
        this.visible = false
      },
      handleChange(info) {
      if (info.file.status === 'uploading') {
        this.loading = true;
        return;
      }
      if (info.file.status === 'done') {
        // Get this url from response in real world.
        getBase64(info.file.originFileObj, imageUrl => {
          this.imageUrl = imageUrl;
          this.loading = false;
        });
      }
    },
    beforeUpload(file) {
      const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
      if (!isJpgOrPng) {
        this.$message.error('You can only upload JPG file!');
      }
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isLt2M) {
        this.$message.error('Image must smaller than 2MB!');
      }
      return isJpgOrPng && isLt2M;
    },
    }
  }
</script>
<style lang="less">
    .avatar-uploader > .ant-upload {
  width: 128px;
  height: 128px;
}
.ant-upload-select-picture-card i {
  font-size: 32px;
  color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  color: #666;
}
.modal{
    position:relative;
}
.reset{
    width:80px;
    height:32px;
    line-height:32px;
    text-align:center;
    border:1px solid #ccc;
    cursor: pointer;
    position:absolute;
    top:355px;
    right:140px;
    &:hover{
        border:1px solid #10aef9;
        color:#10aef9;
    }
}
</style>

+ 196 - 0
_web/src/views/system/homePage/index.vue

@ -0,0 +1,196 @@
<template>
    <div class="webPage">
        <a-tabs type="card" @change="callback">
            <a-tab-pane key="1" tab="banner">
            </a-tab-pane>
            <a-tab-pane key="2" tab="产品生态亮点">
            </a-tab-pane>
            <a-tab-pane key="3" tab="解决方案">
            </a-tab-pane>
            <a-tab-pane key="4" tab="新闻中心">
            </a-tab-pane>
            
        </a-tabs>
        <div class="add"><a-button type="primary" icon="plus" @click="$refs.addForm.add()">新增</a-button></div>
        <a-table
        class="table"
          :columns="columns"
          :pagination='false'
          :data-source="data"
          bordered
          tableLayout="fixed">
            <span slot="operation" slot-scope="">
                <a @click="editor">编辑</a>
                <a-divider type="vertical" />
                <a @click="articleDelect">删除</a>
            </span>
        </a-table>
        <a-pagination
         class="pagination"
          :total="data.length"
          show-size-changer
          show-quick-jumper
          @change="pageChange"
          @showSizeChange="showChange" />
          <add-form ref="addForm" />
    </div>
</template>
<script>
import addForm from './addForm'
  export default {
    components: {
        addForm
    },
    data () {
      return {
        title: '',
        imageUrl:'',
        showModify:false,
        ModifyText:'修改',
        columns:[
            {
                dataIndex: 'key',
                width: 70,
                align: 'center',
                title: '序号',
                key: 'key',
                scopedSlots: { customRender: 'key' }
            },
            {
                title: '排序',
                dataIndex: 'oneMenu',
                align: 'center',
                key: 'oneMenu'
            },
            {
                title: 'banner名称',
                align: 'center',
                dataIndex: 'twoMenu',
                key: 'twoMenu'
            },
            {
                title: '图像',
                align: 'center',
                key: 'title',
                dataIndex: 'title',
                scopedSlots: { customRender: 'title' }
            },
            // {
            //     title: '关联文章',
            //     align: 'center',
            //     key: 'audit',
            //     dataIndex: 'audit',
            //     scopedSlots: { customRender: 'audit' }
            // },
            {
                title: '是否生效',
                align: 'center',
                dataIndex: 'auditDate',
                key: 'auditDate'
            },
            {
                title: '操作',
                dataIndex: 'operation',
                align: 'center',
                key: 'operation',
                scopedSlots: { customRender: 'operation' },
                slots: { title: 'operation' }
            }
        ],
        data:[
            {
                key: '1',
                oneMenu: 32,
                twoMenu: 'New York ',
                title: 'NeYorkNo',
                audit: 'NewYorkNo',
                auditDate: 'NewYork ',
            },
            {
                key: '2',
                oneMenu: 32,
                twoMenu: 'New York ',
                title: 'NeYorkNo',
                audit: 'NewYorkNo',
                auditDate: 'NewYork ',
            },
            {
                key: '3',
                oneMenu: 32,
                twoMenu: 'New York ',
                title: 'NeYorkNo',
                audit: 'NewYorkNo',
                auditDate: 'NewYork ',
            },
            {
                key: '4',
                oneMenu: 32,
                twoMenu: 'New York ',
                title: 'NeYorkNo',
                audit: 'NewYorkNo',
                auditDate: 'NewYork ',
            },
        ]
      }
    },
    created () {},
    methods: {
        onChange (selectedRowKeys, selectedRows) {
            this.selectedRowKeys = selectedRowKeys
            this.selectedRows = selectedRows
        },
        pageChange (value, page) {
            console.log('pageChange', value)
            console.log('pageChange', page)
        },
        showChange (value, page) {
            console.log('showChange', value)
            console.log('showChange', page)
        },
        editor () {
            console.log('bianji')
        },
        articleDelect () {
            console.log('删除')
        },
        callback(key) {
            console.log(key);
            if(key == '1'){
                this.columns[2].title = 'banner名称'
            }else if(key == '2'){
                this.columns[2].title = '产品亮点名称'
            }else if(key == '3'){
                this.columns[2].title = '解决方案名称'
            }else if(key == '4'){
                this.columns[2].title = '新闻名称'
                this.columns.splice(4,0,{
                    title: '关联文章',
                    align: 'center',
                    key: 'audit',
                    dataIndex: 'audit',
                    scopedSlots: { customRender: 'audit' }
                })
            }
        },
    }
  }
</script>
<style lang="less">
    .webPage{
        .ant-tabs-tab{
            width:200px;
            text-align:center;
        }
        .add{
            position:absolute;
            top:145px;
            right:600px;
        }
        .table{
            margin-bottom:20px;
        }
        .pagination{
            float:right;
        }
    }
</style>

+ 265 - 0
_web/src/views/system/onlineUser/addForm.vue

@ -0,0 +1,265 @@
<template>
  <a-modal
    class="modal"
    title="荣誉"
    :width="600"
    okText="保存"
    cancelText='关闭'
    :visible="visible"
    :confirmLoading="confirmLoading"
    @ok="handleSubmit"
    @cancel="handleCancel"
  >
    <a-spin :spinning="confirmLoading">
      <a-form :form="form">
        <a-form-item
          label="banner名称"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="请输入名称" v-decorator="['code', {rules: [{required: true, message: '请输入名称!'}]}]" />
        </a-form-item>
        <a-form-item
          label="图像"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-upload
            name="avatar"
            list-type="picture-card"
            class="avatar-uploader"
            :show-upload-list="false"
            action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
            :before-upload="beforeUpload"
            @change="handleChange"
            v-decorator="['code', {rules: [{required: true, message: '请上传图片!'}]}]"
          >
            <img v-if="imageUrl" :src="imageUrl" alt="avatar" />
            <div v-else>
                <a-icon :type="loading ? 'loading' : 'plus'" />
                <div class="ant-upload-text">上传图片</div>
            </div>
          </a-upload>
        </a-form-item>
        <a-form-item
          label="链接"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="请输入链接" v-decorator="['code', {rules: [{required: true, message: '请输入链接!'}]}]" />
        </a-form-item>
        <a-form-item
          label="排序"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="请输入排序" v-decorator="['code', {rules: [{required: true, message: '请输入排序!'}]}]" />
        </a-form-item>
        <a-form-item
          label="是否生效"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-select
                label-in-value
                :default-value="{ key: 'choose' }"
                @change="handleChange"
                placeholder="请选择"
                v-decorator="['name', {rules: [{required: true, message: '请选择是否生效!'}]}]"
            >
                <a-select-option value="jack">是</a-select-option>
                <a-select-option value="lucy">否</a-select-option>
            </a-select>
        </a-form-item>
      </a-form>
    </a-spin>
  </a-modal>
</template>
<script>
    import { sysAppAdd } from '@/api/modular/system/appManage'
    import E from 'wangeditor'
    function getBase64(img, callback) {
        const reader = new FileReader();
        reader.addEventListener('load', () => callback(reader.result));
        reader.readAsDataURL(img);
    }
  export default {
    data () {
      return {
        labelCol: {
          xs: { span: 24 },
          sm: { span: 5 }
        },
        wrapperCol: {
          xs: { span: 24 },
          sm: { span: 15 }
        },
        visible: false,
        confirmLoading: false,
        form: this.$form.createForm(this),
        options: [
            {
                value: 'zhejiang',
                label: 'Zhejiang',
                children: [
                    {
                        value: 'hangzhou',
                        label: 'Hangzhou',
                        children: [
                            {
                                value: 'xihu',
                                label: 'West Lake'
                            }
                        ]
                    }
                ]
            },
            {
                value: 'chongqin',
                label: 'chongqin',
                children: [
                    {
                    value: 'yubei',
                    label: 'yubei',
                    children: [
                        {
                        value: 'xihus',
                        label: 'West Lakes'
                        }
                    ]
                    }
                ]
            },
            {
                value: 'jiangxi',
                label: 'jiangxi',
                children: [
                    {
                    value: 'ganzhou',
                    label: 'ganzhou',
                    children: [
                        {
                        value: 'huichang',
                        label: 'huichang'
                        }
                    ]
                    }
                ]
            }
        ],
        loading: false,
        imageUrl: '',
        editor:null,
      }
    },
    mounted(){
        this.demo()
    },
    methods: {
        demo(){
            console.log('E',E)
            this.editor = new E(this.$refs.demo)
            this.editor.config.height = 500
            this.editor.create()
        },
      // 初始化方法
      add () {
        this.visible = true
        this.form.getFieldDecorator('active', { initialValue: 'N' })
      },
      handleSubmit () {
        const { form: { validateFields } } = this
        this.confirmLoading = true
        validateFields((errors, values) => {
          if (!errors) {
            sysAppAdd(values).then((res) => {
              this.confirmLoading = false
              if (res.success) {
                this.$message.success('新增成功')
                this.handleCancel()
                this.$emit('ok', values)
              } else {
                this.$message.error('新增失败:' + res.message)
              }
            }).finally((res) => {
              this.confirmLoading = false
            })
          } else {
            this.confirmLoading = false
          }
        })
      },
      handleCancel () {
        this.form.resetFields()
        this.visible = false
      },
      handleChange(info) {
      if (info.file.status === 'uploading') {
        this.loading = true;
        return;
      }
      if (info.file.status === 'done') {
        // Get this url from response in real world.
        getBase64(info.file.originFileObj, imageUrl => {
          this.imageUrl = imageUrl;
          this.loading = false;
        });
      }
    },
    beforeUpload(file) {
      const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
      if (!isJpgOrPng) {
        this.$message.error('You can only upload JPG file!');
      }
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isLt2M) {
        this.$message.error('Image must smaller than 2MB!');
      }
      return isJpgOrPng && isLt2M;
    },
    }
  }
</script>
<style lang="less">
    .avatar-uploader > .ant-upload {
  width: 128px;
  height: 128px;
}
.ant-upload-select-picture-card i {
  font-size: 32px;
  color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  color: #666;
}
.modal{
    position:relative;
}
.reset{
    width:80px;
    height:32px;
    line-height:32px;
    text-align:center;
    border:1px solid #ccc;
    cursor: pointer;
    position:absolute;
    top:355px;
    right:140px;
    &:hover{
        border:1px solid #10aef9;
        color:#10aef9;
    }
}
</style>

+ 179 - 110
_web/src/views/system/onlineUser/index.vue

@ -1,127 +1,196 @@
<template>
  <a-card :bordered="false">
    <s-table
      ref="table"
      size="default"
      :pagination="false"
      :loading="loading"
      :columns="columns"
      :data="loadData"
      :rowKey="(record) => record.sessionId"
      :rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
    >
      <span slot="lastLoginAddress" slot-scope="text">
        <ellipsis :length="20" tooltip>{{ text }}</ellipsis>
      </span>
      <span slot="lastLoginBrowser" slot-scope="text">
        <ellipsis :length="20" tooltip>{{ text }}</ellipsis>
      </span>
      <span slot="action" slot-scope="text, record">
        <a-popconfirm v-if="hasPerm('sysOnlineUser:forceExist')" placement="topRight" title="是否强制下线该用户?" @confirm="() => forceExist(record)">
          <a>强制下线</a>
        </a-popconfirm>
      </span>
    </s-table>
  </a-card>
    <div class="webPage">
        <a-tabs type="card" @change="callback">
            <a-tab-pane key="1" tab="banner">
            </a-tab-pane>
            <a-tab-pane key="2" tab="产品生态亮点">
            </a-tab-pane>
            <a-tab-pane key="3" tab="解决方案">
            </a-tab-pane>
            <a-tab-pane key="4" tab="新闻中心">
            </a-tab-pane>
            
        </a-tabs>
        <div class="add"><a-button type="primary" icon="plus" @click="$refs.addForm.add()">新增</a-button></div>
        <a-table
        class="table"
          :columns="columns"
          :pagination='false'
          :data-source="data"
          bordered
          tableLayout="fixed">
            <span slot="operation" slot-scope="">
                <a @click="editor">编辑</a>
                <a-divider type="vertical" />
                <a @click="articleDelect">删除</a>
            </span>
        </a-table>
        <a-pagination
         class="pagination"
          :total="data.length"
          show-size-changer
          show-quick-jumper
          @change="pageChange"
          @showSizeChange="showChange" />
          <add-form ref="addForm" />
    </div>
</template>
<script>
  import { STable, Ellipsis } from '@/components'
  import { sysOnlineUserForceExist, sysOnlineUserList } from '@/api/modular/system/onlineUserManage'
import addForm from './addForm'
  export default {
    components: {
      STable,
      Ellipsis
        addForm
    },
    data () {
      return {
        // 查询参数
        queryParam: {},
        // 表头
        columns: [
          {
            title: '账号',
            dataIndex: 'account'
          },
          {
            title: '昵称',
            dataIndex: 'nickName'
          },
          {
            title: '最后登录IP',
            dataIndex: 'lastLoginIp'
          },
          {
            title: '最后登录时间',
            dataIndex: 'lastLoginTime'
          },
          {
            title: '最后登录地址',
            dataIndex: 'lastLoginAddress',
            scopedSlots: { customRender: 'lastLoginAddress' }
          },
          {
            title: '最后登录浏览器',
            dataIndex: 'lastLoginBrowser',
            scopedSlots: { customRender: 'lastLoginBrowser' }
          },
          {
            title: '最后登录所用系统',
            dataIndex: 'lastLoginOs'
          }
        ],
        loading: true,
        loadData: parameter => {
          return sysOnlineUserList(Object.assign(parameter, this.queryParam)).then((res) => {
            if (this.hasPerm('sysOnlineUser:list')) {
              return res.data
            } else {
              return new Promise((resolve, reject) => {
                return resolve()
              })
        title: '',
        imageUrl:'',
        showModify:false,
        ModifyText:'修改',
        columns:[
            {
                dataIndex: 'key',
                width: 70,
                align: 'center',
                title: '序号',
                key: 'key',
                scopedSlots: { customRender: 'key' }
            },
            {
                title: '排序',
                dataIndex: 'oneMenu',
                align: 'center',
                key: 'oneMenu'
            },
            {
                title: 'banner名称',
                align: 'center',
                dataIndex: 'twoMenu',
                key: 'twoMenu'
            },
            {
                title: '图像',
                align: 'center',
                key: 'title',
                dataIndex: 'title',
                scopedSlots: { customRender: 'title' }
            },
            // {
            //     title: '关联文章',
            //     align: 'center',
            //     key: 'audit',
            //     dataIndex: 'audit',
            //     scopedSlots: { customRender: 'audit' }
            // },
            {
                title: '是否生效',
                align: 'center',
                dataIndex: 'auditDate',
                key: 'auditDate'
            },
            {
                title: '操作',
                dataIndex: 'operation',
                align: 'center',
                key: 'operation',
                scopedSlots: { customRender: 'operation' },
                slots: { title: 'operation' }
            }
          })
        },
        selectedRowKeys: [],
        selectedRows: []
      }
    },
    // 进页面加载
    created () {
      if (this.hasPerm('sysOnlineUser:forceExist')) {
        this.columns.push({
          title: '操作',
          width: '150px',
          dataIndex: 'action',
          scopedSlots: { customRender: 'action' }
        })
        ],
        data:[
            {
                key: '1',
                oneMenu: 32,
                twoMenu: 'New York ',
                title: 'NeYorkNo',
                audit: 'NewYorkNo',
                auditDate: 'NewYork ',
            },
            {
                key: '2',
                oneMenu: 32,
                twoMenu: 'New York ',
                title: 'NeYorkNo',
                audit: 'NewYorkNo',
                auditDate: 'NewYork ',
            },
            {
                key: '3',
                oneMenu: 32,
                twoMenu: 'New York ',
                title: 'NeYorkNo',
                audit: 'NewYorkNo',
                auditDate: 'NewYork ',
            },
            {
                key: '4',
                oneMenu: 32,
                twoMenu: 'New York ',
                title: 'NeYorkNo',
                audit: 'NewYorkNo',
                auditDate: 'NewYork ',
            },
        ]
      }
    },
    created () {},
    methods: {
      forceExist (record) {
        sysOnlineUserForceExist(record).then((res) => {
          if (res.success) {
            this.$message.success('强制下线成功')
            // 重新加载表格
            this.loadDataList()
          } else {
            this.$message.error('强制下线失败:' + res.message)
          }
        }).catch((err) => {
          this.$message.error('强制下线错误:' + err.message)
        })
      },
      onSelectChange (selectedRowKeys, selectedRows) {
        this.selectedRowKeys = selectedRowKeys
        this.selectedRows = selectedRows
      }
        onChange (selectedRowKeys, selectedRows) {
            this.selectedRowKeys = selectedRowKeys
            this.selectedRows = selectedRows
        },
        pageChange (value, page) {
            console.log('pageChange', value)
            console.log('pageChange', page)
        },
        showChange (value, page) {
            console.log('showChange', value)
            console.log('showChange', page)
        },
        editor () {
            console.log('bianji')
        },
        articleDelect () {
            console.log('删除')
        },
        callback(key) {
            console.log(key);
            if(key == '1'){
                this.columns[2].title = 'banner名称'
            }else if(key == '2'){
                this.columns[2].title = '产品亮点名称'
            }else if(key == '3'){
                this.columns[2].title = '解决方案名称'
            }else if(key == '4'){
                this.columns[2].title = '新闻名称'
                this.columns.splice(4,0,{
                    title: '关联文章',
                    align: 'center',
                    key: 'audit',
                    dataIndex: 'audit',
                    scopedSlots: { customRender: 'audit' }
                })
            }
        },
    }
  }
</script>
<style lang="less">
  .table-operator {
    margin-bottom: 18px;
  }
  button {
    margin-right: 8px;
  }
    .webPage{
        .ant-tabs-tab{
            width:200px;
            text-align:center;
        }
        .add{
            position:absolute;
            top:145px;
            right:600px;
        }
        .table{
            margin-bottom:20px;
        }
        .pagination{
            float:right;
        }
    }
</style>

+ 127 - 0
_web/src/views/system/onlineUser/zaixianyonghu.vue

@ -0,0 +1,127 @@
<template>
  <a-card :bordered="false">
    <s-table
      ref="table"
      size="default"
      :pagination="false"
      :loading="loading"
      :columns="columns"
      :data="loadData"
      :rowKey="(record) => record.sessionId"
      :rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
    >
      <span slot="lastLoginAddress" slot-scope="text">
        <ellipsis :length="20" tooltip>{{ text }}</ellipsis>
      </span>
      <span slot="lastLoginBrowser" slot-scope="text">
        <ellipsis :length="20" tooltip>{{ text }}</ellipsis>
      </span>
      <span slot="action" slot-scope="text, record">
        <a-popconfirm v-if="hasPerm('sysOnlineUser:forceExist')" placement="topRight" title="是否强制下线该用户?" @confirm="() => forceExist(record)">
          <a>强制下线</a>
        </a-popconfirm>
      </span>
    </s-table>
  </a-card>
</template>
<script>
  import { STable, Ellipsis } from '@/components'
  import { sysOnlineUserForceExist, sysOnlineUserList } from '@/api/modular/system/onlineUserManage'
  export default {
    components: {
      STable,
      Ellipsis
    },
    data () {
      return {
        // 查询参数
        queryParam: {},
        // 表头
        columns: [
          {
            title: '账号',
            dataIndex: 'account'
          },
          {
            title: '昵称',
            dataIndex: 'nickName'
          },
          {
            title: '最后登录IP',
            dataIndex: 'lastLoginIp'
          },
          {
            title: '最后登录时间',
            dataIndex: 'lastLoginTime'
          },
          {
            title: '最后登录地址',
            dataIndex: 'lastLoginAddress',
            scopedSlots: { customRender: 'lastLoginAddress' }
          },
          {
            title: '最后登录浏览器',
            dataIndex: 'lastLoginBrowser',
            scopedSlots: { customRender: 'lastLoginBrowser' }
          },
          {
            title: '最后登录所用系统',
            dataIndex: 'lastLoginOs'
          }
        ],
        loading: true,
        loadData: parameter => {
          return sysOnlineUserList(Object.assign(parameter, this.queryParam)).then((res) => {
            if (this.hasPerm('sysOnlineUser:list')) {
              return res.data
            } else {
              return new Promise((resolve, reject) => {
                return resolve()
              })
            }
          })
        },
        selectedRowKeys: [],
        selectedRows: []
      }
    },
    // 进页面加载
    created () {
      if (this.hasPerm('sysOnlineUser:forceExist')) {
        this.columns.push({
          title: '操作',
          width: '150px',
          dataIndex: 'action',
          scopedSlots: { customRender: 'action' }
        })
      }
    },
    methods: {
      forceExist (record) {
        sysOnlineUserForceExist(record).then((res) => {
          if (res.success) {
            this.$message.success('强制下线成功')
            // 重新加载表格
            this.loadDataList()
          } else {
            this.$message.error('强制下线失败:' + res.message)
          }
        }).catch((err) => {
          this.$message.error('强制下线错误:' + err.message)
        })
      },
      onSelectChange (selectedRowKeys, selectedRows) {
        this.selectedRowKeys = selectedRowKeys
        this.selectedRows = selectedRows
      }
    }
  }
</script>
<style lang="less">
  .table-operator {
    margin-bottom: 18px;
  }
  button {
    margin-right: 8px;
  }
</style>

+ 250 - 0
_web/src/views/system/systemName/addForm.vue

@ -0,0 +1,250 @@
<template>
  <a-modal
    class="modal"
    title="制度管理"
    :width="600"
    okText="保存"
    cancelText='关闭'
    :visible="visible"
    :confirmLoading="confirmLoading"
    @ok="handleSubmit"
    @cancel="handleCancel"
  >
    <a-spin :spinning="confirmLoading">
      <a-form :form="form">
        <a-form-item
          label="制度名称"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-input placeholder="请输入制度名称" v-decorator="['code', {rules: [{required: true, message: '请输入制度名称!'}]}]" />
        </a-form-item>
        <a-form-item
          label="制度文件"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-upload
            name="avatar"
            list-type="picture-card"
            class="avatar-uploader"
            :show-upload-list="false"
            action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
            :before-upload="beforeUpload"
            @change="handleChange"
            v-decorator="['code', {rules: [{required: true, message: '请上传制度文件!'}]}]"
          >
            <img v-if="imageUrl" :src="imageUrl" alt="avatar" />
            <div v-else>
                <a-icon :type="loading ? 'loading' : 'plus'" />
                <div class="ant-upload-text">上传制度文件</div>
            </div>
          </a-upload>
        </a-form-item>
        <a-form-item
          label="是否生效"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback
        >
          <a-select
                label-in-value
                :default-value="{ key: 'choose' }"
                @change="handleChange"
                placeholder="请选择"
                v-decorator="['name', {rules: [{required: true, message: '请选择是否生效!'}]}]"
            >
                <a-select-option value="jack">是</a-select-option>
                <a-select-option value="lucy">否</a-select-option>
            </a-select>
        </a-form-item>
      </a-form>
    </a-spin>
  </a-modal>
</template>
<script>
    import { sysAppAdd } from '@/api/modular/system/appManage'
    import E from 'wangeditor'
    function getBase64(img, callback) {
        const reader = new FileReader();
        reader.addEventListener('load', () => callback(reader.result));
        reader.readAsDataURL(img);
    }
  export default {
    data () {
      return {
        labelCol: {
          xs: { span: 24 },
          sm: { span: 5 }
        },
        wrapperCol: {
          xs: { span: 24 },
          sm: { span: 15 }
        },
        visible: false,
        confirmLoading: false,
        form: this.$form.createForm(this),
        options: [
            {
                value: 'zhejiang',
                label: 'Zhejiang',
                children: [
                    {
                        value: 'hangzhou',
                        label: 'Hangzhou',
                        children: [
                            {
                                value: 'xihu',
                                label: 'West Lake'
                            }
                        ]
                    }
                ]
            },
            {
                value: 'chongqin',
                label: 'chongqin',
                children: [
                    {
                    value: 'yubei',
                    label: 'yubei',
                    children: [
                        {
                        value: 'xihus',
                        label: 'West Lakes'
                        }
                    ]
                    }
                ]
            },
            {
                value: 'jiangxi',
                label: 'jiangxi',
                children: [
                    {
                    value: 'ganzhou',
                    label: 'ganzhou',
                    children: [
                        {
                        value: 'huichang',
                        label: 'huichang'
                        }
                    ]
                    }
                ]
            }
        ],
        loading: false,
        imageUrl: '',
        editor:null,
      }
    },
    mounted(){
        this.demo()
    },
    methods: {
        demo(){
            console.log('E',E)
            this.editor = new E(this.$refs.demo)
            this.editor.config.height = 500
            this.editor.create()
        },
      // 初始化方法
      add () {
        this.visible = true
        this.form.getFieldDecorator('active', { initialValue: 'N' })
      },
      handleSubmit () {
        const { form: { validateFields } } = this
        this.confirmLoading = true
        validateFields((errors, values) => {
          if (!errors) {
            sysAppAdd(values).then((res) => {
              this.confirmLoading = false
              if (res.success) {
                this.$message.success('新增成功')
                this.handleCancel()
                this.$emit('ok', values)
              } else {
                this.$message.error('新增失败:' + res.message)
              }
            }).finally((res) => {
              this.confirmLoading = false
            })
          } else {
            this.confirmLoading = false
          }
        })
      },
      handleCancel () {
        this.form.resetFields()
        this.visible = false
      },
      handleChange(info) {
      if (info.file.status === 'uploading') {
        this.loading = true;
        return;
      }
      if (info.file.status === 'done') {
        // Get this url from response in real world.
        getBase64(info.file.originFileObj, imageUrl => {
          this.imageUrl = imageUrl;
          this.loading = false;
        });
      }
    },
    beforeUpload(file) {
      const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
      if (!isJpgOrPng) {
        this.$message.error('You can only upload JPG file!');
      }
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isLt2M) {
        this.$message.error('Image must smaller than 2MB!');
      }
      return isJpgOrPng && isLt2M;
    },
    }
  }
</script>
<style lang="less">
    .avatar-uploader > .ant-upload {
  width: 128px;
  height: 128px;
}
.ant-upload-select-picture-card i {
  font-size: 32px;
  color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  color: #666;
}
.modal{
    position:relative;
}
.reset{
    width:80px;
    height:32px;
    line-height:32px;
    text-align:center;
    border:1px solid #ccc;
    cursor: pointer;
    position:absolute;
    top:355px;
    right:140px;
    &:hover{
        border:1px solid #10aef9;
        color:#10aef9;
    }
}
</style>

+ 288 - 0
_web/src/views/system/systemName/index.vue

@ -0,0 +1,288 @@
<template>
    <div class="systemName">
        <div class="article-header">
            <div class="articletitle">
                <div class="articletitle-text">制度名称</div>
                <a-input class="input" v-mode="title" placeholder="" />
            </div>
            <div class="query">查询</div>
            <div class="query add" @click="$refs.addForm.add()">新增</div>
        </div>
        <a-table
        class="table"
          :columns="columns"
          :pagination='false'
          :data-source="data"
          bordered
          tableLayout="fixed">
            <span slot="operation" slot-scope="">
                <a @click="editor">编辑</a>
                <a-divider type="vertical" />
                <a @click="articleDelect">下载</a>
                <a-divider type="vertical" />
                <a @click="articleDelect" style="color:red">删除</a>
            </span>
        </a-table>
        <a-pagination
         class="pagination"
          :total="data.length"
          show-size-changer
          show-quick-jumper
          @change="pageChange"
          @showSizeChange="showChange" />
        <add-form ref="addForm" />
    </div>
</template>
<script>
    import { STable } from '@/components'
    import addForm from './addForm'
    const columns = [
        {
            dataIndex: 'key',
            width: 70,
            align: 'center',
            title: '序号',
            key: 'key',
            scopedSlots: { customRender: 'key' }
        },
        {
            title: '制度名称',
            dataIndex: 'oneMenu',
            align: 'center',
            key: 'oneMenu'
        },
        {
            title: '是否生效',
            align: 'center',
            dataIndex: 'twoMenu',
            key: 'twoMenu'
        },
        {
            title: '操作',
            dataIndex: 'operation',
            align: 'center',
            key: 'operation',
            scopedSlots: { customRender: 'operation' },
            slots: { title: 'operation' }
        }
    ]
    const data = [
        {
            key: '1',
            serial: 'John',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '2',
            serial: 'John',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '3',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '4',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '5',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '6',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        },
        {
            key: '7',
            serial: 'John Brown',
            oneMenu: 32,
            twoMenu: 'New York ',
            title: 'NeYorkNo',
            audit: 'NewYorkNo',
            auditDate: 'NewYork ',
            auditOpinion: 'New Yo',
            release: 'NewYorkN',
            releaseDate: 'NewYork'
        }
    ]
  export default {
    components: {
      STable,
      addForm
    },
    data () {
      return {
        title: '',
        selectedRowKeys: [],
        options: [
            {
                value: 'zhejiang',
                label: 'Zhejiang',
                children: [
                    {
                        value: 'hangzhou',
                        label: 'Hangzhou',
                        children: [
                            {
                                value: 'xihu',
                                label: 'West Lake'
                            }
                        ]
                    }
                ]
            },
            {
                value: 'chongqin',
                label: 'chongqin',
                children: [
                    {
                    value: 'yubei',
                    label: 'yubei',
                    children: [
                        {
                        value: 'xihus',
                        label: 'West Lakes'
                        }
                    ]
                    }
                ]
            },
            {
                value: 'jiangxi',
                label: 'jiangxi',
                children: [
                    {
                    value: 'ganzhou',
                    label: 'ganzhou',
                    children: [
                        {
                        value: 'huichang',
                        label: 'huichang'
                        }
                    ]
                    }
                ]
            }
        ],
        columns,
        data,
        pageSize: ['10', '20', '30', '40']
      }
    },
    created () {},
    methods: {
      onChange (selectedRowKeys, selectedRows) {
        this.selectedRowKeys = selectedRowKeys
        this.selectedRows = selectedRows
      },
      pageChange (value, page) {
        console.log('pageChange', value)
        console.log('pageChange', page)
      },
      showChange (value, page) {
        console.log('showChange', value)
        console.log('showChange', page)
      },
      editor () {
        console.log('bianji')
      },
      articleDelect () {
        console.log('删除')
      }
    }
  }
</script>
<style lang="less">
    .ant-cascader-menu{
        height:auto;
    }
    .article-header{
        width:100%;
        margin-bottom:30px;
        .articletitle{
            width:300px;
            margin-left:20px;
            display:inline-block;
            .articletitle-text{
                display:inline-block;
                margin-right:10px;
            }
            .input{
                width:200px;
            }
            .ant-input{
                // height:40px;
            }
        }
        .query{
            display:inline-block;
            vertical-align: top;
            height:32px;
            width:60px;
            background:#40a9ff;
            line-height:32px;
            color:#fff;
            text-align:center;
            cursor: pointer;
            border:1px solid #40a9ff;
            border-radius:5px;
        }
        .add{
            margin-left:20px;
        }
    }
    .table{
        margin-bottom:20px;
    }
    .pagination{
        float:right;
    }
</style>

+ 123 - 0
_web/src/views/system/webPage/index.vue

@ -0,0 +1,123 @@
<template>
    <div class="webPage">
        <div class="article-header">
            <div class="articletitle">
                <div class="articletitle-text">地址:</div>
                <a-input class="input" :disabled="!showModify" v-mode="title" placeholder="" />
            </div>
            <div class="articletitle">
                <div class="articletitle-text">联系方式:</div>
                <a-input class="input" :disabled="!showModify" v-mode="title" placeholder="" />
            </div>
            <div class="articletitle">
                <div class="articletitle-text">备案号:</div>
                <a-input class="input" :disabled="!showModify" v-mode="title" placeholder="" />
            </div>
            <div class="upload">
                <div class="upload-text">公众号二维码:</div>
                <div v-if="!showModify" class="image">
                    <img src="@/assets/logo.png" alt="" >
                </div>
                <a-upload
                    name="avatar"
                    v-else
                    list-type="picture-card"
                    class="avatar-uploader"
                    :show-upload-list="false"
                    action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
                    :before-upload="beforeUpload"
                    @change="handleChange"
                >
                    <img v-if="imageUrl" :src="imageUrl" alt="avatar" />
                    <div v-else>
                        <a-icon :type="loading ? 'loading' : 'plus'" />
                        <div class="ant-upload-text">上传图片</div>
                    </div>
                </a-upload>
            </div>
            <div class="Modify" @click="Modify">{{ ModifyText }}</div>
        </div>
    </div>
</template>
<script>
  export default {
    components: {
    },
    data () {
      return {
        title: '',
        imageUrl:'',
        showModify:false,
        ModifyText:'修改'
      }
    },
    created () {},
    methods: {
        Modify(){
            this.showModify = !this.showModify
            if(this.showModify){
                this.ModifyText = '保存'
            }else{
                this.ModifyText = '修改'
            }
            
        }
    }
  }
</script>
<style lang="less">
    .ant-cascader-menu{
        height:auto;
    }
    .article-header{
        width:100%;
        margin-bottom:30px;
        .articletitle{
            width:500px;
            margin-left:100px;
            margin-bottom:20px;
            .articletitle-text{
                display:inline-block;
                width:90px;
                margin-right:30px;
            }
            .input{
                width:300px;
            }
        }
        .upload{
            width:500px;
            margin-left:100px;
            margin-bottom:50px;
            display:flex;
            .upload-text{
                width:120px;
                margin-right:30px;
            }
            .image{
                width:126px;
                height:126px;
                margin-left:-28px;
                margin-bottom:10px;
                border:1px solid #ccc;
                img{
                    width:100%;
                    height:100%;
                }
            }
        }
        .Modify{
           margin-left:350px;
           width:80px;
           height:40px;
           line-height:40px;
           text-align:center;
           background:#1890ff;
           color:#fff;
           border-radius:10px;
           cursor: pointer;
        }
    }
</style>

+ 0 - 1
_web/vue.config.js

@ -103,7 +103,6 @@ const vueConfig = {
  // disable source map in production
  productionSourceMap: false,
  lintOnSave: undefined,
  // babel-loader no-ignore node_modules/*
  transpileDependencies: []
}