diff --git a/report-ui/src/components/AnjiPlus/anji-autocomplete.vue b/report-ui/src/components/AnjiPlus/anji-autocomplete.vue new file mode 100644 index 00000000..c2d9a70b --- /dev/null +++ b/report-ui/src/components/AnjiPlus/anji-autocomplete.vue @@ -0,0 +1,139 @@ +<template> + <el-autocomplete + v-model.trim="inputValue" + :debounce="500" + class="inline-input" + :fetch-suggestions="querySearch" + :disabled="disabled" + @select="handleSelect" + @input="changeInput" + > + <template slot-scope="{ item }"> + <div class="name">{{ getItemLabel(item, item.value) }}</div> + <span class="addr">{{ item[option] }}</span> + </template> + </el-autocomplete> +</template> +<script> +import request from "@/utils/request"; +export default { + props: { + disabled: { + type: Boolean, + default: () => { + return false; + } + }, + value: { + type: String, + default: () => { + return ""; + } + }, + url: { + type: String, + default: () => { + return ""; + } + }, + appointValue: { + type: String, + default: () => { + return ""; + } + }, + label: { + type: String, + default: () => { + return ""; + } + }, + option: { + type: String, + default: () => { + return ""; + } + } + }, + data() { + return { + restaurants: [], + inputValue: "" + }; + }, + watch: { + value(val) { + this.echoInput(val); + } + }, + mounted() { + this.echoInput(this.value); + }, + methods: { + getItemLabel(item, value) { + if (this.label.indexOf("${") < 0 && this.label.indexOf("}" < 0)) { + return item[this.label]; + } + let reg = /\$\{[a-zA-Z0-9]*\}/g; + let list = this.label.match(reg); + console.log(list); + // ["${id}", "${text}"] + let result = this.label; + for (let i = 0; i < list.length; i++) { + let sub = list[i]; + let key = sub.replace("${", "").replace("}", ""); + result = result.replace(sub, item[key]); + } + return value + " " + result; + }, + querySearch(queryString, cb) { + request({ url: this.url }).then(res => { + if (res.code == 200 && res.data) { + this.restaurants = res.data; + } else { + this.restaurants = []; + } + this.restaurants = JSON.parse( + JSON.stringify(this.restaurants).replace( + new RegExp(this.appointValue, "g"), + "value" + ) + ); + let results = queryString + ? this.restaurants.filter(this.createFilter(queryString)) + : this.restaurants; + cb(results); + }); + }, + createFilter(queryString) { + return restaurant => { + return ( + restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === + 0 + ); + }; + }, + handleSelect(item) { + this.$emit("input", item.value); + this.$emit("change", item.value, item); + }, + changeInput(val) { + this.$emit("input", val); + this.$emit("change", val); + }, + // 回显 + echoInput(value) { + if (!value) { + this.inputValue = ""; + } else { + this.inputValue = value; + } + } + } +}; +</script> +<style lang="less" scoped> +.inline-input { + width: 100%; +} +</style> diff --git a/report-ui/src/components/AnjiPlus/anji-cascader.vue b/report-ui/src/components/AnjiPlus/anji-cascader.vue new file mode 100644 index 00000000..13c08e51 --- /dev/null +++ b/report-ui/src/components/AnjiPlus/anji-cascader.vue @@ -0,0 +1,314 @@ +<template> + <div> + <el-row> + <el-col v-if="selectIsHide('country')" :span="4"> + <el-select + v-model.trim="countryCode" + filterable + :placeholder="$lang('GLOBAL.countryName')" + :disabled="disabled" + clearable + @change="countryChange" + > + <el-option + v-for="(option, i) in countryArr" + :key="i" + :value="option.value" + :label="option.label" + /> + </el-select> + </el-col> + <el-col v-if="selectIsHide('province')" :span="7"> + <el-select + v-model.trim="provinceCode" + filterable + :placeholder="$lang('GLOBAL.provinceName')" + :disabled="disabled" + clearable + @change="provinceChange" + > + <el-option + v-for="(option, i) in casCaredArr" + :key="i" + :value="option.value" + :label="option.label" + /> + </el-select> + </el-col> + <el-col v-if="selectIsHide('city')" :span="7"> + <el-select + v-model.trim="cityCode" + filterable + :placeholder="$lang('GLOBAL.cityName')" + :disabled="disabled" + clearable + @change="cityChange" + > + <el-option + v-for="(option, x) in cityArr" + :key="x" + :value="option.value" + :label="option.label" + /> + </el-select> + </el-col> + <el-col v-if="selectIsHide('area')" :span="6"> + <el-select + v-model.trim="areaCode" + filterable + :placeholder="$lang('GLOBAL.districtName')" + :disabled="disabled" + clearable + @change="districtChange" + > + <el-option + v-for="(option, y) in districtArr" + :key="y" + :value="option.value" + :label="option.label" + /> + </el-select> + </el-col> + </el-row> + </div> +</template> +<script> +import axios from "axios"; +import { getToken } from "@/utils/auth"; +import Cookies from "js-cookie"; +export default { + name: "Cselect", + props: { + url: { + type: String, + default: () => "/meta/metaAreaInfo/countryTree" + }, + value: null, + singleDisplay: String, + disabled: Boolean + }, + data() { + return { + countryArr: [], + casCaredArr: [], + cityArr: [], + districtArr: [], + countryCode: "", // 国code + provinceCode: "", // 省code + cityCode: "", // 州市code + areaCode: "", // 区县code + countryName: "", + provinceName: "", + cityName: "", + areaName: "" + }; + }, + watch: { + value(value) { + this.echoSelect(value); + this.initData(); + } + }, + mounted() { + this.initData(); + this.echoSelect(this.value); + }, + methods: { + // singleDisplay 不配显示 country province city area 配那个那个不显示 + selectIsHide(val) { + if (this.singleDisplay === undefined) { + return true; + } else { + return !(this.singleDisplay.indexOf(val) >= 0); + } + }, + // 查询数据 + initData() { + this.queryData(); + }, + queryData() { + axios({ + url: process.env.VUE_APP_BASE_API + this.url, + methods: "get", + headers: { + Authorization: getToken(), + systemCode: process.env.VUE_APP_SYSTEM_CODE + } + }).then(res => { + const data = res.data; + if (data.code != 200 || data.data.length == 0) return; + this.countryArr = data.data; + !this.selectIsHide("country") && + (this.casCaredArr = data.data[0].children); + this.updateCountry(); + this.updateCity(); + this.updateDistrict(); + }); + }, + updateCountry() { + for (let i in this.countryArr) { + let obj = this.countryArr[i]; + if (obj.value == this.countryCode) { + this.casCaredArr = obj.children; + break; + } + } + }, + updateCity() { + for (let i in this.casCaredArr) { + let obj = this.casCaredArr[i]; + if (obj.value) { + if (obj.value == this.provinceCode) { + this.cityArr = obj.children; + break; + } + } + } + }, + updateDistrict() { + for (let i in this.cityArr) { + let obj = this.cityArr[i]; + if (obj.value == this.cityCode) { + this.districtArr = obj.children; + break; + } + } + }, + + // 国 + countryChange(val) { + if (val) { + this.updateCountry(); + this.provinceCode = ""; + this.cityCode = ""; + this.areaCode = ""; + const casCared = this.countryArr.find((n, index) => { + if (n.value == val) { + return n; + } + }); + this.countryName = casCared.label; + const obj = { + countryName: this.countryName, + countryCode: this.countryCode, + provinceCode: this.provinceCode, + cityCode: this.cityCode, + areaCode: this.areaCode, + provinceName: this.provinceName, + cityName: this.cityName, + areaName: this.areaName + }; + this.$emit("input", obj); + this.$emit("change", obj); + } else { + this.$emit("input", {}); + this.$emit("change", {}); + } + }, + // 省 + provinceChange(val) { + if (val) { + this.updateCity(); + this.cityCode = ""; + this.areaCode = ""; + const casCared = this.casCaredArr.find((n, index) => { + if (n.value == val) { + return n; + } + }); + this.provinceName = casCared.label; + const obj = { + countryName: this.countryName, + countryCode: this.countryCode, + provinceCode: this.provinceCode, + cityCode: this.cityCode, + areaCode: this.areaCode, + provinceName: this.provinceName, + cityName: this.cityName, + areaName: this.areaName + }; + this.$emit("input", obj); + this.$emit("change", obj); + } else { + this.$emit("input", {}); + this.$emit("change", {}); + } + }, + // 市 + cityChange(val) { + if (val) { + this.areaCode = ""; + this.updateDistrict(); + const city = this.cityArr.find((n, index) => { + if (n.value == val) { + return n; + } + }); + this.cityName = city.label; + const obj = { + countryName: this.countryName, + countryCode: this.countryCode, + provinceCode: this.provinceCode, + cityCode: this.cityCode, + areaCode: this.areaCode, + provinceName: this.provinceName, + cityName: this.cityName, + areaName: this.areaName + }; + this.$emit("input", obj); + this.$emit("change", obj); + } else { + this.$emit("input", {}); + this.$emit("change", {}); + } + }, + // 区 + districtChange(val) { + if (val) { + const district = this.districtArr.find((n, index) => { + if (n.value == val) { + return n; + } + }); + this.areaName = district.label; + const obj = { + countryName: this.countryName, + countryCode: this.countryCode, + provinceCode: this.provinceCode, + cityCode: this.cityCode, + areaCode: this.areaCode, + provinceName: this.provinceName, + cityName: this.cityName, + areaName: this.areaName + }; + this.$emit("input", obj); + this.$emit("change", obj); + } else { + this.$emit("input", {}); + this.$emit("change", {}); + } + }, + echoSelect(value) { + if (!value) { + this.countryCode = ""; + this.provinceCode = ""; + this.cityCode = ""; + this.areaCode = ""; + this.countryName = ""; + this.provinceName = ""; + this.cityName = ""; + this.areaName = ""; + } else { + this.countryName = this.value.countryName; + this.countryCode = this.value.countryCode; + this.provinceCode = this.value.provinceCode; + this.cityCode = this.value.cityCode; + this.areaCode = this.value.areaCode || this.value.regionCode; + this.provinceName = this.value.provinceName; + this.cityName = this.value.cityName; + this.areaName = this.value.areaName || this.value.regionName; + } + } + } +}; +</script> diff --git a/report-ui/src/components/AnjiPlus/anji-checkbox.vue b/report-ui/src/components/AnjiPlus/anji-checkbox.vue new file mode 100644 index 00000000..e1a649df --- /dev/null +++ b/report-ui/src/components/AnjiPlus/anji-checkbox.vue @@ -0,0 +1,127 @@ +<template> + <el-checkbox-group v-model="selectValue" class="filter-item" @change="change"> + <el-checkbox + v-for="item in options" + :key="item.id" + :label="item.id" + :disabled="disabled" + >{{ item.text }}</el-checkbox + > + </el-checkbox-group> +</template> + +<script> +import request from "@/utils/request"; +import { valueOf } from "screenfull"; +export default { + props: { + dictCode: null, // 当传入dictCode时,可以不用传递url + url: null, + value: null, + placeholder: null, + label: { + type: String, + default: "text" + }, + option: { + type: String, + default: "id" + }, + multiple: null, + localOptions: null, + disabled: null, + clearable: { + type: Boolean, + default: true + }, + collapseTags: { + type: Boolean, + default: false + } + }, + data() { + return { + options: null, + selectValue: [] + }; + }, + computed: { + // 根据dictCode和url拼出最终的请求url + requestUrl() { + if (this.url != null && this.url.trim() != "") { + return this.url; + } + if (this.dictCode != null && this.dictCode.trim() != "") { + return `/tms/gaeaDict/select/${this.dictCode}`; + } + return null; + } + }, + watch: { + value: function(val, oldVal) { + this.echoCheckboxValue(val); + } + }, + mounted() { + this.echoCheckboxValue(this.value); + if (this.requestUrl == null) { + this.options = this.localOptions; + return; + } + this.queryData(); + }, + methods: { + change(value) { + const strValue = value.join(","); + if (value === "") { + value = null; + } + this.$emit("input", strValue); + this.$emit("change", strValue, this.options); + }, + // 从本地localStorage取 gaeaDict + getOptionsFromLocalStorage() { + let dicts = JSON.parse(localStorage.getItem("gaeaDict")); + let options = []; + if (!dicts.hasOwnProperty(this.dictCode)) { + return []; + } + let dictItems = dicts[this.dictCode]; + for (let i = 0; i < dictItems.length; i++) { + let dictItem = dictItems[i]; + options.push({ id: dictItem.id.toString(), text: dictItem.text }); + } + return options; + }, + queryData() { + // 所有从本地localStorage取,因为在App.vue中已经请求远程保存到本地了 + let options = this.getOptionsFromLocalStorage(); + if (this.isNotBlank(options)) { + this.options = options; + return; + } + // 本地localStorage取不到,再从远程接口取 + if (this.requestUrl == null) { + return; + } + request({ + url: this.requestUrl, + params: { + multiple: this.multiple == null ? null : 1 + } + }).then(response => { + this.options = response.data; + }); + }, + // 回显 + echoCheckboxValue(val) { + if (!val) { + this.selectValue = []; + } else { + const arr = val.split(","); + this.selectValue = arr; + } + } + } +}; +</script> diff --git a/report-ui/src/components/AnjiPlus/anji-contextMenu.vue b/report-ui/src/components/AnjiPlus/anji-contextMenu.vue new file mode 100644 index 00000000..f04babbe --- /dev/null +++ b/report-ui/src/components/AnjiPlus/anji-contextMenu.vue @@ -0,0 +1,50 @@ +<!-- + * @Descripttion: 右键菜单 + * @version: + * @Author: qianlishi + * @Date: 2021-10-21 15:52:03 + * @LastEditors: qianlishi + * @LastEditTime: 2021-10-21 19:40:05 +--> +<template> + <div v-show="visible" class="contentmenu" :style="styleObj"> + <slot /> + </div> +</template> +<script> +export default { + props: { + styleObj: Object, + visible: Boolean, + }, + data() { + return {} + }, + watch: { + visible(value) { + if (value) { + document.body.addEventListener('click', this.closeMenu) + } else { + document.body.removeEventListener('click', this.closeMenu) + } + }, + }, + methods: { + closeMenu() { + this.$emit('update:visible', false) + }, + }, +} +</script> +<style lang="scss" scoped> +.contentmenu { + position: fixed; + z-index: 99999; + list-style: none; + -webkit-box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); + padding: 0; + background: #fff; + cursor: pointer; +} +</style> diff --git a/report-ui/src/components/AnjiPlus/anji-countryCity.vue b/report-ui/src/components/AnjiPlus/anji-countryCity.vue new file mode 100644 index 00000000..f98a3465 --- /dev/null +++ b/report-ui/src/components/AnjiPlus/anji-countryCity.vue @@ -0,0 +1,97 @@ +<template> + <el-cascader v-model="selectValue" style="width: 100%" :props="{ lazy: true, lazyLoad: lazyLoad, label: 'text', value: 'id' }" :options="countryCity" /> +</template> + +<script> +import { mapGetters } from 'vuex' + +export default { + props: { + value: null, + }, + computed: { + ...mapGetters(['countryCity']), + selectValue: { + get: function() { + return [...this.value] + }, + set: function(val) { + this.$emit('update:value', val) + }, + }, + }, + mounted() { + if (this.value && this.value.length > 0) { + this.initCity() + } else { + this.$store.dispatch('dict/add_countryCity', { level: 0 }) + } + }, + methods: { + getCityName() { + const value = this.selectValue + const country = this.countryCity.find((item) => item.id === value[0]) + const province = country.children.find((item) => item.id === value[1]) + const city = province.children.find((item) => item.id === value[2]) + const region = city.children.find((item) => item.id === value[3]) + return [country.text, province.text, city.text, region.text] + }, + // 初始化数据 + initCity() { + const value = this.value + // console.log(value) + if (!value) { + return + } + const country = this.countryCity.find((item) => item.id === value[0]) + console.log(country) + if (!country || !country.children) { + this.getData().then((list) => { + this.getData({ country: value[0], level: 1 }).then((list) => { + this.getData({ country: value[0], province: value[1], level: 2 }).then((list) => { + this.getData({ country: value[0], province: value[1], city: value[2], level: 3, update: true }).then((list) => {}) + }) + }) + }) + } else { + const province = country.children.find((item) => item.id === value[1]) + if (!province || !province.children) { + this.getData({ country: value[0], level: 1 }).then((list) => { + this.getData({ country: value[0], province: value[1], level: 2 }).then((list) => { + this.getData({ country: value[0], province: value[1], city: value[2], level: 3, update: true }).then((list) => {}) + }) + }) + } else { + const city = province.children.find((item) => item.id === value[2]) + if (!city || !city.children) { + this.getData({ country: value[0], province: value[1], level: 2 }).then((list) => { + this.getData({ country: value[0], province: value[1], city: value[2], level: 3, update: true }).then((list) => {}) + }) + } else { + const region = city.children.find((item) => item.id === value[3]) + if (!region) { + this.getData({ country: value[0], province: value[1], city: value[2], level: 3, update: true }).then((list) => {}) + } + } + } + } + }, + getData(params) { + return this.$store.dispatch('dict/add_countryCity', params) + }, + lazyLoad(node, resolve) { + console.log(node) + const { level, path, data } = node + if (data && data.children) { + resolve(data.children) + } else { + if (level === 0) { + return + } + const params = { country: path[0], province: path[1], city: path[2], level } + this.$store.dispatch('dict/add_countryCity', params).then((list) => resolve(list)) + } + }, + }, +} +</script> diff --git a/report-ui/src/components/AnjiPlus/anji-crud/anji-crud.vue b/report-ui/src/components/AnjiPlus/anji-crud/anji-crud.vue index bcc89183..059796f5 100644 --- a/report-ui/src/components/AnjiPlus/anji-crud/anji-crud.vue +++ b/report-ui/src/components/AnjiPlus/anji-crud/anji-crud.vue @@ -12,330 +12,357 @@ /> </div> <div class="right-container"> - <!-- 查询表单开始 --> - <el-form - ref="formSearch" - :model="queryParams" - label-width="100px" - v-permission="option.buttons.query.permission" - > - <el-row> - <el-col - v-for="(item, index) in queryFormFieldExcludeTree" - :key="item.field" - :span="queryFormFieldSpan(item)" - > - <el-form-item - v-if="index <= 2 || (index > 2 && queryParams.showMoreSearch)" - :label="item.label" - :rules="item.rules" - :prop="item.field" - > - <!-- 输入框 --> - <el-input - v-if=" - item.inputType == 'input' || item.inputType == 'input-number' - " - v-model.trim="queryParams[item.field]" - :placeholder="item.placeholder || '请输入'" - :clearable="item.clearable !== false" - :disabled="item.disabled" - @change="value => queryFormChange(item.field, value)" - /> - <!-- 开关 --> - <el-switch - v-else-if="item.inputType == 'switch'" - v-model.trim="queryParams[item.field]" - :disabled="item.disabled" - :active-value="item.switchOption.disableValue" - :inactive-value="item.switchOption.enableValue" - active-color="#5887fb" - inactive-color="#ccc" - @change="value => queryFormChange(item.field, value)" - /> - <!-- 下拉框 --> - <anji-select - v-else-if="item.inputType == 'anji-select'" - v-model.trim="queryParams[item.field]" - :multiple="item.anjiSelectOption.multiple" - :dict-code="item.anjiSelectOption.dictCode" - :url="item.anjiSelectOption.url" - :method="item.anjiSelectOption.method" - :query-param="item.anjiSelectOption.queryParam" - :option="item.anjiSelectOption.option" - :label="item.anjiSelectOption.label" - :disabled-options="item.anjiSelectOption.disabledOptions" - :disabled="item.disabled" - :merge-label="item.anjiSelectOption.mergeLabel" - @change="value => queryFormChange(item.field, value)" - /> - <!-- 日期时间框 --> - <el-date-picker - v-else-if="item.inputType.indexOf('date') >= 0" - v-model="queryParams[item.field]" - style="width: 100%" - :placeholder="item.placeholder || '请选择'" - :type="item.inputType" - :clearable="item.clearable !== false" - @change="value => queryFormChange(item.field, value)" - /> - <!-- 待扩展的表单类型,请自行扩展 --> - <el-input - v-else - placeholder="组件不支持此类型表单请至组件内部自行扩展" - disabled - /> - </el-form-item> - </el-col> - - <el-col :span="6" style="text-align: center"> - <el-button type="primary" @click="handleQueryForm('query')" - >查询</el-button - > - <el-button type="danger" @click="handleResetForm()">重置</el-button> - <a - v-if="queryFormFieldExcludeTree.length > 3" - style="margin-left: 8px" - @click="handleToggleMoreSearch" - > - {{ queryParams.showMoreSearch == true ? "收起" : "展开" }} - <i - :class=" - queryParams.showMoreSearch - ? 'el-icon-arrow-up' - : 'el-icon-arrow-down' - " - /> - </a> - </el-col> - </el-row> - </el-form> - <!-- 查询表单结束 --> + <div class="top_part"> + <!-- 查询表单开始 --> + <el-form + v-if="queryFormTreeHide == false" + ref="formSearch" + :model="queryParams" + label-width="100px" + style="border-bottom: 1px solid #dbdde3; margin-bottom: 10px" + > + <div class="screenFlex"> + <div class="searchFormFlex"> + <el-row> + <template v-for="(item, index) in queryFormFieldExcludeTree"> + <el-col + v-if="index < 3 || queryParams.showMoreSearch" + :key="item.field" + :span="8" + > + <el-form-item + :label="item.label" + :rules="item.rules" + :prop="item.field" + > + <!-- 输入框 --> + <el-input + v-if=" + item.inputType == 'input' || + item.inputType == 'input-number' + " + v-model.trim="queryParams[item.field]" + :placeholder="item.placeholder || '请输入'" + :clearable="item.clearable !== false" + :disabled="item.disabled" + @change="value => queryFormChange(item.field, value)" + /> + <!-- 开关 --> + <el-switch + v-else-if="item.inputType == 'switch'" + v-model.trim="queryParams[item.field]" + :disabled="item.disabled" + :active-value="item.switchOption.disableValue" + :inactive-value="item.switchOption.enableValue" + active-color="#5887fb" + inactive-color="#ccc" + @change="value => queryFormChange(item.field, value)" + /> + <!-- 下拉框 --> + <anji-select + v-else-if="item.inputType == 'anji-select'" + v-model.trim="queryParams[item.field]" + :multiple="item.anjiSelectOption.multiple" + :dict-code="item.anjiSelectOption.dictCode" + :url="item.anjiSelectOption.url" + :method="item.anjiSelectOption.method" + :query-param="item.anjiSelectOption.queryParam" + :option="item.anjiSelectOption.option" + :label="item.anjiSelectOption.label" + :disabled-options=" + item.anjiSelectOption.disabledOptions + " + :disabled="item.disabled" + :merge-label="item.anjiSelectOption.mergeLabel" + :local-options="item.anjiSelectOption.localOptions" + @change="value => queryFormChange(item.field, value)" + /> + <!-- 日期时间框 --> + <el-date-picker + v-else-if="item.inputType.indexOf('date') >= 0" + v-model="queryParams[item.field]" + style="width: 100%" + :placeholder="item.placeholder || '请选择'" + :type="item.inputType" + :format="item.format" + :value-format="item.valueFormat" + :clearable="item.clearable !== false" + @change="value => queryFormChange(item.field, value)" + /> + <anji-cascader + v-else-if="item.inputType == 'anji-cascader'" + v-model.trim="queryParams[item.field]" + :disabled="item.disabled" + :single-display="item.anjiCascader.singleDisplay" + :url="item.anjiCascader.url" + @change=" + value => queryFormChange(item.field, value, null) + " + /> + <!-- 待扩展的表单类型,请自行扩展 --> + <el-input + v-else + placeholder="组件不支持此类型表单请至组件内部自行扩展" + disabled + /> + </el-form-item> + </el-col> + </template> + </el-row> + </div> - <!-- 批量操作 --> - <slot name="buttonLeftOnTable" /> - <el-button - v-if=" - option.buttons.add.isShow == undefined - ? true - : option.buttons.add.isShow - " - v-permission="option.buttons.add.permission" - type="primary" - icon="el-icon-plus" - @click="handleOpenEditView('add')" - >新增</el-button - > - <el-button - v-if=" - option.buttons.delete.isShow == undefined - ? true - : option.buttons.delete.isShow - " - v-permission="option.buttons.delete.permission" - :disabled="disableBatchDelete" - type="danger" - icon="el-icon-delete" - @click="handleDeleteBatch()" - >删除</el-button - > + <div class="screenButtons"> + <el-button + v-if="queryFormFieldExcludeTree.length > 3" + class="button" + size="mini" + plain + @click="handleToggleMoreSearch" + > + <i + :class=" + queryParams.showMoreSearch + ? 'el-icon-arrow-up' + : 'el-icon-arrow-down' + " + /> + {{ queryParams.showMoreSearch == true ? "展开" : "收起" }} + </el-button> + <el-button + class="button" + size="mini" + plain + @click="handleResetForm()" + >重置</el-button + > + <el-button + class="button" + size="mini" + type="primary" + @click="handleQueryForm('query')" + >查询</el-button + > + </div> + </div> + </el-form> + <!-- 查询表单结束 --> + <!-- 批量操作 --> + <div style="padding-bottom: 8px"> + <slot name="buttonLeftOnTable" :selection="checkRecords" /> + <el-button + v-if=" + option.buttons.add.isShow == undefined + ? true + : option.buttons.add.isShow + " + v-permission="option.buttons.add.permission" + class="button" + plain + icon="el-icon-plus" + @click="handleOpenEditView('add')" + >新增</el-button + > + <el-button + v-if=" + option.buttons.delete.isShow == undefined + ? true + : option.buttons.delete.isShow + " + v-permission="option.buttons.delete.permission" + class="button" + plain + :disabled="disableBatchDelete" + type="danger" + icon="el-icon-delete" + @click="handleDeleteBatch()" + >删除</el-button + > + <slot name="buttonRightOnTable" :selection="checkRecords" /> + </div> + </div> <!-- 表格开始 --> - <el-table - class="anji_curd_table" - :data="records" - border - @selection-change="handleSelectionChange" - @sort-change="handleSortChange" - > - <!--多选--> - <el-table-column fixed type="selection" width="50" align="center" /> - <!--隐藏列--> - <el-table-column v-if="tableExpandColumns.length > 0" type="expand"> - <template slot-scope="scope"> - <p - v-for="item in tableExpandColumns" - :key="item.field" - class="table-expand-item" - > - <span class="titel"> {{ item.label }}: </span> - <span>{{ scope.row[item.field] }}</span> - </p> - </template> - </el-table-column> - <!--序号--> - <el-table-column label="序号" min-width="50" align="center"> - <template slot-scope="scope"> - {{ - queryParams.pageSize * (queryParams.pageNumber - 1) + - scope.$index + - 1 - }} - </template> - </el-table-column> - - <template v-for="item in option.columns"> - <el-table-column - v-if="item.tableHide != true && item.columnType != 'expand'" - :key="item.field" - :prop="item.field" - :label="fieldLabel(item)" - :min-width="item.minWidth || 110" - :sortable="item.sortable" - :show-overflow-tooltip="true" + <div class="main_part"> + <div class="page_main"> + <el-table + ref="tables" + class="elTable" align="center" + :data="records" + :row-class-name="tableRowClassName" + border + @selection-change="handleSelectionChange" + @sort-change="handleSortChange" + @row-dblclick="handleSelectionDblclick" + @row-contextmenu="rowContextMenu" > - <template slot-scope="scope"> - <div v-if="item.columnType == 'imgPreview'"> - <!-- 图片缩略图--> - <el-image - style="width: 25%; height: 50%" - fit="contain" - :src="scope.row[item.field]" - :preview-src-list="[scope.row[item.field]]" - /> - </div> - <div v-else> - <span v-if="item.inputType == 'switch' && !item.colorStyle"> - <el-switch - v-model.trim="scope.row[item.field]" - :active-value="1" - :inactive-value="0" - active-color="#5887fb" - inactive-color="#ccc" - @change="switchChange(scope.row, item.switchOption)" - /> - </span> - <!-- 带单位 --> - <span v-else-if="item.inputType == 'anji-input'">{{ - fieldValueByAnjiInput(scope.row[item.field], item) - }}</span> - <!--表格 a 合并 b上--> - <span v-else-if="item.mergeColumn" - >{{ scope.row[item.field] }}({{ - scope.row[item.mergeColumn] - }})</span - > - <!-- 没有单位 --> - <span - v-else-if="item.colorStyle" - :class="item.colorStyle[scope.row[item.editField]]" - >{{ fieldValueByRowRenderer(scope.row, item) }}</span + <!--多选--> + <el-table-column fixed type="selection" width="50" align="center" /> + <!--隐藏列--> + <el-table-column v-if="tableExpandColumns.length > 0" type="expand"> + <template slot-scope="scope"> + <p + v-for="item in tableExpandColumns" + :key="item.field" + class="table-expand-item" > - <span v-else>{{ - fieldValueByRowRenderer(scope.row, item) - }}</span> - <!-- 正常展示模式 - <div v-if="!item.custom"> - 是第一列数据 && 需要高亮字段不为false 高亮并且可以点击 - <span v-if="!index && item.operate !== false" class="view" @click="handleOpenEditView('view', scope.row)">{{ scope.row[item.field] }}</span> - <span v-else>{{ scope.row[item.field] }}</span> - </div> - --> - <!-- 自定义展示数据 - <div v-else v-html="item.renderer(scope.row)" />--> - </div> + <span class="titel"> {{ item.label }}: </span> + <span>{{ scope.row[item.field] }}</span> + </p> + </template> + </el-table-column> + <!--序号--> + <el-table-column label="序号" min-width="50" align="center"> + <template slot-scope="scope"> + {{ + queryParams.pageSize * (queryParams.pageNumber - 1) + + scope.$index + + 1 + }} + </template> + </el-table-column> + + <template v-for="(item, index) in option.columns"> + <el-table-column + v-if="item.tableHide != true && item.columnType != 'expand'" + :key="index" + :prop="item.field" + :label="fieldLabel(item)" + :min-width="item.minWidth || 110" + :sortable="item.sortable" + :show-overflow-tooltip="true" + align="center" + > + <template slot-scope="scope"> + <div v-if="item.columnType == 'imgPreview'"> + <!-- 图片缩略图--> + <el-image + style="width: 25%; height: 50%" + fit="contain" + :src="scope.row[item.field]" + :preview-src-list="[scope.row[item.field]]" + /> + </div> + <div v-else> + <span v-if="item.inputType == 'switch' && !item.colorStyle"> + <el-switch + v-model.trim="scope.row[item.field]" + :active-value="1" + :inactive-value="0" + active-color="#5887fb" + inactive-color="#ccc" + @change="switchChange(scope.row, item.switchOption)" + /> + </span> + <!-- 带单位 --> + <span v-else-if="item.inputType == 'anji-input'">{{ + fieldValueByAnjiInput(scope.row[item.field], item) + }}</span> + <!--表格 a 合并 b上--> + <span v-else-if="item.mergeColumn" + >{{ scope.row[item.field] }}({{ + scope.row[item.mergeColumn] + }})</span + > + <!-- 没有单位 --> + <span + v-else-if="item.colorStyle" + :class="item.colorStyle[scope.row[item.editField]]" + >{{ fieldValueByRowRenderer(scope.row, item) }}</span + > + <span v-else>{{ + fieldValueByRowRenderer(scope.row, item) + }}</span> + </div> + </template> + </el-table-column> </template> - </el-table-column> - </template> - <!--操作栏--> - <el-table-column - align="center" - fixed="right" - label="操作" - :width=" - option.buttons.customButton && - option.buttons.customButton.operationWidth - ? option.buttons.customButton.operationWidth - : 100 - " - > - <template slot-scope="scope"> - <slot name="edit" :msg="scope.row" /> - <el-button - v-if=" - (option.buttons.query.isShow == undefined - ? true - : option.buttons.query.isShow) && - hasPermission(option.buttons.edit.permission) == false - " - type="text" - size="small" - @click="handleOpenEditView('view', scope.row)" - v-permission="option.buttons.query.permission" - >查看</el-button - > - <el-button - v-if=" - option.buttons.edit.isShow == undefined - ? true - : option.buttons.edit.isShow - " - type="text" - size="small" - @click="handleOpenEditView('edit', scope.row)" - v-permission="option.buttons.edit.permission" - >编辑</el-button - > - <el-button - v-if=" - hasRowCustomButton == false && - option.buttons.delete.isShow == undefined - ? true - : option.buttons.edit.isShow + <!--操作栏--> + <el-table-column + align="center" + fixed="right" + label="操作" + :width=" + option.buttons.customButton && + option.buttons.customButton.operationWidth + ? option.buttons.customButton.operationWidth + : 100 " - type="text" - size="small" - @click="handleDeleteBatch(scope.row)" - v-permission="option.buttons.delete.permission" - >删除</el-button > - <el-dropdown v-if="hasRowCustomButton" trigger="click"> - <span class="el-dropdown-link"> - 更多<i class="el-icon-caret-bottom el-icon--right" /> - </span> - <el-dropdown-menu slot="dropdown"> - <el-dropdown-item class="clearfix"> - <slot name="rowButton" :msg="scope.row" /> - <el-button - v-if=" - option.buttons.delete.isShow == undefined - ? true - : option.buttons.edit.isShow - " - type="text" - size="small" - @click="handleDeleteBatch(scope.row)" - v-permission="option.buttons.delete.permission" - >删除</el-button - > - </el-dropdown-item> - </el-dropdown-menu> - </el-dropdown> - </template> - </el-table-column> - </el-table> - <div class="pagination"> - <el-pagination - v-show="total > 0" - background - :current-page.sync="queryParams.pageNumber" - :page-sizes="$pageSizeAll" - :page-size="queryParams.pageSize" - layout="total, prev, pager, next, jumper, sizes" - :total="total" - @size-change="handleSizeChange" - @current-change="handleCurrentChange" - /> - <div> - <slot name="tableSelectionBtn" :selection="checkRecords" /> + <template slot-scope="scope"> + <slot name="rowButton" :msg="scope.row" /> + <el-button + v-if=" + option.buttons.edit.isShow == undefined + ? true + : option.buttons.edit.isShow + " + type="text" + size="small" + @click="handleOpenEditView('edit', scope.row)" + >编辑</el-button + > + <el-button + v-if=" + hasCustomButtonInRowMore == false && + option.buttons.delete.isShow == undefined + ? true + : option.buttons.edit.isShow + " + type="text" + size="small" + @click="handleDeleteBatch(scope.row)" + >删除</el-button + > + <el-dropdown v-if="hasCustomButtonInRowMore" trigger="click"> + <span class="el-dropdown-link" + >更多<i class="el-icon-caret-bottom el-icon--right" /> + </span> + <el-dropdown-menu slot="dropdown"> + <el-dropdown-item class="clearfix"> + <slot name="rowButtonInMore" :msg="scope.row" /> + <el-button + v-if=" + option.buttons.delete.isShow == undefined + ? true + : option.buttons.edit.isShow + " + type="text" + size="small" + @click="handleDeleteBatch(scope.row)" + >删除</el-button + > + </el-dropdown-item> + </el-dropdown-menu> + </el-dropdown> + </template> + </el-table-column> + </el-table> + <div class="page_bottom"> + <div class="pagination"> + <div> + <slot name="tableSelectionBtn" :selection="checkRecords" /> + </div> + <el-pagination + v-show="total > 0" + background + :current-page.sync="queryParams.pageNumber" + :page-sizes="$pageSizeAll" + :page-size="queryParams.pageSize" + layout="total, prev, pager, next, jumper, sizes" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> </div> </div> - <!-- 表格结束 --> - <EditDialog ref="edit" + :submit-detail-data="option.submitDetailData" + :handle-detail-data="option.handleDetailData" :option="option" :model-type="editDialogModelType" :visible="editDialogOpen" @@ -351,16 +378,37 @@ </EditDialog> </div> <slot name="pageSection" /> + <!-- 右键菜单 --> + <anji-contextMenu + :visible.sync="isShowRowContextMenu" + :style-obj="contextMenuConfigStyle" + > + <div + v-for="(item, index) in option.contextMenu" + :key="index" + class="contextMenu" + > + <el-button + type="text" + :disabled="item.disabled" + class="contextMenuItem" + @click="handleContextMenuItem(item)" + >{{ item.label }}</el-button + > + </div> + </anji-contextMenu> </div> </template> <script> import AnjiTree from "@/components/AnjiPlus/anji-tree.vue"; import EditDialog from "./edit"; import request from "@/utils/request"; +import anjiContextMenu from "@/components/AnjiPlus/anji-contextMenu"; export default { components: { EditDialog, - AnjiTree + AnjiTree, + anjiContextMenu }, props: { option: { @@ -368,6 +416,11 @@ export default { type: Object, default: () => { return { + formHeight: this.$refs.formSearch.$el.offsetHeight, + // 详情页中输入框左边文字宽度 + labelWidth: "120px", + // 查询区隐藏 + queryFormHide: false, // 查询表单条件 queryFormFields: [], // 按钮 @@ -404,13 +457,24 @@ export default { editDialogRowData: {}, // 编辑时的主键 editDialogModelType: "view", // 编辑 查看 - hasRowCustomButton: false // 除了编辑删除外,还有自定义的行按钮 + hasCustomButtonInRowMore: false, // 除了编辑删除外,还有自定义的行按钮 + + isShowRowContextMenu: false, + contextMenuConfigStyle: {}, + contextMenuRow: {} }; }, + computed: { + // 查询区隐藏 + queryFormTreeHide() { + const flag = + this.option.queryFormHide != null && this.option.queryFormHide == true; + return flag; + }, // 左侧树形查询条件 queryFormTreeField() { - var treeField = this.option.queryFormFields.find( + const treeField = this.option.queryFormFields.find( item => item["inputType"] == "anji-tree" ); return treeField; @@ -421,29 +485,26 @@ export default { }, // 不包含树形控件的查询条件 queryFormFieldExcludeTree() { - var treeFields = this.option.queryFormFields.filter( + let treeFields = this.option.queryFormFields.filter( item => item["inputType"] != "anji-tree" ); return treeFields; }, // 主键的列名 primaryKeyFieldName() { - var primaryKey = this.option.columns.find( + let primaryKey = this.option.columns.find( item => item["primaryKey"] == true ); if (primaryKey != null) { return primaryKey["field"]; } else { return null; - console.warn( - "在columns中查找primaryKey=true失败,会导致查询详情和删除失败" - ); } }, // 表格中可展开的列 tableExpandColumns() { - var expandColumns = this.option.columns.filter( + let expandColumns = this.option.columns.filter( item => item["columnType"] == "expand" ); return expandColumns; @@ -461,36 +522,26 @@ export default { this.$set(this.queryParams, item.field, item.defaultValue || null); }); // 查询列表 - this.handleQueryForm("query"); + if (this.option.skipQuery || this.option.skipQuery == undefined) { + this.handleQueryForm("query"); + } this.queryFormChange(); }, mounted() { - if (this.$scopedSlots["rowButton"] != null) { - this.hasRowCustomButton = true; + if (this.$scopedSlots["rowButtonInMore"] != null) { + this.hasCustomButtonInRowMore = true; } else { - this.hasRowCustomButton = false; + this.hasCustomButtonInRowMore = false; } + console.log(`是否有自定义行按钮: ${this.hasCustomButtonInRowMore}`); }, methods: { queryFormFieldSpan(item) { - // console.log(item) - if (item.span != null) { return item.span; } else { return 6; } - // let rowLength = this.option.queryFormFields.length; - // console.log(rowLength, "ss") - // console.log(rowLength % 3) - // if (rowLength <= 3) { - // return 6 - // } - // else if (rowLength % 3 == 0) { - // return 8 - // } else if (rowLength > 6) { - // return 8 - // } }, // 切换更多搜索条件 handleToggleMoreSearch() { @@ -503,8 +554,8 @@ export default { console.warn("排序字段名prop为空,无法排序"); return; } - var sort = column.prop; // 列表查询默认排序列 - var order = column.order == "ascending" ? "ASC" : "DESC"; + let sort = column.prop; // 列表查询默认排序列 + let order = column.order == "ascending" ? "ASC" : "DESC"; this.queryParams["sort"] = sort; this.queryParams["order"] = order; this.handleQueryForm("query"); @@ -520,7 +571,7 @@ export default { // 如果是点树查询,把查询区里的属性去掉 if (from == "tree") { if (this.hasTreeFieldInQueryForm) { - var treeVal = this.queryParams[this.queryFormTreeField.field]; + let treeVal = this.queryParams[this.queryFormTreeField.field]; this.queryParams = { pageNumber: 1, pageSize: 10 @@ -537,12 +588,25 @@ export default { this.queryParams["order"] = this.option.buttons.query.order; } this.queryParams.pageNumber = 1; + + // 添加一些其他的查询参数 + if (this.option.buttons.query.params) { + const params = this.option.buttons.query.params; + for (const key in params) { + this.queryParams[key] = params[key]; + } + } + this.handleQueryPageList(); }, + // 外部追加参数进来 + handleAddQueryParams(k, v) { + this.queryParams[k] = v; + }, // 列表查询 async handleQueryPageList() { - var params = this.queryParams; - // 将特殊参数值urlcode处理 var params = this.urlEncodeObject(this.queryParams, 'order,sort') + // 将特殊参数值urlcode处理 + let params = this.urlEncodeObject(this.queryParams, "order,sort"); const { data, code } = await this.option.buttons.query.api(params); if (code != "200") return; this.records = data.records; @@ -550,21 +614,30 @@ export default { }, // 重置 handleResetForm() { + const showMoreSearch = this.queryParams.showMoreSearch; this.queryParams = { + order: "", + sort: "", pageNumber: 1, - pageSize: 10 + pageSize: 10, + showMoreSearch }; - // this.$refs['queryForm'].resetFields() - // this.records = [] - // this.total = 0 + + // 查询条件表单只读模式下不重置默认值 + const queryFormFieldsOption = this.option.queryFormFields; + queryFormFieldsOption.forEach(el => { + if (el.disabled) { + this.queryParams[el.field] = el.defaultValue; + } + }); }, // 树形查询条件点击回调 handleTreeNodeCheck() { this.handleQueryForm("tree"); // 为新建页面的对应属性值,绑定上对应的默认值 - var treeFieldName = this.queryFormTreeField["field"]; - for (var i = 0; i < this.option.columns.length; i++) { - var item = this.option.columns[i]; + let treeFieldName = this.queryFormTreeField["field"]; + for (let i = 0; i < this.option.columns.length; i++) { + let item = this.option.columns[i]; if ( item["editField"] == treeFieldName || item["field"] == treeFieldName @@ -606,13 +679,14 @@ export default { ) { this.$refs.queryFormTree.queryData(); } + this.$emit("handleCustomClose"); this.handleQueryPageList(); // 关闭时 清空表单的验证规则 this.$refs.edit.$refs.mainForm.$refs.editForm.resetFields(); }, // 批量删除 handleDeleteBatch(row) { - var ids = []; + let ids = []; if (row != null) { ids.push(row[this.primaryKeyFieldName]); // 删除指定的行 } else { @@ -645,8 +719,59 @@ export default { // 选择项改变时 handleSelectionChange(val) { + if (val.length > 0) { + val.forEach(el => { + this.records.forEach(ev => { + if (el.id == ev.id) { + ev.dblClickFlag = true; + ev.bgColor = true; + } + }); + }); + } else { + this.records.forEach(ev => { + ev.dblClickFlag = false; + ev.bgColor = false; + }); + } + this.isShowRowContextMenu = false; this.checkRecords = val; }, + // 双击 + handleSelectionDblclick(row) { + row.dblClickFlag = !row.dblClickFlag; + row.bgColor = row.dblClickFlag; + this.$refs.tables.toggleRowSelection(row, row.dblClickFlag); + }, + // 右键 + rowContextMenu(row, column, event) { + event.preventDefault(); + this.option.contextMenu.forEach(el => { + if (el.flag == "all") { + el.disabled = !(this.checkRecords.length > 1); + } else { + el.disabled = this.checkRecords.length > 1; + } + }); + + // 设置右键位置 + this.contextMenuConfigStyle = { + left: event.clientX + "px", + top: event.clientY + "px", + display: "block" + }; + // 获取当前右键行数据 + this.contextMenuRow = row; + // 获取我们自定义的右键菜单 + this.isShowRowContextMenu = true; + }, + handleContextMenuItem(item) { + if (item.flag == "all") { + item.click({ selection: this.checkRecords }); + } else { + item.click({ msg: this.contextMenuRow }); + } + }, // 页码改变 handleCurrentChange(pageNumber) { this.queryParams.pageNumber = pageNumber; @@ -674,6 +799,19 @@ export default { }, // 带单位的列,需要转换 fieldLabel(columnConfig) { + let objUnitText = ""; + const localStorageUnit = this.getSettingByName("unit_conversion"); + const objUnit = {}; + for (const key in localStorageUnit) { + columnConfig.anjiInput && + key + .toLowerCase() + .indexOf(columnConfig.anjiInput.unit.toLowerCase()) != -1 && + (objUnit[key] = localStorageUnit[key]); + } + for (const key in objUnit) { + key.toLowerCase().indexOf("text") != -1 && (objUnitText = objUnit[key]); + } if (columnConfig == null) { return ""; } @@ -681,13 +819,38 @@ export default { columnConfig.inputType == "anji-input" && columnConfig.anjiInput != null ) { - return `${columnConfig.label}(${columnConfig.anjiInput.unit})`; + return columnConfig.anjiInput["defaultUnit"] == undefined + ? `${columnConfig.label}(${objUnitText})` + : `${columnConfig.label}(${columnConfig.anjiInput["defaultUnit"]})`; } else { return columnConfig.label; } }, // 带单位的输入框 fieldValueByAnjiInput(value, columnConfig) { + const localStorageUnit = this.getSettingByName("unit_conversion"); + let objUnitConversion = ""; + let objUnitKeepPoint = ""; + let objUnitConversionRadioGroup = []; + const objUnit = {}; + for (const key in localStorageUnit) { + columnConfig.anjiInput && + key + .toLowerCase() + .indexOf(columnConfig.anjiInput.unit.toLowerCase()) != -1 && + (objUnit[key] = localStorageUnit[key]); + } + for (const key in objUnit) { + key.toLowerCase().indexOf("conversion") != -1 && + key.toLowerCase().indexOf("conversiontext") == -1 && + key.toLowerCase().indexOf("conversionradiogroup") == -1 && + (objUnitConversion = objUnit[key]); + key.toLowerCase().indexOf("keeppoint") != -1 && + (objUnitKeepPoint = objUnit[key]); + Array.isArray(objUnit[key]) && + (objUnitConversionRadioGroup = objUnit[key]); + } + if (columnConfig == null) { return value; } @@ -695,7 +858,15 @@ export default { columnConfig.inputType == "anji-input" && columnConfig.anjiInput != null ) { - return value / columnConfig.anjiInput.conversion; + if (columnConfig.anjiInput["defaultUnit"] == undefined) { + // 不存在 + return (value / objUnitConversion).toFixed(objUnitKeepPoint || 2); + } else { + const coversion = objUnitConversionRadioGroup.find( + item => item.label == columnConfig.anjiInput["defaultUnit"] + )["value"]; + return (value / coversion).toFixed(objUnitKeepPoint || 2); + } } else { return value; } @@ -732,12 +903,78 @@ export default { if (typeof this.option.queryFormChange == "function") { this.option.queryFormChange(this.queryParams, fileName, fieldVal); } + }, + // 给表格某行改变颜色 + tableRowClassName({ row, rowIndex }) { + if ((row.urgentFlag || row.tableRow) && !row.bgColor) { + return "warning-row"; + } else if ((row.urgentFlag || row.tableRow) && row.bgColor) { + return "warning-row bgColor"; + } else if ((!row.urgentFlag || !row.tableRow) && row.bgColor) { + return "bgColor"; + } + if ((rowIndex + 1) % 2 === 0) { + return "success-row"; + } } } }; </script> <style scoped lang="scss"> +.right-container { + display: flex; + flex: 1; + flex-direction: column; + .main_part { + display: flex; + flex-direction: column; + flex: 1; + background: #fff; + border-radius: 4px; + padding: 12px 20px 12px; + margin-top: 4px; + height: 100%; + position: relative; + } +} +/deep/.button { + box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.08); + border-radius: 6px; +} +/deep/.el-table th > .cell { + text-align: center; +} +/deep/.el-table .cell { + text-align: center; +} +/deep/.elTable { + margin: 10px 0 50px; +} +.el-table { + // 看这里!!! + // 深度选择器,去除默认的padding + /deep/ th { + padding: 0; + height: 36px; + } + /deep/ td { + padding: 0; + height: 36px; + } +} +/deep/.el-table--striped .el-table__body tr.el-table__row--striped td { + background: #f9fbfd; +} +.screenFlex { + display: flex; +} +.searchFormFlex { + flex: 1; +} +.screenButtons { + padding-left: 20px; +} .style-btn { pointer-events: none; } @@ -788,21 +1025,87 @@ export default { &:hover { background: none !important; } + /deep/.el-button--text:hover, + .el-button--text:focus { + color: #799ffc !important; + background-color: #ecf5ff !important; + border-color: transparent; + } .el-button--mini { float: right; } + .el-button--text:hover, + .el-button--text:focus { + color: #799ffc; + border-color: transparent; + // background-color: transparent; + // background: red !important; + } .el-button + .el-button { margin-left: 0 !important; float: right; } } +/deep/.el-pagination.is-background .btn-prev, +.el-pagination.is-background .btn-next, +.el-pagination.is-background .el-pager li { + margin: 0 5px; + border-radius: 2px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +/deep/.el-pagination.is-background .el-pager li:not(.disabled).active { + background-color: #5887fb; + color: #ffffff; + border-radius: 4px; +} +.page_bottom { + width: 100%; + position: absolute; + bottom: 0; +} .pagination { display: flex; flex-direction: row; justify-content: space-between; - margin-top: 20px; + margin-bottom: 14px; + margin-right: 20px; +} +.el-table /deep/ .warning-row { + color: red !important; +} +.el-table /deep/ .bgColor { + background: #d9ecff; +} +/deep/.edit_button { + width: 22px; + height: 22px; + padding: 0; + margin: 0; + margin-right: 5px; + /deep/ i { + font-size: 30px; + } +} +.el-form-item--mini.el-form-item { + margin-bottom: 12px; } -.anji_curd_table { - margin-top: 20px; +.el-table /deep/ .success-row { + background: #f9fbfd !important; +} + +.contextMenu { + width: 100px; + .contextMenuItem { + width: 100%; + font-size: 12px; + line-height: 20px; + padding: 5px; + } + &:hover { + background: #f9fbfd; + } } </style> diff --git a/report-ui/src/components/AnjiPlus/anji-crud/edit-form.vue b/report-ui/src/components/AnjiPlus/anji-crud/edit-form.vue index d186a84e..89ab2559 100644 --- a/report-ui/src/components/AnjiPlus/anji-crud/edit-form.vue +++ b/report-ui/src/components/AnjiPlus/anji-crud/edit-form.vue @@ -1,11 +1,8 @@ -<!-- - * @Author: lide1202@hotmail.com - * @Date: 2021-5-4 11:04:24 - * @Last Modified by: lide1202@hotmail.com - * @Last Modified time: 2021-5-6 11:04:24 - !--> <template> - <div v-if="option['hide'] == null || option['hide'] == false" class="anji-card"> + <div + v-if="option['hide'] == null || option['hide'] == false" + class="anji-card" + > <div class="card-head"> {{ option.title }} <div class="main-card-header-button"> @@ -15,30 +12,97 @@ </div> </div> <div class="card-body"> - <el-form ref="editForm" :model="editForm" :label-width="option.labelWidth || '100px'"> + <el-form + ref="editForm" + :model="editForm" + :label-width="option.labelWidth || '100px'" + > <!--:disabled="modelType == 'view'"--> <template v-for="group in columnGroups"> - <el-divider v-if="groupModel" :key="group" content-position="left">{{ group }}</el-divider> + <el-divider v-if="groupModel" :key="group" content-position="left">{{ + group + }}</el-divider> <el-row :key="group" class="form_table"> <template v-for="item in groupFormFields[group]"> - <el-col v-if="fieldIsHide(item.editHide) == false" :key="item.editField" :span="item.rowColSpan == null ? cardRowColSpan : item.rowColSpan"> - <el-form-item :label="item.label" :rules="item.rules" :prop="item.editField" :disabled="item.disabled"> + <el-col + v-if="fieldIsHide(item.editHide) == false" + :key="item.editField" + :span=" + item.rowColSpan == null ? cardRowColSpan : item.rowColSpan + " + > + <el-form-item + :label="item.label" + :rules="item.rules" + :prop="item.editField" + :disabled="item.disabled" + > <!-- 输入框 --> - <span v-if="item.tips != '' && item.tips != null" :style="{ 'margin-left': '-13px' }" class="input_tips"> - <el-tooltip class="item" effect="dark" :content="item.tips" placement="top-start"> + <span + v-if="item.tips != '' && item.tips != null" + :style="{ 'margin-left': '-13px' }" + class="input_tips" + > + <el-tooltip + class="item" + effect="dark" + :content="item.tips" + placement="top-start" + > <svg-icon icon-class="tishi-yiwen" /> </el-tooltip> </span> - <el-input v-if="item.inputType == 'input'" v-model.trim="editForm[item.editField]" :placeholder="item.placeholder || '请输入'" :clearable="item.clearable !== false" :disabled="fieldIsDisable(item.disabled)" @change="(value) => formChange(item.editField, value, null)" /> + <el-input + v-if="item.inputType == 'input'" + v-model.trim="editForm[item.editField]" + :placeholder=" + item.placeholder || $lang('placeholder_input') + " + :clearable="item.clearable !== false" + :disabled="fieldIsDisable(item.disabled)" + @change="value => formChange(item.editField, value, null)" + /> <!-- 开关 --> - <el-switch v-else-if="item.inputType == 'switch'" v-model.trim="editForm[item.editField]" :disabled="fieldIsDisable(item.disabled)" :active-value="1" :inactive-value="0" inactive-color="#ccc" active-color="#5887fb" @change="(value) => formChange(item.editField, value, null)" /> - <el-input-number v-else-if="item.inputType == 'input-number'" v-model.trim="editForm[item.editField]" :min="item.inputNumberOption.min" :max="item.inputNumberOption.max" :placeholder="item.placeholder || '请输入'" :clearable="item.clearable !== false" :disabled="fieldIsDisable(item.disabled)" @change="(value) => formChange(item.editField, value, null)" /> + <el-switch + v-else-if="item.inputType == 'switch'" + v-model.trim="editForm[item.editField]" + :disabled="fieldIsDisable(item.disabled)" + :active-value="1" + :inactive-value="0" + inactive-color="#ccc" + active-color="#5887fb" + @change="value => formChange(item.editField, value, null)" + /> + <el-input-number + v-else-if="item.inputType == 'input-number'" + v-model.trim="editForm[item.editField]" + :min="item.inputNumberOption.min" + :max="item.inputNumberOption.max" + :placeholder=" + item.placeholder || $lang('placeholder_input') + " + :clearable="item.clearable !== false" + :disabled="fieldIsDisable(item.disabled)" + @change="value => formChange(item.editField, value, null)" + /> <!-- 自定义input --> - <anji-input v-else-if="item.inputType == 'anji-input'" v-model.trim="editForm[item.editField]" :unit="item.anjiInput.unit" :conversion="item.anjiInput.conversion" :keep-point="item.anjiInput.keepPoint" :rounding="item.anjiInput.rounding" :placeholder="item.placeholder || '请输入'" :clearable="item.clearable !== false" :disabled="fieldIsDisable(item.disabled)" @change="(value) => formChange(item.editField, value, null)" /> + <anji-input + v-else-if="item.inputType == 'anji-input'" + v-model.trim="editForm[item.editField]" + :unit="item.anjiInput.unit" + :default-unit="item.anjiInput.defaultUnit" + :placeholder=" + item.placeholder || $lang('placeholder_input') + " + :clearable="item.clearable !== false" + :disabled="fieldIsDisable(item.disabled)" + @change="value => formChange(item.editField, value, null)" + /> <!-- 下拉框 --> <anji-select v-else-if="item.inputType == 'anji-select'" v-model.trim="editForm[item.editField]" + :allow-create="item.anjiSelectOption.allowCreate" :multiple="item.anjiSelectOption.multiple" :disabled="fieldIsDisable(item.disabled)" :dict-code="item.anjiSelectOption.dictCode" @@ -51,21 +115,97 @@ :label="item.anjiSelectOption.label" :remote-filter="item.anjiSelectOption.remoteFilter" :disabled-options="item.anjiSelectOption.disabledOptions" - @change="(value, option) => formChange(item.editField, value, option)" + :select-keyword="item.anjiSelectOption.selectKeyword" + @change=" + (value, option) => + formChange(item.editField, value, option) + " /> <!-- 日期时间框 --> - <el-date-picker v-else-if="item.inputType.indexOf('date') >= 0" v-model="editForm[item.editField]" style="width: 100%" :placeholder="item.placeholder || '请选择'" :type="item.inputType" :format="item.format" :value-format="item.valueFormat" :disabled="fieldIsDisable(item.disabled)" :clearable="item.clearable !== false" @change="(value) => formChange(item.editField, value, null)" /> + <el-date-picker + v-else-if="item.inputType.indexOf('date') >= 0" + v-model="editForm[item.editField]" + style="width: 100%" + :placeholder=" + item.placeholder || $lang('placeholder_select') + " + :type="item.inputType" + :format="item.format" + :value-format="item.valueFormat" + :disabled="fieldIsDisable(item.disabled)" + :clearable="item.clearable !== false" + @change="value => formChange(item.editField, value, null)" + /> <!-- checkbox --> - <anji-checkbox v-else-if="item.inputType == 'checkbox'" v-model.trim="editForm[item.editField]" :dict-code="item.anjiCheckbox.dictCode" :label="item.anjiCheckbox.label" :disabled="fieldIsDisable(item.disabled)" @change="(value, options) => formChange(item.editField, value, options)" /> + <anji-checkbox + v-else-if="item.inputType == 'checkbox'" + v-model.trim="editForm[item.editField]" + :dict-code="item.anjiCheckbox.dictCode" + :url="item.anjiCheckbox.url" + :label="item.anjiCheckbox.label" + :disabled="fieldIsDisable(item.disabled)" + @change=" + (value, options) => + formChange(item.editField, value, options) + " + /> <!-- 城市三级联动 --> - <anji-cascader v-else-if="item.inputType == 'anji-cascader'" v-model.trim="editForm[item.editField]" :disabled="fieldIsDisable(item.disabled)" :url="item.anjiCascader.url" @change="(value) => formChange(item.editField, value, null)" /> + <anji-cascader + v-else-if="item.inputType == 'anji-cascader'" + v-model.trim="editForm[item.editField]" + :disabled="fieldIsDisable(item.disabled)" + :single-display="item.anjiCascader.singleDisplay" + :url="item.anjiCascader.url" + @change="value => formChange(item.editField, value, null)" + /> <!-- 上传组件 --> - <anji-upload v-else-if="item.inputType == 'anji-upload'" v-model.trim="editForm[item.editField]" :up-load-url="item.anjiUpload.upLoadUrl" :view-url="item.anjiUpload.viewUrl" :upload-type="item.anjiUpload.uploadType" :limit="item.anjiUpload.limit" @change="(value) => formChange(item.editField, value, null)" /> + <anji-upload + v-else-if="item.inputType == 'anji-upload'" + v-model.trim="editForm[item.editField]" + :up-load-url="item.anjiUpload.upLoadUrl" + :view-url="item.anjiUpload.viewUrl" + :upload-type="item.anjiUpload.uploadType" + :limit="item.anjiUpload.limit" + @change="value => formChange(item.editField, value, null)" + /> <!-- input自带输入建议 --> - <anji-autocomplete v-else-if="item.inputType == 'anji-autocomplete'" v-model.trim="editForm[item.editField]" :disabled="fieldIsDisable(item.disabled)" :label="item.anjiAutocomplete.label" :option="item.anjiAutocomplete.option" :appoint-value="item.anjiAutocomplete.appointValue" :url="item.anjiAutocomplete.url" @change="(value, option) => formChange(item.editField, value, option)" /> + <anji-autocomplete + v-else-if="item.inputType == 'anji-autocomplete'" + v-model.trim="editForm[item.editField]" + :disabled="fieldIsDisable(item.disabled)" + :label="item.anjiAutocomplete.label" + :option="item.anjiAutocomplete.option" + :appoint-value="item.anjiAutocomplete.appointValue" + :url="item.anjiAutocomplete.url" + @change=" + (value, option) => + formChange(item.editField, value, option) + " + /> <!-- textarea --> - <el-input v-else-if="item.inputType == 'textarea'" v-model.trim="editForm[item.editField]" :placeholder="item.placeholder || '请输入'" :clearable="item.clearable !== false" :disabled="fieldIsDisable(item.disabled)" type="textarea" :rows="2" @change="(value) => formChange(item.editField, value, null)" /> - <el-input v-else placeholder="组件不支持此类型表单请至组件内部自行扩展" disabled /> + <el-input + v-else-if="item.inputType == 'textarea'" + v-model.trim="editForm[item.editField]" + :placeholder=" + item.placeholder || $lang('placeholder_input') + " + :clearable="item.clearable !== false" + :disabled="fieldIsDisable(item.disabled)" + type="textarea" + :rows="2" + @change="value => formChange(item.editField, value, null)" + /> + <!-- 城市四级联动 --> + <anji-fourlevel + v-else-if="item.inputType == 'anji-country'" + v-model.trim="editForm[item.editField]" + @change="value => formChange(item.editField, value, null)" + /> + <el-input + v-else + placeholder="组件不支持此类型表单请至组件内部自行扩展" + disabled + /> </el-form-item> </el-col> </template> @@ -87,97 +227,103 @@ export default { type: [Object], default: () => { return { - title: '', // 页面标题 - labelWidth: '', // 表单输入框label宽度 + title: "", // 页面标题 + labelWidth: "", // 表单输入框label宽度 queryFormFields: [], // 查询表单条件 buttons: { // 按钮 query: {}, edit: {}, delete: {}, - add: {}, + add: {} }, columns: [], // 表格列 - formChange: (formData, fieldName, fieldVal, fieldExtend) => {}, // 弹出框表单修改回调 - } - }, + formChange: (formData, fieldName, fieldVal, fieldExtend) => {} // 弹出框表单修改回调 + }; + } }, // 当relateData不为空时,该组件是渲染与relateData一对一关联的子表信息 relateData: { type: [Object], default: () => { - return {} - }, + return {}; + } }, value: { type: [Object], default: () => { - return {} - }, - }, + return {}; + } + } }, data() { return { - cardRowColNum: 2, // 主信息一行显示几列 - editForm: {}, // 提交表单的数据 - } + cardRowColNum: this.option.rowColForm || 2, // 主信息一行显示几列 + editForm: {} // 提交表单的数据 + }; }, computed: { // 主键的列名 primaryKeyFieldName() { - var primaryKey = this.option.columns.find((item) => item['primaryKey'] == true) + let primaryKey = this.option.columns.find( + item => item["primaryKey"] == true + ); if (primaryKey != null) { - return primaryKey['field'] + return primaryKey["field"]; } else { - return null - console.warn('在columns中查找primaryKey=true失败,会导致查询详情和删除失败') + return null; + console.warn( + "在columns中查找primaryKey=true失败,会导致查询详情和删除失败" + ); } }, // 指定当前实体关联主表的 joinColumn() { - var columnName = this.option.joinColumn + let columnName = this.option.joinColumn; if (this.isBlank(columnName)) { - console.warn('在joinEntity中查找joinColumn属性失败,会导致查询详情和删除失败') - columnName = '' + console.warn( + "在joinEntity中查找joinColumn属性失败,会导致查询详情和删除失败" + ); + columnName = ""; } - return columnName + return columnName; }, // 提交表单中所有的列,因部分翻译字段,表格中和表单中的key不一样,field editField不全,这里补全下, formFields() { if (this.option.columns == null) { - return [] + return []; } - var fields = this.deepClone(this.option.columns) - fields = fields.map((item) => { - if (this.isBlank(item['editField'])) { - item['editField'] = item['field'] + let fields = this.deepClone(this.option.columns); + fields = fields.map(item => { + if (this.isBlank(item["editField"])) { + item["editField"] = item["field"]; } // 没有设定分组的,全部补全成 其它信息 - if (this.isBlank(item['group'])) { - item['group'] = '其它' + if (this.isBlank(item["group"])) { + item["group"] = this.$lang("crudEditDialogGroupOther"); } - return item - }) - return fields + return item; + }); + return fields; }, // 卡片设定中一行显示几列,每列的col数 cardRowColSpan() { - return 24 / this.cardRowColNum + return 24 / this.cardRowColNum; }, // 如果表单内容较多,启用了分组,这里先算出所有的分组 columnGroups() { if (this.isBlank(this.formFields)) { - return [] + return []; } else { // 找出所有hide != true的关联表 - var groups = this.formFields - .map((item) => { - return item['group'] + let groups = this.formFields + .map(item => { + return item["group"]; }) .filter((currentValue, index, arr) => { - return arr.indexOf(currentValue) == index - }) - return groups + return arr.indexOf(currentValue) == index; + }); + return groups; } }, /* { @@ -187,167 +333,176 @@ export default { groupFormFields() { if (this.showDialog) { // 将每个分组初始化 - var groupFormFields = {} + let groupFormFields = {}; this.columnGroups.forEach((value, index, array) => { - groupFormFields[value] = [] - }) + groupFormFields[value] = []; + }); // 将所有编辑列,按分组存放 this.formFields.forEach((item, index, array) => { - groupFormFields[item['group']].push(item) - }) - return groupFormFields + groupFormFields[item["group"]].push(item); + }); + return groupFormFields; } - return [] + return []; }, groupModel() { - return this.columnGroups.length > 1 - }, + return this.columnGroups.length > 1; + } }, created() { // 如果表单,是做为主表的编辑页面,如果是通过v-model传递进来的值,通过监听value,更新this.editForm this.$watch( - function () { - return this.value + function() { + return this.value; }, - function (newVal, oldVal) { - this.editForm = newVal + function(newVal, oldVal) { + this.editForm = newVal; // 通过v-model传递值进来时,说明当前form是主表信息 - this.formChange() + this.formChange(); } - ) + ); // 如果表单,是做为子表的编辑页面,当relateData中的关联字段发生更新时,触发查询,比如在goods详情中,goodsCode this.$watch( - function () { - return this.relateData[this.joinColumn] + function() { + return this.relateData[this.joinColumn]; }, - function (newVal, oldVal) { + function(newVal, oldVal) { // 如果是父组件(弹出框)关闭时,设置this.relateData = {}时触发,清空本组件的数据 if (this.isBlank(this.relateData)) { - this.cardRowColNum = 2 - this.editForm = {} - return + this.cardRowColNum = 2; + this.editForm = {}; + return; } // 如果是关联字段发生更新,触发查询 if (this.isNotBlank(newVal)) { - this.queryDetail() + this.queryDetail(); } } - ) + ); }, mounted() { // 如果表单,是做为主表的编辑页面,如果是通过v-model传递进来的值 if (this.isNotBlank(this.value)) { - this.editForm = this.value - this.formChange() + this.editForm = this.value; + this.formChange(); } // 如果表单,是做为子表的编辑页面,首次打开时,根据关联属性,加载详情数据 - if (this.isNotBlank(this.relateData) && this.isNotBlank(this.relateData[this.joinColumn])) { - this.queryDetail() + if ( + this.isNotBlank(this.relateData) && + this.isNotBlank(this.relateData[this.joinColumn]) + ) { + this.queryDetail(); } }, methods: { // 该行是否显示 true/false/ 'hideOnAdd hideOnView hideOnEdit' fieldIsHide(editHide) { - if (typeof editHide == 'boolean') { - return editHide + if (typeof editHide == "boolean") { + return editHide; } - if (typeof editHide == 'string') { - if (this.modelType == 'add') { - return editHide.indexOf('hideOnAdd') >= 0 + if (typeof editHide == "string") { + if (this.modelType == "add") { + return editHide.indexOf("hideOnAdd") >= 0; } - if (this.modelType == 'view') { - return editHide.indexOf('hideOnView') >= 0 + if (this.modelType == "view") { + return editHide.indexOf("hideOnView") >= 0; } - if (this.modelType == 'edit') { - return editHide.indexOf('hideOnEdit') >= 0 + if (this.modelType == "edit") { + return editHide.indexOf("hideOnEdit") >= 0; } } - return false + return false; }, // 该行是否禁用 true/false/ 'disableOnAdd disableOnView disableOnEdit' fieldIsDisable(disable) { - if (typeof disable == 'boolean') { - return disable + if (typeof disable == "boolean") { + return disable; } - if (typeof disable == 'string') { - if (this.modelType == 'add') { - return disable.indexOf('disableOnAdd') >= 0 + if (typeof disable == "string") { + if (this.modelType == "add") { + return disable.indexOf("disableOnAdd") >= 0; } - if (this.modelType == 'view') { - return disable.indexOf('disableOnView') >= 0 + if (this.modelType == "view") { + return disable.indexOf("disableOnView") >= 0; } - if (this.modelType == 'edit') { - return disable.indexOf('disableOnEdit') >= 0 + if (this.modelType == "edit") { + return disable.indexOf("disableOnEdit") >= 0; } } - return false + return false; }, // 设置一行显示几列 handleSetRowColNum(num) { - this.cardRowColNum = num - this.$emit('changeRowColNum', num) + this.cardRowColNum = num; + this.$emit("changeRowColNum", num); }, async queryDetail() { - var queryParams = this.relateData - const { data, code } = await this.option.buttons.queryByPrimarykey.api(queryParams) - if (code != '200') return - this.editForm = data - this.formChange() + let queryParams = this.relateData; + const { data, code } = await this.option.buttons.queryByPrimarykey.api( + queryParams + ); + if (code != "200") return; + this.editForm = data; + this.formChange(); }, // 校验表单 validate(callback) { this.$refs.editForm.validate(async (valid, obj) => { if (callback != null) { - callback(valid) + callback(valid); } - }) + }); }, handleSave(callback) { this.$refs.editForm.validate(async (valid, obj) => { if (valid) { - if (this.modelType == 'add') { + if (this.modelType == "add") { // 当edit-from是作为关联子表的界面,补全关联属性 - if (typeof this.option.beforeInsert == 'function') { - this.option.beforeInsert(this.relateData, this.editForm) + if (typeof this.option.beforeInsert == "function") { + this.option.beforeInsert(this.relateData, this.editForm); } - const { code, message } = await this.option.buttons.add.api(this.editForm) - if (code == '200') { + const { code, message } = await this.option.buttons.add.api( + this.editForm + ); + if (code == "200") { if (callback != null) { - callback() + callback(); } } else { - console.log(`提交表单调用新增接口失败:${message}`) + console.log(`提交表单调用新增接口失败:${message}`); } } else { // 当edit-from是作为关联子表的界面,补全关联属性 - if (typeof this.option.beforeUpdate == 'function') { - this.option.beforeUpdate(this.relateData, this.editForm) + if (typeof this.option.beforeUpdate == "function") { + this.option.beforeUpdate(this.relateData, this.editForm); } - const { code, message } = await this.option.buttons.edit.api(this.editForm) - if (code == '200') { + const { code, message } = await this.option.buttons.edit.api( + this.editForm + ); + if (code == "200") { if (callback != null) { - callback() + callback(); } } else { - console.log(`提交表单调用更新接口失败:${message}`) + console.log(`提交表单调用更新接口失败:${message}`); } } } else { - console.log('表单校验失败') + console.log("表单校验失败"); } - }) + }); }, // 表单任何一个变动时,通知外部v-model formChange(fieldName, fieldVal, fieldExtend) { - this.$emit('input', this.editForm) + this.$emit("input", this.editForm); // 表单变动后,回调option中的formChange事件 - if (typeof this.option.formChange == 'function') { - this.option.formChange(this.editForm, fieldName, fieldVal, fieldExtend) + if (typeof this.option.formChange == "function") { + this.option.formChange(this.editForm, fieldName, fieldVal, fieldExtend); } - }, - }, -} + } + } +}; </script> <style scoped lang="scss"> diff --git a/report-ui/src/components/AnjiPlus/anji-crud/edit-table.vue b/report-ui/src/components/AnjiPlus/anji-crud/edit-table.vue index df3b030b..14bc0b48 100644 --- a/report-ui/src/components/AnjiPlus/anji-crud/edit-table.vue +++ b/report-ui/src/components/AnjiPlus/anji-crud/edit-table.vue @@ -1,138 +1,207 @@ -<!-- - * @Author: lide1202@hotmail.com - * @Date: 2021-5-4 11:04:24 - * @Last Modified by: lide1202@hotmail.com - * @Last Modified time: 2021-5-6 11:04:24 - !--> <template> - <div v-if="option['hide'] == null || option['hide'] == false" - class="anji-card"> + <div + v-if="option['hide'] == null || option['hide'] == false" + class="anji-card" + > <div class="card-head">{{ option.title }}</div> <div class="card-body"> - <el-form ref="form" - :model="form"> + <el-form ref="form" :model="form"> <!-- 表格开始 --> - <el-table :data="formRecordsUndelete" - border - :row-class-name="tableRowClassAdapter" - @selection-change="handleSelectionChange" - @row-click="handleTableRowClick"> + <el-table + :data="formRecordsUndelete" + border + :row-class-name="tableRowClassAdapter" + @selection-change="handleSelectionChange" + @row-click="handleTableRowClick" + > <!-- <el-table-column fixed type="selection" width="50" align="center" /> --> - <el-table-column label="序号" - min-width="50" - align="center"> + <el-table-column + :label="$lang('GLOBAL.table_index')" + min-width="50" + align="center" + > <template slot-scope="scope"> {{ scope.$index + 1 }} </template> </el-table-column> <template v-for="item in option.columns"> - <el-table-column v-if="fieldIsHide(item.tableHide) != true && item.columnType != 'expand'" - :key="item.field" - :label="item.label" - :min-width="item.minWidth || 110" - align="center"> + <el-table-column + v-if=" + fieldIsHide(item.tableHide) != true && + item.columnType != 'expand' + " + :key="item.field" + :label="item.label" + :min-width="item.minWidth || 110" + align="center" + > <template slot-scope="scope"> - <el-form-item :prop="'records.' + scope.$index + '.' + item.field" - :rules="item.rules"> + <el-form-item + :prop="'records.' + scope.$index + '.' + item.field" + :rules="item.rules" + > <!-- 输入框 --> - <el-input v-if="item.inputType == 'input'" - v-model="scope.row[item.field]" - size="small" - :placeholder="item.placeholder || '请输入'" - :clearable="item.clearable !== false" - :disabled="saveButtonStatus[scope.$index] == 'inShow' || item.disabled" - @change="(value) => tableRowChange(scope.$index, item.field, value)" /> + <el-input + v-if="item.inputType == 'input'" + v-model="scope.row[item.field]" + size="small" + :placeholder=" + item.placeholder || $lang('placeholder_input') + " + :clearable="item.clearable !== false" + :disabled=" + saveButtonStatus[scope.$index] == 'inShow' || + item.disabled + " + @change=" + value => tableRowChange(scope.$index, item.field, value) + " + /> <!-- 开关 --> - <el-switch v-else-if="item.inputType == 'switch'" - v-model="scope.row[item.field]" - :disabled="saveButtonStatus[scope.$index] == 'inShow' || item.disabled" - :active-value="item.switchOption.disableValue" - :inactive-value="item.switchOption.enableValue" - @change="(value) => tableRowChange(scope.$index, item.field, value)" - active-color="#5887fb" - inactive-color="#ccc"> + <el-switch + v-else-if="item.inputType == 'switch'" + v-model="scope.row[item.field]" + :disabled=" + saveButtonStatus[scope.$index] == 'inShow' || + item.disabled + " + :active-value="item.switchOption.disableValue" + :inactive-value="item.switchOption.enableValue" + @change=" + value => tableRowChange(scope.$index, item.field, value) + " + active-color="#5887fb" + inactive-color="#ccc" + > </el-switch> - <el-input v-else-if="item.inputType == 'input-number'" - v-model="scope.row[item.field]" - size="small" - :min="item.inputNumberOption.min" - :max="item.inputNumberOption.max" - :placeholder="item.placeholder || '请输入'" - :clearable="item.clearable !== false" - :disabled="saveButtonStatus[scope.$index] == 'inShow' || item.disabled" - @change="(value) => tableRowChange(scope.$index, item.field, value)" /> + <el-input + v-else-if="item.inputType == 'input-number'" + v-model="scope.row[item.field]" + size="small" + :min="item.inputNumberOption.min" + :max="item.inputNumberOption.max" + :placeholder=" + item.placeholder || $lang('placeholder_input') + " + :clearable="item.clearable !== false" + :disabled=" + saveButtonStatus[scope.$index] == 'inShow' || + item.disabled + " + @change=" + value => tableRowChange(scope.$index, item.field, value) + " + /> <!-- 自定义input --> - <anji-input v-else-if="item.inputType == 'anji-input'" - v-model.trim="scope.row[item.field]" - :default-value="item.defaultValue" - :unit="item.anjiInput.unit" - :conversion="item.anjiInput.conversion" - :placeholder="item.placeholder || '请输入'" - :clearable="item.clearable !== false" - :disabled="saveButtonStatus[scope.$index] == 'inShow' || item.disabled" - @change="(value) => tableRowChange(scope.$index, item.field, value)" /> + <anji-input + v-else-if="item.inputType == 'anji-input'" + v-model.trim="scope.row[item.field]" + :default-value="item.defaultValue" + :unit="item.anjiInput.unit" + :conversion="item.anjiInput.conversion" + :placeholder=" + item.placeholder || $lang('placeholder_input') + " + :clearable="item.clearable !== false" + :disabled=" + saveButtonStatus[scope.$index] == 'inShow' || + item.disabled + " + @change=" + value => tableRowChange(scope.$index, item.field, value) + " + /> <!-- 下拉框 --> - <anji-select v-else-if="item.inputType == 'anji-select'" - v-model.trim="scope.row[item.field]" - :multiple="item.anjiSelectOption.multiple" - :default-value="item.defaultValue" - :dict-code="item.anjiSelectOption.dictCode" - :url="item.anjiSelectOption.url" - :method="item.anjiSelectOption.method" - :query-param="item.anjiSelectOption.queryParam" - :option="item.anjiSelectOption.option" - :label="item.anjiSelectOption.label" - :disabled-options="item.anjiSelectOption.disabledOptions" - :disabled="saveButtonStatus[scope.$index] == 'inShow' || item.disabled" - @change="(value, option) => tableRowChange(scope.$index, item.field, value, option)" /> + <anji-select + v-else-if="item.inputType == 'anji-select'" + v-model.trim="scope.row[item.field]" + :multiple="item.anjiSelectOption.multiple" + :default-value="item.defaultValue" + :dict-code="item.anjiSelectOption.dictCode" + :url="item.anjiSelectOption.url" + :method="item.anjiSelectOption.method" + :query-param="item.anjiSelectOption.queryParam" + :option="item.anjiSelectOption.option" + :label="item.anjiSelectOption.label" + :disabled-options="item.anjiSelectOption.disabledOptions" + :disabled=" + saveButtonStatus[scope.$index] == 'inShow' || + item.disabled + " + @change=" + (value, option) => + tableRowChange(scope.$index, item.field, value, option) + " + /> <!-- 日期时间框 --> - <el-date-picker v-else-if="item.inputType.indexOf('date') >= 0" - v-model="scope.row[item.field]" - style="width: 100%" - :placeholder="item.placeholder || '请选择'" - :type="item.inputType" - :clearable="item.clearable !== false" - :disabled="saveButtonStatus[scope.$index] == 'inShow' || item.disabled" - @change="(value) => tableRowChange(scope.$index, item.field, value)" /> + <el-date-picker + v-else-if="item.inputType.indexOf('date') >= 0" + v-model="scope.row[item.field]" + style="width: 100%" + :placeholder=" + item.placeholder || $lang('placeholder_select') + " + :type="item.inputType" + :clearable="item.clearable !== false" + :disabled=" + saveButtonStatus[scope.$index] == 'inShow' || + item.disabled + " + @change=" + value => tableRowChange(scope.$index, item.field, value) + " + /> <!-- 待扩展的表单类型,请自行扩展 --> - <el-input v-else - placeholder="组件不支持此类型表单请至组件内部自行扩展" - disabled /> + <el-input + v-else + placeholder="组件不支持此类型表单请至组件内部自行扩展" + disabled + /> </el-form-item> </template> </el-table-column> </template> - <el-table-column fixed="right" - label="操作" - width="100"> + <el-table-column + fixed="right" + :label="$lang('GLOBAL.table_operation')" + width="100" + > <template slot-scope="scope"> - <el-button type="text" - size="small" - @click="handleAddOrUpdate(scope.row, scope.$index)">{{ getRowEditButton(scope.$index) }}</el-button> - <el-button type="text" - size="small" - @click="handleDelete(scope.row, scope.$index)">删除</el-button> + <el-button + type="text" + size="small" + @click="handleAddOrUpdate(scope.row, scope.$index)" + >{{ getRowEditButton(scope.$index) }}</el-button + > + <el-button + type="text" + size="small" + @click="handleDelete(scope.row, scope.$index)" + >{{ $lang("btn_delete") }}</el-button + > </template> </el-table-column> </el-table> <!-- 表格结束 --> </el-form> - <button v-if="modelType != 'view'" - class="table-add-row-button" - @click="handleAdd"> + <button + v-if="modelType != 'view'" + class="table-add-row-button" + @click="handleAdd" + > <i class="el-icon-plus" /> - <span>新增</span> + <span>{{ $lang("btn_add") }}</span> </button> </div> </div> </template> <script> -const ROW_DELETE_FLAG = 'deletedFlag' +const ROW_DELETE_FLAG = "deletedFlag"; export default { components: {}, props: { @@ -142,242 +211,268 @@ export default { type: [Object], default: () => { return { - title: '', // 页面标题 - labelWidth: '', + title: "", // 页面标题 + labelWidth: "", queryFormFields: [], // 查询表单条件 buttons: { // 按钮 query: {}, edit: {}, delete: {}, - add: {}, + add: {} }, - columns: [], // 表格列 - } - }, + columns: [] // 表格列 + }; + } }, relateData: { // 关联的主记录 type: [Object], default: () => { - return {} - }, + return {}; + } }, value: { type: [Array], default: () => { - return [] - }, + return []; + } }, valueNew: { type: [Array], default: () => { - return [] - }, + return []; + } } }, - data () { + data() { return { checkRecords: [], // 表格中当前选中的记录 form: { records: [], // 接口返回的记录列表 - total: 0, // 接口返回的总条数 + total: 0 // 接口返回的总条数 }, saveButtonStatus: [], // 维护表格中每行编辑按钮的状态 inShow inEditing inAdding rowIdList: [] - } + }; }, computed: { // 主键的列名 - primaryKeyFieldName () { - var primaryKey = this.option.columns.find((item) => item['primaryKey'] == true) + primaryKeyFieldName() { + let primaryKey = this.option.columns.find( + item => item["primaryKey"] == true + ); if (primaryKey != null) { - return primaryKey['field'] + return primaryKey["field"]; } else { - return null - console.warn('在columns中查找primaryKey=true失败,会导致查询详情和删除失败') + return null; + console.warn( + "在columns中查找primaryKey=true失败,会导致查询详情和删除失败" + ); } }, // 指定当前实体关联主表的关联字段,孙子关联表,没有该属性 - joinColumn () { - var columnName = this.option.joinColumn + joinColumn() { + let columnName = this.option.joinColumn; if (this.isBlank(columnName)) { - console.warn('在columns中查找关联字段失败,会导致查询详情和删除失败,孙子关联表忽略该错误') - columnName = '' + console.warn( + "在columns中查找关联字段失败,会导致查询详情和删除失败,孙子关联表忽略该错误" + ); + columnName = ""; } - return columnName + return columnName; }, // 未删除的记录 - formRecordsUndelete () { + formRecordsUndelete() { if (this.form.records == null) { - return [] + return []; } - return this.form.records.filter((item) => item[ROW_DELETE_FLAG] == null || item[ROW_DELETE_FLAG] == false) - }, + return this.form.records.filter( + item => item[ROW_DELETE_FLAG] == null || item[ROW_DELETE_FLAG] == false + ); + } }, watch: {}, - created () { + created() { // 主表 relateData 的关联字段 joinColumn 变动时,触发查询子表的查询,孙子关联儿子的无效 if (this.isNotBlank(this.joinColumn)) { this.$watch( - function () { - return this.relateData[this.joinColumn] + function() { + return this.relateData[this.joinColumn]; }, - function (newVal, oldVal) { + function(newVal, oldVal) { // 如果是关联字段发生更新,触发查询 if (this.isNotBlank(newVal)) { - this.handleQueryPageList(newVal) + this.handleQueryPageList(newVal); } else { // 如果关联字段为空,清空本表格的数据,如果是父组件(弹出框)关闭时,设置this.relateData = {默认值}时触发 - this.checkRecords = [] - this.form.records = [] - this.form.total = 0 - this.saveButtonStatus = [] + this.checkRecords = []; + this.form.records = []; + this.form.total = 0; + this.saveButtonStatus = []; } } - ) + ); } }, - mounted () { + mounted() { // 首次打开时,根据主表关联字段查询子表,加载表格数据 - if (this.isNotBlank(this.relateData) && this.isNotBlank(this.relateData[this.joinColumn])) { - this.handleQueryPageList() + if ( + this.isNotBlank(this.relateData) && + this.isNotBlank(this.relateData[this.joinColumn]) + ) { + this.handleQueryPageList(); } }, methods: { // 该行是否显示 true/false/ 'hideOnAdd hideOnView hideOnEdit' - fieldIsHide (tableHide) { - if (typeof tableHide == 'boolean') { - return tableHide + fieldIsHide(tableHide) { + if (typeof tableHide == "boolean") { + return tableHide; } - if (typeof tableHide == 'string') { - if (this.modelType == 'add') { - return tableHide.indexOf('hideOnAdd') >= 0 + if (typeof tableHide == "string") { + if (this.modelType == "add") { + return tableHide.indexOf("hideOnAdd") >= 0; } - if (this.modelType == 'view') { - return tableHide.indexOf('hideOnView') >= 0 + if (this.modelType == "view") { + return tableHide.indexOf("hideOnView") >= 0; } - if (this.modelType == 'edit') { - return tableHide.indexOf('hideOnEdit') >= 0 + if (this.modelType == "edit") { + return tableHide.indexOf("hideOnEdit") >= 0; } } - return false + return false; }, // 获取行的提交按钮文字 - getRowEditButton (index) { - if (this.saveButtonStatus[index] == 'inEditing') { - return 'btn_savetemp' - } else if (this.saveButtonStatus[index] == 'inAdding') { - return 'btn_savetemp' - } else if (this.saveButtonStatus[index] == 'inShow') { - return 'btn_edit' + getRowEditButton(index) { + if (this.saveButtonStatus[index] == "inEditing") { + return this.$lang("btn_savetemp"); + } else if (this.saveButtonStatus[index] == "inAdding") { + return this.$lang("btn_savetemp"); + } else if (this.saveButtonStatus[index] == "inShow") { + return this.$lang("btn_edit"); } else { - return 'not_permission' + return "not_permission"; } }, // 表格行渲染前前置处理 - tableRowClassAdapter ({ row, rowIndex }) { - row.index = rowIndex + tableRowClassAdapter({ row, rowIndex }) { + row.index = rowIndex; }, // 查询 - async handleQueryPageList (joinColumnValue) { + async handleQueryPageList(joinColumnValue) { if (this.isBlank(joinColumnValue)) { - joinColumnValue = this.relateData[this.joinColumn] + joinColumnValue = this.relateData[this.joinColumn]; } - var params = {} - params[this.joinColumn] = joinColumnValue - this.queryPageList(params) + let params = {}; + params[this.joinColumn] = joinColumnValue; + this.queryPageList(params); }, // 暴露给外部直接调用带参数 - async queryPageList (params) { + async queryPageList(params) { // 默认的排序 if (this.isNotBlank(this.option.buttons.query.order)) { - params['sort'] = this.option.buttons.query.sort - params['order'] = this.option.buttons.query.order + params["sort"] = this.option.buttons.query.sort; + params["order"] = this.option.buttons.query.order; } - const { data, code } = await this.option.buttons.query.api(params) - if (code != '200') return - this.form.records = data.records - this.form.total = data.total - this.$emit('input', this.form.records) - for (var i = 0; i < this.form.total; i++) { - this.saveButtonStatus.push('inShow') + const { data, code } = await this.option.buttons.query.api(params); + if (code != "200") return; + this.form.records = data.records; + this.form.total = data.total; + this.$emit("input", this.form.records); + for (let i = 0; i < this.form.total; i++) { + this.saveButtonStatus.push("inShow"); } }, // 选择项改变时 - handleSelectionChange (val) { - this.checkRecords = val + handleSelectionChange(val) { + this.checkRecords = val; }, // 表格选中某一行时 - handleTableRowClick (row, column, event) { + handleTableRowClick(row, column, event) { // console.log(row) // console.log(column) // 行点击后,回调option中的tableRowClick事件 - if (typeof this.option.tableRowClick == 'function') { - this.option.tableRowClick(this.form.records, row, row.index, this.relateData) + if (typeof this.option.tableRowClick == "function") { + this.option.tableRowClick( + this.form.records, + row, + row.index, + this.relateData + ); } }, // 行数据更新时回调 - tableRowChange (rowIndex, fieldName, fieldVal, fieldExtend) { + tableRowChange(rowIndex, fieldName, fieldVal, fieldExtend) { // 通知外面的组件 - this.$emit('input', this.form.records) + this.$emit("input", this.form.records); // 表单变动后,回调option中的tableRowChange事件 - if (typeof this.option.tableChange == 'function') { - this.option.tableChange(this.form.records, rowIndex, fieldName, fieldVal, fieldExtend, this.relateData) + if (typeof this.option.tableChange == "function") { + this.option.tableChange( + this.form.records, + rowIndex, + fieldName, + fieldVal, + fieldExtend, + this.relateData + ); } }, // 新增 - handleAdd () { - this.saveButtonStatus.push('inAdding') - this.form.records.push({}) + handleAdd() { + this.saveButtonStatus.push("inAdding"); + this.form.records.push({}); }, // 父节点Change,子节点表格更新 - handleUpdata () { - this.saveButtonStatus = [] - this.form.records = [] + handleUpdata() { + this.saveButtonStatus = []; + this.form.records = []; }, // 提交和修改 - handleAddOrUpdate (row, index) { + handleAddOrUpdate(row, index) { // 编辑状态下点击保存提交 - if (this.saveButtonStatus[index] == 'inEditing' || this.saveButtonStatus[index] == 'inAdding') { - this.handleSaveTemp(row, index) + if ( + this.saveButtonStatus[index] == "inEditing" || + this.saveButtonStatus[index] == "inAdding" + ) { + this.handleSaveTemp(row, index); } else { - this.$set(this.saveButtonStatus, index, 'inEditing') + this.$set(this.saveButtonStatus, index, "inEditing"); } }, // 校验表单 - validate (callback) { - this.$refs['form'].validate(async (valid, obj) => { + validate(callback) { + this.$refs["form"].validate(async (valid, obj) => { if (callback != null) { - callback(valid) + callback(valid); } - }) + }); }, // 暂存 - async handleSaveTemp (row, index) { - this.$refs['form'].validate((valid) => { + async handleSaveTemp(row, index) { + this.$refs["form"].validate(valid => { if (valid) { if (this.isBlank(row[this.primaryKeyFieldName])) { // 补全关联属性 - if (typeof this.option.beforeInsert == 'function') { - this.option.beforeInsert(this.relateData, row) + if (typeof this.option.beforeInsert == "function") { + this.option.beforeInsert(this.relateData, row); } } else { // 补全关联属性 - if (typeof this.option.beforeUpdate == 'function') { - this.option.beforeUpdate(this.relateData, row) + if (typeof this.option.beforeUpdate == "function") { + this.option.beforeUpdate(this.relateData, row); } } // 将行按钮的文字改成编辑 - this.$set(this.saveButtonStatus, index, 'inShow') + this.$set(this.saveButtonStatus, index, "inShow"); // 通知外面的组件 - this.$emit('input', this.form.records) + this.$emit("input", this.form.records); } - }) + }); /* this.$refs['form'].validate((valid) => { if (valid) { @@ -417,32 +512,34 @@ export default { */ }, // 删除 - handleDelete (row, index) { - this.saveButtonStatus.splice(index, 1) // 清空状态 + handleDelete(row, index) { + this.saveButtonStatus.splice(index, 1); // 清空状态 // 界面上临时新增出来的一行,还没有提交到数据库,可以直接删除 - if (this.saveButtonStatus[index] == 'inAdding') { - this.form.records.splice(index, 1) - this.saveButtonStatus.splice(index, 1) - this.$emit('input', this.form.records) - return + if (this.saveButtonStatus[index] == "inAdding") { + this.form.records.splice(index, 1); + this.saveButtonStatus.splice(index, 1); + this.$emit("input", this.form.records); + return; } // if (this.isBlank(row) || this.isBlank(row[this.primaryKeyFieldName])) { // return // } // 将对应的行标识成删除 // 找出该行在原始记录中的index - // var realIndex = this.form.records.findIndex((item) => item[this.primaryKeyFieldName] == row[this.primaryKeyFieldName]) - // row[ROW_DELETE_FLAG] = true - // this.$set(this.form.records, realIndex, row) + let realIndex = this.form.records.findIndex( + item => item[this.primaryKeyFieldName] == row[this.primaryKeyFieldName] + ); + row[ROW_DELETE_FLAG] = true; + this.$set(this.form.records, realIndex, row); + this.$emit("input", this.form.records); + // this.form.records.splice(index, 1) + // this.rowIdList.push(row.id) // this.$emit('input', this.form.records) - this.form.records.splice(index, 1) - this.rowIdList.push(row.id) - this.$emit('input', this.form.records) - this.$emit('update:valueNew', this.rowIdList) + // this.$emit('update:valueNew', this.rowIdList) /* 之前是直接调用接口删除,后面统一改成在主表接口中增加、更新、删除 // 已经保存在数据库的的行,要调用删除按钮 - var primaryKey = row[this.primaryKeyFieldName] + let primaryKey = row[this.primaryKeyFieldName] this.$confirm(this.$lang('promptMessage_deleteTip'), this.$lang('promptMessage_deleteTipTitle'), { type: 'warning', confirmButtonClass: 'delete_sure', @@ -459,9 +556,9 @@ export default { e }) */ - }, - }, -} + } + } +}; </script> <style scoped lang="scss"> diff --git a/report-ui/src/components/AnjiPlus/anji-crud/edit.vue b/report-ui/src/components/AnjiPlus/anji-crud/edit.vue index 76bb6d6b..b13411a2 100644 --- a/report-ui/src/components/AnjiPlus/anji-crud/edit.vue +++ b/report-ui/src/components/AnjiPlus/anji-crud/edit.vue @@ -1,13 +1,7 @@ -<!-- - * @Author: lide1202@hotmail.com - * @Date: 2021-3-13 11:04:24 - * @Last Modified by: lide1202@hotmail.com - * @Last Modified time: 2021-3-13 11:04:24 - !--> <template> <el-dialog :width="dialogWidth" - :class="dialogFullScreen?'full-screen':'notfull-screen'" + :class="dialogFullScreen ? 'full-screen' : 'notfull-screen'" :close-on-click-modal="false" center :visible.sync="showDialog" @@ -15,7 +9,7 @@ @close="handleCloseDialog('close')" > <template v-slot:title> - {{ option.title + '--' + modelType }} + {{ option.title + "--" + $lang(`btn_${modelType}`) }} <button type="button" aria-label="Close" @@ -67,49 +61,55 @@ <!--自定义的卡片插槽--> <slot name="customCard" /> - <div - slot="footer" - style="text-align: center" - > - <slot - v-if="modelType =='edit'" - name="editBtn" - :rowData="rowData" - /> - <el-button - type="danger" - plain - @click="handleCloseDialog('close')" - >关闭</el-button> + <div slot="footer" style="text-align: center"> + <slot v-if="modelType == 'edit'" name="editBtn" :rowData="rowData" /> + <el-button type="danger" plain @click="handleCloseDialog('close')">{{ + $lang("btn_close") + }}</el-button> <el-button - v-if="modelType!='view'" + v-if="modelType != 'view'" type="primary" plain @click="handleValidateAndSave" - >保存</el-button> + >{{ $lang("btn_save") }}</el-button + > </div> </el-dialog> </template> <script> -import EditForm from './edit-form' -import EditTable from './edit-table' +import EditForm from "./edit-form"; +import EditTable from "./edit-table"; export default { - name: 'EditDialog', + name: "EditDialog", components: { EditForm, EditTable }, props: { visible: { type: [Boolean], default: () => { - return false - }, + return false; + } }, rowData: { // 查询参数,对应表格那行数据 type: [Object], default: () => { - return {} - }, + return {}; + } + }, + // 预处理详情接口数据 + handleDetailData: { + type: Function, + default: data => { + return data; + } + }, + // 预处理提交数据 + submitDetailData: { + type: Function, + default: (data, tpe) => { + return data; + } }, modelType: String, // add view edit option: { @@ -117,20 +117,20 @@ export default { type: Object, default: () => { return { - title: '', // 页面标题 - labelWidth: '', // 表单输入框label宽度 + title: "", // 页面标题 + labelWidth: "", // 表单输入框label宽度 queryFormFields: [], // 查询表单条件 buttons: { // 按钮 query: {}, edit: {}, delete: {}, - add: {}, + add: {} }, - columns: [], // 表格列 - } - }, - }, + columns: [] // 表格列 + }; + } + } }, data() { return { @@ -141,191 +141,230 @@ export default { // 提交表单的数据 saveForm: {}, // 已成功校验的关联表单个数 - countForValidJoinForm: 0, - } + countForValidJoinForm: 0 + }; }, computed: { // 弹出框的宽度,根据一行显示几列动态调整 dialogWidth() { if (this.cardRowColNum == 2) { - return '60%' + return "60%"; } if (this.cardRowColNum == 3) { - return '70%' + return "70%"; } if (this.cardRowColNum == 4) { - return '80%' + return "80%"; } - return '60%' + return "60%"; }, // 关联属性表 joinEntitys() { if (this.isBlank(this.option.joinEntitys)) { - return [] + return []; } else { - return this.option.joinEntitys + return this.option.joinEntitys; // 找出所有hide != true的关联表 - // var entitys = this.option.joinEntitys.filter((item) => item['hide'] == null || item['hide'] == false) + // let entitys = this.option.joinEntitys.filter((item) => item['hide'] == null || item['hide'] == false) // return entitys } }, // 一对一关联表的个数 countJoinEntityOneToOne() { - var entitys = this.joinEntitys.filter((item) => item['joinType'] == 'OneToOne') + let entitys = this.joinEntitys.filter( + item => item["joinType"] == "OneToOne" + ); if (entitys == null) { - return 0 + return 0; } - return entitys.length - }, + return entitys.length; + } }, watch: { // 监控dialog的显示隐藏变量 visible(newValue, oldValue) { - this.showDialog = newValue + this.showDialog = newValue; // 为主表的编辑表单,渲染上默认值 - this.initDefaultSaveForm() + this.initDefaultSaveForm(); }, rowData(newValue, oldValue) { if (newValue != null) { - this.queryByPrimarykey(newValue) + this.queryByPrimarykey(newValue); } - }, + } }, mounted() { // 为主表的编辑表单,渲染上默认值 - this.initDefaultSaveForm() + this.initDefaultSaveForm(); }, methods: { // 暴露给外部crud页面,回传saveForm的值 getSaveForm() { - return this.saveForm + return this.saveForm; }, setSaveForm(saveForm) { - this.saveForm = saveForm + this.saveForm = saveForm; }, initDefaultSaveForm() { // saveForm的默认值 - var defaultSaveForm = {} - this.option.columns.forEach((item) => { - var key = item.editField + let defaultSaveForm = {}; + this.option.columns.forEach(item => { + let key = item.editField; if (this.isBlank(key)) { - key = item.field + key = item.field; } - var val = item.defaultValue + let val = item.defaultValue; if (this.isNotBlank(val)) { - defaultSaveForm[key] = val + defaultSaveForm[key] = val; } - }) + }); // 为主表的编辑表单,渲染上默认值 - this.saveForm = this.deepClone(defaultSaveForm) - console.log('编辑框默认值:' + JSON.stringify(this.saveForm)) + this.saveForm = this.deepClone(defaultSaveForm); + console.log("编辑框默认值:" + JSON.stringify(this.saveForm)); }, handleCloseDialog(val) { // 为主表的编辑表单,渲染上默认值 - this.initDefaultSaveForm() - this.showDialog = false, // 编辑详情弹框是否显示 - this.dialogFullScreen = false, // 弹出框全屏 - this.cardRowColNum = 2, // 主信息一行显示几列 - this.countForValidJoinForm = 0, // 已成功校验的关联表单个数 - this.$emit('closeEvent', val) + this.initDefaultSaveForm(); + this.showDialog = false; // 编辑详情弹框是否显示 + this.dialogFullScreen = false; // 弹出框全屏 + this.cardRowColNum = 2; // 主信息一行显示几列 + this.countForValidJoinForm = 0; // 已成功校验的关联表单个数 + this.$emit("closeEvent", val); + }, + handleTopCloseDialog() { + // 为主表的编辑表单,渲染上默认值 + this.initDefaultSaveForm(); + this.showDialog = false; // 编辑详情弹框是否显示 + this.dialogFullScreen = false; // 弹出框全屏 + this.cardRowColNum = 2; // 主信息一行显示几列 + this.countForValidJoinForm = 0; // 已成功校验的关联表单个数 }, // 设置一行显示几列 handleSetRowColNum(num) { - this.cardRowColNum = num + this.cardRowColNum = num; }, // 根据关联类型计算组件 getComponentByJoinType(type, item) { - if (type == 'OneToOne') { - return 'EditForm' - } else if (type == 'OneToMany') { - return 'EditTable' + if (type == "OneToOne") { + return "EditForm"; + } else if (type == "OneToMany") { + return "EditTable"; } else { - return '' + return ""; } }, async queryByPrimarykey(rowData) { - const { data, code } = await this.option.buttons.queryByPrimarykey.api(rowData) - if (code != '200') return - this.showDialog = true - this.saveForm = data + const { data, code } = await this.option.buttons.queryByPrimarykey.api( + rowData + ); + if (code != "200") return; + this.showDialog = true; + this.saveForm = this.handleDetailData(data); }, // 保存前,先调用校验 handleValidateAndSave() { - this.countForValidJoinForm = 0 + this.countForValidJoinForm = 0; // 主表单校验 - this.$refs.mainForm.validate((mainValid) => { + this.$refs.mainForm.validate(mainValid => { if (mainValid == false) { - console.warn('主表单校验失败') - return + console.warn("主表单校验失败"); + return; } - console.log('主表单校验完成') + console.log("主表单校验完成"); if (this.joinEntitys == null || this.joinEntitys.length == 0) { // 如果子表没有信息,直接提交 - this.handleSave() - return + this.handleSave(); + return; } - for (var i = 0; i < this.joinEntitys.length; i++) { - console.log(`开始校验子表单-${i} 校验`) - var item = this.joinEntitys[i] - if (this.$refs['joinForm' + i] == null || item.hide == true || this.saveForm[item.fieldNameInMainEntityOnSave] == null || this.saveForm[item.fieldNameInMainEntityOnSave].length == 0) { - console.log('子表单没有数据,直接跳过') - this.countForValidJoinForm++ - console.log('已经校验的子表单:' + this.countForValidJoinForm + ' 共:' + this.joinEntitys.length) + for (let i = 0; i < this.joinEntitys.length; i++) { + console.log(`开始校验子表单-${i} 校验`); + let item = this.joinEntitys[i]; + console.log(item); + if ( + this.$refs["joinForm" + i] == null || + item.hide == true || + this.saveForm[item.fieldNameInMainEntityOnSave] == null || + this.saveForm[item.fieldNameInMainEntityOnSave].length == 0 + ) { + console.warn("子表单校验失败"); + } else { + const childrenChecked = this.checkedChildrenValidate( + this.saveForm[item.fieldNameInMainEntityOnSave], + item.columns + ); + if (!childrenChecked) { + return; + } + + // console.log('子表单没有数据,直接跳过') + this.countForValidJoinForm++; + console.log( + "已经校验的子表单:" + + this.countForValidJoinForm + + " 共:" + + this.joinEntitys.length + ); // 所有关联表单校验通过 if (this.countForValidJoinForm == this.joinEntitys.length) { - console.log('子表单校验完成,提交主表单') - this.handleSave() + console.log("子表单校验完成,提交主表单"); + this.handleSave(); } - continue + continue; } - var joinForm = this.$refs['joinForm' + i] - if (toString.call(joinForm) == '[object Array]') { - joinForm = joinForm[0] + let joinForm = this.$refs["joinForm" + i]; + if (toString.call(joinForm) == "[object Array]") { + joinForm = joinForm[0]; } - joinForm.validate((joinValid) => { + joinForm.validate(joinValid => { if (joinValid) { - this.countForValidJoinForm++ - console.log('已经校验的子表单:' + this.countForValidJoinForm + ' 共:' + this.joinEntitys.length) + this.countForValidJoinForm++; + console.log( + "已经校验的子表单:" + + this.countForValidJoinForm + + " 共:" + + this.joinEntitys.length + ); // 所有关联表单校验通过 if (this.countForValidJoinForm == this.joinEntitys.length) { - console.log('子表单校验完成,提交主表单') - this.handleSave() + console.log("子表单校验完成,提交主表单"); + this.handleSave(); } } else { - console.warn(`子表单${i}校验失败:`) + console.warn(`子表单${i}校验失败:`); } - }) + }); } - }) + }); }, async handleSave() { + const params = this.submitDetailData(this.saveForm, this.modelType); // 新增 - if (this.modelType == 'add') { - const { code, message } = await this.option.buttons.add.api(this.saveForm) - if (code == '200') { + if (this.modelType == "add") { + const { code, message } = await this.option.buttons.add.api(params); + if (code == "200") { // 保存结束,关闭对话框 - this.handleCloseDialog() + this.handleCloseDialog(); // 向外层发关闭事件 - this.$emit('closeEvent') - return + // this.$emit('closeEvent') + return; } else { - this.countForValidJoinForm = 0, // 已成功校验的关联表单个数 - console.log(`提交表单调用新增接口失败:${message}`) + // ;(this.countForValidJoinForm = 0), // 已成功校验的关联表单个数 + console.log(`提交表单调用新增接口失败:${message}`); } } // 修改 - if (this.modelType == 'edit') { + if (this.modelType == "edit") { // console.log(this.$slots.customCard[0].context.$refs.cardInEditData.updateData.settingValue) - const { code, message } = await this.option.buttons.edit.api(this.saveForm) - if (code == '200') { + const { code, message } = await this.option.buttons.edit.api(params); + if (code == "200") { // 保存结束,关闭对话框 - this.handleCloseDialog() + this.handleCloseDialog(); // 向外层发关闭事件 - this.$emit('closeEvent') - return + // this.$emit('closeEvent') + return; } else { - this.countForValidJoinForm = 0, // 已成功校验的关联表单个数 - console.log(`提交表单调用更新接口失败:${message}`) + // ;(this.countForValidJoinForm = 0), // 已成功校验的关联表单个数 + console.log(`提交表单调用更新接口失败:${message}`); } } /* 分步提交 @@ -340,7 +379,7 @@ export default { return } // 主表保存成功后,保存子表 - for (var i = 0; i < this.joinEntitys.length; i++) { + for (let i = 0; i < this.joinEntitys.length; i++) { if (this.joinEntitys[i].joinType == 'OneToOne') { this.$refs['joinForm' + i].handleSave(() => { this.countForSavedOneToOneJoinEntity++ @@ -355,8 +394,24 @@ export default { } })*/ }, - }, -} + // 子表单数据校验 + checkedChildrenValidate(list, confingList) { + const configFileds = confingList.map(item => item.field); + for (let i = 0; i < list.length; i++) { + const item = list[i]; + for (let key = 0; key < configFileds.length; key++) { + if ( + item.hasOwnProperty(configFileds[key]) && + !item[configFileds[key]] + ) { + return false; + } + } + } + return true; + } + } +}; </script> <style scoped lang="scss"> diff --git a/report-ui/src/components/AnjiPlus/anji-daterange.vue b/report-ui/src/components/AnjiPlus/anji-daterange.vue new file mode 100644 index 00000000..3cebf091 --- /dev/null +++ b/report-ui/src/components/AnjiPlus/anji-daterange.vue @@ -0,0 +1,151 @@ +<!-- +:v-model="" +:format="'yyyy-MM-dd HH:mm:ss'" 绑定值的格式,一般是参数传到后台的数据格式 +:defaultValue="['00:00:00','23:59:59']" 选中日期后的默认具体时刻 数据格式为数组 ['00:00:00', '23:59:59'] +@change="" +--> +<template> + <div> + <el-date-picker + v-model="selectedRangeValue" + style="width: 100%" + type="datetimerange" + range-separator="至" + start-placeholder="开始日期" + end-placeholder="结束日期" + :value-format="format" + unlink-panels + :picker-options="pickerOptions" + :default-time="defaultValue" + @change="valueChanged" + /> + </div> +</template> +<script> +import miment from "miment"; +export default { + props: { + format: { + type: String, + default: "yyyy-MM-dd HH:mm:ss" + }, + defaultValue: { + type: Array, + default: () => { + return []; + } + }, + value: { + type: String, + default: "" + } + }, + data() { + return { + selectedRangeValue: [], + pickerOptions: { + shortcuts: [ + { + text: "今天", + onClick(picker) { + const end = new Date(); + const start = new Date( + new Date(new Date().getTime()).setHours(0, 0, 0, 0) + ); + picker.$emit("pick", [start, end]); + } + }, + { + text: "昨天", + onClick(picker) { + const start = new Date( + new Date(new Date().getTime() - 24 * 60 * 60 * 1000).setHours( + 0, + 0, + 0, + 0 + ) + ); + const end = new Date( + new Date(new Date().getTime() - 24 * 60 * 60 * 1000).setHours( + 23, + 59, + 59, + 999 + ) + ); + picker.$emit("pick", [start, end]); + } + }, + { + text: "最近一周", + onClick(picker) { + const end = new Date(); + const start = new Date(); + start.setTime( + miment() + .add(-1, "ww") + .stamp() + ); + picker.$emit("pick", [start, end]); + } + }, + { + text: "最近一个月", + onClick(picker) { + const end = new Date(); + const start = new Date(); + start.setTime( + miment() + .add(-1, "MM") + .stamp() + ); + picker.$emit("pick", [start, end]); + } + }, + { + text: "最近三个月", + onClick(picker) { + const end = new Date(); + const start = new Date(); + start.setTime( + miment() + .add(-3, "MM") + .stamp() + ); + picker.$emit("pick", [start, end]); + } + } + ], + onPick: ({ maxDate, minDate }) => { + this.minDate = minDate; + this.maxDate = maxDate; + } + } + }; + }, + watch: { + value(val) { + this.parseDefaultVal(val); + } + }, + created() {}, + methods: { + // el-date-range的值默认是数组,gaea需要的是'start,end'字符串,这里做下转换 + parseDefaultVal(val) { + if (val != null) { + this.selectedRangeValue = val.split(","); + } else { + this.selectedRangeValue = []; + } + }, + valueChanged(val) { + if (val != null) { + let rangeVal = val.toString(); + this.$emit("change", rangeVal); + this.$emit("input", rangeVal); + } + } + } +}; +</script> diff --git a/report-ui/src/components/AnjiPlus/anji-dialog.vue b/report-ui/src/components/AnjiPlus/anji-dialog.vue new file mode 100644 index 00000000..03ce18ed --- /dev/null +++ b/report-ui/src/components/AnjiPlus/anji-dialog.vue @@ -0,0 +1,209 @@ +<template> + <el-dialog + :width="dialogWidth" + :class="dialogFullScreen ? 'full-screen' : 'notfull-screen'" + center + :fullscreen="dialogFullScreen" + :visible.sync="dialogConfig.dialogVisible" + :before-close="handleDialogClose" + append-to-body + modal-append-to-body + > + <template v-slot:title> + {{ getDialogTitle(dialogConfig.dialogType) }} + <button + v-if="dialogConfig.isFullScreen" + type="button" + aria-label="Close" + class="el-dialog__headerbtn" + style="right: 50px" + @click="dialogFullScreen = !dialogFullScreen" + > + <i class="el-dialog__close el-icon el-icon-full-screen" /> + </button> + </template> + <div class="card-body"> + <div class="anji-card"> + <div v-if="dialogConfig.isSetColRow" class="card-head"> + <div class="main-card-header-button"> + <el-button type="text" @click="handleSetRowColNum(4)" + >||||</el-button + > + <el-button type="text" @click="handleSetRowColNum(3)" + >|||</el-button + > + <el-button type="text" @click="handleSetRowColNum(2)">||</el-button> + </div> + </div> + <slot name="dialogCont" /> + <slot /> + </div> + </div> + <div slot="footer" class="anji-button"> + <el-button + v-if="isBtnClose" + type="danger" + plain + @click="handleDialogClose" + >{{ dialogConfig.isBtnClose.text || $lang("btn_close") }}</el-button + > + <el-button + v-if="isBtnSave" + type="primary" + plain + @click="handleDialogSave" + >{{ dialogConfig.isBtnSave.text || $lang("btn_save") }}</el-button + > + <slot name="dialogBtn" /> + </div> + </el-dialog> +</template> + +<script> +export default { + props: { + // 弹框配置文件 + dialogConfig: { + required: true, + type: Object, + default: () => { + return { + dialogVisible: false, + dialogType: "add", + dialogWidth: "60%", + isFullScreen: true, + isSetColRow: true, + isBtnClose: { + value: true, + text: this.$lang("btn_close") + }, + isBtnSave: { + value: true, + text: this.$lang("btn_save") + }, + column: 2, + setColumnFn: () => {} + }; + } + } + }, + data() { + return { + dialogFullScreen: false // 弹出框全屏 + }; + }, + computed: { + dialogWidth() { + if (this.dialogConfig.dialogWidth) { + return this.dialogConfig.dialogWidth; + } else { + if (this.dialogConfig.column == 2) { + return "60%"; + } + if (this.dialogConfig.column == 3) { + return "70%"; + } + if (this.dialogConfig.column == 4) { + return "80%"; + } + } + return "60%"; + }, + isBtnClose() { + return this.dialogConfig.isBtnClose || this.dialogConfig.isBtnClose.value; + }, + isBtnSave() { + return this.dialogConfig.isBtnSave || this.dialogConfig.isBtnSave.value; + } + }, + methods: { + getDialogTitle(type) { + let title = this.$lang("btn_add"); + switch (type) { + case "add": + title = this.$lang("btn_add"); + break; + case "edit": + title = this.$lang("btn_edit"); + break; + case "view": + title = this.$lang("btn_view"); + break; + default: + title = type; + break; + } + return title; + }, + handleSetRowColNum(val) { + const cardRowColSpan = 24 / val; + this.dialogConfig.setColumnFn(cardRowColSpan); + }, + handleDialogClose() { + this.$emit("handleClose"); + }, + handleDialogSave() { + this.$emit("handleDialogSave"); + } + } +}; +</script> + +<style scoped lang="scss"> +.notfull-screen { + /deep/.el-dialog__body { + background-color: rgb(240, 242, 245); + padding: 5px; + max-height: 60vh; + overflow: auto; + } +} +.full-screen { + /deep/.el-dialog__body { + background-color: rgb(240, 242, 245); + padding: 5px; + height: calc(100vh - 110px); + overflow: auto; + } +} +.anji-card { + margin-bottom: 5px; + box-sizing: border-box; + padding: 0 20px; + color: rgba(0, 0, 0, 0.65); + font-size: 14px; + font-letiant: tabular-nums; + line-height: 1.5; + list-style: none; + font-feature-settings: "tnum"; + position: relative; + background: #fff; + border-radius: 2px; + transition: all 0.3s; +} +.drawerContainer { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + .drawerMain { + flex: 1; + overflow-y: auto; + overflow-x: hidden; + padding: 0 20px; + } + .footer { + border-top: 1px solid #eff0f3; + height: 66px; + display: flex; + justify-content: center; + align-items: center; + } +} +.addForm { + text-align: center; +} +.activeColor /deep/.el-form-item__label { + color: #5887fb; +} +</style> diff --git a/report-ui/src/components/AnjiPlus/anji-fourLevel.vue b/report-ui/src/components/AnjiPlus/anji-fourLevel.vue new file mode 100644 index 00000000..92a53d8b --- /dev/null +++ b/report-ui/src/components/AnjiPlus/anji-fourLevel.vue @@ -0,0 +1,72 @@ +<template> + <el-cascader ref="country" v-model="countryValue" size="mini" :props="props" :options="countryOptions" style="width: 100%" clearable @change="handleChange" /> +</template> +<script> +import { postRequest } from '@/api/common.js' +export default { + props: { + value: null, + }, + data() { + return { + countryValue: [], + props: { + value: 'value', + label: 'label', + children: 'children', + }, + countryOptions: [], + } + }, + watch: { + value(val) { + this.handleCountryEcho(val) + }, + }, + created() { + this.provinceFn() + this.handleCountryEcho(this.value) + }, + methods: { + // 获取省市区 + async provinceFn() { + const { code, data } = await postRequest() + if (code != 200) return + this.countryOptions = data + }, + handleChange(value) { + if (value.length > 0) { + const countryNameArr = this.$refs.country.getCheckedNodes()[0].pathLabels + const countryObj = { + countryName: countryNameArr[0], + provinceName: countryNameArr[1], + cityName: countryNameArr[2], + areaName: countryNameArr[3], + countryCode: value[0], + provinceCode: value[1], + cityCode: value[2], + areaCode: value[3], + } + + this.$emit('input', countryObj) + this.$emit('change', countryObj) + } else { + this.$emit('input', {}) + this.$emit('change', {}) + } + }, + handleCountryEcho(val) { + if (val) { + this.countryValue = [val.countryCode, val.provinceCode, val.cityCode, val.areaCode || val.regionCode] + } else { + this.countryValue = [] + } + }, + }, +} +</script> +<style lang="scss" scoped> +.con { + display: inline-block; +} +</style> diff --git a/report-ui/src/components/AnjiPlus/anji-input.vue b/report-ui/src/components/AnjiPlus/anji-input.vue new file mode 100644 index 00000000..5399ad6c --- /dev/null +++ b/report-ui/src/components/AnjiPlus/anji-input.vue @@ -0,0 +1,180 @@ +<template> + <div class="anji-input"> + <el-input v-model="inputValue" type="number" :placeholder="placeholder" :disabled="disabled" clearable @change="change"> + <template slot="append"> + <el-dropdown @command="handleClick"> + <el-button type="primary"> {{ systemUnit }}</el-button> + <el-dropdown-menu slot="dropdown"> + <el-dropdown-item v-for="item in SystemTimeConversionRadioGroup" :key="item.label" :command="item">{{ item.label }}</el-dropdown-item> + </el-dropdown-menu> + </el-dropdown> + </template> + </el-input> + </div> +</template> +<script> +export default { + props: { + value: null, + placeholder: null, + unit: String, + defaultUnit: String, + disabled: Boolean, + }, + data() { + return { + inputValue: '', + input: '', + unitObj: {}, + systemUnit: '', // 单位 + systemConversion: '', // 转换单位 + systemKeepPoint: '', // 保留小数位 + systemRounding: '', // 取整方案 + SystemTimeConversionRadioGroup: [], // 单位选择 + } + }, + watch: { + value: function (val, oldVal) { + this.echoInputValue(val) + }, + }, + mounted() { + this.getLocalStorage() + this.getSystemData() + this.echoInputValue(this.value) + }, + methods: { + getSystemData() { + const defaultUnit = this.defaultUnit + this.systemKeepPoint = this.getSystemKeepPoint() + this.systemRounding = this.getSystemRounding() + this.SystemTimeConversionRadioGroup = this.getSystemTimeConversionRadioGroup() + if (defaultUnit == undefined) { + this.systemUnit = this.getSystemUnit() + this.systemConversion = this.getSystemConversion() + } else { + this.systemUnit = defaultUnit + this.systemConversion = this.SystemTimeConversionRadioGroup.find((item) => item.label == this.systemUnit)['value'] + } + }, + // 获取单位 + getSystemUnit() { + let unit = '' + for (const key in this.unitObj) { + if (key.toLowerCase().indexOf('conversiontext') != -1) { + unit = this.unitObj[key] + } + } + return unit + }, + // 获取转换关系 + getSystemConversion() { + let conversion = '' + for (const key in this.unitObj) { + if (key.toLowerCase().indexOf('conversion') != -1 && key.toLowerCase().indexOf('conversiontext') == -1 && key.toLowerCase().indexOf('conversionradiogroup') == -1) { + conversion = this.unitObj[key] + } + } + return conversion + }, + // 获取保留几位小数 + getSystemKeepPoint() { + let keepPoint = '' + for (const key in this.unitObj) { + if (key.toLowerCase().indexOf('keeppoint') != -1) { + keepPoint = this.unitObj[key] + } + } + return keepPoint + }, + // 获取怎么取整 + getSystemRounding() { + let rounding = '' + for (const key in this.unitObj) { + if (key.toLowerCase().indexOf('pointrounding') != -1) { + rounding = this.unitObj[key] + } + } + return rounding + }, + // 获取各类型的全部单位 + getSystemTimeConversionRadioGroup() { + let radionGroup = '' + for (const key in this.unitObj) { + if (key.toLowerCase().indexOf('radiogroup') != -1) { + radionGroup = this.unitObj[key] + } + } + return radionGroup + }, + handleClick(command) { + this.systemUnit = command.label + this.systemConversion = command.value + this.echoInputValue(this.value) + }, + // 从本地获取数据 + getLocalStorage() { + const localstorageData = this.getSettingByName('unit_conversion') + const unitObj = {} + for (const key in localstorageData) { + if (key.toLowerCase().indexOf(this.unit.toLowerCase()) != -1) { + unitObj[key] = localstorageData[key] + } + } + this.unitObj = unitObj + }, + change(val) { + if (val === null || val === '') { + this.$emit('input', val) + this.$emit('change', val) + return + } + this.inputValue = val + if (this.systemRounding != undefined) { + let newVal + if (this.systemRounding == 'up') { + newVal = this.upFixed(val, this.systemKeepPoint) + } + if (this.systemRounding == 'down') { + newVal = this.downFixed(val, this.systemKeepPoint) + } + this.inputValue = newVal + const value = (newVal || val) * this.systemConversion + this.$emit('input', value) + this.$emit('change', value) + } else { + const value = val * this.systemConversion + this.inputValue = val + this.$emit('input', value) + this.$emit('change', value) + } + }, + echoInputValue(val) { + if (val === undefined || val === '') { + this.inputValue = '' + } else { + this.inputValue = val / this.systemConversion + } + }, + // 向上取整 + upFixed(num, fix) { + return Math.ceil(num * Math.pow(10, fix)) / Math.pow(10, fix).toFixed(fix) + }, + // 向下取整 + downFixed(num, fix) { + return Math.floor(num * Math.pow(10, fix)) / Math.pow(10, fix).toFixed(fix) + }, + }, +} +</script> +<style lang="less" scoped> +// /deep/.el-input-group__append { +// padding: 0 5px; +// } +/deep/.el-input__suffix { + padding: 0 6px; +} +.anji-input /deep/ .el-input__inner { + padding-right: 0 !important; +} +</style> diff --git a/report-ui/src/components/AnjiPlus/anji-select.vue b/report-ui/src/components/AnjiPlus/anji-select.vue index 7e952ffd..e2830c43 100644 --- a/report-ui/src/components/AnjiPlus/anji-select.vue +++ b/report-ui/src/components/AnjiPlus/anji-select.vue @@ -25,6 +25,8 @@ <el-select v-model="selectValue" :clearable="clearable" + :allow-create="!!allowCreate" + :default-first-option="!!allowCreate" :collapse-tags="collapseTags" filterable class="filter-item" @@ -39,29 +41,39 @@ v-for="(item, index) in options" :key="index" :label="getItemLabel(item, label)" - :value="item[option]" + :value="item[option] + ''" :disabled="isDisabledOption(item)" > <template v-if="mergeLabel"> <span style="float: left">{{ getItemLabel(item, label) }}</span> - <span style="float: right; color: #8492a6; font-size: 13px">{{ - item[option] - }}</span> + <span + v-if="!dictCode && !localOptions" + style="float: right; color: #8492a6; font-size: 13px" + >{{ item[option] }}</span + > </template> </el-option> - <el-option v-if="totalPage > 1" label="搜索更多" value="" disabled /> + <el-option v-if="totalPage >= 1" value="" disabled>{{ + $lang("GLOBAL.placeholder_select_remote_search") + }}</el-option> </el-select> </div> </template> <script> import request from "@/utils/request"; -import { getStorageItem } from "@/utils/storage"; export default { props: { dictCode: null, // 当传入dictCode时,可以不用传递url url: null, - method: null, + allowCreate: { + type: Boolean, + default: false + }, + method: { + type: String, + default: "get" + }, queryParam: { type: Object, default: () => { @@ -91,7 +103,7 @@ export default { }, mergeLabel: { type: Boolean, - default: false + default: true }, // 禁用的下拉选项 disabledOptions: { @@ -117,10 +129,13 @@ export default { computed: { // 根据dictCode和url拼出最终的请求url requestUrl() { + if (this.localOptions) { + return null; + } if (this.url != null && this.url.trim() != "") { if (this.url.indexOf("?") > 0) { if (this.option == null) { - console.log("url-" + this.url.substring(this.url.indexOf("?"))); + // console.log('url-' + this.url.substring(this.url.indexOf('?'))) } if (this.label == null) { } @@ -134,20 +149,39 @@ export default { } }, watch: { - value: function(val, oldVal) { - if (this.multiple != null) { - if (!this.value) { - this.selectValue = []; - } else { - this.selectValue = this.value; + dictCode(val) { + if (val) { + this.queryData(); + } + }, + // 监听接口地址变化时,触发刷新请求 + localOptions(val) { + this.options = val; + }, + value: { + handler(val) { + if ( + typeof val == "string" && + this.url != null && + this.url.trim() != "" + ) { + this.remoteQuery(val); } - } else { - if (this.value != null && this.value != undefined) { - this.selectValue = this.value; + if (this.multiple != null) { + if (!this.value) { + this.selectValue = []; + } else { + this.selectValue = this.value; + } } else { - this.selectValue = ""; + if (this.value != null && this.value != undefined) { + this.selectValue = this.value + ""; + } else { + this.selectValue = ""; + } } - } + }, + immediate: true }, url() { setTimeout(() => { @@ -160,7 +194,7 @@ export default { this.selectValue = this.value; } else { if (this.value != null) { - this.selectValue = this.value; + this.selectValue = this.value + ""; } } }, @@ -181,17 +215,17 @@ export default { ) { return false; } - var currentOptionVal = option[this.option]; + let currentOptionVal = option[this.option]; return this.disabledOptions.indexOf(currentOptionVal) >= 0; }, change(value) { if (value === "") { - value = null; + value = ""; } this.$emit("input", value); // 根据当前值,找出对应的选项 - var optionItem = this.options.find(item => item[this.option] == value); + let optionItem = this.options.find(item => item[this.option] == value); this.$emit("change", value, optionItem); }, // 根据用户配置的label,生成对应的标签 @@ -199,34 +233,38 @@ export default { if (label.indexOf("${") < 0 && label.indexOf("}" < 0)) { return item[label]; } - var reg = /\$\{[a-zA-Z0-9]*\}/g; - var list = label.match(reg); + let reg = /\$\{[a-zA-Z0-9]*\}/g; + let list = label.match(reg); // ["${id}", "${text}"] - var result = label; - for (var i = 0; i < list.length; i++) { - var sub = list[i]; - var key = sub.replace("${", "").replace("}", ""); + let result = label; + for (let i = 0; i < list.length; i++) { + let sub = list[i]; + let key = sub.replace("${", "").replace("}", ""); result = result.replace(sub, item[key]); } return result; }, // 从本地localStorage取 gaeaDict getOptionsFromLocalStorage() { - var dicts = getStorageItem("gaeaDict"); - var options = []; + let dicts = JSON.parse(localStorage.getItem("gaeaDict")); + let options = []; if (!dicts.hasOwnProperty(this.dictCode)) { return []; } - var dictItems = dicts[this.dictCode]; - for (var i = 0; i < dictItems.length; i++) { - var dictItem = dictItems[i]; - options.push({ id: dictItem.id, text: dictItem.text }); + let dictItems = dicts[this.dictCode]; + for (let i = 0; i < dictItems.length; i++) { + let dictItem = dictItems[i]; + options.push({ + id: dictItem.id.toString(), + text: dictItem.text, + extend: dictItem.extend + }); } return options; }, queryData() { // 所有从本地localStorage取,因为在App.vue中已经请求远程保存到本地了 - var options = this.getOptionsFromLocalStorage(); + let options = this.getOptionsFromLocalStorage(); if (this.isNotBlank(options)) { this.options = options; return; @@ -245,7 +283,7 @@ export default { } }, queryDataByGet(keyword) { - var param = this.deepClone(this.queryParam); + let param = this.deepClone(this.queryParam); if (this.isNotBlank(keyword)) { param["keyword"] = keyword; } @@ -255,11 +293,12 @@ export default { headers: { noPrompt: true }, params: param }).then(response => { + // console.log(response) this.setOptions(response.data); }); }, queryDataByPost(keyword) { - var param = this.deepClone(this.queryParam); + let param = this.deepClone(this.queryParam); if (this.isNotBlank(keyword)) { param["keyword"] = keyword; } @@ -299,9 +338,9 @@ export default { this.options = resData.records; }, remoteQuery(keyword) { - if (this.isBlank(keyword)) { - return; - } + // if (this.isBlank(keyword)) { + // return + // } setTimeout(() => { if ( this.method != null && @@ -316,8 +355,11 @@ export default { } }; </script> -<style scoped> -.filter-item { - width: 100%; +<style lang="scss" scoped> +.el-select-dropdown__item.selected { + text-align: center; +} +.el-select-dropdown__item.is-disabled { + text-align: center; } </style> diff --git a/report-ui/src/components/AnjiPlus/anji-tree.vue b/report-ui/src/components/AnjiPlus/anji-tree.vue index dd767518..107878ac 100644 --- a/report-ui/src/components/AnjiPlus/anji-tree.vue +++ b/report-ui/src/components/AnjiPlus/anji-tree.vue @@ -6,90 +6,107 @@ !--> <template> <div> - <el-input class="filterInput" placeholder="搜索" v-model="filterText" v-if="enableFilter" /> + <el-input + class="filterInput" + placeholder="搜索" + v-model="filterText" + v-if="enableFilter" + /> <div class="title">{{ labelName }}</div> - <el-tree ref="table_tree" :data="treeData" node-key="id" :default-expand-all="isOpen" :expand-on-click-node="false" :filter-node-method="filterNode" @node-click="nodeClick" @check="checkedEvent" /> + <el-tree + ref="table_tree" + :data="treeData" + node-key="id" + :default-expand-all="isOpen" + :expand-on-click-node="false" + :filter-node-method="filterNode" + @node-click="nodeClick" + @check="checkedEvent" + /> </div> </template> <script> -import request from '@/utils/request' +import request from "@/utils/request"; export default { components: {}, props: { url: { type: [String], default: () => { - return '' - }, + return ""; + } }, id: { type: [String], default: () => { - return 'id' - }, + return "id"; + } }, label: { type: [String], default: () => { - return '' - }, + return ""; + } }, value: { type: [String], default: () => { - return '' - }, + return ""; + } }, labelName: String, enableFilter: Boolean, - isOpen: Boolean, + isOpen: Boolean }, data() { return { - filterText: '', - treeData: [], - } + filterText: "", + treeData: [] + }; }, computed: {}, watch: { filterText(val) { - this.$refs.table_tree.filter(val) - }, + this.$refs.table_tree.filter(val); + } }, mounted() { - this.queryData() + this.queryData(); }, methods: { filterNode(val, data) { - if (!val) return true - return data.label.indexOf(val) !== -1 + if (!val) return true; + return data.label.indexOf(val) !== -1; }, queryData() { if (this.isBlank(this.url)) { - return + return; } request({ url: this.url, - method: 'GET', - }).then((response) => { - if (response.code != '200') { - return + method: "GET" + }).then(response => { + if (response.code != "200") { + return; } - this.treeData = Object.prototype.toString.call(response.data) == '[object Array]' ? response.data : response.data.tree|| response.data.menuTree - }) + this.treeData = + Object.prototype.toString.call(response.data) == "[object Array]" + ? response.data + : response.data.tree || response.data.menuTree; + }); }, // 点击tree节点时 将tree的id作为上级机构代码 查询列表 nodeClick(node) { - this.$emit('input', node['id']) - this.$emit('node-click', node['id']) + this.$emit("input", node["id"]); + this.$emit("node-click", node["id"]); }, checkedEvent(item, evt) { - var ids = evt.checkedKeys.toString() - this.$emit('input', ids) - }, - }, -} + let ids = evt.checkedKeys.toString(); + this.$emit("input", ids); + } + } +}; </script> <style scoped lang="scss"> diff --git a/report-ui/src/components/AnjiPlus/anji-upload.vue b/report-ui/src/components/AnjiPlus/anji-upload.vue index 7b16bffe..565d17df 100644 --- a/report-ui/src/components/AnjiPlus/anji-upload.vue +++ b/report-ui/src/components/AnjiPlus/anji-upload.vue @@ -13,7 +13,43 @@ :before-upload="handleBeforeUpload" :class="fileList && fileList.length >= limit ? 'hide_box' : ''" > - <i class="el-icon-plus" /> + <i slot="default" class="el-icon-plus" /> + <div slot="file" slot-scope="{ file }" class="imgBox"> + <img + v-if="typeImgShow(file)" + class="el-upload-list__item-thumbnail" + :src="file.url" + alt="" + /> + <svg-icon + v-else-if="typePdfShow(file)" + icon-class="PDF" + class="iconFont" + /> + <svg-icon + v-else-if="typeExcelShow(file)" + icon-class="Excel" + class="iconFont" + /> + <span class="el-upload-list__item-actions"> + <span + v-if="typeImgShow(file)" + class="el-upload-list__item-preview" + @click="handlePictureCardPreview(file)" + > + <i class="el-icon-zoom-in" /> + </span> + <span + class="el-upload-list__item-delete" + @click="handleDownload(file)" + > + <i class="el-icon-download" /> + </span> + <span class="el-upload-list__item-delete" @click="handleRemove(file)"> + <i class="el-icon-delete" /> + </span> + </span> + </div> </el-upload> <el-dialog :visible.sync="dialogVisibleImageUpload" :modal="false"> <img width="100%" :src="imageUploadUrl" alt="" /> @@ -33,19 +69,25 @@ export default { viewUrl: { type: String, default: () => { - return process.env.BASE_API + "/file/download/"; + return ""; } }, limit: { type: Number, default: () => { - return 1; + return 3; } }, value: { + type: Array, + default: () => { + return []; + } + }, + uploadType: { type: String, default: () => { - return ""; + return "img"; } } }, @@ -53,15 +95,16 @@ export default { return { imageUploadUrl: "", dialogVisibleImageUpload: false, - fileList: [] + fileList: [], + modeString: "" }; }, computed: { requestUrl() { if (this.upLoadUrl != null && this.upLoadUrl.trim() != "") { - return process.env.BASE_API + this.upLoadUrl; + return process.env.VUE_APP_BASE_API + this.upLoadUrl; } else { - return process.env.BASE_API + "/file/upload"; + return process.env.VUE_APP_BASE_API + "/meta/file/upload"; } }, headers() { @@ -73,37 +116,80 @@ export default { watch: { value: { handler(val) { - this.echoUpload(this.value); + this.echoUpload(val); }, immediate: true } }, - mounted() { - this.echoUpload(this.value); - }, + mounted() {}, methods: { + // 图片 + typeImgShow(file) { + if (!file.fileType) return; + const fileType = file.fileType.toLowerCase(); + if ( + fileType == "jpg" || + fileType == "png" || + fileType == "gif" || + fileType == "icon" + ) { + return true; + } + return false; + }, + // pdf + typePdfShow(file) { + if (!file.fileType) return; + const fileType = file.fileType.toLowerCase(); + if (fileType == "pdf") { + return true; + } + return false; + }, + // excel + typeExcelShow(file) { + if (!file.fileType) return; + const fileType = file.fileType.toLowerCase(); + if (fileType == "xlsx" || fileType == "xls" || fileType == "csv") { + return true; + } + return false; + }, handleRemove(file) { - this.fileList = []; + const fileList = []; + this.fileList.forEach(el => { + if (el.fileId != file.fileId) { + fileList.push(el); + } + }); + this.fileList = fileList; this.change(); }, handlePictureCardPreview(file) { this.imageUploadUrl = file.url; this.dialogVisibleImageUpload = true; }, + // 下载 + handleDownload(file) { + window.open(file.url); + }, // 上传成功的回调 handleSuccess(response, file, fileList) { + console.log(fileList); if (response.code != 200) { this.$message.error("上传失败"); return; } this.fileList.push({ - url: file.response.data.urlPath + url: file.response.data.urlPath, + fileId: file.response.data.fileId, + fileType: file.response.data.fileType }); this.change(); }, // 回传出去 change() { - const fileList = (this.fileList.length > 0 && this.fileList[0].url) || ""; + const fileList = this.fileList; this.$emit("input", fileList); this.$emit("change", fileList); }, @@ -113,7 +199,18 @@ export default { .split(".") [file.name.split(".").length - 1].toLowerCase(); // .png|.jpg|.gif|.icon|.pdf|.xlsx|.xls|.csv|.mp4|.avi - const extensionList = ["png", "jpg", "gif", "icon"]; + const extensionList = [ + "png", + "jpg", + "gif", + "icon", + "pdf", + "xlsx", + "xls", + "csv", + "mp4", + "avi" + ]; if (extensionList.indexOf(extension) < 0) { this.$message.warning("请上传正确的格式文件"); return false; @@ -122,11 +219,20 @@ export default { }, // 回显 echoUpload(val) { - if (!val) { - this.fileList = []; + if (val && val.length > 0) { + const fileList = []; + for (let i = 0; i < val.length; i++) { + const obj = {}; + obj.url = val[i].urlPath || val[i].url; + obj.fileType = val[i].fileType; + obj.fileId = val[i].fileId; + fileList.push(obj); + } + fileList.forEach((el, index) => { + this.$set(this.fileList, index, el); + }); } else { - const list = [{ url: val }]; - this.fileList = list; + this.fileList = []; } } } @@ -142,7 +248,7 @@ export default { width: 60px; height: 60px; } -.hide_box /deep/ .el-upload--picture-card { +.hide_box .el-upload--picture-card { display: none; } .el-upload-list__item { diff --git a/report-ui/src/components/AnjiPlus备份/anji-crud/anji-crud.vue b/report-ui/src/components/AnjiPlus备份/anji-crud/anji-crud.vue new file mode 100644 index 00000000..bcc89183 --- /dev/null +++ b/report-ui/src/components/AnjiPlus备份/anji-crud/anji-crud.vue @@ -0,0 +1,808 @@ +<template> + <div :class="[hasTreeFieldInQueryForm ? 'page-container' : 'app-container']"> + <div v-if="hasTreeFieldInQueryForm" class="left-container"> + <AnjiTree + ref="queryFormTree" + v-model.trim="queryParams[queryFormTreeField.field]" + :is-open="queryFormTreeField.anjiTreeOption.isOpen" + :enable-filter="queryFormTreeField.anjiTreeOption.enableFilter" + :label-name="queryFormTreeField.label" + :url="queryFormTreeField.anjiTreeOption.url" + @node-click="handleTreeNodeCheck" + /> + </div> + <div class="right-container"> + <!-- 查询表单开始 --> + <el-form + ref="formSearch" + :model="queryParams" + label-width="100px" + v-permission="option.buttons.query.permission" + > + <el-row> + <el-col + v-for="(item, index) in queryFormFieldExcludeTree" + :key="item.field" + :span="queryFormFieldSpan(item)" + > + <el-form-item + v-if="index <= 2 || (index > 2 && queryParams.showMoreSearch)" + :label="item.label" + :rules="item.rules" + :prop="item.field" + > + <!-- 输入框 --> + <el-input + v-if=" + item.inputType == 'input' || item.inputType == 'input-number' + " + v-model.trim="queryParams[item.field]" + :placeholder="item.placeholder || '请输入'" + :clearable="item.clearable !== false" + :disabled="item.disabled" + @change="value => queryFormChange(item.field, value)" + /> + <!-- 开关 --> + <el-switch + v-else-if="item.inputType == 'switch'" + v-model.trim="queryParams[item.field]" + :disabled="item.disabled" + :active-value="item.switchOption.disableValue" + :inactive-value="item.switchOption.enableValue" + active-color="#5887fb" + inactive-color="#ccc" + @change="value => queryFormChange(item.field, value)" + /> + <!-- 下拉框 --> + <anji-select + v-else-if="item.inputType == 'anji-select'" + v-model.trim="queryParams[item.field]" + :multiple="item.anjiSelectOption.multiple" + :dict-code="item.anjiSelectOption.dictCode" + :url="item.anjiSelectOption.url" + :method="item.anjiSelectOption.method" + :query-param="item.anjiSelectOption.queryParam" + :option="item.anjiSelectOption.option" + :label="item.anjiSelectOption.label" + :disabled-options="item.anjiSelectOption.disabledOptions" + :disabled="item.disabled" + :merge-label="item.anjiSelectOption.mergeLabel" + @change="value => queryFormChange(item.field, value)" + /> + <!-- 日期时间框 --> + <el-date-picker + v-else-if="item.inputType.indexOf('date') >= 0" + v-model="queryParams[item.field]" + style="width: 100%" + :placeholder="item.placeholder || '请选择'" + :type="item.inputType" + :clearable="item.clearable !== false" + @change="value => queryFormChange(item.field, value)" + /> + <!-- 待扩展的表单类型,请自行扩展 --> + <el-input + v-else + placeholder="组件不支持此类型表单请至组件内部自行扩展" + disabled + /> + </el-form-item> + </el-col> + + <el-col :span="6" style="text-align: center"> + <el-button type="primary" @click="handleQueryForm('query')" + >查询</el-button + > + <el-button type="danger" @click="handleResetForm()">重置</el-button> + <a + v-if="queryFormFieldExcludeTree.length > 3" + style="margin-left: 8px" + @click="handleToggleMoreSearch" + > + {{ queryParams.showMoreSearch == true ? "收起" : "展开" }} + <i + :class=" + queryParams.showMoreSearch + ? 'el-icon-arrow-up' + : 'el-icon-arrow-down' + " + /> + </a> + </el-col> + </el-row> + </el-form> + <!-- 查询表单结束 --> + + <!-- 批量操作 --> + <slot name="buttonLeftOnTable" /> + <el-button + v-if=" + option.buttons.add.isShow == undefined + ? true + : option.buttons.add.isShow + " + v-permission="option.buttons.add.permission" + type="primary" + icon="el-icon-plus" + @click="handleOpenEditView('add')" + >新增</el-button + > + <el-button + v-if=" + option.buttons.delete.isShow == undefined + ? true + : option.buttons.delete.isShow + " + v-permission="option.buttons.delete.permission" + :disabled="disableBatchDelete" + type="danger" + icon="el-icon-delete" + @click="handleDeleteBatch()" + >删除</el-button + > + + <!-- 表格开始 --> + <el-table + class="anji_curd_table" + :data="records" + border + @selection-change="handleSelectionChange" + @sort-change="handleSortChange" + > + <!--多选--> + <el-table-column fixed type="selection" width="50" align="center" /> + <!--隐藏列--> + <el-table-column v-if="tableExpandColumns.length > 0" type="expand"> + <template slot-scope="scope"> + <p + v-for="item in tableExpandColumns" + :key="item.field" + class="table-expand-item" + > + <span class="titel"> {{ item.label }}: </span> + <span>{{ scope.row[item.field] }}</span> + </p> + </template> + </el-table-column> + <!--序号--> + <el-table-column label="序号" min-width="50" align="center"> + <template slot-scope="scope"> + {{ + queryParams.pageSize * (queryParams.pageNumber - 1) + + scope.$index + + 1 + }} + </template> + </el-table-column> + + <template v-for="item in option.columns"> + <el-table-column + v-if="item.tableHide != true && item.columnType != 'expand'" + :key="item.field" + :prop="item.field" + :label="fieldLabel(item)" + :min-width="item.minWidth || 110" + :sortable="item.sortable" + :show-overflow-tooltip="true" + align="center" + > + <template slot-scope="scope"> + <div v-if="item.columnType == 'imgPreview'"> + <!-- 图片缩略图--> + <el-image + style="width: 25%; height: 50%" + fit="contain" + :src="scope.row[item.field]" + :preview-src-list="[scope.row[item.field]]" + /> + </div> + <div v-else> + <span v-if="item.inputType == 'switch' && !item.colorStyle"> + <el-switch + v-model.trim="scope.row[item.field]" + :active-value="1" + :inactive-value="0" + active-color="#5887fb" + inactive-color="#ccc" + @change="switchChange(scope.row, item.switchOption)" + /> + </span> + <!-- 带单位 --> + <span v-else-if="item.inputType == 'anji-input'">{{ + fieldValueByAnjiInput(scope.row[item.field], item) + }}</span> + <!--表格 a 合并 b上--> + <span v-else-if="item.mergeColumn" + >{{ scope.row[item.field] }}({{ + scope.row[item.mergeColumn] + }})</span + > + <!-- 没有单位 --> + <span + v-else-if="item.colorStyle" + :class="item.colorStyle[scope.row[item.editField]]" + >{{ fieldValueByRowRenderer(scope.row, item) }}</span + > + <span v-else>{{ + fieldValueByRowRenderer(scope.row, item) + }}</span> + <!-- 正常展示模式 + <div v-if="!item.custom"> + 是第一列数据 && 需要高亮字段不为false 高亮并且可以点击 + <span v-if="!index && item.operate !== false" class="view" @click="handleOpenEditView('view', scope.row)">{{ scope.row[item.field] }}</span> + <span v-else>{{ scope.row[item.field] }}</span> + </div> + --> + <!-- 自定义展示数据 + <div v-else v-html="item.renderer(scope.row)" />--> + </div> + </template> + </el-table-column> + </template> + <!--操作栏--> + <el-table-column + align="center" + fixed="right" + label="操作" + :width=" + option.buttons.customButton && + option.buttons.customButton.operationWidth + ? option.buttons.customButton.operationWidth + : 100 + " + > + <template slot-scope="scope"> + <slot name="edit" :msg="scope.row" /> + <el-button + v-if=" + (option.buttons.query.isShow == undefined + ? true + : option.buttons.query.isShow) && + hasPermission(option.buttons.edit.permission) == false + " + type="text" + size="small" + @click="handleOpenEditView('view', scope.row)" + v-permission="option.buttons.query.permission" + >查看</el-button + > + <el-button + v-if=" + option.buttons.edit.isShow == undefined + ? true + : option.buttons.edit.isShow + " + type="text" + size="small" + @click="handleOpenEditView('edit', scope.row)" + v-permission="option.buttons.edit.permission" + >编辑</el-button + > + <el-button + v-if=" + hasRowCustomButton == false && + option.buttons.delete.isShow == undefined + ? true + : option.buttons.edit.isShow + " + type="text" + size="small" + @click="handleDeleteBatch(scope.row)" + v-permission="option.buttons.delete.permission" + >删除</el-button + > + <el-dropdown v-if="hasRowCustomButton" trigger="click"> + <span class="el-dropdown-link"> + 更多<i class="el-icon-caret-bottom el-icon--right" /> + </span> + <el-dropdown-menu slot="dropdown"> + <el-dropdown-item class="clearfix"> + <slot name="rowButton" :msg="scope.row" /> + <el-button + v-if=" + option.buttons.delete.isShow == undefined + ? true + : option.buttons.edit.isShow + " + type="text" + size="small" + @click="handleDeleteBatch(scope.row)" + v-permission="option.buttons.delete.permission" + >删除</el-button + > + </el-dropdown-item> + </el-dropdown-menu> + </el-dropdown> + </template> + </el-table-column> + </el-table> + <div class="pagination"> + <el-pagination + v-show="total > 0" + background + :current-page.sync="queryParams.pageNumber" + :page-sizes="$pageSizeAll" + :page-size="queryParams.pageSize" + layout="total, prev, pager, next, jumper, sizes" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + <div> + <slot name="tableSelectionBtn" :selection="checkRecords" /> + </div> + </div> + + <!-- 表格结束 --> + + <EditDialog + ref="edit" + :option="option" + :model-type="editDialogModelType" + :visible="editDialogOpen" + :row-data="editDialogRowData" + @closeEvent="editDialogClosedEvent" + > + <template v-slot:customCard> + <slot name="cardInEditPage" /> + </template> + <template slot="editBtn" slot-scope="scope"> + <slot name="editBtnPage" :rowData="scope" /> + </template> + </EditDialog> + </div> + <slot name="pageSection" /> + </div> +</template> +<script> +import AnjiTree from "@/components/AnjiPlus/anji-tree.vue"; +import EditDialog from "./edit"; +import request from "@/utils/request"; +export default { + components: { + EditDialog, + AnjiTree + }, + props: { + option: { + require: true, + type: Object, + default: () => { + return { + // 查询表单条件 + queryFormFields: [], + // 按钮 + buttons: { + query: {}, + edit: {}, + delete: {}, + add: {} + }, + // 表格列 + columns: [], + queryFormChange: (fileName, val) => {} + }; + } + } + }, + data() { + return { + // 查询表单提交的值 + queryParams: { + showMoreSearch: false, // 是否展开更多搜索条件 + pageNumber: 1, + pageSize: 10, + order: "", + sort: "" + }, + + checkRecords: [], // 表格中当前选中的记录 + records: [], // 接口返回的记录列表 + total: 0, // 接口返回的总条数 + + // 编辑详情弹框 + editDialogOpen: false, // 新建时主动打开编辑弹框 + editDialogRowData: {}, // 编辑时的主键 + editDialogModelType: "view", // 编辑 查看 + + hasRowCustomButton: false // 除了编辑删除外,还有自定义的行按钮 + }; + }, + computed: { + // 左侧树形查询条件 + queryFormTreeField() { + var treeField = this.option.queryFormFields.find( + item => item["inputType"] == "anji-tree" + ); + return treeField; + }, + // 查询条件里是否有树形控件 + hasTreeFieldInQueryForm() { + return this.isNotBlank(this.queryFormTreeField); + }, + // 不包含树形控件的查询条件 + queryFormFieldExcludeTree() { + var treeFields = this.option.queryFormFields.filter( + item => item["inputType"] != "anji-tree" + ); + return treeFields; + }, + // 主键的列名 + primaryKeyFieldName() { + var primaryKey = this.option.columns.find( + item => item["primaryKey"] == true + ); + if (primaryKey != null) { + return primaryKey["field"]; + } else { + return null; + console.warn( + "在columns中查找primaryKey=true失败,会导致查询详情和删除失败" + ); + } + }, + + // 表格中可展开的列 + tableExpandColumns() { + var expandColumns = this.option.columns.filter( + item => item["columnType"] == "expand" + ); + return expandColumns; + }, + + // 是否可以批量删除 + disableBatchDelete() { + return this.checkRecords.length <= 0; + } + }, + created() { + // 为查询框中所有input加上默认值 + this.option.queryFormFields.forEach(item => { + // 动态添加属性 + this.$set(this.queryParams, item.field, item.defaultValue || null); + }); + // 查询列表 + this.handleQueryForm("query"); + this.queryFormChange(); + }, + mounted() { + if (this.$scopedSlots["rowButton"] != null) { + this.hasRowCustomButton = true; + } else { + this.hasRowCustomButton = false; + } + }, + methods: { + queryFormFieldSpan(item) { + // console.log(item) + + if (item.span != null) { + return item.span; + } else { + return 6; + } + // let rowLength = this.option.queryFormFields.length; + // console.log(rowLength, "ss") + // console.log(rowLength % 3) + // if (rowLength <= 3) { + // return 6 + // } + // else if (rowLength % 3 == 0) { + // return 8 + // } else if (rowLength > 6) { + // return 8 + // } + }, + // 切换更多搜索条件 + handleToggleMoreSearch() { + this.queryParams.showMoreSearch = !this.queryParams.showMoreSearch; + }, + // 列上排序切换 + handleSortChange(column) { + // {column: {…}, prop: "orgCode", order: "ascending"} + if (column == null || column.prop == null) { + console.warn("排序字段名prop为空,无法排序"); + return; + } + var sort = column.prop; // 列表查询默认排序列 + var order = column.order == "ascending" ? "ASC" : "DESC"; + this.queryParams["sort"] = sort; + this.queryParams["order"] = order; + this.handleQueryForm("query"); + }, + // 查询按钮 + handleQueryForm(from) { + // 如果是点查询按钮,把树的查询属性去掉 + if (from == "query") { + if (this.hasTreeFieldInQueryForm) { + delete this.queryParams[this.queryFormTreeField.field]; + } + } + // 如果是点树查询,把查询区里的属性去掉 + if (from == "tree") { + if (this.hasTreeFieldInQueryForm) { + var treeVal = this.queryParams[this.queryFormTreeField.field]; + this.queryParams = { + pageNumber: 1, + pageSize: 10 + }; + this.queryParams[this.queryFormTreeField.field] = treeVal; + } + } + // 默认的排序 + if ( + this.isBlank(this.queryParams["order"]) && + this.isNotBlank(this.option.buttons.query.order) + ) { + this.queryParams["sort"] = this.option.buttons.query.sort; + this.queryParams["order"] = this.option.buttons.query.order; + } + this.queryParams.pageNumber = 1; + this.handleQueryPageList(); + }, + // 列表查询 + async handleQueryPageList() { + var params = this.queryParams; + // 将特殊参数值urlcode处理 var params = this.urlEncodeObject(this.queryParams, 'order,sort') + const { data, code } = await this.option.buttons.query.api(params); + if (code != "200") return; + this.records = data.records; + this.total = data.total; + }, + // 重置 + handleResetForm() { + this.queryParams = { + pageNumber: 1, + pageSize: 10 + }; + // this.$refs['queryForm'].resetFields() + // this.records = [] + // this.total = 0 + }, + // 树形查询条件点击回调 + handleTreeNodeCheck() { + this.handleQueryForm("tree"); + // 为新建页面的对应属性值,绑定上对应的默认值 + var treeFieldName = this.queryFormTreeField["field"]; + for (var i = 0; i < this.option.columns.length; i++) { + var item = this.option.columns[i]; + if ( + item["editField"] == treeFieldName || + item["field"] == treeFieldName + ) { + this.$set( + this.option.columns[i], + "defaultValue", + this.queryParams[treeFieldName] + ); + break; + } + } + }, + // 编辑和查看操作 + handleOpenEditView(modelType, row) { + if (modelType == "view" || modelType == "edit") { + this.editDialogRowData = row; + } + this.editDialogModelType = modelType; + if (modelType == "add") { + // 新增模式,不需要查询数据详情,直接打开 + this.editDialogOpen = true; + } + const obj = { + type: modelType, + value: row + }; + this.$emit("handleCustomValue", obj); + }, + // 弹框被关闭时的回调事件 + editDialogClosedEvent(value) { + // 把列表页中弹框打开标记改成已关闭 + this.editDialogOpen = false; + // 关闭弹出框时,如果有树,刷新下 + if ( + this.hasTreeFieldInQueryForm && + this.$refs.queryFormTree != null && + !value + ) { + this.$refs.queryFormTree.queryData(); + } + this.handleQueryPageList(); + // 关闭时 清空表单的验证规则 + this.$refs.edit.$refs.mainForm.$refs.editForm.resetFields(); + }, + // 批量删除 + handleDeleteBatch(row) { + var ids = []; + if (row != null) { + ids.push(row[this.primaryKeyFieldName]); // 删除指定的行 + } else { + // 批量删除选中的行 + ids = this.checkRecords.map(item => item[this.primaryKeyFieldName]); + } + this.$confirm("删除确认", "确认要删除吗?", { + type: "warning", + confirmButtonClass: "delete_sure", + cancelButtonClass: "el-button--danger is-plain" + }) + .then(() => { + this.option.buttons.delete.api(ids).then(res => { + // {code: "200", message: "操作成功", data: true} + this.checkRecords = []; + // 关闭弹出框时,如果有树,刷新下 + if ( + this.hasTreeFieldInQueryForm && + this.$refs.queryFormTree != null + ) { + this.$refs.queryFormTree.queryData(); + } + this.handleQueryPageList(); + }); + }) + .catch(e => { + e; + }); + }, + + // 选择项改变时 + handleSelectionChange(val) { + this.checkRecords = val; + }, + // 页码改变 + handleCurrentChange(pageNumber) { + this.queryParams.pageNumber = pageNumber; + this.handleQueryPageList(); + }, + // 每页size改变时 + handleSizeChange(val) { + this.queryParams.pageNumber = 1; + this.queryParams.pageSize = val; + this.handleQueryPageList(); + }, + // table列文件缩略图 + thumbnailUrl(row, field) { + // return 'http://10.108.3.123:9090/tms/file/download/79ee7e8b-2a9a-4142-b06d-706ac8089205' + // if (row.filePath) { + // if (row.filePath.endsWith('xlsx') || row.filePath.endsWith('xls')) { + // return fileExcel; + // } else if (row.filePath.endsWith('pdf')) { + // return filePdf; + // } + // return process.env.VUE_APP_BASE_API + '/tms/file/download/' + row.fileId; + // } else { + // return logo; + // } + }, + // 带单位的列,需要转换 + fieldLabel(columnConfig) { + if (columnConfig == null) { + return ""; + } + if ( + columnConfig.inputType == "anji-input" && + columnConfig.anjiInput != null + ) { + return `${columnConfig.label}(${columnConfig.anjiInput.unit})`; + } else { + return columnConfig.label; + } + }, + // 带单位的输入框 + fieldValueByAnjiInput(value, columnConfig) { + if (columnConfig == null) { + return value; + } + if ( + columnConfig.inputType == "anji-input" && + columnConfig.anjiInput != null + ) { + return value / columnConfig.anjiInput.conversion; + } else { + return value; + } + }, + // 带表格列格式化的值 + fieldValueByRowRenderer(row, columnConfig) { + if ( + columnConfig == null || + typeof columnConfig.fieldTableRowRenderer != "function" + ) { + return row[columnConfig.field]; + } else { + return columnConfig.fieldTableRowRenderer(row); + } + }, + // 暴露给外部crud页面,回传saveForm的值 + getMainEntity() { + return this.$refs.edit.getSaveForm(); + }, + setMainEntity(object) { + this.$refs.edit.setSaveForm(object); + }, + async switchChange(val, api) { + request({ + url: api.url, + method: "put", + headers: { noPrompt: false }, + data: [val.id] + }).then(response => { + this.handleQueryPageList(); + }); + }, + queryFormChange(fileName, fieldVal) { + if (typeof this.option.queryFormChange == "function") { + this.option.queryFormChange(this.queryParams, fileName, fieldVal); + } + } + } +}; +</script> + +<style scoped lang="scss"> +.style-btn { + pointer-events: none; +} +.page-container { + height: 100%; + position: relative; + .left-container { + width: 20%; + position: absolute; + top: 0; + left: 0; + background: #fff; + border-radius: 4px 0px 0px 4px; + padding: 20px 20px 0; + overflow: hidden; + overflow-y: auto; + height: 100%; + } + .right-container { + width: calc(80% - 5px); + position: absolute; + top: 0; + right: 0; + background: #fff; + border-radius: 0px 4px 4px 0px; + padding: 20px 20px 0; + height: 100%; + } +} +.el-table .cell, +.el-table td div { + overflow: hidden; + text-overflow: ellipsis; +} +.el-dropdown { + font-size: 12px; + display: inline; + color: #5887fb; + cursor: pointer; +} +.el-dropdown-menu--mini .el-dropdown-menu__item { + min-width: 80px; + max-width: 110px; + float: right; + .el-button--text { + float: right; + } + &:hover { + background: none !important; + } + .el-button--mini { + float: right; + } + .el-button + .el-button { + margin-left: 0 !important; + float: right; + } +} +.pagination { + display: flex; + flex-direction: row; + justify-content: space-between; + margin-top: 20px; +} +.anji_curd_table { + margin-top: 20px; +} +</style> diff --git a/report-ui/src/components/AnjiPlus备份/anji-crud/edit-form.vue b/report-ui/src/components/AnjiPlus备份/anji-crud/edit-form.vue new file mode 100644 index 00000000..d186a84e --- /dev/null +++ b/report-ui/src/components/AnjiPlus备份/anji-crud/edit-form.vue @@ -0,0 +1,362 @@ +<!-- + * @Author: lide1202@hotmail.com + * @Date: 2021-5-4 11:04:24 + * @Last Modified by: lide1202@hotmail.com + * @Last Modified time: 2021-5-6 11:04:24 + !--> +<template> + <div v-if="option['hide'] == null || option['hide'] == false" class="anji-card"> + <div class="card-head"> + {{ option.title }} + <div class="main-card-header-button"> + <el-button type="text" @click="handleSetRowColNum(4)">||||</el-button> + <el-button type="text" @click="handleSetRowColNum(3)">|||</el-button> + <el-button type="text" @click="handleSetRowColNum(2)">||</el-button> + </div> + </div> + <div class="card-body"> + <el-form ref="editForm" :model="editForm" :label-width="option.labelWidth || '100px'"> + <!--:disabled="modelType == 'view'"--> + <template v-for="group in columnGroups"> + <el-divider v-if="groupModel" :key="group" content-position="left">{{ group }}</el-divider> + <el-row :key="group" class="form_table"> + <template v-for="item in groupFormFields[group]"> + <el-col v-if="fieldIsHide(item.editHide) == false" :key="item.editField" :span="item.rowColSpan == null ? cardRowColSpan : item.rowColSpan"> + <el-form-item :label="item.label" :rules="item.rules" :prop="item.editField" :disabled="item.disabled"> + <!-- 输入框 --> + <span v-if="item.tips != '' && item.tips != null" :style="{ 'margin-left': '-13px' }" class="input_tips"> + <el-tooltip class="item" effect="dark" :content="item.tips" placement="top-start"> + <svg-icon icon-class="tishi-yiwen" /> + </el-tooltip> + </span> + <el-input v-if="item.inputType == 'input'" v-model.trim="editForm[item.editField]" :placeholder="item.placeholder || '请输入'" :clearable="item.clearable !== false" :disabled="fieldIsDisable(item.disabled)" @change="(value) => formChange(item.editField, value, null)" /> + <!-- 开关 --> + <el-switch v-else-if="item.inputType == 'switch'" v-model.trim="editForm[item.editField]" :disabled="fieldIsDisable(item.disabled)" :active-value="1" :inactive-value="0" inactive-color="#ccc" active-color="#5887fb" @change="(value) => formChange(item.editField, value, null)" /> + <el-input-number v-else-if="item.inputType == 'input-number'" v-model.trim="editForm[item.editField]" :min="item.inputNumberOption.min" :max="item.inputNumberOption.max" :placeholder="item.placeholder || '请输入'" :clearable="item.clearable !== false" :disabled="fieldIsDisable(item.disabled)" @change="(value) => formChange(item.editField, value, null)" /> + <!-- 自定义input --> + <anji-input v-else-if="item.inputType == 'anji-input'" v-model.trim="editForm[item.editField]" :unit="item.anjiInput.unit" :conversion="item.anjiInput.conversion" :keep-point="item.anjiInput.keepPoint" :rounding="item.anjiInput.rounding" :placeholder="item.placeholder || '请输入'" :clearable="item.clearable !== false" :disabled="fieldIsDisable(item.disabled)" @change="(value) => formChange(item.editField, value, null)" /> + <!-- 下拉框 --> + <anji-select + v-else-if="item.inputType == 'anji-select'" + v-model.trim="editForm[item.editField]" + :multiple="item.anjiSelectOption.multiple" + :disabled="fieldIsDisable(item.disabled)" + :dict-code="item.anjiSelectOption.dictCode" + :placeholder="item.placeholder" + :url="item.anjiSelectOption.url" + :method="item.anjiSelectOption.method" + :query-param="item.anjiSelectOption.queryParam" + :merge-label="item.anjiSelectOption.mergeLabel" + :option="item.anjiSelectOption.option" + :label="item.anjiSelectOption.label" + :remote-filter="item.anjiSelectOption.remoteFilter" + :disabled-options="item.anjiSelectOption.disabledOptions" + @change="(value, option) => formChange(item.editField, value, option)" + /> + <!-- 日期时间框 --> + <el-date-picker v-else-if="item.inputType.indexOf('date') >= 0" v-model="editForm[item.editField]" style="width: 100%" :placeholder="item.placeholder || '请选择'" :type="item.inputType" :format="item.format" :value-format="item.valueFormat" :disabled="fieldIsDisable(item.disabled)" :clearable="item.clearable !== false" @change="(value) => formChange(item.editField, value, null)" /> + <!-- checkbox --> + <anji-checkbox v-else-if="item.inputType == 'checkbox'" v-model.trim="editForm[item.editField]" :dict-code="item.anjiCheckbox.dictCode" :label="item.anjiCheckbox.label" :disabled="fieldIsDisable(item.disabled)" @change="(value, options) => formChange(item.editField, value, options)" /> + <!-- 城市三级联动 --> + <anji-cascader v-else-if="item.inputType == 'anji-cascader'" v-model.trim="editForm[item.editField]" :disabled="fieldIsDisable(item.disabled)" :url="item.anjiCascader.url" @change="(value) => formChange(item.editField, value, null)" /> + <!-- 上传组件 --> + <anji-upload v-else-if="item.inputType == 'anji-upload'" v-model.trim="editForm[item.editField]" :up-load-url="item.anjiUpload.upLoadUrl" :view-url="item.anjiUpload.viewUrl" :upload-type="item.anjiUpload.uploadType" :limit="item.anjiUpload.limit" @change="(value) => formChange(item.editField, value, null)" /> + <!-- input自带输入建议 --> + <anji-autocomplete v-else-if="item.inputType == 'anji-autocomplete'" v-model.trim="editForm[item.editField]" :disabled="fieldIsDisable(item.disabled)" :label="item.anjiAutocomplete.label" :option="item.anjiAutocomplete.option" :appoint-value="item.anjiAutocomplete.appointValue" :url="item.anjiAutocomplete.url" @change="(value, option) => formChange(item.editField, value, option)" /> + <!-- textarea --> + <el-input v-else-if="item.inputType == 'textarea'" v-model.trim="editForm[item.editField]" :placeholder="item.placeholder || '请输入'" :clearable="item.clearable !== false" :disabled="fieldIsDisable(item.disabled)" type="textarea" :rows="2" @change="(value) => formChange(item.editField, value, null)" /> + <el-input v-else placeholder="组件不支持此类型表单请至组件内部自行扩展" disabled /> + </el-form-item> + </el-col> + </template> + </el-row> + </template> + </el-form> + </div> + </div> +</template> + +<script> +export default { + components: {}, + props: { + modelType: String, // add view edit + showDialog: Boolean, + option: { + // 界面渲染相关配置json + type: [Object], + default: () => { + return { + title: '', // 页面标题 + labelWidth: '', // 表单输入框label宽度 + queryFormFields: [], // 查询表单条件 + buttons: { + // 按钮 + query: {}, + edit: {}, + delete: {}, + add: {}, + }, + columns: [], // 表格列 + formChange: (formData, fieldName, fieldVal, fieldExtend) => {}, // 弹出框表单修改回调 + } + }, + }, + // 当relateData不为空时,该组件是渲染与relateData一对一关联的子表信息 + relateData: { + type: [Object], + default: () => { + return {} + }, + }, + value: { + type: [Object], + default: () => { + return {} + }, + }, + }, + data() { + return { + cardRowColNum: 2, // 主信息一行显示几列 + editForm: {}, // 提交表单的数据 + } + }, + computed: { + // 主键的列名 + primaryKeyFieldName() { + var primaryKey = this.option.columns.find((item) => item['primaryKey'] == true) + if (primaryKey != null) { + return primaryKey['field'] + } else { + return null + console.warn('在columns中查找primaryKey=true失败,会导致查询详情和删除失败') + } + }, + // 指定当前实体关联主表的 + joinColumn() { + var columnName = this.option.joinColumn + if (this.isBlank(columnName)) { + console.warn('在joinEntity中查找joinColumn属性失败,会导致查询详情和删除失败') + columnName = '' + } + return columnName + }, + // 提交表单中所有的列,因部分翻译字段,表格中和表单中的key不一样,field editField不全,这里补全下, + formFields() { + if (this.option.columns == null) { + return [] + } + var fields = this.deepClone(this.option.columns) + fields = fields.map((item) => { + if (this.isBlank(item['editField'])) { + item['editField'] = item['field'] + } + // 没有设定分组的,全部补全成 其它信息 + if (this.isBlank(item['group'])) { + item['group'] = '其它' + } + return item + }) + return fields + }, + // 卡片设定中一行显示几列,每列的col数 + cardRowColSpan() { + return 24 / this.cardRowColNum + }, + // 如果表单内容较多,启用了分组,这里先算出所有的分组 + columnGroups() { + if (this.isBlank(this.formFields)) { + return [] + } else { + // 找出所有hide != true的关联表 + var groups = this.formFields + .map((item) => { + return item['group'] + }) + .filter((currentValue, index, arr) => { + return arr.indexOf(currentValue) == index + }) + return groups + } + }, + /* { + '分组1': [{column1.1}], + '分组2': [{column2.1}], + }*/ + groupFormFields() { + if (this.showDialog) { + // 将每个分组初始化 + var groupFormFields = {} + this.columnGroups.forEach((value, index, array) => { + groupFormFields[value] = [] + }) + // 将所有编辑列,按分组存放 + this.formFields.forEach((item, index, array) => { + groupFormFields[item['group']].push(item) + }) + return groupFormFields + } + return [] + }, + groupModel() { + return this.columnGroups.length > 1 + }, + }, + created() { + // 如果表单,是做为主表的编辑页面,如果是通过v-model传递进来的值,通过监听value,更新this.editForm + this.$watch( + function () { + return this.value + }, + function (newVal, oldVal) { + this.editForm = newVal + // 通过v-model传递值进来时,说明当前form是主表信息 + this.formChange() + } + ) + // 如果表单,是做为子表的编辑页面,当relateData中的关联字段发生更新时,触发查询,比如在goods详情中,goodsCode + this.$watch( + function () { + return this.relateData[this.joinColumn] + }, + function (newVal, oldVal) { + // 如果是父组件(弹出框)关闭时,设置this.relateData = {}时触发,清空本组件的数据 + if (this.isBlank(this.relateData)) { + this.cardRowColNum = 2 + this.editForm = {} + return + } + // 如果是关联字段发生更新,触发查询 + if (this.isNotBlank(newVal)) { + this.queryDetail() + } + } + ) + }, + mounted() { + // 如果表单,是做为主表的编辑页面,如果是通过v-model传递进来的值 + if (this.isNotBlank(this.value)) { + this.editForm = this.value + this.formChange() + } + // 如果表单,是做为子表的编辑页面,首次打开时,根据关联属性,加载详情数据 + if (this.isNotBlank(this.relateData) && this.isNotBlank(this.relateData[this.joinColumn])) { + this.queryDetail() + } + }, + methods: { + // 该行是否显示 true/false/ 'hideOnAdd hideOnView hideOnEdit' + fieldIsHide(editHide) { + if (typeof editHide == 'boolean') { + return editHide + } + if (typeof editHide == 'string') { + if (this.modelType == 'add') { + return editHide.indexOf('hideOnAdd') >= 0 + } + if (this.modelType == 'view') { + return editHide.indexOf('hideOnView') >= 0 + } + if (this.modelType == 'edit') { + return editHide.indexOf('hideOnEdit') >= 0 + } + } + return false + }, + // 该行是否禁用 true/false/ 'disableOnAdd disableOnView disableOnEdit' + fieldIsDisable(disable) { + if (typeof disable == 'boolean') { + return disable + } + if (typeof disable == 'string') { + if (this.modelType == 'add') { + return disable.indexOf('disableOnAdd') >= 0 + } + if (this.modelType == 'view') { + return disable.indexOf('disableOnView') >= 0 + } + if (this.modelType == 'edit') { + return disable.indexOf('disableOnEdit') >= 0 + } + } + return false + }, + // 设置一行显示几列 + handleSetRowColNum(num) { + this.cardRowColNum = num + this.$emit('changeRowColNum', num) + }, + + async queryDetail() { + var queryParams = this.relateData + const { data, code } = await this.option.buttons.queryByPrimarykey.api(queryParams) + if (code != '200') return + this.editForm = data + this.formChange() + }, + // 校验表单 + validate(callback) { + this.$refs.editForm.validate(async (valid, obj) => { + if (callback != null) { + callback(valid) + } + }) + }, + handleSave(callback) { + this.$refs.editForm.validate(async (valid, obj) => { + if (valid) { + if (this.modelType == 'add') { + // 当edit-from是作为关联子表的界面,补全关联属性 + if (typeof this.option.beforeInsert == 'function') { + this.option.beforeInsert(this.relateData, this.editForm) + } + const { code, message } = await this.option.buttons.add.api(this.editForm) + if (code == '200') { + if (callback != null) { + callback() + } + } else { + console.log(`提交表单调用新增接口失败:${message}`) + } + } else { + // 当edit-from是作为关联子表的界面,补全关联属性 + if (typeof this.option.beforeUpdate == 'function') { + this.option.beforeUpdate(this.relateData, this.editForm) + } + const { code, message } = await this.option.buttons.edit.api(this.editForm) + if (code == '200') { + if (callback != null) { + callback() + } + } else { + console.log(`提交表单调用更新接口失败:${message}`) + } + } + } else { + console.log('表单校验失败') + } + }) + }, + // 表单任何一个变动时,通知外部v-model + formChange(fieldName, fieldVal, fieldExtend) { + this.$emit('input', this.editForm) + // 表单变动后,回调option中的formChange事件 + if (typeof this.option.formChange == 'function') { + this.option.formChange(this.editForm, fieldName, fieldVal, fieldExtend) + } + }, + }, +} +</script> + +<style scoped lang="scss"> +.input_tips { + position: absolute; + margin-top: -8px; + .svg-icon { + font-size: 20px; + color: rgb(71, 8, 8); + } +} +</style> diff --git a/report-ui/src/components/AnjiPlus备份/anji-crud/edit-table.vue b/report-ui/src/components/AnjiPlus备份/anji-crud/edit-table.vue new file mode 100644 index 00000000..df3b030b --- /dev/null +++ b/report-ui/src/components/AnjiPlus备份/anji-crud/edit-table.vue @@ -0,0 +1,498 @@ +<!-- + * @Author: lide1202@hotmail.com + * @Date: 2021-5-4 11:04:24 + * @Last Modified by: lide1202@hotmail.com + * @Last Modified time: 2021-5-6 11:04:24 + !--> +<template> + <div v-if="option['hide'] == null || option['hide'] == false" + class="anji-card"> + <div class="card-head">{{ option.title }}</div> + <div class="card-body"> + <el-form ref="form" + :model="form"> + <!-- 表格开始 --> + <el-table :data="formRecordsUndelete" + border + :row-class-name="tableRowClassAdapter" + @selection-change="handleSelectionChange" + @row-click="handleTableRowClick"> + <!-- <el-table-column fixed type="selection" width="50" align="center" /> --> + + <el-table-column label="序号" + min-width="50" + align="center"> + <template slot-scope="scope"> + {{ scope.$index + 1 }} + </template> + </el-table-column> + + <template v-for="item in option.columns"> + <el-table-column v-if="fieldIsHide(item.tableHide) != true && item.columnType != 'expand'" + :key="item.field" + :label="item.label" + :min-width="item.minWidth || 110" + align="center"> + <template slot-scope="scope"> + <el-form-item :prop="'records.' + scope.$index + '.' + item.field" + :rules="item.rules"> + <!-- 输入框 --> + <el-input v-if="item.inputType == 'input'" + v-model="scope.row[item.field]" + size="small" + :placeholder="item.placeholder || '请输入'" + :clearable="item.clearable !== false" + :disabled="saveButtonStatus[scope.$index] == 'inShow' || item.disabled" + @change="(value) => tableRowChange(scope.$index, item.field, value)" /> + <!-- 开关 --> + <el-switch v-else-if="item.inputType == 'switch'" + v-model="scope.row[item.field]" + :disabled="saveButtonStatus[scope.$index] == 'inShow' || item.disabled" + :active-value="item.switchOption.disableValue" + :inactive-value="item.switchOption.enableValue" + @change="(value) => tableRowChange(scope.$index, item.field, value)" + active-color="#5887fb" + inactive-color="#ccc"> + </el-switch> + <el-input v-else-if="item.inputType == 'input-number'" + v-model="scope.row[item.field]" + size="small" + :min="item.inputNumberOption.min" + :max="item.inputNumberOption.max" + :placeholder="item.placeholder || '请输入'" + :clearable="item.clearable !== false" + :disabled="saveButtonStatus[scope.$index] == 'inShow' || item.disabled" + @change="(value) => tableRowChange(scope.$index, item.field, value)" /> + + <!-- 自定义input --> + <anji-input v-else-if="item.inputType == 'anji-input'" + v-model.trim="scope.row[item.field]" + :default-value="item.defaultValue" + :unit="item.anjiInput.unit" + :conversion="item.anjiInput.conversion" + :placeholder="item.placeholder || '请输入'" + :clearable="item.clearable !== false" + :disabled="saveButtonStatus[scope.$index] == 'inShow' || item.disabled" + @change="(value) => tableRowChange(scope.$index, item.field, value)" /> + + <!-- 下拉框 --> + <anji-select v-else-if="item.inputType == 'anji-select'" + v-model.trim="scope.row[item.field]" + :multiple="item.anjiSelectOption.multiple" + :default-value="item.defaultValue" + :dict-code="item.anjiSelectOption.dictCode" + :url="item.anjiSelectOption.url" + :method="item.anjiSelectOption.method" + :query-param="item.anjiSelectOption.queryParam" + :option="item.anjiSelectOption.option" + :label="item.anjiSelectOption.label" + :disabled-options="item.anjiSelectOption.disabledOptions" + :disabled="saveButtonStatus[scope.$index] == 'inShow' || item.disabled" + @change="(value, option) => tableRowChange(scope.$index, item.field, value, option)" /> + <!-- 日期时间框 --> + <el-date-picker v-else-if="item.inputType.indexOf('date') >= 0" + v-model="scope.row[item.field]" + style="width: 100%" + :placeholder="item.placeholder || '请选择'" + :type="item.inputType" + :clearable="item.clearable !== false" + :disabled="saveButtonStatus[scope.$index] == 'inShow' || item.disabled" + @change="(value) => tableRowChange(scope.$index, item.field, value)" /> + <!-- 待扩展的表单类型,请自行扩展 --> + <el-input v-else + placeholder="组件不支持此类型表单请至组件内部自行扩展" + disabled /> + </el-form-item> + </template> + </el-table-column> + </template> + <el-table-column fixed="right" + label="操作" + width="100"> + <template slot-scope="scope"> + <el-button type="text" + size="small" + @click="handleAddOrUpdate(scope.row, scope.$index)">{{ getRowEditButton(scope.$index) }}</el-button> + <el-button type="text" + size="small" + @click="handleDelete(scope.row, scope.$index)">删除</el-button> + </template> + </el-table-column> + </el-table> + <!-- 表格结束 --> + </el-form> + <button v-if="modelType != 'view'" + class="table-add-row-button" + @click="handleAdd"> + <i class="el-icon-plus" /> + <span>新增</span> + </button> + </div> + </div> +</template> + +<script> +const ROW_DELETE_FLAG = 'deletedFlag' +export default { + components: {}, + props: { + modelType: String, // add view edit + option: { + // 界面渲染相关配置json + type: [Object], + default: () => { + return { + title: '', // 页面标题 + labelWidth: '', + queryFormFields: [], // 查询表单条件 + buttons: { + // 按钮 + query: {}, + edit: {}, + delete: {}, + add: {}, + }, + columns: [], // 表格列 + } + }, + }, + relateData: { + // 关联的主记录 + type: [Object], + default: () => { + return {} + }, + }, + value: { + type: [Array], + default: () => { + return [] + }, + }, + valueNew: { + type: [Array], + default: () => { + return [] + }, + } + }, + data () { + return { + checkRecords: [], // 表格中当前选中的记录 + + form: { + records: [], // 接口返回的记录列表 + total: 0, // 接口返回的总条数 + }, + + saveButtonStatus: [], // 维护表格中每行编辑按钮的状态 inShow inEditing inAdding + + rowIdList: [] + } + }, + computed: { + // 主键的列名 + primaryKeyFieldName () { + var primaryKey = this.option.columns.find((item) => item['primaryKey'] == true) + if (primaryKey != null) { + return primaryKey['field'] + } else { + return null + console.warn('在columns中查找primaryKey=true失败,会导致查询详情和删除失败') + } + }, + // 指定当前实体关联主表的关联字段,孙子关联表,没有该属性 + joinColumn () { + var columnName = this.option.joinColumn + if (this.isBlank(columnName)) { + console.warn('在columns中查找关联字段失败,会导致查询详情和删除失败,孙子关联表忽略该错误') + columnName = '' + } + return columnName + }, + // 未删除的记录 + formRecordsUndelete () { + if (this.form.records == null) { + return [] + } + return this.form.records.filter((item) => item[ROW_DELETE_FLAG] == null || item[ROW_DELETE_FLAG] == false) + }, + }, + watch: {}, + created () { + // 主表 relateData 的关联字段 joinColumn 变动时,触发查询子表的查询,孙子关联儿子的无效 + if (this.isNotBlank(this.joinColumn)) { + this.$watch( + function () { + return this.relateData[this.joinColumn] + }, + function (newVal, oldVal) { + // 如果是关联字段发生更新,触发查询 + if (this.isNotBlank(newVal)) { + this.handleQueryPageList(newVal) + } else { + // 如果关联字段为空,清空本表格的数据,如果是父组件(弹出框)关闭时,设置this.relateData = {默认值}时触发 + this.checkRecords = [] + this.form.records = [] + this.form.total = 0 + this.saveButtonStatus = [] + } + } + ) + } + }, + mounted () { + // 首次打开时,根据主表关联字段查询子表,加载表格数据 + if (this.isNotBlank(this.relateData) && this.isNotBlank(this.relateData[this.joinColumn])) { + this.handleQueryPageList() + } + }, + methods: { + // 该行是否显示 true/false/ 'hideOnAdd hideOnView hideOnEdit' + fieldIsHide (tableHide) { + if (typeof tableHide == 'boolean') { + return tableHide + } + if (typeof tableHide == 'string') { + if (this.modelType == 'add') { + return tableHide.indexOf('hideOnAdd') >= 0 + } + if (this.modelType == 'view') { + return tableHide.indexOf('hideOnView') >= 0 + } + if (this.modelType == 'edit') { + return tableHide.indexOf('hideOnEdit') >= 0 + } + } + return false + }, + // 获取行的提交按钮文字 + getRowEditButton (index) { + if (this.saveButtonStatus[index] == 'inEditing') { + return 'btn_savetemp' + } else if (this.saveButtonStatus[index] == 'inAdding') { + return 'btn_savetemp' + } else if (this.saveButtonStatus[index] == 'inShow') { + return 'btn_edit' + } else { + return 'not_permission' + } + }, + // 表格行渲染前前置处理 + tableRowClassAdapter ({ row, rowIndex }) { + row.index = rowIndex + }, + // 查询 + async handleQueryPageList (joinColumnValue) { + if (this.isBlank(joinColumnValue)) { + joinColumnValue = this.relateData[this.joinColumn] + } + var params = {} + params[this.joinColumn] = joinColumnValue + this.queryPageList(params) + }, + // 暴露给外部直接调用带参数 + async queryPageList (params) { + // 默认的排序 + if (this.isNotBlank(this.option.buttons.query.order)) { + params['sort'] = this.option.buttons.query.sort + params['order'] = this.option.buttons.query.order + } + const { data, code } = await this.option.buttons.query.api(params) + if (code != '200') return + this.form.records = data.records + this.form.total = data.total + this.$emit('input', this.form.records) + for (var i = 0; i < this.form.total; i++) { + this.saveButtonStatus.push('inShow') + } + }, + // 选择项改变时 + handleSelectionChange (val) { + this.checkRecords = val + }, + // 表格选中某一行时 + handleTableRowClick (row, column, event) { + // console.log(row) + // console.log(column) + // 行点击后,回调option中的tableRowClick事件 + if (typeof this.option.tableRowClick == 'function') { + this.option.tableRowClick(this.form.records, row, row.index, this.relateData) + } + }, + // 行数据更新时回调 + tableRowChange (rowIndex, fieldName, fieldVal, fieldExtend) { + // 通知外面的组件 + this.$emit('input', this.form.records) + + // 表单变动后,回调option中的tableRowChange事件 + if (typeof this.option.tableChange == 'function') { + this.option.tableChange(this.form.records, rowIndex, fieldName, fieldVal, fieldExtend, this.relateData) + } + }, + // 新增 + handleAdd () { + this.saveButtonStatus.push('inAdding') + this.form.records.push({}) + }, + // 父节点Change,子节点表格更新 + handleUpdata () { + this.saveButtonStatus = [] + this.form.records = [] + }, + // 提交和修改 + handleAddOrUpdate (row, index) { + // 编辑状态下点击保存提交 + if (this.saveButtonStatus[index] == 'inEditing' || this.saveButtonStatus[index] == 'inAdding') { + this.handleSaveTemp(row, index) + } else { + this.$set(this.saveButtonStatus, index, 'inEditing') + } + }, + // 校验表单 + validate (callback) { + this.$refs['form'].validate(async (valid, obj) => { + if (callback != null) { + callback(valid) + } + }) + }, + // 暂存 + async handleSaveTemp (row, index) { + this.$refs['form'].validate((valid) => { + if (valid) { + if (this.isBlank(row[this.primaryKeyFieldName])) { + // 补全关联属性 + if (typeof this.option.beforeInsert == 'function') { + this.option.beforeInsert(this.relateData, row) + } + } else { + // 补全关联属性 + if (typeof this.option.beforeUpdate == 'function') { + this.option.beforeUpdate(this.relateData, row) + } + } + // 将行按钮的文字改成编辑 + this.$set(this.saveButtonStatus, index, 'inShow') + // 通知外面的组件 + this.$emit('input', this.form.records) + } + }) + /* + this.$refs['form'].validate((valid) => { + if (valid) { + // 验证通过 + if (this.isBlank(row[this.primaryKeyFieldName])) { + // 补全关联属性 + if (typeof this.option.beforeInsert == 'function') { + this.option.beforeInsert(this.relateData, row) + } + // 主键为空,新增 + this.option.buttons.add.api(row).then((response) => { + if (response.code == 200) { + this.$set(this.saveButtonStatus, index, 'inShow') + // 保存完成后刷新列表 + this.handleQueryPageList() + } + }) + } else { + // 补全关联属性 + if (typeof this.option.beforeUpdate == 'function') { + this.option.beforeUpdate(this.relateData, row) + } + // 修改 + this.option.buttons.edit.api(row).then((response) => { + if (response.code == 200) { + this.$set(this.saveButtonStatus, index, 'inShow') + // 保存完成后刷新列表 + this.handleQueryPageList() + } + }) + } + } else { + console.log('valid fail') + return false + } + }) + */ + }, + // 删除 + handleDelete (row, index) { + this.saveButtonStatus.splice(index, 1) // 清空状态 + // 界面上临时新增出来的一行,还没有提交到数据库,可以直接删除 + if (this.saveButtonStatus[index] == 'inAdding') { + this.form.records.splice(index, 1) + this.saveButtonStatus.splice(index, 1) + this.$emit('input', this.form.records) + return + } + // if (this.isBlank(row) || this.isBlank(row[this.primaryKeyFieldName])) { + // return + // } + // 将对应的行标识成删除 + // 找出该行在原始记录中的index + // var realIndex = this.form.records.findIndex((item) => item[this.primaryKeyFieldName] == row[this.primaryKeyFieldName]) + // row[ROW_DELETE_FLAG] = true + // this.$set(this.form.records, realIndex, row) + // this.$emit('input', this.form.records) + this.form.records.splice(index, 1) + this.rowIdList.push(row.id) + this.$emit('input', this.form.records) + this.$emit('update:valueNew', this.rowIdList) + /* + 之前是直接调用接口删除,后面统一改成在主表接口中增加、更新、删除 + // 已经保存在数据库的的行,要调用删除按钮 + var primaryKey = row[this.primaryKeyFieldName] + this.$confirm(this.$lang('promptMessage_deleteTip'), this.$lang('promptMessage_deleteTipTitle'), { + type: 'warning', + confirmButtonClass: 'delete_sure', + cancelButtonClass: 'el-button--danger is-plain', + }) + .then(() => { + this.option.buttons.delete.api(primaryKey).then((res) => { + // {code: "200", message: "操作成功", data: true} + this.checkRecords = [] + this.handleQueryPageList() + }) + }) + .catch((e) => { + e + }) + */ + }, + }, +} +</script> + +<style scoped lang="scss"> +.table-add-row-button { + width: 100%; + margin-top: 0px; + margin-bottom: 0px; + border-color: #d9d9d9; + border-style: dashed; + line-height: 1.499; + position: relative; + display: inline-block; + font-weight: 400; + white-space: nowrap; + text-align: center; + background-image: none; + border: 1px solid transparent; + box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015); + cursor: pointer; + transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + -ms-touch-action: manipulation; + touch-action: manipulation; + height: 32px; + padding: 0 15px; + font-size: 14px; + border-radius: 4px; + color: rgba(0, 0, 0, 0.65); + background-color: #fff; + border-color: #d9d9d9; +} +</style> diff --git a/report-ui/src/components/AnjiPlus备份/anji-crud/edit.vue b/report-ui/src/components/AnjiPlus备份/anji-crud/edit.vue new file mode 100644 index 00000000..76bb6d6b --- /dev/null +++ b/report-ui/src/components/AnjiPlus备份/anji-crud/edit.vue @@ -0,0 +1,386 @@ +<!-- + * @Author: lide1202@hotmail.com + * @Date: 2021-3-13 11:04:24 + * @Last Modified by: lide1202@hotmail.com + * @Last Modified time: 2021-3-13 11:04:24 + !--> +<template> + <el-dialog + :width="dialogWidth" + :class="dialogFullScreen?'full-screen':'notfull-screen'" + :close-on-click-modal="false" + center + :visible.sync="showDialog" + :fullscreen="dialogFullScreen" + @close="handleCloseDialog('close')" + > + <template v-slot:title> + {{ option.title + '--' + modelType }} + <button + type="button" + aria-label="Close" + class="el-dialog__headerbtn" + style="right: 50px" + @click="dialogFullScreen = !dialogFullScreen" + > + <i class="el-dialog__close el-icon el-icon-full-screen" /> + </button> + </template> + + <!--主表详情信息--> + <component + :is="'EditForm'" + ref="mainForm" + v-model="saveForm" + :option="option" + :model-type="modelType" + :show-dialog="showDialog" + @changeRowColNum="handleSetRowColNum" + /> + + <!--关联表相关--> + <template v-for="(item, index) in joinEntitys"> + <component + :is="getComponentByJoinType(item.joinType, item)" + :ref="'joinForm' + index" + :key="index" + v-model="saveForm[item.fieldNameInMainEntityOnSave]" + :value-new.sync="saveForm[item.fieldNameInMainEntityOnId]" + :option="item" + :model-type="modelType" + :relate-data="saveForm" + /> + + <!--孙子的关联表--> + <template v-for="(grandsonItem, grandsonIndex) in item.joinEntitys"> + <component + :is="getComponentByJoinType(grandsonItem.joinType, grandsonItem)" + ref="grandsonForm" + :key="index + '.' + grandsonIndex" + :option="grandsonItem" + :model-type="modelType" + :relate-data="saveForm" + /> + </template> + </template> + + <!--自定义的卡片插槽--> + <slot name="customCard" /> + + <div + slot="footer" + style="text-align: center" + > + <slot + v-if="modelType =='edit'" + name="editBtn" + :rowData="rowData" + /> + <el-button + type="danger" + plain + @click="handleCloseDialog('close')" + >关闭</el-button> + <el-button + v-if="modelType!='view'" + type="primary" + plain + @click="handleValidateAndSave" + >保存</el-button> + </div> + </el-dialog> +</template> + +<script> +import EditForm from './edit-form' +import EditTable from './edit-table' +export default { + name: 'EditDialog', + components: { EditForm, EditTable }, + props: { + visible: { + type: [Boolean], + default: () => { + return false + }, + }, + rowData: { + // 查询参数,对应表格那行数据 + type: [Object], + default: () => { + return {} + }, + }, + modelType: String, // add view edit + option: { + require: true, + type: Object, + default: () => { + return { + title: '', // 页面标题 + labelWidth: '', // 表单输入框label宽度 + queryFormFields: [], // 查询表单条件 + buttons: { + // 按钮 + query: {}, + edit: {}, + delete: {}, + add: {}, + }, + columns: [], // 表格列 + } + }, + }, + }, + data() { + return { + showDialog: false, // 编辑详情弹框是否显示 + dialogFullScreen: false, // 弹出框全屏 + cardRowColNum: 2, // 主信息一行显示几列 + + // 提交表单的数据 + saveForm: {}, + // 已成功校验的关联表单个数 + countForValidJoinForm: 0, + } + }, + computed: { + // 弹出框的宽度,根据一行显示几列动态调整 + dialogWidth() { + if (this.cardRowColNum == 2) { + return '60%' + } + if (this.cardRowColNum == 3) { + return '70%' + } + if (this.cardRowColNum == 4) { + return '80%' + } + return '60%' + }, + // 关联属性表 + joinEntitys() { + if (this.isBlank(this.option.joinEntitys)) { + return [] + } else { + return this.option.joinEntitys + // 找出所有hide != true的关联表 + // var entitys = this.option.joinEntitys.filter((item) => item['hide'] == null || item['hide'] == false) + // return entitys + } + }, + // 一对一关联表的个数 + countJoinEntityOneToOne() { + var entitys = this.joinEntitys.filter((item) => item['joinType'] == 'OneToOne') + if (entitys == null) { + return 0 + } + return entitys.length + }, + }, + watch: { + // 监控dialog的显示隐藏变量 + visible(newValue, oldValue) { + this.showDialog = newValue + // 为主表的编辑表单,渲染上默认值 + this.initDefaultSaveForm() + }, + rowData(newValue, oldValue) { + if (newValue != null) { + this.queryByPrimarykey(newValue) + } + }, + }, + mounted() { + // 为主表的编辑表单,渲染上默认值 + this.initDefaultSaveForm() + }, + methods: { + // 暴露给外部crud页面,回传saveForm的值 + getSaveForm() { + return this.saveForm + }, + setSaveForm(saveForm) { + this.saveForm = saveForm + }, + initDefaultSaveForm() { + // saveForm的默认值 + var defaultSaveForm = {} + this.option.columns.forEach((item) => { + var key = item.editField + if (this.isBlank(key)) { + key = item.field + } + var val = item.defaultValue + if (this.isNotBlank(val)) { + defaultSaveForm[key] = val + } + }) + // 为主表的编辑表单,渲染上默认值 + this.saveForm = this.deepClone(defaultSaveForm) + console.log('编辑框默认值:' + JSON.stringify(this.saveForm)) + }, + handleCloseDialog(val) { + // 为主表的编辑表单,渲染上默认值 + this.initDefaultSaveForm() + this.showDialog = false, // 编辑详情弹框是否显示 + this.dialogFullScreen = false, // 弹出框全屏 + this.cardRowColNum = 2, // 主信息一行显示几列 + this.countForValidJoinForm = 0, // 已成功校验的关联表单个数 + this.$emit('closeEvent', val) + }, + // 设置一行显示几列 + handleSetRowColNum(num) { + this.cardRowColNum = num + }, + // 根据关联类型计算组件 + getComponentByJoinType(type, item) { + if (type == 'OneToOne') { + return 'EditForm' + } else if (type == 'OneToMany') { + return 'EditTable' + } else { + return '' + } + }, + async queryByPrimarykey(rowData) { + const { data, code } = await this.option.buttons.queryByPrimarykey.api(rowData) + if (code != '200') return + this.showDialog = true + this.saveForm = data + }, + // 保存前,先调用校验 + handleValidateAndSave() { + this.countForValidJoinForm = 0 + // 主表单校验 + this.$refs.mainForm.validate((mainValid) => { + if (mainValid == false) { + console.warn('主表单校验失败') + return + } + console.log('主表单校验完成') + if (this.joinEntitys == null || this.joinEntitys.length == 0) { + // 如果子表没有信息,直接提交 + this.handleSave() + return + } + for (var i = 0; i < this.joinEntitys.length; i++) { + console.log(`开始校验子表单-${i} 校验`) + var item = this.joinEntitys[i] + if (this.$refs['joinForm' + i] == null || item.hide == true || this.saveForm[item.fieldNameInMainEntityOnSave] == null || this.saveForm[item.fieldNameInMainEntityOnSave].length == 0) { + console.log('子表单没有数据,直接跳过') + this.countForValidJoinForm++ + console.log('已经校验的子表单:' + this.countForValidJoinForm + ' 共:' + this.joinEntitys.length) + // 所有关联表单校验通过 + if (this.countForValidJoinForm == this.joinEntitys.length) { + console.log('子表单校验完成,提交主表单') + this.handleSave() + } + continue + } + var joinForm = this.$refs['joinForm' + i] + if (toString.call(joinForm) == '[object Array]') { + joinForm = joinForm[0] + } + joinForm.validate((joinValid) => { + if (joinValid) { + this.countForValidJoinForm++ + console.log('已经校验的子表单:' + this.countForValidJoinForm + ' 共:' + this.joinEntitys.length) + // 所有关联表单校验通过 + if (this.countForValidJoinForm == this.joinEntitys.length) { + console.log('子表单校验完成,提交主表单') + this.handleSave() + } + } else { + console.warn(`子表单${i}校验失败:`) + } + }) + } + }) + }, + async handleSave() { + // 新增 + if (this.modelType == 'add') { + const { code, message } = await this.option.buttons.add.api(this.saveForm) + if (code == '200') { + // 保存结束,关闭对话框 + this.handleCloseDialog() + // 向外层发关闭事件 + this.$emit('closeEvent') + return + } else { + this.countForValidJoinForm = 0, // 已成功校验的关联表单个数 + console.log(`提交表单调用新增接口失败:${message}`) + } + } + // 修改 + if (this.modelType == 'edit') { + // console.log(this.$slots.customCard[0].context.$refs.cardInEditData.updateData.settingValue) + const { code, message } = await this.option.buttons.edit.api(this.saveForm) + if (code == '200') { + // 保存结束,关闭对话框 + this.handleCloseDialog() + // 向外层发关闭事件 + this.$emit('closeEvent') + return + } else { + this.countForValidJoinForm = 0, // 已成功校验的关联表单个数 + console.log(`提交表单调用更新接口失败:${message}`) + } + } + /* 分步提交 + // 提交主表 + this.$refs.mainForm.handleSave(() => { + // 如果没有一对一的关联表,直接关闭对话框 + if (this.countJoinEntityOneToOne == 0) { + // 保存结束,关闭对话框 + this.handleCloseDialog() + // 向外层发关闭事件 + this.$emit('closeEvent') + return + } + // 主表保存成功后,保存子表 + for (var i = 0; i < this.joinEntitys.length; i++) { + if (this.joinEntitys[i].joinType == 'OneToOne') { + this.$refs['joinForm' + i].handleSave(() => { + this.countForSavedOneToOneJoinEntity++ + if (this.countForSavedOneToOneJoinEntity == this.countJoinEntityOneToOne) { + // 保存结束,关闭对话框 + this.handleCloseDialog() + // 向外层发关闭事件 + this.$emit('closeEvent') + } + }) + } + } + })*/ + }, + }, +} +</script> + +<style scoped lang="scss"> +// /deep/.el-dialog__body { +// background-color: rgb(240, 242, 245); +// padding: 5px; +// max-height: 60vh; +// overflow: auto; +// height: calc(100vh - 100px); +// } +.notfull-screen { + /deep/.el-dialog__body { + background-color: rgb(240, 242, 245); + padding: 5px; + max-height: 60vh; + overflow: auto; + } +} +.full-screen { + /deep/.el-dialog__body { + background-color: rgb(240, 242, 245); + padding: 5px; + height: calc(100vh - 110px); + overflow: auto; + } +} +</style> diff --git a/report-ui/src/components/AnjiPlus备份/anji-select.vue b/report-ui/src/components/AnjiPlus备份/anji-select.vue new file mode 100644 index 00000000..7e952ffd --- /dev/null +++ b/report-ui/src/components/AnjiPlus备份/anji-select.vue @@ -0,0 +1,323 @@ +<!--element下拉列表封装 + 使用: + <hyb-select ref="hybSelect" + url="/v1/orgs" + v-model="search.orgId" option="orgId" label="orgName" + placeholder multiple localOptions></hyb-select> + + 1.url:要显示的下拉列表数据来源 + 规范:返回的数据要符合(JSON中对应的字段必须:label和value,不能其他) + [ + {label:'显示1',value:'值1'}, + {label:'显示2',value:'值2'}, + {label:'显示3',value:'值3'}, + ... + ] + 2.v-model数据的双向绑定,绑定父组件中的字段 + 3.option自定义select的value对应的字段 + 4.label自定义select的label对应的字段 + 5.placeholder下拉列表提示 + 6.multiple是否是多选 + 7.localOptions使用本地的数据,不用请求远程数据,注意:使用该属性时Url属性不能要,不然无效 +--> +<template> + <div> + <el-select + v-model="selectValue" + :clearable="clearable" + :collapse-tags="collapseTags" + filterable + class="filter-item" + :placeholder="placeholder" + :disabled="disabled" + :multiple="multiple == null ? false : true" + :remote="remoteFilter" + :remote-method="remoteQuery" + @change="change" + > + <el-option + v-for="(item, index) in options" + :key="index" + :label="getItemLabel(item, label)" + :value="item[option]" + :disabled="isDisabledOption(item)" + > + <template v-if="mergeLabel"> + <span style="float: left">{{ getItemLabel(item, label) }}</span> + <span style="float: right; color: #8492a6; font-size: 13px">{{ + item[option] + }}</span> + </template> + </el-option> + <el-option v-if="totalPage > 1" label="搜索更多" value="" disabled /> + </el-select> + </div> +</template> + +<script> +import request from "@/utils/request"; +import { getStorageItem } from "@/utils/storage"; +export default { + props: { + dictCode: null, // 当传入dictCode时,可以不用传递url + url: null, + method: null, + queryParam: { + type: Object, + default: () => { + return {}; + } + }, + value: null, + placeholder: null, + label: { + type: String, + default: "text" + }, + option: { + type: String, + default: "id" + }, + multiple: null, + localOptions: null, + disabled: null, + clearable: { + type: Boolean, + default: true + }, + collapseTags: { + type: Boolean, + default: false + }, + mergeLabel: { + type: Boolean, + default: false + }, + // 禁用的下拉选项 + disabledOptions: { + type: String, + default: () => { + return ""; + } + }, + // 使用远程搜索 + remoteFilter: { + type: Boolean, + default: false + } + }, + data() { + return { + options: null, + selectValue: null, + // 如果是分页的, + totalPage: 0 + }; + }, + computed: { + // 根据dictCode和url拼出最终的请求url + requestUrl() { + if (this.url != null && this.url.trim() != "") { + if (this.url.indexOf("?") > 0) { + if (this.option == null) { + console.log("url-" + this.url.substring(this.url.indexOf("?"))); + } + if (this.label == null) { + } + } + return this.url; + } + if (this.dictCode != null && this.dictCode.trim() != "") { + return `/meta/gaeaDict/select/${this.dictCode}`; + } + return null; + } + }, + watch: { + value: function(val, oldVal) { + if (this.multiple != null) { + if (!this.value) { + this.selectValue = []; + } else { + this.selectValue = this.value; + } + } else { + if (this.value != null && this.value != undefined) { + this.selectValue = this.value; + } else { + this.selectValue = ""; + } + } + }, + url() { + setTimeout(() => { + this.queryData(); + }, 500); + } + }, + created() { + if (this.multiple != null) { + this.selectValue = this.value; + } else { + if (this.value != null) { + this.selectValue = this.value; + } + } + }, + mounted() { + if (this.requestUrl == null) { + this.options = this.localOptions; + return; + } + this.queryData(); + }, + methods: { + // 判断选择是否已经禁用 + isDisabledOption(option) { + if ( + option == null || + this.disabledOptions == null || + this.disabledOptions.length == 0 + ) { + return false; + } + var currentOptionVal = option[this.option]; + return this.disabledOptions.indexOf(currentOptionVal) >= 0; + }, + change(value) { + if (value === "") { + value = null; + } + this.$emit("input", value); + + // 根据当前值,找出对应的选项 + var optionItem = this.options.find(item => item[this.option] == value); + this.$emit("change", value, optionItem); + }, + // 根据用户配置的label,生成对应的标签 + getItemLabel(item, label) { + if (label.indexOf("${") < 0 && label.indexOf("}" < 0)) { + return item[label]; + } + var reg = /\$\{[a-zA-Z0-9]*\}/g; + var list = label.match(reg); + // ["${id}", "${text}"] + var result = label; + for (var i = 0; i < list.length; i++) { + var sub = list[i]; + var key = sub.replace("${", "").replace("}", ""); + result = result.replace(sub, item[key]); + } + return result; + }, + // 从本地localStorage取 gaeaDict + getOptionsFromLocalStorage() { + var dicts = getStorageItem("gaeaDict"); + var options = []; + if (!dicts.hasOwnProperty(this.dictCode)) { + return []; + } + var dictItems = dicts[this.dictCode]; + for (var i = 0; i < dictItems.length; i++) { + var dictItem = dictItems[i]; + options.push({ id: dictItem.id, text: dictItem.text }); + } + return options; + }, + queryData() { + // 所有从本地localStorage取,因为在App.vue中已经请求远程保存到本地了 + var options = this.getOptionsFromLocalStorage(); + if (this.isNotBlank(options)) { + this.options = options; + return; + } + // 本地localStorage取不到,再从远程接口取 + if (this.requestUrl == null) { + return; + } + if ( + this.method != null && + this.method.toLocaleLowerCase().trim() == "post" + ) { + this.queryDataByPost(); + } else { + this.queryDataByGet(); + } + }, + queryDataByGet(keyword) { + var param = this.deepClone(this.queryParam); + if (this.isNotBlank(keyword)) { + param["keyword"] = keyword; + } + param["multiple"] = this.multiple == null ? null : 1; + request({ + url: this.requestUrl, + headers: { noPrompt: true }, + params: param + }).then(response => { + this.setOptions(response.data); + }); + }, + queryDataByPost(keyword) { + var param = this.deepClone(this.queryParam); + if (this.isNotBlank(keyword)) { + param["keyword"] = keyword; + } + request({ + url: this.requestUrl, + method: "post", + headers: { noPrompt: true }, + data: param + }).then(response => { + this.setOptions(response.data); + }); + }, + setOptions(resData) { + if (resData == null || resData.length == 0) { + this.options = []; + this.totalPage = 0; + return; + } + if (this.isArray(resData)) { + this.options = resData; + this.totalPage = 1; + return; + } + if ( + resData.records == null || + resData.total == null || + resData.pages == null + ) { + this.options = []; + return; + } + this.totalPage = resData.pages; + // resData.records + // resData.total + // resData.size + // resData.current + this.options = resData.records; + }, + remoteQuery(keyword) { + if (this.isBlank(keyword)) { + return; + } + setTimeout(() => { + if ( + this.method != null && + this.method.toLocaleLowerCase().trim() == "post" + ) { + this.queryDataByPost(keyword); + } else { + this.queryDataByGet(keyword); + } + }, 200); + } + } +}; +</script> +<style scoped> +.filter-item { + width: 100%; +} +</style> diff --git a/report-ui/src/components/AnjiPlus备份/anji-tree.vue b/report-ui/src/components/AnjiPlus备份/anji-tree.vue new file mode 100644 index 00000000..dd767518 --- /dev/null +++ b/report-ui/src/components/AnjiPlus备份/anji-tree.vue @@ -0,0 +1,99 @@ +<!-- + * @Author: lide1202@hotmail.com + * @Date: 2021-5-4 11:04:24 + * @Last Modified by: lide1202@hotmail.com + * @Last Modified time: 2021-5-5 11:04:24 + !--> +<template> + <div> + <el-input class="filterInput" placeholder="搜索" v-model="filterText" v-if="enableFilter" /> + <div class="title">{{ labelName }}</div> + <el-tree ref="table_tree" :data="treeData" node-key="id" :default-expand-all="isOpen" :expand-on-click-node="false" :filter-node-method="filterNode" @node-click="nodeClick" @check="checkedEvent" /> + </div> +</template> + +<script> +import request from '@/utils/request' +export default { + components: {}, + props: { + url: { + type: [String], + default: () => { + return '' + }, + }, + id: { + type: [String], + default: () => { + return 'id' + }, + }, + label: { + type: [String], + default: () => { + return '' + }, + }, + value: { + type: [String], + default: () => { + return '' + }, + }, + labelName: String, + enableFilter: Boolean, + isOpen: Boolean, + }, + data() { + return { + filterText: '', + treeData: [], + } + }, + computed: {}, + watch: { + filterText(val) { + this.$refs.table_tree.filter(val) + }, + }, + mounted() { + this.queryData() + }, + methods: { + filterNode(val, data) { + if (!val) return true + return data.label.indexOf(val) !== -1 + }, + queryData() { + if (this.isBlank(this.url)) { + return + } + request({ + url: this.url, + method: 'GET', + }).then((response) => { + if (response.code != '200') { + return + } + this.treeData = Object.prototype.toString.call(response.data) == '[object Array]' ? response.data : response.data.tree|| response.data.menuTree + }) + }, + // 点击tree节点时 将tree的id作为上级机构代码 查询列表 + nodeClick(node) { + this.$emit('input', node['id']) + this.$emit('node-click', node['id']) + }, + checkedEvent(item, evt) { + var ids = evt.checkedKeys.toString() + this.$emit('input', ids) + }, + }, +} +</script> + +<style scoped lang="scss"> +.filterInput { + margin-bottom: 20px; +} +</style> diff --git a/report-ui/src/components/AnjiPlus备份/anji-upload.vue b/report-ui/src/components/AnjiPlus备份/anji-upload.vue new file mode 100644 index 00000000..7b16bffe --- /dev/null +++ b/report-ui/src/components/AnjiPlus备份/anji-upload.vue @@ -0,0 +1,161 @@ +<template> + <div class="uploadImage"> + <el-upload + :headers="headers" + :limit="limit" + :action="requestUrl" + list-type="picture-card" + :file-list="fileList" + :on-preview="handlePictureCardPreview" + :on-remove="handleRemove" + :on-success="handleSuccess" + :show-file-list="true" + :before-upload="handleBeforeUpload" + :class="fileList && fileList.length >= limit ? 'hide_box' : ''" + > + <i class="el-icon-plus" /> + </el-upload> + <el-dialog :visible.sync="dialogVisibleImageUpload" :modal="false"> + <img width="100%" :src="imageUploadUrl" alt="" /> + </el-dialog> + </div> +</template> +<script> +import { getToken } from "@/utils/auth"; // get token from cookie +export default { + props: { + upLoadUrl: { + type: String, + default: () => { + return ""; + } + }, + viewUrl: { + type: String, + default: () => { + return process.env.BASE_API + "/file/download/"; + } + }, + limit: { + type: Number, + default: () => { + return 1; + } + }, + value: { + type: String, + default: () => { + return ""; + } + } + }, + data() { + return { + imageUploadUrl: "", + dialogVisibleImageUpload: false, + fileList: [] + }; + }, + computed: { + requestUrl() { + if (this.upLoadUrl != null && this.upLoadUrl.trim() != "") { + return process.env.BASE_API + this.upLoadUrl; + } else { + return process.env.BASE_API + "/file/upload"; + } + }, + headers() { + return { + Authorization: getToken() // 直接从本地获取token就行 + }; + } + }, + watch: { + value: { + handler(val) { + this.echoUpload(this.value); + }, + immediate: true + } + }, + mounted() { + this.echoUpload(this.value); + }, + methods: { + handleRemove(file) { + this.fileList = []; + this.change(); + }, + handlePictureCardPreview(file) { + this.imageUploadUrl = file.url; + this.dialogVisibleImageUpload = true; + }, + // 上传成功的回调 + handleSuccess(response, file, fileList) { + if (response.code != 200) { + this.$message.error("上传失败"); + return; + } + this.fileList.push({ + url: file.response.data.urlPath + }); + this.change(); + }, + // 回传出去 + change() { + const fileList = (this.fileList.length > 0 && this.fileList[0].url) || ""; + this.$emit("input", fileList); + this.$emit("change", fileList); + }, + // 上传检验 + handleBeforeUpload(file) { + const extension = file.name + .split(".") + [file.name.split(".").length - 1].toLowerCase(); + // .png|.jpg|.gif|.icon|.pdf|.xlsx|.xls|.csv|.mp4|.avi + const extensionList = ["png", "jpg", "gif", "icon"]; + if (extensionList.indexOf(extension) < 0) { + this.$message.warning("请上传正确的格式文件"); + return false; + } + return true; + }, + // 回显 + echoUpload(val) { + if (!val) { + this.fileList = []; + } else { + const list = [{ url: val }]; + this.fileList = list; + } + } + } +}; +</script> +<style lang="scss" scoped> +.uploadImage .el-upload--picture-card { + width: 60px; + height: 60px; + line-height: 65px; +} +.uploadImage .el-upload-list__item { + width: 60px; + height: 60px; +} +.hide_box /deep/ .el-upload--picture-card { + display: none; +} +.el-upload-list__item { + line-height: 1.5; +} +.el-upload-list--picture-card .el-upload-list__item-actions { + text-align: left; + display: flex; + flex-wrap: wrap; +} +.imgBox, +.iconFont { + width: 100% !important; + height: 100% !important; +} +</style> diff --git a/report-ui/src/components/Breadcrumb/index.vue b/report-ui/src/components/Breadcrumb/index.vue index 90fd9cec..b80dfae2 100644 --- a/report-ui/src/components/Breadcrumb/index.vue +++ b/report-ui/src/components/Breadcrumb/index.vue @@ -1,67 +1,81 @@ <template> <el-breadcrumb class="app-breadcrumb" separator="/"> <transition-group name="breadcrumb"> - <el-breadcrumb-item v-for="(item,index) in levelListArr" :key="item.path"> - <span v-if="item.redirect==='noredirect'||index==levelListArr.length-1" class="no-redirect">{{ item.meta.title }}</span> - <router-link v-else :to="item.redirect||item.path" class="no-redirect">{{ item.meta.title }}</router-link> + <el-breadcrumb-item + v-for="(item, index) in levelListArr" + :key="item.path" + > + <span + v-if=" + item.redirect === 'noredirect' || index == levelListArr.length - 1 + " + class="no-redirect" + >{{ item.meta.title }}</span + > + <router-link + v-else + :to="item.redirect || item.path" + class="no-redirect" + >{{ item.meta.title }}</router-link + > </el-breadcrumb-item> </transition-group> </el-breadcrumb> </template> <script> -import pathToRegexp from 'path-to-regexp' +import pathToRegexp from "path-to-regexp"; export default { data() { return { levelList: null - } + }; }, watch: { $route() { - this.getBreadcrumb() + this.getBreadcrumb(); } }, - computed:{ - levelListArr(){ - return this.levelList.filter(item => item.meta && item.meta.title) + computed: { + levelListArr() { + return this.levelList.filter(item => item.meta && item.meta.title); } }, created() { - this.getBreadcrumb() + this.getBreadcrumb(); }, methods: { getBreadcrumb() { - const { params } = this.$route + const { params } = this.$route; let matched = this.$route.matched.filter(item => { if (item.name) { // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561 - var toPath = pathToRegexp.compile(item.path) - item.path = toPath(params) - return true + let toPath = pathToRegexp.compile(item.path); + item.path = toPath(params); + return true; } - }) + }); // const first = matched[0] // if (first && first.name !== 'dashboard') { // matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched) // } - this.levelList = matched + this.levelList = matched; } } -} +}; </script> <style rel="stylesheet/scss" lang="scss" scoped> - .app-breadcrumb.el-breadcrumb { - display: inline-block; - font-size: 14px; - line-height: 50px; - margin-left: 10px; - color: #fff; - .no-redirect { - color: #333; - cursor: text; - } +.app-breadcrumb.el-breadcrumb { + display: inline-block; + font-size: 14px; + line-height: 50px; + margin-left: 10px; + color: #fff; + .no-redirect { + color: #333; + cursor: text; } +} </style> diff --git a/report-ui/src/components/Permission/permission.js b/report-ui/src/components/Permission/permission.js index 623f3354..045bb1a2 100644 --- a/report-ui/src/components/Permission/permission.js +++ b/report-ui/src/components/Permission/permission.js @@ -2,7 +2,7 @@ import { hasPermission } from '@/utils/auth' export default { inserted(el, binding, vnode) { const { value } = binding // v-permission 绑定的权限值 - var checkFlag = hasPermission(value) + let checkFlag = hasPermission(value) if(checkFlag == false && el.parentNode ){ el.parentNode.removeChild(el) } diff --git a/report-ui/src/components/codeSelect.vue b/report-ui/src/components/codeSelect.vue index 4c94189c..b489f9ed 100644 --- a/report-ui/src/components/codeSelect.vue +++ b/report-ui/src/components/codeSelect.vue @@ -1,154 +1,171 @@ -/* -* 使用方式 <code-select v-model="params.enableFlag" dictname="ENABLE_FLAG" @changed="handler" placeholder="启用状态" style="width: 120px;"/> -* 根据/data/basecode.js中字典值,生成下拉列表 -* @property dictname ENABLE_FLAG -* @property placeholder -* @property style -*/ +/* * 使用方式 +<code-select + v-model="params.enableFlag" + dictname="ENABLE_FLAG" + @changed="handler" + placeholder="启用状态" + style="width: 120px;" +/> +* 根据/data/basecode.js中字典值,生成下拉列表 * @property dictname ENABLE_FLAG * +@property placeholder * @property style */ <template> - <el-select :name="inputName" v-model="selectValue" :disabled="disabled" :placeholder="placeholder" :style="mystyle" clearable class="filter-item code-selected" @change="selectChange" @visible-change="drowShow"> - <el-option v-for="(item,index) in optionList" :key="index" :label="item[label]" :value="item[valWord]" /> + <el-select + :name="inputName" + v-model="selectValue" + :disabled="disabled" + :placeholder="placeholder" + :style="mystyle" + clearable + class="filter-item code-selected" + @change="selectChange" + @visible-change="drowShow" + > + <el-option + v-for="(item, index) in optionList" + :key="index" + :label="item[label]" + :value="item[valWord]" + /> </el-select> </template> <script> - import request from '@/api/axios' - import { getStorageItem } from '@/utils/storage' - export default { - props: { - value: { - type: [String, Number], - default: '' - }, - //用localStrage中的basecode生成下拉 - dictname: { - type: String, - default: '' - }, - //远程请求,生成下拉 - remoteurl: { - type: String, - default: '' - }, - remoteParams: { - type: Object, - default: ()=>{} - }, - inputName: { - type: String, - default: '' - }, - placeholder: { - type: String, - default: '请选择' - }, - mystyle: { - type: String, - default: 'width: 100px' - }, - disabled: { - type: Boolean, - default: false - }, - label:{ - type: String, - default: 'label' - }, - valWord:{ - type: String, - default: 'value' - }, +import request from "@/api/axios"; +import { getStorageItem } from "@/utils/storage"; +export default { + props: { + value: { + type: [String, Number], + default: "" }, - data () { - return { - selectValue: '', - optionList: [], - dictList: [], - } + //用localStrage中的basecode生成下拉 + dictname: { + type: String, + default: "" }, - watch: { - value:{ - handler(newValue, oldValue){ - if (typeof newValue === 'string') { - this.selectValue = newValue - } else { - this.selectValue = this.parseString(newValue); - } - }, - immediate: true - }, + //远程请求,生成下拉 + remoteurl: { + type: String, + default: "" }, - computed: {}, - created () { - if (this.dictname !== '') { - this.optionList = this.getListFromBaseCode() - } - if (this.remoteurl !== '') { - this.getListFromAjax() - } + remoteParams: { + type: Object, + default: () => {} }, - mounted () {}, - methods: { - getListFromBaseCode() { - let basecode = getStorageItem('queryForCodeSelect') - let list = [] - if (!basecode.hasOwnProperty(this.dictname)) { - return [] - } - this.dictList = basecode[this.dictname] - for (let i = 0; i < this.dictList.length; i++) { - var codeItem = this.dictList[i] - list.push({ 'value': codeItem.value.toString(), 'label': codeItem.label }) + inputName: { + type: String, + default: "" + }, + placeholder: { + type: String, + default: "请选择" + }, + mystyle: { + type: String, + default: "width: 100px" + }, + disabled: { + type: Boolean, + default: false + }, + label: { + type: String, + default: "label" + }, + valWord: { + type: String, + default: "value" + } + }, + data() { + return { + selectValue: "", + optionList: [], + dictList: [] + }; + }, + watch: { + value: { + handler(newValue, oldValue) { + if (typeof newValue === "string") { + this.selectValue = newValue; + } else { + this.selectValue = this.parseString(newValue); } - return list - }, + immediate: true + } + }, + computed: {}, + created() { + if (this.dictname !== "") { + this.optionList = this.getListFromBaseCode(); + } + if (this.remoteurl !== "") { + this.getListFromAjax(); + } + }, + mounted() {}, + methods: { + getListFromBaseCode() { + let basecode = getStorageItem("queryForCodeSelect"); + let list = []; + if (!basecode.hasOwnProperty(this.dictname)) { + return []; + } + this.dictList = basecode[this.dictname]; + for (let i = 0; i < this.dictList.length; i++) { + let codeItem = this.dictList[i]; + list.push({ value: codeItem.value.toString(), label: codeItem.label }); + } + return list; + }, - getListFromAjax() { - //将url中的参数转换成json,提交 - var reqData = {}; - /*var params = this.remoteurl.slice(this.remoteurl.indexOf('?') + 1).split('&'); - for (var i = 0; i < params.length; i++) { - var map = params[i].split('='); - var key = map[0]; - var val = map[1]; + getListFromAjax() { + //将url中的参数转换成json,提交 + let reqData = {}; + /*let params = this.remoteurl.slice(this.remoteurl.indexOf('?') + 1).split('&'); + for (let i = 0; i < params.length; i++) { + let map = params[i].split('='); + let key = map[0]; + let val = map[1]; if(','.indexOf(val)>0 && val.split(',').length>1){ val = val.split(','); } reqData[map[0]] = val; }*/ - if(this.remoteParams != null){ - reqData = this.remoteParams; + if (this.remoteParams != null) { + reqData = this.remoteParams; + } + request({ + url: this.remoteurl, + method: "post", + data: reqData + }).then(response => { + if (response.repCode == "0000") { + this.optionList = response.repData; } - request({ - url: this.remoteurl, - method: 'post', - data: reqData - }).then(response => { - if (response.repCode == '0000') { - this.optionList = response.repData - } - }) - }, + }); + }, - selectChange (val) { - this.$emit('input', val) - var list = this.optionList - for (var i in list) { - var item = list[i] - if (item[this.valWord] === val) { - this.$emit('changed', item) - break - } + selectChange(val) { + this.$emit("input", val); + let list = this.optionList; + for (let i in list) { + let item = list[i]; + if (item[this.valWord] === val) { + this.$emit("changed", item); + break; } - }, - drowShow (val) { - this.$emit('show', val) - this.$emit('click', val) } + }, + drowShow(val) { + this.$emit("show", val); + this.$emit("click", val); } } +}; </script> <!--<style rel="stylesheet/scss" lang="less" scoped>--> diff --git a/report-ui/src/components/verifition/utils/ase.js b/report-ui/src/components/verifition/utils/ase.js index 4c1c5594..16af3ac0 100644 --- a/report-ui/src/components/verifition/utils/ase.js +++ b/report-ui/src/components/verifition/utils/ase.js @@ -4,8 +4,8 @@ import CryptoJS from 'crypto-js' * @keyWord String 服务器随机返回的关键字 * */ export function aesEncrypt(word,keyWord="XwKsGlMcdPMEhR1B"){ - var key = CryptoJS.enc.Utf8.parse(keyWord); - var srcs = CryptoJS.enc.Utf8.parse(word); - var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7}); + let key = CryptoJS.enc.Utf8.parse(keyWord); + let srcs = CryptoJS.enc.Utf8.parse(word); + let encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7}); return encrypted.toString(); } diff --git a/report-ui/src/components/verifition/utils/util.js b/report-ui/src/components/verifition/utils/util.js index 55f65d42..7ac5b403 100644 --- a/report-ui/src/components/verifition/utils/util.js +++ b/report-ui/src/components/verifition/utils/util.js @@ -1,8 +1,8 @@ export function resetSize(vm) { - var img_width, img_height, bar_width, bar_height; //图片的宽度、高度,移动条的宽度、高度 + let img_width, img_height, bar_width, bar_height; //图片的宽度、高度,移动条的宽度、高度 - var parentWidth = vm.$el.parentNode.offsetWidth || window.offsetWidth - var parentHeight = vm.$el.parentNode.offsetHeight || window.offsetHeight + let parentWidth = vm.$el.parentNode.offsetWidth || window.offsetWidth + let parentHeight = vm.$el.parentNode.offsetHeight || window.offsetHeight if (vm.imgSize.width.indexOf('%') != -1) { img_width = parseInt(this.imgSize.width) / 100 * parentWidth + 'px' diff --git a/report-ui/src/filter/index.js b/report-ui/src/filter/index.js index 202ac593..9685a2c9 100644 --- a/report-ui/src/filter/index.js +++ b/report-ui/src/filter/index.js @@ -1,3 +1,11 @@ +/* + * @Descripttion: + * @version: + * @Author: qianlishi + * @Date: 2021-12-11 14:48:27 + * @LastEditors: qianlishi + * @LastEditTime: 2021-12-13 10:15:29 + */ import { getStorageItem } from '@/utils/storage'; // 字典 @@ -9,11 +17,11 @@ export function basecode(value, dicName) { return value } - var basecode = getStorageItem('queryForCodeSelect') - var dictList = basecode[dicName] - var dictLabel = value - for (var i = 0; i < dictList.length; i++) { - var codeItem = dictList[i] + let basecode = getStorageItem('queryForCodeSelect') + let dictList = basecode[dicName] + let dictLabel = value + for (let i = 0; i < dictList.length; i++) { + let codeItem = dictList[i] if(codeItem.value == value || codeItem.labelEng == value){ dictLabel = codeItem.label break @@ -25,9 +33,9 @@ export function basecode(value, dicName) { // 根据字典值获取数据 export function getDataByCode(keyCode) { - var dict = basecode[this.keyCode] + let dict = basecode[this.keyCode] let list = [] - for (var key in dict) { + for (let key in dict) { list.push({ 'value': key, 'text': dict[key] @@ -38,7 +46,7 @@ export function getDataByCode(keyCode) { //保留两位小数 export function fixed(value){ -var intVal = null; +let intVal = null; if(typeof value == 'string' && /^[0-9.]+$/.test(value)){ intVal = parseInt(value); } @@ -57,16 +65,16 @@ export function formatTimestamp(value) { if (value == null) { return '' } - var date = new Date(value) - var y = date.getFullYear() - var m = date.getMonth() + 1 + let date = new Date(value) + let y = date.getFullYear() + let m = date.getMonth() + 1 m = m < 10 ? ('0' + m) : m - var d = date.getDate() + let d = date.getDate() d = d < 10 ? ('0' + d) : d - var h = date.getHours() + let h = date.getHours() h = h < 10 ? ('0' + h) : h - var minute = date.getMinutes() - var second = date.getSeconds() + let minute = date.getMinutes() + let second = date.getSeconds() minute = minute < 10 ? ('0' + minute) : minute second = second < 10 ? ('0' + second) : second return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second @@ -78,11 +86,11 @@ export function formatDate(value) { if (value == null) { return '' } - var date = new Date(value) - var y = date.getFullYear() - var m = date.getMonth() + 1 + let date = new Date(value) + let y = date.getFullYear() + let m = date.getMonth() + 1 m = m < 10 ? ('0' + m) : m - var d = date.getDate() + let d = date.getDate() d = d < 10 ? ('0' + d) : d return y + '-' + m + '-' + d } \ No newline at end of file diff --git a/report-ui/src/mixins/access.js b/report-ui/src/mixins/access.js index 40c76d5d..63e7819d 100644 --- a/report-ui/src/mixins/access.js +++ b/report-ui/src/mixins/access.js @@ -15,7 +15,7 @@ export default { return getToken() }, getUser: function () { - var user = getAccessUser() + let user = getAccessUser() if (user != null) { return user; } else { diff --git a/report-ui/src/mixins/common.js b/report-ui/src/mixins/common.js index 34411f43..fb71f697 100644 --- a/report-ui/src/mixins/common.js +++ b/report-ui/src/mixins/common.js @@ -60,7 +60,7 @@ export default { }, // 封装定制删除数组中的值 contains (a, obj) { - var i = a.length + let i = a.length while (i--) { if (a[i] === obj) { return i @@ -90,8 +90,8 @@ export default { }, sortArray (propertyName) { return function (object1, object2) { - var value1 = object1[propertyName]; - var value2 = object2[propertyName]; + let value1 = object1[propertyName]; + let value2 = object2[propertyName]; if (value1 < value2) { return -1; @@ -104,8 +104,8 @@ export default { }, // 获取对象类型 getObjectType (obj) { - var toString = Object.prototype.toString - var map = { + let toString = Object.prototype.toString + let map = { '[object Boolean]': 'boolean', '[object Number]': 'number', '[object String]': 'string', @@ -146,7 +146,7 @@ export default { return val.trim() == '' } if (typeof val === 'object') { - for (var key in val) { + for (let key in val) { return false } return true @@ -168,7 +168,7 @@ export default { list.forEach((ele) => { delete val[ele] }) - for (var o in val) { + for (let o in val) { return false } return true @@ -183,8 +183,8 @@ export default { // 对象深拷贝 deepClone (data) { - var type = this.getObjectType(data) - var obj + let type = this.getObjectType(data) + let obj if (type === 'array') { obj = [] } else if (type === 'object') { @@ -194,7 +194,7 @@ export default { return data } if (type === 'array') { - for (var i = 0, len = data.length; i < len; i++) { + for (let i = 0, len = data.length; i < len; i++) { data[i] = (() => { if (data[i] === 0) { return data[i] @@ -207,7 +207,7 @@ export default { obj.push(this.deepClone(data[i])) } } else if (type === 'object') { - for (var key in data) { + for (let key in data) { if (data) { delete data.$parent } @@ -219,12 +219,12 @@ export default { // 合并json mergeObject () { - var target = arguments[0] || {} - var deep = false - var arr = Array.prototype.slice.call(arguments) - var i = 1 - var options, src, key, copy - var isArray = false + let target = arguments[0] || {} + let deep = false + let arr = Array.prototype.slice.call(arguments) + let i = 1 + let options, src, key, copy + let isArray = false if (typeof target === 'boolean') { deep = target i++ @@ -262,9 +262,9 @@ export default { // 获取dom在屏幕中的top和left getDomTopLeftById (id) { - var dom = document.getElementById(id) - var top = 0 - var left = 0 + let dom = document.getElementById(id) + let top = 0 + let left = 0 if (dom != null) { top = dom.getBoundingClientRect().top left = dom.getBoundingClientRect().left @@ -272,10 +272,10 @@ export default { return { top: top, left: left } }, objToOne (obj) { - var tmpData = {} - for (var index in obj) { + let tmpData = {} + for (let index in obj) { if (typeof obj[index] == 'object') { - var resObj = this.objToOne(obj[index]) + let resObj = this.objToOne(obj[index]) Object.assign(tmpData, resObj) // 这里使用对象合并 } else { tmpData[index] = obj[index] @@ -293,8 +293,8 @@ export default { if (toString.call(obj) != '[object Object]') { return obj } - var result = {} - for (var key in obj) { + let result = {} + for (let key in obj) { if (this.isBlank(obj[key])) { continue } @@ -309,13 +309,13 @@ export default { // 根据数据字典,查询指定字典dict指定值code的,返回整个dictItem{id, text, extend} getDictItemByCode (dict, code) { - var dicts = getStorageItem('gaeaDict') + let dicts = getStorageItem('gaeaDict') if (!dicts.hasOwnProperty(dict)) { return null } - var dictItems = dicts[dict] - for (var i = 0; i < dictItems.length; i++) { - var dictItem = dictItems[i] + let dictItems = dicts[dict] + for (let i = 0; i < dictItems.length; i++) { + let dictItem = dictItems[i] if (typeof (code) == 'number') { code = code.toString() } @@ -327,7 +327,7 @@ export default { }, // 根据数据字典,查询指定字典dict指定值code的dictItem.text getDictLabelByCode (dict, code) { - var dictItem = this.getDictItemByCode(dict, code) + let dictItem = this.getDictItemByCode(dict, code) if (dictItem != null) { return dictItem['text'] } else { @@ -336,15 +336,24 @@ export default { }, // 根据数据字典,查询指定字典dict指定值code的dictItem.extend getDictExtendByCode (dict, code) { - var dictItem = this.getDictItemByCode(dict, code) + let dictItem = this.getDictItemByCode(dict, code) if (dictItem == null) { return null } - var extend = dictItem['extend'] + let extend = dictItem['extend'] if (extend == null || extend.trim() == 'null') { return null } return dictItem['extend'] }, + getSettingByName(settingName) { + let gaeaSetting = JSON.parse(localStorage.getItem('gaeaDict')) + if (gaeaSetting[settingName] != null) { + return gaeaSetting[settingName] + } else { + console.error('没有找到系统参数' + settingName + ',请与后端联系') + return null + } + }, } } diff --git a/report-ui/src/store/modules/user.js b/report-ui/src/store/modules/user.js index b8f7591d..57488282 100644 --- a/report-ui/src/store/modules/user.js +++ b/report-ui/src/store/modules/user.js @@ -24,7 +24,7 @@ const user = { const userName = userInfo.userName.trim() const password = userInfo.password.trim() const captchaVerification = userInfo.captchaVerification.trim() - var data ={ + let data ={ userName, password,captchaVerification } return new Promise((resolve, reject) => { diff --git a/report-ui/src/utils/aes.js b/report-ui/src/utils/aes.js index 5f264e1a..05c4c384 100644 --- a/report-ui/src/utils/aes.js +++ b/report-ui/src/utils/aes.js @@ -1,12 +1,12 @@ import CryptoJS from 'crypto-js' export function aesEncrypt(word){ - var key = CryptoJS.enc.Utf8.parse("BGxdEUOZkXka4HSj"); - var srcs = CryptoJS.enc.Utf8.parse(word); - var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7}); + let key = CryptoJS.enc.Utf8.parse("BGxdEUOZkXka4HSj"); + let srcs = CryptoJS.enc.Utf8.parse(word); + let encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7}); return encrypted.toString(); } export function aesDecrypt(word){ - var key = CryptoJS.enc.Utf8.parse("BGxdEUOZkXka4HSj"); - var decrypt = CryptoJS.AES.decrypt(word, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7}); + let key = CryptoJS.enc.Utf8.parse("BGxdEUOZkXka4HSj"); + let decrypt = CryptoJS.AES.decrypt(word, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7}); return CryptoJS.enc.Utf8.stringify(decrypt).toString(); } diff --git a/report-ui/src/utils/auth.js b/report-ui/src/utils/auth.js index 4e3dae80..9035c0c7 100644 --- a/report-ui/src/utils/auth.js +++ b/report-ui/src/utils/auth.js @@ -41,17 +41,17 @@ export function hasPermission(permissionStr) { } // 登录用户的全部权限码 - var user = getAccessUser() + let user = getAccessUser() if (user == null || user.authorities == null) { return false } - var opAuthoritiesStr = JSON.stringify(user.authorities) + let opAuthoritiesStr = JSON.stringify(user.authorities) // permissionStr可能是:authorityManage、authorityManage:insert、authorityManage:insert|authorityManage:update - var needPermissionArray = permissionStr.split('|') - for (var i = 0; i < needPermissionArray.length; i++) { + let needPermissionArray = permissionStr.split('|') + for (let i = 0; i < needPermissionArray.length; i++) { // 只要有其中的一个权限,就返回true - var needPermission = needPermissionArray[i] // authorityManage、authorityManage:insert + let needPermission = needPermissionArray[i] // authorityManage、authorityManage:insert needPermission = needPermission.replace(/\ /g, "") // 去除authorityManage : insert中:前后的空格 if(opAuthoritiesStr.indexOf(needPermission)>=0){ diff --git a/report-ui/src/utils/common.js b/report-ui/src/utils/common.js index b828c136..c4a54be3 100644 --- a/report-ui/src/utils/common.js +++ b/report-ui/src/utils/common.js @@ -2,8 +2,8 @@ export default { timestamp2String: function (timestamp, fmt) { if (timestamp == null) return; if (fmt == null || fmt == '') fmt = 'yyyy-MM-dd hh:mm:ss'; - var date = new Date(timestamp); - var o = { + let date = new Date(timestamp); + let o = { "M+": date.getMonth() + 1, //月份 "d+": date.getDate(), //日 "h+": date.getHours(), //小时 @@ -14,7 +14,7 @@ export default { }; if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)); - for (var k in o) + for (let k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); return fmt; @@ -24,12 +24,12 @@ export default { if (second == null || second == 0) { return "0秒"; } - var day = Math.floor(second / (24 * 3600)); - var hour = Math.floor((second - day * 24 * 3600) / 3600); - var minute = Math.floor((second - day * 24 * 3600 - hour * 3600) / 60); - var second = second - day * 24 * 3600 - hour * 3600 - minute * 60; + let day = Math.floor(second / (24 * 3600)); + let hour = Math.floor((second - day * 24 * 3600) / 3600); + let minute = Math.floor((second - day * 24 * 3600 - hour * 3600) / 60); + let second = second - day * 24 * 3600 - hour * 3600 - minute * 60; - var result = ""; + let result = ""; if (day > 0) { result = result + day + "天"; } diff --git a/report-ui/src/utils/index.js b/report-ui/src/utils/index.js index 0cc42693..9fc2f8a7 100644 --- a/report-ui/src/utils/index.js +++ b/report-ui/src/utils/index.js @@ -96,12 +96,12 @@ function padLeftZero (str) { * 生成uuid */ export function getUUID () { - var d = new Date().getTime() + let d = new Date().getTime() if (window.performance && typeof window.performance.now === 'function') { d += performance.now() // use high-precision timer if available } - var uuid = 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - var r = (d + Math.random() * 16) % 16 | 0 + let uuid = 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + let r = (d + Math.random() * 16) % 16 | 0 d = Math.floor(d / 16) return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16) }) diff --git a/report-ui/src/utils/signUtil.js b/report-ui/src/utils/signUtil.js index 85bbc548..9d5ed1d3 100644 --- a/report-ui/src/utils/signUtil.js +++ b/report-ui/src/utils/signUtil.js @@ -4,8 +4,8 @@ function jsonString (obj) { if (isObject(obj)) { return sortObjByKey(obj); } else if (isArray(obj)) { - var sortArray = []; - for (var i = 0; i < obj.length; i++) { + let sortArray = []; + for (let i = 0; i < obj.length; i++) { if (isObject(obj[i])) { sortArray.push(sortObjByKey(obj[i])); } else { @@ -20,10 +20,10 @@ function jsonString (obj) { // 将通讯录按照 ABCD字母的顺序排序 function sortObjByKey (obj) { - var keys = Object.keys(obj).sort(); - var newObj = {} - for (var i = 0; i < keys.length; i++) { - var index = keys[i]; + let keys = Object.keys(obj).sort(); + let newObj = {} + for (let i = 0; i < keys.length; i++) { + let index = keys[i]; newObj[index] = jsonString(obj[index]); } return newObj; @@ -50,13 +50,13 @@ export default { if (typeof (data) == "undefined" || data == null) { data = {}; } - var gatewayRequest = {};//currentPage pageSize orderBy data time token sign isFrom - var time = new Date().getTime(); + let gatewayRequest = {};//currentPage pageSize orderBy data time token sign isFrom + let time = new Date().getTime(); //找出data中值非null的key,同时排除分页参数 //ignoreKeyList data中哪些key不参与签名 - var dataKeyArray = []; - var excludeKeyArray = ['currentPage', 'pageSize', 'orderBy', 'ignoreKeyList']; - for (var key in data) { + let dataKeyArray = []; + let excludeKeyArray = ['currentPage', 'pageSize', 'orderBy', 'ignoreKeyList']; + for (let key in data) { if (data[key] == null) { continue; } @@ -65,7 +65,7 @@ export default { delete data[key]; if (key === 'ignoreKeyList') { //遍历ignoreKeyList,不参与签名校验 - for (var i = 0; i < data[key].length; i++) { + for (let i = 0; i < data[key].length; i++) { delete data[data[key][i]]; } } @@ -77,10 +77,10 @@ export default { dataKeyArray.sort(); //生成签名串"time=%s&" + tempSignStr + "&token=%s" - var tempSignStr = "time=" + time; - for (var i = 0; i < dataKeyArray.length; i++) { - var key = dataKeyArray[i]; - var value = data[key]; + let tempSignStr = "time=" + time; + for (let i = 0; i < dataKeyArray.length; i++) { + let key = dataKeyArray[i]; + let value = data[key]; tempSignStr += "&"; tempSignStr += key; tempSignStr += "="; @@ -88,7 +88,7 @@ export default { } tempSignStr += "&token="; tempSignStr += token; - var signStr = md5(tempSignStr); + let signStr = md5(tempSignStr); gatewayRequest['data'] = data; gatewayRequest['time'] = time; gatewayRequest['token'] = token; diff --git a/report-ui/src/utils/storage.js b/report-ui/src/utils/storage.js index 02a2aad1..7c14a4ec 100644 --- a/report-ui/src/utils/storage.js +++ b/report-ui/src/utils/storage.js @@ -1,10 +1,18 @@ +/* + * @Descripttion: + * @version: + * @Author: qianlishi + * @Date: 2021-12-11 14:48:27 + * @LastEditors: qianlishi + * @LastEditTime: 2021-12-13 10:16:49 + */ import Cookies from 'js-cookie' export function setCookie(k, v) { if(typeof(v) == "undefined" || v == null){ return; } - var val = v; + let val = v; if(typeof(v) == "object"){ val = JSON.stringify(v); } @@ -13,7 +21,7 @@ export function setCookie(k, v) { } export function getCookie(k) { - var val = Cookies.get(k); + let val = Cookies.get(k); try{ //如果是number boolean jsonstring是不会报错的 return JSON.parse(val); @@ -32,7 +40,7 @@ export function setStorageItem(k, v) { return; } - var val = v; + let val = v; if(typeof(v) == "object"){ val = JSON.stringify(v); } @@ -40,7 +48,7 @@ export function setStorageItem(k, v) { } export function getStorageItem(k) { - var val = localStorage.getItem(k); + let val = localStorage.getItem(k); try{ //如果是number boolean jsonstring是不会报错的 return JSON.parse(val); diff --git a/report-ui/src/utils/throttle.js b/report-ui/src/utils/throttle.js index 68396b40..93b8ad79 100644 --- a/report-ui/src/utils/throttle.js +++ b/report-ui/src/utils/throttle.js @@ -1,9 +1,17 @@ +/* + * @Descripttion: + * @version: + * @Author: qianlishi + * @Date: 2021-12-11 14:48:27 + * @LastEditors: qianlishi + * @LastEditTime: 2021-12-13 10:16:48 + */ /** * 函数节流 */ export function _throttle(fn,delay){ let timer - var delay = delay || 1000; //一秒内触发一次 + let delay = delay || 1000; //一秒内触发一次 return function(...args){ const context = this let canExecute = !timer