|
@@ -1,18 +1,137 @@
|
|
|
<template>
|
|
|
- <div class="customized-column-content">
|
|
|
- <div class="column-area">
|
|
|
- <div class="column-select-panel">
|
|
|
- <div class="panel-title-line">
|
|
|
- 可添加的列
|
|
|
+ <a-modal
|
|
|
+ v-model:visible="columnShow"
|
|
|
+ title="自定义列"
|
|
|
+ @ok="makeDine"
|
|
|
+ @cancel="cancelDine"
|
|
|
+ :width="722"
|
|
|
+ :confirm-loading="confirmLoading"
|
|
|
+ ok-text="应用自定义列"
|
|
|
+ >
|
|
|
+ <div class="customized-column-content">
|
|
|
+ <div class="column-area">
|
|
|
+ <div class="column-select-panel">
|
|
|
+ <div class="panel-title-line">
|
|
|
+ 可添加的列
|
|
|
+ </div>
|
|
|
+ <div class="panel-content">
|
|
|
+ <div class="column-select-area column-select-area0">
|
|
|
+ <div class="column-group clearfix">
|
|
|
+ <div class="group-title ad-d-flex">
|
|
|
+ <span>广告</span>
|
|
|
+ </div>
|
|
|
+ <div class="column-items clearfix">
|
|
|
+ <div class="column-item">
|
|
|
+ <a-checkbox
|
|
|
+ v-model:checked="checkedadAll"
|
|
|
+ :indeterminate="adIndeterminate"
|
|
|
+ @change="onCheckAllChange('ad')"
|
|
|
+ >
|
|
|
+ 全选
|
|
|
+ </a-checkbox>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <a-checkbox-group
|
|
|
+ v-model:value="adCheckedList"
|
|
|
+ @change="onCheckChange('ad')"
|
|
|
+ >
|
|
|
+ <div class="column-item" v-for="ad in adList">
|
|
|
+ <a-checkbox :value="ad.name" @change="checkOne">
|
|
|
+ {{ ad.desc }}
|
|
|
+ </a-checkbox>
|
|
|
+ </div>
|
|
|
+ </a-checkbox-group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="column-group clearfix">
|
|
|
+ <div class="group-title ad-d-flex">
|
|
|
+ <span>数据</span>
|
|
|
+ </div>
|
|
|
+ <div class="column-items clearfix">
|
|
|
+ <div class="column-item">
|
|
|
+ <a-checkbox
|
|
|
+ v-model:checked="checkedstatAll"
|
|
|
+ :indeterminate="statIndeterminate"
|
|
|
+ @change="onCheckAllChange('stat')"
|
|
|
+ >
|
|
|
+ 全选
|
|
|
+ </a-checkbox>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <a-checkbox-group
|
|
|
+ v-model:value="statCheckedList"
|
|
|
+ @change="onCheckChange('stat')"
|
|
|
+ >
|
|
|
+ <div class="column-item" v-for="ad in statList">
|
|
|
+ <a-checkbox :value="ad.name" @change="checkOne">
|
|
|
+ {{ ad.desc }}
|
|
|
+ </a-checkbox>
|
|
|
+ </div>
|
|
|
+ </a-checkbox-group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div class="column-selected">
|
|
|
- <div class="panel-title-line">
|
|
|
- 已选26列<span class="delete-all">清空全部</span>
|
|
|
+ <div class="column-selected">
|
|
|
+ <div class="panel-title-line">
|
|
|
+ <span
|
|
|
+ >已选{{ dragList.length }}列
|
|
|
+ <a-tooltip>
|
|
|
+ <template #title>
|
|
|
+ 拖动单项可以排序,左侧可以设置列宽,右侧移除列
|
|
|
+ </template>
|
|
|
+ <question-circle-outlined></question-circle-outlined>
|
|
|
+ </a-tooltip>
|
|
|
+ </span>
|
|
|
+
|
|
|
+ <span class="delete-all" @click="clearAll">清空全部</span>
|
|
|
+ </div>
|
|
|
+ <div class="panel-selected" ref="draged">
|
|
|
+ <drag-wrapper :source="dragList" @after-drag="sureDrag">
|
|
|
+ <template v-slot:default="slotProps">
|
|
|
+ <div class="selected-column-item">
|
|
|
+ <a-popover title="额外参数" trigger="click">
|
|
|
+ <template #content>
|
|
|
+ <div class="hovers-content">
|
|
|
+ <span class="label">列宽:</span
|
|
|
+ ><a-input-number
|
|
|
+ size="small"
|
|
|
+ :min="60"
|
|
|
+ :max="1000"
|
|
|
+ v-model:value="slotProps.data.width"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <!-- <div class="hovers-content">
|
|
|
+ <span class="label">固定:</span
|
|
|
+ ><a-radio-group
|
|
|
+ v-model:value="slotProps.data.fixed"
|
|
|
+ size="small"
|
|
|
+ >
|
|
|
+ <a-radio-button :value="true">
|
|
|
+ 固定列
|
|
|
+ </a-radio-button>
|
|
|
+ <a-radio-button :value="false">
|
|
|
+ 原始列
|
|
|
+ </a-radio-button>
|
|
|
+ </a-radio-group>
|
|
|
+ </div> -->
|
|
|
+ </template>
|
|
|
+ <align-left-outlined></align-left-outlined>
|
|
|
+ </a-popover>
|
|
|
+ <p>{{ slotProps.data.desc }}</p>
|
|
|
+ <close-outlined
|
|
|
+ style="font-size:10px;color:#666;"
|
|
|
+ @click="clearSingle(slotProps.data)"
|
|
|
+ ></close-outlined>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </drag-wrapper>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
+ </a-modal>
|
|
|
</template>
|
|
|
<script lang="ts">
|
|
|
import {
|
|
@@ -22,36 +141,247 @@ import {
|
|
|
ref,
|
|
|
watchEffect,
|
|
|
onMounted,
|
|
|
+ onUpdated,
|
|
|
} from "vue";
|
|
|
-import { getCoustomClomuns } from "@/api";
|
|
|
-interface itemLine {}
|
|
|
+import { getCoustomClomuns, setCoustomClomuns } from "@/api";
|
|
|
+import DragWrapper from "@/components/drag-wrapper/index.vue";
|
|
|
+import {
|
|
|
+ AlignLeftOutlined,
|
|
|
+ CloseOutlined,
|
|
|
+ QuestionCircleOutlined,
|
|
|
+} from "@ant-design/icons-vue";
|
|
|
+import state from "@/store/modules/app/state";
|
|
|
+interface itemLine {
|
|
|
+ desc: string;
|
|
|
+ name: string;
|
|
|
+ fixed?: boolean;
|
|
|
+ order: number;
|
|
|
+ type: string;
|
|
|
+ width?: number;
|
|
|
+ checked: boolean;
|
|
|
+}
|
|
|
+
|
|
|
+type adList = "adList" | "statList";
|
|
|
+type adCheckedList = "adCheckedList" | "statCheckedList";
|
|
|
+type checkedadAll = "checkedadAll" | "checkedstatAll";
|
|
|
+type adIndeterminate = "adIndeterminate" | "statIndeterminate";
|
|
|
+
|
|
|
const CustomCloumn = defineComponent({
|
|
|
- props: {},
|
|
|
- setup(props) {
|
|
|
+ props: {
|
|
|
+ show: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ components: {
|
|
|
+ DragWrapper,
|
|
|
+ AlignLeftOutlined,
|
|
|
+ CloseOutlined,
|
|
|
+ QuestionCircleOutlined,
|
|
|
+ },
|
|
|
+ setup(props, { emit }) {
|
|
|
const state = reactive({
|
|
|
- ad: ref<any[]>([]),
|
|
|
+ adList: ref<itemLine[]>([]),
|
|
|
+ statList: ref<itemLine[]>([]),
|
|
|
+ adCheckedList: ref<string[]>([]),
|
|
|
+ statCheckedList: ref<string[]>([]),
|
|
|
+ dragList: ref<itemLine[]>([]),
|
|
|
+ checkedadAll: false,
|
|
|
+ checkedstatAll: false,
|
|
|
+ adIndeterminate: false,
|
|
|
+ statIndeterminate: false,
|
|
|
+ confirmLoading: false,
|
|
|
+ columnShow: props.show,
|
|
|
+ });
|
|
|
+ watchEffect(() => {
|
|
|
+ state.columnShow = props.show;
|
|
|
});
|
|
|
-
|
|
|
const getData = () => {
|
|
|
- getCoustomClomuns().then((res) => {
|
|
|
- console.log(res);
|
|
|
+ state.adCheckedList = [];
|
|
|
+ state.statCheckedList = [];
|
|
|
+ getCoustomClomuns().then((res: any) => {
|
|
|
+ let drawgList: Array<itemLine> = [];
|
|
|
+ let nad = res.data.ad.map((r: itemLine) => {
|
|
|
+ if (r.order > 0) {
|
|
|
+ state.adCheckedList.push(r.name);
|
|
|
+ drawgList.push(r);
|
|
|
+ }
|
|
|
+ r.type = "ad";
|
|
|
+ return r;
|
|
|
+ });
|
|
|
+ let nstat = res.data.stat.map((r: itemLine) => {
|
|
|
+ if (r.order > 0) {
|
|
|
+ state.statCheckedList.push(r.name);
|
|
|
+ drawgList.push(r);
|
|
|
+ }
|
|
|
+ r.type = "stat";
|
|
|
+ return r;
|
|
|
+ });
|
|
|
+ drawgList.sort((a, b) => {
|
|
|
+ return b.order - a.order;
|
|
|
+ });
|
|
|
+ state.dragList = drawgList;
|
|
|
+ state.adCheckedList.length > 0 &&
|
|
|
+ state.adCheckedList.length < nad.length
|
|
|
+ ? (state.adIndeterminate = true)
|
|
|
+ : state.adCheckedList.length == nad.length
|
|
|
+ ? (state.checkedadAll = true)
|
|
|
+ : (state.checkedadAll = false);
|
|
|
+ state.statCheckedList.length > 0 &&
|
|
|
+ state.statCheckedList.length < nstat.length
|
|
|
+ ? (state.statIndeterminate = true)
|
|
|
+ : state.statCheckedList.length == nstat.length
|
|
|
+ ? (state.checkedstatAll = true)
|
|
|
+ : (state.checkedstatAll = false);
|
|
|
+
|
|
|
+ state.adList = nad;
|
|
|
+ state.statList = nstat;
|
|
|
});
|
|
|
};
|
|
|
|
|
|
- onMounted(() => {
|
|
|
- getData();
|
|
|
+ onUpdated(() => {
|
|
|
+ if (props.show && state.confirmLoading == false) {
|
|
|
+ getData();
|
|
|
+ }
|
|
|
});
|
|
|
+ return { ...toRefs(state) };
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ onCheckAllChange(type: string) {
|
|
|
+ let otype = type == "stat" ? "ad" : "stat";
|
|
|
+ if (this[<checkedadAll>`checked${type}All`]) {
|
|
|
+ //全选
|
|
|
+ let list: Array<string> = [];
|
|
|
+ let dragList: Array<itemLine> = [];
|
|
|
+ this[<adList>`${type}List`].forEach((d) => {
|
|
|
+ list.push(d.name);
|
|
|
+ dragList.push(d);
|
|
|
+ });
|
|
|
+ this[<adCheckedList>`${type}CheckedList`] = list;
|
|
|
+ let moreDragList = this.dragList.filter((r) => {
|
|
|
+ return this[<adList>`${otype}List`].find((d) => d.name === r.name);
|
|
|
+ });
|
|
|
+ dragList = moreDragList.concat(dragList);
|
|
|
+ this.dragList = dragList;
|
|
|
+ this.toListDown();
|
|
|
+ } else {
|
|
|
+ //全部取消
|
|
|
+ let dragList: Array<itemLine> = [];
|
|
|
+ this[<adCheckedList>`${type}CheckedList`] = [];
|
|
|
+ dragList = this.dragList.filter((r) => {
|
|
|
+ return !this[<adList>`${type}List`].some((d) => d.name === r.name);
|
|
|
+ });
|
|
|
+ this.dragList = dragList;
|
|
|
+ }
|
|
|
+ this[<adIndeterminate>`${type}Indeterminate`] = false;
|
|
|
+ },
|
|
|
+ onCheckChange(type: string) {
|
|
|
+ this[<adIndeterminate>`${type}Indeterminate`] = !!(
|
|
|
+ this[<adCheckedList>`${type}CheckedList`].length > 0 &&
|
|
|
+ this[<adCheckedList>`${type}CheckedList`].length <
|
|
|
+ this[<adList>`${type}List`].length
|
|
|
+ );
|
|
|
+ this[<checkedadAll>`checked${type}All`] =
|
|
|
+ this[<adCheckedList>`${type}CheckedList`].length ===
|
|
|
+ this[<adList>`${type}List`].length;
|
|
|
+ },
|
|
|
+ sureDrag(list: Array<itemLine>) {
|
|
|
+ this.dragList = list;
|
|
|
+ },
|
|
|
+ toListDown() {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ let element = this.$refs.draged;
|
|
|
+ let listHeight =
|
|
|
+ document &&
|
|
|
+ (document.querySelector(".smooth-dnd-container") as HTMLElement)
|
|
|
+ .offsetHeight;
|
|
|
+ if (listHeight && listHeight > 395) {
|
|
|
+ (element as HTMLElement).scrollTop = (listHeight as number) - 380;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ checkOne(e: any) {
|
|
|
+ if (e.target.checked) {
|
|
|
+ let current = [...this.adList, ...this.statList].find((r) => {
|
|
|
+ return r.name == e.target.value;
|
|
|
+ });
|
|
|
+ current && this.dragList.push(current) && this.toListDown();
|
|
|
+ } else {
|
|
|
+ let dragList = this.dragList;
|
|
|
+ let newList = dragList.filter((r) => r.name != e.target.value);
|
|
|
+ this.dragList = newList;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ clearSingle(item: itemLine) {
|
|
|
+ let type = item.type;
|
|
|
+ let dragList = this.dragList.filter((r) => r.name !== item.name);
|
|
|
+ let checkList = this[<adCheckedList>`${type}CheckedList`].filter(
|
|
|
+ (r) => r !== item.name
|
|
|
+ );
|
|
|
+ this[<adCheckedList>`${type}CheckedList`] = checkList;
|
|
|
+ this.dragList = dragList;
|
|
|
+ if (this[<adCheckedList>`${type}CheckedList`].length == 0) {
|
|
|
+ this[<adIndeterminate>`${type}Indeterminate`] = false;
|
|
|
+ }
|
|
|
+ if (this[<checkedadAll>`checked${type}All`]) {
|
|
|
+ this[<checkedadAll>`checked${type}All`] = false;
|
|
|
+ this[<adIndeterminate>`${type}Indeterminate`] = true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ clearAll() {
|
|
|
+ this.dragList = [];
|
|
|
+ this.adCheckedList = [];
|
|
|
+ this.statCheckedList = [];
|
|
|
+ this.adIndeterminate = false;
|
|
|
+ this.statIndeterminate = false;
|
|
|
+ this.checkedadAll = false;
|
|
|
+ this.checkedstatAll = false;
|
|
|
+ },
|
|
|
+ makeDine() {
|
|
|
+ this.confirmLoading = true;
|
|
|
+ let list: Array<itemLine> = [];
|
|
|
+ this.dragList.forEach((d, i) => {
|
|
|
+ list[i] = d;
|
|
|
+ list[i].order = this.dragList.length - i;
|
|
|
+ delete list[i].type;
|
|
|
+ });
|
|
|
|
|
|
- return {};
|
|
|
+ setCoustomClomuns(list).then((res: any) => {
|
|
|
+ this.$message.success("保存自定义列成功");
|
|
|
+ this.confirmLoading = false;
|
|
|
+ }).catch((e:any)=>{
|
|
|
+ this.confirmLoading = false;
|
|
|
+ });
|
|
|
+ //this.$emit('dineClounmList')
|
|
|
+ },
|
|
|
+ cancelDine() {
|
|
|
+ this.$emit("closeClomnShow");
|
|
|
+ },
|
|
|
},
|
|
|
- methods: {},
|
|
|
});
|
|
|
|
|
|
export default CustomCloumn;
|
|
|
</script>
|
|
|
<style lang="scss" scoped>
|
|
|
+.hovers-content {
|
|
|
+ margin: 8px 0 5px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ .label {
|
|
|
+ display: inline-block;
|
|
|
+ max-width: 50px;
|
|
|
+ width: 50px;
|
|
|
+ }
|
|
|
+ .ant-switch {
|
|
|
+ width: 50px;
|
|
|
+ }
|
|
|
+}
|
|
|
.column-area {
|
|
|
height: 445px;
|
|
|
+ .ad-d-flex {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
.panel-title-line {
|
|
|
background-color: #f9fafd;
|
|
|
border: #e4e9ed 1px solid;
|
|
@@ -64,6 +394,31 @@ export default CustomCloumn;
|
|
|
float: left;
|
|
|
height: 445px;
|
|
|
padding-bottom: 9px;
|
|
|
+ .panel-selected {
|
|
|
+ border: #e4e9ed 1px solid;
|
|
|
+ border-top: 0;
|
|
|
+ box-sizing: border-box;
|
|
|
+ height: 395px;
|
|
|
+ padding: 0 12px 12px 4px;
|
|
|
+ overflow-y: auto;
|
|
|
+ .selected-column-item {
|
|
|
+ width: 198px;
|
|
|
+ height: auto;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ background: #f8f8f8;
|
|
|
+ border-radius: 4px;
|
|
|
+ margin-top: 8px;
|
|
|
+ line-height: 18px;
|
|
|
+ padding: 5px 12px;
|
|
|
+
|
|
|
+ p {
|
|
|
+ padding: 0 5px;
|
|
|
+ cursor: move;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
.delete-all {
|
|
|
cursor: pointer;
|
|
|
font-size: 14px;
|
|
@@ -76,6 +431,45 @@ export default CustomCloumn;
|
|
|
float: left;
|
|
|
margin-right: 16px;
|
|
|
height: 445px;
|
|
|
+ .panel-content {
|
|
|
+ border: #e4e9ed 1px solid;
|
|
|
+ border-top: 0;
|
|
|
+ box-sizing: border-box;
|
|
|
+ height: 395px;
|
|
|
+ padding: 0;
|
|
|
+ overflow: hidden;
|
|
|
+ .column-select-area {
|
|
|
+ height: 395px;
|
|
|
+ overflow-y: auto;
|
|
|
+ width: 100%;
|
|
|
+ .column-group {
|
|
|
+ border-bottom: #e4e9ed 1px solid;
|
|
|
+ padding: 0 16px;
|
|
|
+ .column-items {
|
|
|
+ margin-bottom: 4px;
|
|
|
+ }
|
|
|
+ .group-title {
|
|
|
+ cursor: pointer;
|
|
|
+ line-height: 46px;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #333;
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+ .column-item {
|
|
|
+ width: 188px;
|
|
|
+ float: left;
|
|
|
+ min-height: 34px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|
|
|
+<style lang="scss">
|
|
|
+.selected-column-item {
|
|
|
+ .anticon {
|
|
|
+ cursor: pointer;
|
|
|
}
|
|
|
}
|
|
|
</style>
|