guhongwei 2 anni fa
parent
commit
3265cf9dbb

+ 47 - 0
src/components/frame/c-button.vue

@@ -0,0 +1,47 @@
+<template>
+  <div id="c-button">
+    <el-row>
+      <el-col :span="24" class="button">
+        <el-button type="primary" size="small" icon="el-icon-plus" @click="toAdd()">新增</el-button>
+        <el-button type="primary" size="small" icon="el-icon-download">导出</el-button>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'c-button',
+  props: {},
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    toAdd() {
+      this.$emit('toAdd');
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.button {
+  margin: 0 0 10px 0;
+}
+</style>

+ 50 - 0
src/components/frame/c-dialog.vue

@@ -0,0 +1,50 @@
+<template>
+  <div id="e-dialog">
+    <el-dialog :title="dialog.title" :visible.sync="dialog.show" :width="width" :before-close="toClose" :close-on-click-modal="false" :append-to-body="true">
+      <slot name="info"></slot>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'e-dialog',
+  props: {
+    dialog: { type: Object, default: () => {} },
+    width: { type: String, default: '40%' },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    toClose() {
+      this.$emit('toClose');
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+/deep/.el-dialog__body {
+  padding: 10px;
+  min-height: 30px;
+  max-height: 400px;
+  overflow-y: auto;
+}
+</style>

+ 218 - 0
src/components/frame/c-form.vue

@@ -0,0 +1,218 @@
+<template>
+  <div id="c-form">
+    <el-row>
+      <el-col :span="24" class="c-form">
+        <el-form ref="form" :model="form" :rules="rules" :label-width="labelWidth" @submit.native.prevent>
+          <el-col :span="24" class="form">
+            <el-col :span="span" class="form-1" v-for="(item, index) in fields" :key="'form-field-' + index">
+              <el-form-item v-if="display(item)" :label="getField('label', item)" :prop="item.model" :required="item.required">
+                <template v-if="!item.custom">
+                  <template v-if="item.type === 'textarea'">
+                    <el-input
+                      clearable
+                      v-model="form[item.model]"
+                      :type="item.type"
+                      :placeholder="getField('placeholder', item)"
+                      v-bind="item.options"
+                      @change="dataChange(item.model)"
+                      show-word-limit
+                    ></el-input>
+                  </template>
+                  <template v-else-if="item.type === 'radio'">
+                    <el-radio-group v-model="form[item.model]" :type="item.type" v-bind="item.options" @change="dataChange(item.model)">
+                      <slot :name="item.model" v-bind="{ item }"></slot>
+                    </el-radio-group>
+                  </template>
+                  <template v-else-if="item.type === 'checkbox'">
+                    <el-checkbox-group v-model="form[item.model]" :type="item.type" v-bind="item.options">
+                      <slot :name="item.model" v-bind="{ item }"></slot>
+                    </el-checkbox-group>
+                  </template>
+                  <template v-else-if="item.type === 'select'">
+                    <el-select
+                      clearable
+                      filterable
+                      v-model="form[item.model]"
+                      :type="item.type"
+                      :placeholder="getField('selectplaceholder', item)"
+                      v-bind="item.options"
+                      @change="dataChange(item.model)"
+                      style="width: 100%"
+                    >
+                      <slot :name="item.model" v-bind="{ item }"></slot>
+                    </el-select>
+                  </template>
+                  <template v-else-if="item.type === 'selectMany'">
+                    <el-select
+                      filterable
+                      clearable
+                      multiple
+                      collapse-tags
+                      v-model="form[item.model]"
+                      :type="item.type"
+                      :placeholder="getField('selectplaceholder', item)"
+                      v-bind="item.options"
+                      @change="dataChange(item.model)"
+                      style="width: 100%"
+                    >
+                      <slot :name="item.model" v-bind="{ item }"></slot>
+                    </el-select>
+                  </template>
+                  <template
+                    v-else-if="
+                      item.type === `year` ||
+                      item.type == 'month' ||
+                      item.type == 'date' ||
+                      item.type == 'daterange' ||
+                      item.type == 'datetime' ||
+                      item.type == 'datetimerange'
+                    "
+                  >
+                    <el-date-picker
+                      v-model="form[item.model]"
+                      :type="item.type"
+                      :placeholder="getField('selectplaceholder', item)"
+                      :format="getDateFormat(item.type)"
+                      :value-format="getDateFormat(item.type)"
+                      v-bind="item.options"
+                      @change="dataChange(item.model)"
+                      range-separator="至"
+                      style="width: 100%"
+                    >
+                    </el-date-picker>
+                  </template>
+                  <template v-else-if="item.type === `time`">
+                    <el-time-picker
+                      v-model="form[item.model]"
+                      :placeholder="getField('selectplaceholder', item)"
+                      :format="getDateFormat(item.type)"
+                      :value-format="getDateFormat(item.type)"
+                      v-bind="item.options"
+                      @change="dataChange(item.model)"
+                      style="width: 100%"
+                    >
+                    </el-time-picker>
+                  </template>
+                  <template v-else>
+                    <el-input
+                      clearable
+                      v-model="form[item.model]"
+                      :type="getField('type', item)"
+                      :placeholder="getField('placeholder', item)"
+                      :show-password="getField('type', item) === 'password'"
+                      v-bind="item.options"
+                      @change="dataChange(item.model)"
+                    ></el-input>
+                  </template>
+                </template>
+                <template v-else>
+                  <slot :name="item.model" v-bind="{ item }"></slot>
+                </template>
+              </el-form-item>
+            </el-col>
+          </el-col>
+          <el-col :span="24" class="btn" v-if="isSave">
+            <slot name="submit">
+              <el-button type="primary" size="small" @click="save">{{ submitText }}</el-button>
+            </slot>
+          </el-col>
+        </el-form>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'c-form',
+  props: {
+    fields: { type: Array, default: () => [{ readonly: false }] },
+    form: null,
+    rules: { type: Object, default: () => {} },
+    labelWidth: { type: String, default: 'auto' },
+    isSave: { type: Boolean, default: true },
+    submitText: { type: String, default: '提交保存' },
+    reset: { type: Boolean, default: false },
+    span: { type: Number, default: 12 }, // 限制表单显示长度
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    // 提交保存
+    save() {
+      this.$refs['form'].validate((valid) => {
+        if (valid) {
+          this.$emit(`save`, { data: JSON.parse(JSON.stringify(this.form)) });
+          if (this.reset) this.$refs.form.resetFields();
+        } else {
+          console.warn('form validate error!!!');
+        }
+      });
+    },
+    display(field) {
+      let dis = _.get(field, `display`);
+      if (!_.isFunction(dis)) return true;
+      else return dis(field, this.form);
+    },
+    // 表单数据类型,提示语,是否禁用,是否错误
+    getField(item, data) {
+      let res = _.get(data, item, null);
+      if (item === 'type') res = res === null ? `text` : res;
+      if (item === 'placeholder') res = res === null ? `请输入${data.label}` : res;
+      if (item === 'selectplaceholder') res = res === null ? `请选择${data.label}` : res;
+      if (item === 'required') res = res === null ? false : res;
+      if (item === `error`) res = res === null ? `${data.label}错误` : res;
+      return res;
+    },
+    dataChange(model) {
+      const value = JSON.parse(JSON.stringify(this.form[model]));
+      this.$emit('dataChange', { model, value });
+    },
+    getDateFormat(e) {
+      if (e === 'year') return 'yyyy';
+      if (e === 'month') return 'MM';
+      if (e === 'date') return 'yyyy-MM-dd';
+      if (e === 'daterange') return 'yyyy-MM-dd';
+      if (e === 'datetime') return 'yyyy-MM-dd HH:mm:ss';
+      if (e === 'datetimerange') return 'yyyy-MM-dd HH:mm:ss';
+      if (e === 'time') return 'HH:mm:ss';
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.c-form {
+  .form {
+    display: flex;
+    flex-wrap: wrap;
+    .form-1 {
+      padding: 0 0 0 10px;
+      .el-form-item {
+        float: left;
+        width: 100%;
+      }
+    }
+  }
+  .btn {
+    text-align: center;
+  }
+}
+</style>

+ 173 - 0
src/components/frame/c-search.vue

@@ -0,0 +1,173 @@
+<template>
+  <div id="c-search">
+    <el-row>
+      <el-col :span="24" class="title" v-if="is_title">
+        <el-col :span="24" class="title_1">
+          <span>{{ title || $route.meta.title }}</span>
+          <span>{{ tip }}</span>
+        </el-col>
+        <el-col :span="24" class="title_2">
+          <span>{{ remark }}</span>
+        </el-col>
+      </el-col>
+      <el-col :span="24" class="search" v-if="is_search">
+        <el-form ref="form" :model="form" label-width="auto">
+          <template v-for="(item, index) in fields">
+            <el-col :span="8" class="form_1" :key="'form-field-' + index" v-if="item.isSearch == true">
+              <el-form-item :label="getField('label', item)" :prop="item.model">
+                <template v-if="!item.custom">
+                  <template v-if="item.type === 'select'">
+                    <el-select v-model="form[item.model]" v-bind="item.options" filterable clearable @change="dataChange(item.model)" size="small">
+                      <slot :name="item.model" v-bind="{ item }"></slot>
+                    </el-select>
+                  </template>
+                  <template v-else>
+                    <el-input
+                      v-model="form[item.model]"
+                      :type="getField('type', item)"
+                      :placeholder="getField('place', item)"
+                      size="small"
+                      clearable
+                      v-bind="item.options"
+                      @change="dataChange(item.model)"
+                    ></el-input>
+                  </template>
+                </template>
+                <template v-else>
+                  <slot :name="item.model" v-bind="{ item }"></slot>
+                  <!-- <el-input v-model="form[item.model]" clearable :placeholder="`输入${item.label}`"></el-input> -->
+                </template>
+              </el-form-item>
+            </el-col>
+          </template>
+          <el-col :span="24" class="btn">
+            <el-button type="primary" size="mini" @click="toSubmit()">查询</el-button>
+            <el-button type="danger" size="mini" @click="toReset()">重置</el-button>
+          </el-col>
+        </el-form>
+      </el-col>
+      <el-col :span="24" class="back" v-if="is_back">
+        <el-button type="primary" size="small" @click="toBack()">返回</el-button>
+        <slot name="custombtn"></slot>
+      </el-col>
+      <el-col :span="24" class="slot">
+        <slot name="isslot"></slot>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const _ = require('lodash');
+export default {
+  name: 'c-search',
+  props: {
+    is_title: { type: Boolean, default: true },
+    is_search: { type: Boolean, default: false },
+    is_back: { type: Boolean, default: false },
+    fields: { type: Array },
+    title: { type: String },
+    tip: { type: String },
+    remark: { type: String },
+  },
+  components: {},
+  data: function () {
+    return {
+      form: {},
+    };
+  },
+  created() {},
+  methods: {
+    // 查询
+    toSubmit() {
+      const obj = _.pickBy(this.form);
+      this.$emit('search', { ...obj });
+    },
+    // 重置
+    toReset() {
+      this.$set(this, `form`, {});
+      this.$emit('search');
+      this.$emit('toReset');
+    },
+    // 文字描述
+    getField(item, data) {
+      let res = _.get(data, item, null);
+      if (item === 'type') res = res === null ? `text` : res;
+      if (item === 'place') res = res === null ? `请输入${data.label}` : res;
+      if (item === 'required') res = res === null ? false : res;
+      if (item === `error`) res = res === null ? `${data.label}错误` : res;
+      return res;
+    },
+    // 获取输入值
+    dataChange(model) {
+      // console.log(model);
+      const value = JSON.parse(JSON.stringify(this.form[model]));
+      // console.log(value);
+    },
+    // 返回
+    toBack() {
+      this.$emit('toBack');
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.title {
+  margin: 0 0 5px 0;
+  .title_1 {
+    margin: 0 0 5px 0;
+    span:first-child {
+      font-size: 20px;
+      font-weight: 700;
+      margin-right: 10px;
+    }
+    span:last-child {
+      font-size: 14px;
+      color: #979797;
+    }
+  }
+  .title_2 {
+    span {
+      color: #8baae7;
+      font-size: 14px;
+      margin-top: 10px;
+    }
+  }
+}
+.search {
+  margin: 0 0 10px 0;
+  .form_1 {
+    padding: 0 0 0 10px;
+    .el-form-item {
+      float: left;
+      width: 100%;
+      margin: 0 0 10px 0;
+    }
+    .el-select {
+      width: 100%;
+    }
+  }
+  .btn {
+    text-align: right;
+  }
+}
+.back {
+  text-align: left;
+  margin: 0 0 10px 0;
+}
+</style>

+ 294 - 0
src/components/frame/c-table.vue

@@ -0,0 +1,294 @@
+<template>
+  <div id="c-table">
+    <el-table
+      ref="table"
+      :row-key="rowKey"
+      :data="data"
+      border
+      stripe
+      size="mini"
+      :max-height="height !== null ? height : ''"
+      @select="handleSelectionChange"
+      @select-all="handleSelectAll"
+      :show-summary="useSum"
+      @row-click="rowClick"
+      :summary-method="computedSum"
+    >
+      <el-table-column type="selection" width="55" v-if="select" :prop="rowKey" :reserve-selection="true"> </el-table-column>
+      <template v-for="(item, index) in fields">
+        <template v-if="item.custom">
+          <el-table-column
+            :key="index"
+            align="center"
+            :label="item.label"
+            v-bind="item.options"
+            :show-overflow-tooltip="item.showTip === false ? item.showTip : true"
+          >
+            <template v-slot="{ row }">
+              <slot :name="item.model" v-bind="{ item, row }"></slot>
+            </template>
+          </el-table-column>
+        </template>
+        <template v-else>
+          <el-table-column
+            :key="index"
+            align="center"
+            :label="item.label"
+            :prop="item.model"
+            :formatter="toFormatter"
+            :sortable="true"
+            v-bind="item.options"
+            :show-overflow-tooltip="item.showTip === false ? item.showTip : true"
+          >
+          </el-table-column>
+        </template>
+      </template>
+      <template v-if="opera.length > 0">
+        <el-table-column label="操作" align="center" :width="operaWidth">
+          <template v-slot="{ row, $index }">
+            <template v-for="(item, index) in opera">
+              <template v-if="display(item, row)">
+                <template v-if="vOpera">
+                  <el-link
+                    v-opera="item.method"
+                    :key="`${item.model}-column-${index}`"
+                    :type="item.type || 'primary'"
+                    :icon="item.icon || ''"
+                    size="mini"
+                    style="padding-right: 10px"
+                    :underline="false"
+                    @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index, item.confirmWord)"
+                  >
+                    {{ item.label }}
+                  </el-link>
+                </template>
+                <template v-else>
+                  <el-link
+                    :key="`${item.model}-column-${index}`"
+                    :type="item.type || 'primary'"
+                    :icon="item.icon || ''"
+                    size="mini"
+                    style="padding-right: 10px"
+                    :underline="false"
+                    @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index, item.confirmWord)"
+                  >
+                    {{ item.label }}
+                  </el-link>
+                </template>
+              </template>
+            </template>
+          </template>
+        </el-table-column>
+      </template>
+    </el-table>
+    <el-row type="flex" align="middle" justify="end" style="padding-top: 1rem" v-if="usePage">
+      <el-col :span="24" style="text-align: right">
+        <el-pagination
+          background
+          layout="sizes,total, prev, pager, next"
+          :page-sizes="[10, 50, 100, 150, 200]"
+          :total="total"
+          :page-size="limit"
+          :current-page.sync="currentPage"
+          @current-change="changePage"
+          @size-change="sizeChange"
+        >
+        </el-pagination>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'c-table',
+  props: {
+    fields: { type: Array, required: true },
+    data: { type: Array, required: true },
+    opera: { type: Array, default: () => [] },
+    rowKey: { type: String, default: '_id' },
+    select: { type: Boolean, default: false },
+    selected: { type: Array, default: () => [] },
+    usePage: { type: Boolean, default: true },
+    total: { type: Number, default: 0 },
+    useSum: { type: Boolean, default: false },
+    sumcol: { type: Array, default: () => [] },
+    sumres: { type: String, default: 'total' },
+    // limit: { type: Number, default: 10 },
+    height: null,
+    operaWidth: { type: Number, default: 200 },
+    vOpera: { type: Boolean, default: false },
+  },
+  components: {},
+  data: function () {
+    return {
+      pageSelected: [],
+      currentPage: 1,
+      limit: this.$limit,
+    };
+  },
+  created() {},
+  methods: {
+    toFormatter(row, column, cellValue, index) {
+      let this_fields = this.fields.filter((fil) => fil.model === column.property);
+      if (this_fields.length > 0) {
+        let format = _.get(this_fields[0], `format`, false);
+        if (format) {
+          let res;
+          if (_.isFunction(format)) {
+            res = format(cellValue);
+          } else {
+            res = this.toFormat({
+              model: this_fields[0].model,
+              value: cellValue,
+            });
+          }
+          return res;
+        } else return cellValue;
+      }
+    },
+    handleOpera(data, method, confirm = false, methodZh, label, index, confirmWord) {
+      let self = true;
+      if (_.isFunction(methodZh)) {
+        methodZh = methodZh(data);
+      } else if (!_.isString(methodZh)) {
+        methodZh = label;
+        self = false;
+      }
+      if (confirm) {
+        let word = self ? methodZh : `您确认${methodZh}该数据?`;
+        if (confirmWord) word = confirmWord;
+        this.$confirm(word, '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning',
+        })
+          .then(() => {
+            this.$emit(method, { data, index });
+          })
+          .catch(() => {});
+      } else {
+        this.$emit(method, { data, index });
+      }
+    },
+    handleSelectionChange(selection, row) {
+      //根据row是否再pageSelected中,判断是添加还是删除
+      let isSelecteds = _.cloneDeep(this.pageSelected);
+      const is_has = isSelecteds.findIndex((f) => f[this.rowKey] === row[this.rowKey]);
+      if (is_has <= -1) {
+        // 没有找到,属于添加
+        isSelecteds.push(row);
+      } else {
+        // 找到了,删除
+        isSelecteds.splice(is_has, 1);
+      }
+      this.$set(this, 'pageSelected', isSelecteds);
+      this.$emit(`handleSelect`, isSelecteds);
+    },
+    handleSelectAll(selection) {
+      //处于没全选状态,选择之后一定是全选,只有处于全选状态时,才会反选(全取消)
+      // console.log(selection);
+      let res = [];
+      if (selection.length > 0) {
+        //全选
+        res = _.uniqBy(this.pageSelected.concat(selection), this.rowKey);
+      } else {
+        //全取消
+        res = _.differenceBy(this.pageSelected, this.data, this.rowKey);
+      }
+      this.$set(this, `pageSelected`, res);
+      this.$emit(`handleSelect`, res);
+    },
+    initSelection() {
+      this.$nextTick(() => {
+        this.$refs.table.clearSelection();
+        this.selected.forEach((info) => {
+          let d = this.data.filter((p) => p._id === info._id);
+          if (d.length > 0) this.$refs.table.toggleRowSelection(d[0]);
+        });
+      });
+    },
+    selectReset() {
+      this.$refs.table.clearSelection();
+    },
+    changePage(page = this.currentPage) {
+      this.$emit('query', { skip: (page - 1) * this.limit, limit: this.limit, ...this.searchInfo });
+    },
+    sizeChange(limit) {
+      this.limit = limit;
+      this.currentPage = 1;
+      this.$emit('query', { skip: 0, limit: this.limit, ...this.searchInfo });
+    },
+    rowClick(row, column, event) {
+      this.$emit(`rowClick`, row);
+    },
+    display(item, row) {
+      let display = _.get(item, `display`, true);
+      if (display === true) return true;
+      else {
+        let res = display(row);
+        return res;
+      }
+    },
+    // 计算合计
+    computedSum({ columns, data }) {
+      if (columns.length <= 0 || data.length <= 0) return '';
+      const result = [];
+      const reg = new RegExp(/^\d+$/);
+      for (const column of columns) {
+        // 判断有没有prop属性
+        const prop = _.get(column, 'property');
+        if (!prop) {
+          result.push('');
+          continue;
+        }
+        // 判断是否需要计算
+        const inlist = this.sumcol.find((f) => f == prop);
+        if (!inlist) {
+          result.push('');
+          continue;
+        }
+        let res = 0;
+        // 整理出要计算的属性(只取出数字或者可以为数字的值)
+        const resetList = data.map((i) => {
+          const d = _.get(i, prop);
+          return d * 1;
+        });
+        if (this.sumres === 'total') {
+          res = this.totalComputed(resetList);
+        } else if (this.sumres === 'avg') {
+          res = this.avgComputed(resetList);
+        } else if (this.sumres === 'max') {
+          res = this.maxComputed(resetList);
+        } else if (this.sumres === 'min') {
+          res = this.minComputed(resetList);
+        }
+        result.push(res);
+      }
+      result[0] = '合计';
+      return result;
+    },
+    // 合计计算
+    totalComputed(data) {
+      // console.log(data);
+      const total = data.reduce((p, n) => p + parseFloat(n), 0);
+      return total;
+    },
+    // 平均值计算
+    avgComputed(data) {
+      const total = this.totalComputed(data);
+      return _.round(_.divide(total, data.length), 2);
+    },
+    // 最大值计算
+    maxComputed(data) {
+      return _.max(data);
+    },
+    // 最小值计算
+    minComputed(data) {
+      return _.min(data);
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 96 - 0
src/components/frame/c-upload.vue

@@ -0,0 +1,96 @@
+<template>
+  <div id="c-upload">
+    <el-upload
+      v-if="url"
+      ref="upload"
+      :action="url"
+      :limit="limit"
+      :accept="accept"
+      :list-type="listType"
+      :file-list="list"
+      :on-exceed="outLimit"
+      :on-preview="filePreview"
+      :on-success="onSuccess"
+      :before-remove="onRemove"
+    >
+      <el-button type="primary" size="mini">选择文件</el-button>
+      <template #tip v-if="tip">
+        <p style="color: #ff0000">{{ tip }}</p>
+      </template>
+    </el-upload>
+    <el-dialog :visible.sync="dialog.show" append-to-body>
+      <img width="100%" :src="dialog.url" alt="" />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+export default {
+  name: 'c-upload',
+  props: {
+    // 图片上传地址
+    url: { type: String },
+    // 可上传文件数目
+    limit: { type: Number },
+    // 接收上传的文件类型
+    accept: { type: String, default: 'image/png, image/jpeg' },
+    // 文件列表的类型--picture-card---picture
+    listType: { type: String, default: 'picture-card' },
+    // 文件提醒
+    tip: { type: String, default: undefined },
+    // 已有数据,赋值,预览
+    list: { type: Array },
+  },
+  model: {
+    prop: 'list',
+    event: 'change',
+  },
+  data: function () {
+    return {
+      // 图片预览
+      dialog: { show: false, url: '' },
+      // 图片列表
+      fileList: [],
+      vueapphost: 'http://broadcast.waityou24.cn',
+    };
+  },
+  methods: {
+    // 图片预览
+    filePreview(file) {
+      // this.dialog = { show: true, url: file.url };
+      window.open(file.url);
+    },
+    // 只允许上传多少个文件
+    outLimit() {
+      this.$message.error(`只允许上传${this.limit}个文件`);
+    },
+    // 上传成功,response:成功信息,file:图片信息,fileList:图片列表
+    onSuccess(response, file, fileList) {
+      if (response.errcode !== 0) {
+        this.$message({ message: `上传失败`, type: 'error' });
+        return;
+      }
+      response = _.omit(response, ['errcode', 'errmsg']);
+      let list = _.cloneDeep(this.list);
+      if (_.isArray(list)) {
+        list.push({ ...response, name: file.name, url: `${this.vueapphost}${response.uri}` });
+      } else {
+        list = [{ ...response, name: file.name, url: `${this.vueapphost}${response.uri}` }];
+      }
+      this.$emit('change', list);
+    },
+    // 删除图片
+    onRemove(file, fileList) {
+      // console.log(file);
+      let list = _.cloneDeep(this.list);
+      // console.log(list);
+      list = list.filter((f) => f.uri !== _.get(file, 'uri'));
+      this.$emit('change', list);
+      return true;
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 44 - 25
src/layout/site.js

@@ -49,31 +49,50 @@ export const menus = [
     type: '0',
   },
   {
-    _id: 'menus_2',
+    id: 'menus_2',
     icon: 'el-icon-user',
-    name: '二级菜单',
-    type: '1',
-    children: [
-      {
-        _id: 'menus_2_1',
-        icon: 'el-icon-user',
-        name: '二级菜单-1',
-        path: '/test/test1',
-      },
-      {
-        _id: 'menus_2_2',
-        icon: 'el-icon-user',
-        name: '三级菜单',
-        type: '2',
-        children: [
-          {
-            _id: 'menus_2_2_1',
-            icon: 'el-icon-user',
-            name: '三级菜单-1',
-            path: '/test/test2/test1',
-          },
-        ],
-      },
-    ],
+    name: '电视节目管理',
+    path: '/tvadmin',
+    type: '0',
+  },
+  // {
+  //   _id: 'menus_2',
+  //   icon: 'el-icon-user',
+  //   name: '二级菜单',
+  //   type: '1',
+  //   children: [
+  //     {
+  //       _id: 'menus_2_1',
+  //       icon: 'el-icon-user',
+  //       name: '二级菜单-1',
+  //       path: '/test/test1',
+  //     },
+  //     {
+  //       _id: 'menus_2_2',
+  //       icon: 'el-icon-user',
+  //       name: '三级菜单',
+  //       type: '2',
+  //       children: [
+  //         {
+  //           _id: 'menus_2_2_1',
+  //           icon: 'el-icon-user',
+  //           name: '三级菜单-1',
+  //           path: '/test/test2/test1',
+  //         },
+  //       ],
+  //     },
+  //   ],
+  // },
+];
+
+// 是否啓用
+export const is_use = [
+  {
+    dict_label: '是',
+    dict_value: '0',
+  },
+  {
+    dict_label: '否',
+    dict_value: '1',
   },
 ];