123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- <script setup>
- import { ref, onMounted, watch, getCurrentInstance } from 'vue'
- const that = getCurrentInstance().proxy
- const props = defineProps({
- // 要回显的分组id
- echo: {
- type: String,
- default: ''
- },
- // 分组列表
- list: {
- type: Array,
- default: () => []
- }
- })
- // 属性
- const groupList = ref([])
- const newGroupName = ref('')
- const showAdd = ref(false)
- const isDisabled = ref(false)
- const currentSelect = ref([])
- // 冒泡事件名
- const emits = defineEmits(['emitDisabled', 'onChange', 'onAdd', 'onEdit'])
- onMounted(() => {
- initData()
- })
- // 监听isDisabled属性
- watch(
- () => isDisabled.value,
- (newVal) => {
- emits('emitDisabled', newVal)
- }
- )
- // 监听list属性
- watch(
- () => props.list,
- (newVal) => {
- initData()
- }
- )
- function initData() {
- if (!props.list || !props.list.length) return
- const formatList = props.list.map((v) => {
- return {
- id: v.id,
- name: v.s_name || v.name,
- input: '',
- showEdit: false,
- canEdit: v.isPut,
- checked: currentSelect.value.length
- ? currentSelect.value.includes(v.id)
- : v.isSelect
- }
- })
- groupList.value = formatList
- if (props.echo) {
- setGroupSelected(props.echo)
- }
- }
- // 新增分组改变交互方法
- function onAddAction() {
- showAdd.value = true
- newGroupName.value = ''
- isDisabled.value = true
- }
- // 新增分组确认方法
- function onAddConfirm() {
- if (!newGroupName.value) {
- return that.$toast('请输入分组名称')
- }
- if (groupList.value.some((v) => v.name === newGroupName.value)) {
- return that.$toast('分组名称已存在')
- }
- const newItem = {
- // id: Math.random(),
- name: newGroupName.value,
- showEdit: false,
- checked: false,
- input: ''
- }
- groupList.value.splice(1, 0, newItem)
- showAdd.value = false
- isDisabled.value = false
- emits('add', { name: newGroupName.value })
- }
- // 新增分组取消方法
- function onAddCancel() {
- newGroupName.value = ''
- showAdd.value = false
- isDisabled.value = false
- }
- // 单项编辑分组
- function onEditGroup(item) {
- item.input = item.name
- item.showEdit = true
- isDisabled.value = true
- }
- // 单项编辑输入方法
- function onItemInput(event, item) {
- // item.input = event
- }
- // 单项编辑确认方法
- function onItemConfirm(item) {
- const list = groupList.value
- if (!item.input) {
- return that.$toast('请输入分组名称')
- }
- if (list.some((v) => v.name === item.input)) {
- return that.$toast('分组名称已存在')
- }
- item.name = item.input
- item.showEdit = false
- isDisabled.value = false
- emits('edit', { groupId: item.id, name: item.name })
- }
- // 单项编辑取消方法
- function onItemCancel(item) {
- item.showEdit = false
- isDisabled.value = false
- }
- // 分组名称选中事件
- function changeGroupState(item) {
- const list = groupList.value
- if (item.name === '默认分组') {
- list.forEach((v) => {
- v.checked = false
- })
- item.checked = true
- } else {
- item.checked = !item.checked
- const allChecked = list.some((s) => {
- return s.checked
- })
- if (allChecked) {
- list[0].checked = false
- } else {
- list[0].checked = true
- }
- }
- const selected = getSelected()
- emits('onChange', selected)
- }
- // 获取选中的分组
- function getSelected() {
- const data = []
- const lists = groupList.value
- lists.forEach((v) => {
- if (v.checked) {
- data.push(v.id)
- }
- })
- currentSelect.value = data
- return data.toString()
- }
- // 设置选中的分组
- function setGroupSelected(data) {
- if (!data) return
- const list = groupList.value
- const newData = data.split(',')
- list.forEach((v) => {
- v.checked = false
- newData.forEach((s) => {
- if (s === v.id) {
- v.checked = true
- }
- })
- })
- }
- defineExpose({
- getSelected
- })
- </script>
- <template>
- <div class="monitor-group" :class="{ disabled: isDisabled }">
- <div class="flex flex-(items-center justify-end) group-add-container">
- <div
- class="flex flex-(items-center justify-between) add-container"
- v-if="showAdd"
- >
- <el-input
- v-model="newGroupName"
- placeholder="请输入分组名称"
- class="add-input"
- maxlength="15"
- autofocus
- @keyup.enter.native="onAddConfirm"
- >
- <template #suffix>
- <span class="el-input__count">
- <span class="el-input__count-inner">
- <em :class="{ 'already-count': newGroupName.length > 0 }">{{
- newGroupName.length
- }}</em
- >/15
- </span>
- </span>
- </template>
- </el-input>
- <div class="flex flex-items-center add-action">
- <span class="add-confirm" @click="onAddConfirm">确定</span>
- <span class="add-cancel" @click="onAddCancel">取消</span>
- </div>
- </div>
- <el-button
- v-else
- type="text"
- icon="el-icon-plus"
- @click="onAddAction"
- class="add-btn"
- >
- 新增分组
- </el-button>
- </div>
- <div class="group-list-container">
- <div v-for="(item, key) in groupList" :key="key" class="group-item">
- <div
- v-if="!item.showEdit"
- class="flex flex-(items-center justify-between) item-name-container"
- :class="{ 'item-name-checked': item.checked }"
- @click="changeGroupState(item)"
- >
- <div class="flex flex-items-center flex-1">
- <div
- v-if="item.name === '默认分组'"
- class="j-radio"
- :class="item.checked ? 'r-checked' : ''"
- ></div>
- <div
- v-else
- class="j-checkbox"
- :class="item.checked ? 'checked' : ''"
- ></div>
- <span class="item-name" :data-id="item.id">{{ item.name }}</span>
- </div>
- <span
- class="item-edit"
- v-if="item.canEdit"
- @click.stop="onEditGroup(item)"
- >编辑</span
- >
- </div>
- <div
- v-else
- class="flex flex-(item-center space-between) item-edit-container"
- >
- <el-input
- v-model="item.input"
- placeholder="请输入分组名称"
- class="add-input input-bg"
- maxlength="15"
- autofocus
- @input="onItemInput($event, item)"
- @keyup.enter.native="onItemConfirm(item)"
- >
- <template #suffix>
- <span class="el-input__count">
- <span class="el-input__count-inner">
- <em :class="{ 'already-count': item.input.length > 0 }">{{
- item.input.length
- }}</em
- >/15
- </span>
- </span>
- </template>
- </el-input>
- <div class="flex items-center add-action">
- <span class="add-confirm" @click="onItemConfirm(item)">确定</span>
- <span class="add-cancel" @click="onItemCancel(item)">取消</span>
- </div>
- </div>
- </div>
- </div>
- </div>
- </template>
- <style lang="scss" scoped>
- .monitor-group {
- .j-radio {
- width: 20px;
- height: 20px;
- margin-right: 4px;
- background: url('~@/assets/images/icon/radio_default.png') no-repeat center
- center;
- cursor: pointer;
- background-size: 20px;
- &.r-checked {
- background: url('~@/assets/images/icon/radio_checked2.png') no-repeat
- center center;
- background-size: 20px;
- }
- }
- .j-checkbox {
- width: 20px;
- height: 20px;
- margin-right: 4px;
- border: 0;
- background: url('~@/assets/images/icon/checkbox_default.png') no-repeat
- center center;
- cursor: pointer;
- background-size: 20px;
- &.checked {
- border: 0;
- background: url('~@/assets/images/icon/checkbox_checked.png') no-repeat
- center center;
- background-size: 20px;
- &[disabled] {
- background: url('~@/assets/images/icon/checkbox_checked_disabled.png')
- no-repeat;
- background-size: 20px;
- }
- }
- }
- .group-add-container {
- .add-container {
- width: 100%;
- }
- }
- .group-list-container {
- margin-top: 20px;
- max-height: 380px;
- overflow-y: auto;
- border: 1px solid rgba(236, 236, 236, 1);
- border-radius: 4px;
- &::-webkit-scrollbar {
- width: 3px;
- }
- .item-name {
- margin-left: 4px;
- line-height: 22px;
- }
- .item-edit {
- display: none;
- color: $color_main;
- cursor: pointer;
- line-height: 22px;
- }
- .group-item {
- cursor: pointer;
- &:hover {
- background: #eaf8fa;
- .item-edit {
- display: block;
- }
- }
- &:not(:last-child) {
- border-bottom: 1px solid rgba(0, 0, 0, 0.05);
- }
- }
- .item-name-container {
- padding: 8px 12px 8px 16px;
- &.item-name-checked {
- background: #eaf8fa;
- color: $color_main;
- }
- }
- .item-edit-container {
- padding: 4px 12px 4px 16px;
- }
- }
- .add-confirm {
- margin-left: 12px;
- color: $color_main;
- font-size: 14px;
- line-height: 22px;
- cursor: pointer;
- }
- .add-cancel {
- margin-left: 12px;
- color: #1d1d1d;
- font-size: 14px;
- line-height: 22px;
- cursor: pointer;
- }
- ::v-deep {
- .add-input {
- flex: 1;
- .el-input__inner {
- padding: 0 12px;
- height: 30px;
- line-height: 30px;
- color: #1d1d1d;
- }
- &.input-bg {
- background: #fff;
- .el-input__inner {
- background: #eaf8fa;
- }
- }
- }
- .add-btn {
- padding: 2px 0;
- span {
- margin-left: 0px;
- }
- }
- .el-input__count-inner {
- background: transparent !important;
- }
- .already-count {
- color: $color_main;
- }
- }
- &.disabled {
- .group-list-container {
- background: #f5f6f7;
- }
- .add-btn {
- color: #999999;
- }
- .group-item {
- &:hover {
- .item-edit {
- display: none;
- }
- }
- }
- .item-edit-container {
- background: #fff;
- }
- .item-name-container,
- .add-btn {
- pointer-events: none;
- cursor: not-allowed;
- }
- .item-name {
- color: #999999;
- }
- .j-radio {
- background-image: url('~@/assets/images/icon/radio_default_disabled.png');
- &.r-checked {
- background-image: url('~@/assets/images/icon/radio_checked_disabled2.png');
- }
- }
- .j-checkbox {
- background-image: url('~@/assets/images/icon/checkbox_default_disabled.png');
- &.checked {
- background-image: url('~@/assets/images/icon/checkbox_checked_disabled.png');
- }
- }
- }
- }
- </style>
|