Initial commit

This commit is contained in:
danshihao
2024-06-11 15:39:01 +08:00
commit 00acf31aa3
1589 changed files with 520803 additions and 0 deletions
@@ -0,0 +1,143 @@
<template>
<div class="selection-wrapper">
<div class="box-title-text">
<a-input class="box-input"
:value="nameStr || value"
:title="value"
disabled
:max-length="500"
:placeholder="placeholder">
<a-icon v-if="(nameStr || value) && !disabled" slot="suffix" class="close-icon" type="close-circle" theme="filled" @click="clearInput" />
</a-input>
<a-button v-if="!disabled" type="primary" class="button-box" @click="clauseClick">
{{ $t('clauseSelect.selectClause') }}
</a-button>
</div>
<clause-selection-modal ref="clauseSelectionModal"
v-bind="$attrs"
:value="value"
:info-id="infoId"
@change="modalInput"
@nameChange="modalNameChange"
@listChange="modalListChange"></clause-selection-modal>
</div>
</template>
<script>
import ClauseSelectionModal from './ClauseSelectionModal'
export default {
name: 'ClauseSelection',
components: { ClauseSelectionModal },
props: {
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
// 是否只能选择
selectOnly: {
type: Boolean,
required: false,
default: false
},
// 自定义点击标准选择按钮的事件
customClickFunc: {
type: Function
},
// 回显内容的字符串
nameStr: {
type: String,
required: false,
default: null
},
// 标准拆分id
infoId: {
type: String,
required: false,
default: ''
}
},
methods: {
// 点击选择条款按钮
clauseClick () {
if (!this.infoId) {
this.$message.warning(this.$t('clauseSelect.pleaseSelectStandard'))
return
}
if (this.customClickFunc && typeof this.customClickFunc === 'function') {
this.customClickFunc(() => {
this.$refs.clauseSelectionModal.open()
})
return
}
this.$refs.clauseSelectionModal.open()
},
// 清空输入框
clearInput () {
console.log('输入框清空了')
this.$emit('change', '')
this.$emit('nameChange', '')
this.$emit('listChange', [])
},
// 输入框输入监听
indexClick (event) {
this.$emit('change', event.target.value)
},
modalInput (value) {
this.$emit('change', value)
},
modalNameChange (value) {
this.$emit('nameChange', value)
},
modalListChange (value) {
this.$emit('listChange', value)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
@import '~@assets/less/common.less';
.selection-wrapper {
height: 40px;
line-height: 40px;
}
.box-title-text {
height: 100%;
display: flex;
align-items: center;
.box-input {
width: 100%;
}
.button-box {
margin-left: 10px;
}
}
.close-icon {
font-size: 12px;
color: rgba(0, 0, 0, 0.25);
transition: color 0.3s;
}
.close-icon:hover {
color: rgba(0, 0, 0, 0.45);
}
</style>
@@ -0,0 +1,275 @@
<template>
<a-drawer
:title="$t('clauseSelect.selectClause')"
:maskClosable="false"
:width="1000"
placement="right"
:closable="true"
@close="handleCancel"
:visible="visible"
class="custom-drawer-style">
<div class="custom-drawer-style-scroll">
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :sm="8">
<a-form-item :label="$t('clauseSelect.clauseNumber')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('clauseSelect.clauseNumber')"
v-model="queryParam.item_num"></a-input>
</a-form-item>
</a-col>
<a-col :sm="8">
<a-form-item :label="$t('clauseSelect.clauseName')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('clauseSelect.clauseName')"
v-model="queryParam.item_title"></a-input>
</a-form-item>
</a-col>
<div style="float: right;overflow: hidden;margin-right: 41px;margin-bottom: 20px"
class="table-page-search-submitButtons">
<a-button style="margin-left: 8px" type="primary" icon="search" @click="searchQuery">{{ $t('query') }}</a-button>
<a-button style="margin-left: 8px" type="primary" ghost icon="reload" @click="searchReset">{{ $t('reset') }}</a-button>
</div>
</a-row>
</a-form>
</div>
<a-table
:columns="columns"
rowKey="id"
:scroll="{x: 900}"
:data-source="dataList"
:pagination="ipagination"
:row-selection="{ type: type, selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
:loading="loading"
@change="handleTableChange">
<template slot="text" slot-scope="text">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
<!-- 条款内容 -->
<template v-slot:clauseContent="text, record">
<div class="table-text can-click-table-text" v-if="text || text === 0" @click="showContent('item_content', text,record)">
{{ text && text !== 'null' ? text.replace(/<.*?>/ig, ' ') : '' }}
</div>
<div class="table-text" v-else>{{ global.emptyLine }}</div>
</template>
</a-table>
</div>
<div class="custom-drawer-style-bottom-btn">
<a-button @click="handleCancel">{{ $t('cancel') }}</a-button>
<a-button @click="handleSubmit" type="primary" :loading="confirmLoading">{{ $t('submit') }}</a-button>
</div>
<!--条文内容-->
<split-clause-detail ref="splitClauseDetail" />
</a-drawer>
</template>
<script>
import { getClauseListByStandardInfoId } from '../../api/api'
import SplitClauseDetail from '../../views/documentTool/documentSplit/modules/SplitClauseDetail'
export default {
name: 'ClauseSelectionModal',
components: { SplitClauseDetail },
props: {
value: {
type: String,
default: ''
},
type: {
type: String,
required: false,
default: 'checkbox'
},
// 标准拆分id
infoId: {
type: String,
required: false,
default: ''
}
},
data () {
return {
visible: false,
confirmLoading: false,
labelCol: {
sm: 8
},
wrapperCol: {
sm: 14
},
selectedRowKeys: [],
selectedRowList: [],
loading: false,
queryParam: {},
/* 分页参数 */
ipagination: {
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '30', '50', '100', '150', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
columns: [
{ // 条款号
title: this.$t('clauseSelect.clauseNumber'),
dataIndex: 'item_num',
align: 'center',
width: 150,
scopedSlots: { customRender: 'text' }
},
{ // 条款名称
title: this.$t('clauseSelect.clauseName'),
dataIndex: 'item_title',
align: 'center',
width: 150,
scopedSlots: { customRender: 'text' }
},
{ // 条款内容
title: this.$t('clauseSelect.clauseContent'),
dataIndex: 'item_content',
align: 'center',
width: 150,
scopedSlots: { customRender: 'clauseContent' }
}
],
dataList: [],
filters: {}
}
},
methods: {
open () {
this.visible = true
this.queryParam = {}
if (this.infoId) {
this.filters.info_id = this.infoId
}
this.replacePage()
},
// 获取表格数据
replacePage (arg) {
if (arg === 1) {
this.ipagination.current = 1
}
const query = {
...this.queryParam,
...this.filters,
pageNo: this.ipagination.current,
pageSize: this.ipagination.pageSize
}
// this.selectedRowKeys = []
this.loading = true
getClauseListByStandardInfoId(query).then((res) => {
if (res.success) {
this.dataList = res.result.records
this.ipagination.total = res.result.total
this.selectedRowKeys = this.value ? this.value.split(',').map(item => item.trim()) : (this.selectedRowKeys || [])
} else {
this.dataList = []
}
}).finally(() => {
this.loading = false
})
},
searchQuery () {
this.replacePage(1)
},
searchReset () {
this.queryParam = {}
this.replacePage(1)
},
// 表格选择改变
onSelectChange (selectedRowKeys, selectedRows) {
this.selectedRowKeys = selectedRowKeys
// this.selectedRowList = row
if (this.type === 'checkbox') {
if (selectedRowKeys.length > this.selectedRowList.length) {
// 说明是增加了数据
for (const rowIndex in selectedRows) {
if (!this.selectedRowList.find(item => item.id === selectedRows[rowIndex].id)) {
// 不存在,追加
this.selectedRowList.push(selectedRows[rowIndex])
}
}
} else {
// 说明是删除了数据
if (selectedRowKeys && selectedRowKeys.length > 0) {
// 没有选中数据,说明这一页没有选中数据了
for (let i = 0; i < this.selectedRowList.length; i++) {
if (!selectedRowKeys.find(item => item === this.selectedRowList[i].id)) {
// 表格选中中没有找到这一条数据,说明已经被删了
this.selectedRowList.splice(i, 1)
i--
}
}
} else {
this.selectedRowList = []
}
}
console.log(this.selectedRowList)
} else {
this.selectedRowList = selectedRows
}
},
handleTableChange (pagination) {
// 分页、排序、筛选变化时触发
this.ipagination = pagination
this.replacePage()
},
handleCancel () {
this.close()
},
handleSubmit () {
const itemNumArr = []
if (this.selectedRowKeys && this.selectedRowKeys.length > 0) {
this.selectedRowList.forEach(res => {
itemNumArr.push(res.item_num)
})
this.$emit('change', this.selectedRowKeys.join(','))
this.$emit('nameChange', itemNumArr.join(','))
this.$emit('listChange', this.selectedRowList)
this.close()
} else {
this.$message.warning(this.$t('selectLeastOne'))
}
},
close () {
this.visible = false
this.selectedRowKeys = []
this.ipagination = {
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '30', '50', '100', '150', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
}
},
// 点击条款内容
showContent (fieldName, val) {
const title = (this.columns.find(tt => tt.dbFieldName === fieldName) || {}).dbFieldTxt
if (title) {
this.$refs.splitClauseDetail.title = title
}
this.$refs.splitClauseDetail.open(val)
}
}
}
</script>
<style scoped lang="less">
@import '~@assets/less/common.less';
</style>
@@ -0,0 +1,80 @@
<template>
<div class="selection-wrapper">
<div class="box-title-text">
<a-input class="box-input" :value="standardNumber" :title="standardNumber" @click="standardClick"
disabled readonly :placeholder="placeholder"/>
<a-button v-if="!disabled" type="primary" class="button-box" @click="standardClick">
{{ $t('enterprisePlanSelect.title')}}
</a-button>
</div>
<enterprise-plan-selection-modal ref="enterprisePlanSelectionModal" v-bind="$attrs" :value="value" @change="modalChange" @standardNumberChange="standardNumberChange" @listChange="modalListChange"></enterprise-plan-selection-modal>
</div>
</template>
<script>
import EnterprisePlanSelectionModal from './EnterprisePlanSelectionModal'
export default {
name: 'EnterprisePlanSelection',
components: { EnterprisePlanSelectionModal },
props: {
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
standardNumber: {
type: String,
default: ''
}
},
methods: {
// 点击选择标准按钮
standardClick () {
this.$refs.enterprisePlanSelectionModal.open()
},
modalChange (value) {
this.$emit('change', value)
},
standardNumberChange (value) {
this.$emit('standardNumberChange', value)
},
modalListChange (value) {
this.$emit('listChange', value)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
.selection-wrapper {
height: 40px;
line-height: 40px;
}
.box-title-text {
height: 100%;
display: flex;
align-items: center;
.box-input {
width: 100%;
}
/deep/ .ant-input-disabled {
background: #fff;
color: rgba(0, 0, 0, 0.65);
cursor: default;
}
.button-box {
margin-left: 10px;
}
}
</style>
@@ -0,0 +1,403 @@
<template>
<a-drawer
:title="$t('enterprisePlanSelect.title')"
:maskClosable="false"
:width="1000"
placement="right"
:closable="true"
@close="handleCancel"
:visible="visible"
class="custom-drawer-style">
<div class="custom-drawer-style-scroll">
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<!-- 原企标编号 -->
<a-col :span="8">
<a-form-item :label="$t('enterpriseStandardLibrary.plan.oldEnterpriseStandardNum')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('enterpriseStandardLibrary.plan.oldEnterpriseStandardNum')" v-model="queryParam.originEnStandardNo"></a-input>
</a-form-item>
</a-col>
<!-- 原企标名称 -->
<a-col :span="8">
<a-form-item :label="$t('enterpriseStandardLibrary.plan.oldEnterpriseStandardName')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('enterpriseStandardLibrary.plan.oldEnterpriseStandardName')" v-model="queryParam.originEnStandardName"></a-input>
</a-form-item>
</a-col>
<!-- 主起草人 -->
<a-col :span="8">
<a-form-item :label="$t('enterpriseStandardLibrary.plan.principalDrafter')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('enterpriseStandardLibrary.plan.principalDrafter')" v-model="queryParam.mainDraftingUser"></a-input>
</a-form-item>
</a-col>
<!-- 主起草单位 -->
<a-col :span="8">
<a-form-item :label="$t('enterpriseStandardLibrary.plan.mainDraftingUnit')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-tree-select
tree-node-filter-prop="title"
v-model="queryParam.mainDraftingUnit"
:maxTagCount="1"
:show-search="true"
:getPopupContainer="triggerNode=> triggerNode.parentNode"
class="box-input"
style="width: 100%"
:tree-data="categoryTreeList"
:placeholder="$t('pleaseSelect') + $t('enterpriseStandardLibrary.plan.mainDraftingUnit')"
/>
</a-form-item>
</a-col>
<!-- 主起草单位负责人 -->
<a-col :span="8">
<a-form-item :label="$t('enterpriseStandardLibrary.plan.headOfMainDraftingUnit')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('enterpriseStandardLibrary.plan.headOfMainDraftingUnit')" v-model="queryParam.mainDraftingUnitResponsiblePerson"></a-input>
</a-form-item>
</a-col>
<!-- 制修订类型 -->
<a-col :span="8">
<a-form-item :label="$t('enterpriseStandardLibrary.plan.revisionType')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<j-dict-select-tag
:placeholder="$t('pleaseEnter')+$t('enterpriseStandardLibrary.plan.revisionType')"
dict-code="esp_revision_type"
v-model="queryParam.revisionType">
</j-dict-select-tag>
</a-form-item>
</a-col>
<div style="float: right;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search" style="margin-left: 8px">{{ $t('query') }}</a-button>
<a-button type="primary" ghost @click="searchReset" icon="reload" style="margin-left: 8px">{{ $t('reset') }}</a-button>
</div>
</a-row>
</a-form>
</div>
<a-table
:columns="columns"
rowKey="id"
:scroll="{x: 900}"
:data-source="dataList"
:pagination="ipagination"
:row-selection="{ type: type, selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
:loading="loading"
@change="handleTableChange">
<template slot="text" slot-scope="text">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
<!-- 原企标编号/企标名称 -->
<template v-slot:toDetailOld="text, record">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<a v-if="text" class="link-a" @click="handleGoDetailOld(record)">{{ text }}</a>
<div v-else class="table-text">{{ global.emptyLine }}</div>
</a-tooltip>
</template>
<!-- 新企标编号/新企标名称 -->
<template v-slot:toDetailNew="text, record">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<a v-if="text && ['3', '5'].includes(record.projectStatus)" class="link-a" @click="handleGoDetailNew(record)">{{ text }}</a>
<div v-else-if="text" class="table-text">{{ text }}</div>
<div v-else class="table-text">{{ global.emptyLine }}</div>
</a-tooltip>
</template>
</a-table>
</div>
<div class="custom-drawer-style-bottom-btn">
<a-button @click="handleCancel">{{ $t('cancel') }}</a-button>
<a-button @click="handleSubmit" type="primary" :loading="confirmLoading">{{ $t('submit') }}</a-button>
</div>
</a-drawer>
</template>
<script>
import { getEnterpriseStandardPlanPage } from '@/api/enterpriseStandardLibraryApi'
import { queryDepartTreeList } from '@/api/api'
export default {
name: 'EnterprisePlanSelectionModal',
props: {
value: {
type: String,
default: ''
},
type: {
type: String,
required: false,
default: 'checkbox'
},
searchParam: { // 根据不同模块传入固定的查询参数
type: Object,
required: false,
default () {
return {}
}
}
},
data () {
return {
visible: false,
confirmLoading: false,
labelCol: {
sm: 8
},
wrapperCol: {
sm: 14
},
selectedRowKeys: [],
selectedRowList: [],
loading: false,
queryParam: {},
/* 分页参数 */
ipagination: {
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '30', '50', '100', '150', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
columns: [
{ // 制修订类型
title: this.$t('enterpriseStandardLibrary.plan.revisionType'),
align: 'center',
width: 180,
dataIndex: 'applicationCategory_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 原企标编号
title: this.$t('enterpriseStandardLibrary.plan.oldEnterpriseStandardNum'),
align: 'center',
width: 180,
dataIndex: 'originEnStandardNo',
scopedSlots: { customRender: 'toDetailOld' }
},
{ // 新企标编号
title: this.$t('enterpriseStandardLibrary.plan.newEnterpriseStandardNum'),
align: 'center',
width: 180,
dataIndex: 'newEnStandardNo',
scopedSlots: { customRender: 'toDetailNew' }
},
{ // 原企标名称
title: this.$t('enterpriseStandardLibrary.plan.oldEnterpriseStandardName'),
align: 'center',
width: 180,
dataIndex: 'originEnStandardName',
scopedSlots: { customRender: 'toDetailOld' }
},
{ // 新企标名称
title: this.$t('enterpriseStandardLibrary.plan.newEnterpriseStandardName'),
align: 'center',
width: 180,
dataIndex: 'newEnStandardName',
scopedSlots: { customRender: 'toDetailNew' }
},
{ // 授权部门
title: this.$t('enterpriseStandardLibrary.plan.authDepartment'),
align: 'center',
width: 180,
dataIndex: 'authDept_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 企业标准代号
title: this.$t('enterpriseStandardLibrary.plan.enterpriseStandardCode'),
align: 'center',
width: 180,
dataIndex: 'enStandardCode_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 配合单位
title: this.$t('enterpriseStandardLibrary.plan.suitUnit'),
align: 'center',
width: 180,
dataIndex: 'cooperationUnit_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 主起草人
title: this.$t('enterpriseStandardLibrary.plan.principalDrafter'),
align: 'center',
width: 180,
dataIndex: 'mainDraftingUser_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 主起草单位
title: this.$t('enterpriseStandardLibrary.plan.mainDraftingUnit'),
align: 'center',
width: 180,
dataIndex: 'mainDraftingUnit_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 主起草单位负责人
title: this.$t('enterpriseStandardLibrary.plan.headOfMainDraftingUnit'),
align: 'center',
width: 180,
dataIndex: 'mainDraftingUnitResponsiblePerson_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 标准推进人
title: this.$t('enterpriseStandardLibrary.plan.standardPusher'),
align: 'center',
width: 180,
dataIndex: 'standardPromoter_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 草稿计划完成日期
title: this.$t('enterpriseStandardLibrary.plan.draftPlanFinishDate'),
align: 'center',
width: 180,
dataIndex: 'draftPlannedCompleteDate',
scopedSlots: { customRender: 'specialDate' }
},
{ // 征求意见稿计划完成日期
title: this.$t('enterpriseStandardLibrary.plan.exposureDraftPlanFinishDate'),
align: 'center',
width: 200,
dataIndex: 'solicitationDraftPlanCompleteDate',
scopedSlots: { customRender: 'specialDate' }
},
{ // 计划报批日期
title: this.$t('enterpriseStandardLibrary.plan.planSubmissionDate'),
align: 'center',
width: 180,
dataIndex: 'planApprovalDate',
scopedSlots: { customRender: 'specialDate' }
},
{ // 项目状态
title: this.$t('enterpriseStandardLibrary.plan.projectStatus'),
align: 'center',
width: 180,
dataIndex: 'projectStatus_dictText',
scopedSlots: { customRender: 'text' }
}
],
dataList: [],
categoryTreeList: [] // 组织机构下拉框数据
}
},
mounted () {
this.getSysCategoryTree()
},
methods: {
open () {
this.visible = true
this.queryParam = {}
this.$nextTick(() => {
this.replacePage()
})
},
// 获取组织机构树
getSysCategoryTree () {
queryDepartTreeList().then((res) => {
if (res.success) {
this.categoryTreeList = res.result
} else {
this.categoryTreeList = []
}
})
},
// 企标编号,企标名称跳转详情,原企标
handleGoDetailOld (record) {
this.$openPageNewSheet({
path: '/enterpriseStandardLibrary/enterpriseStandardDetail',
query: {
standardNumber: record.originEnStandardNo
}
})
},
// 新企标点击跳转企标详情
handleGoDetailNew (record) {
this.$openPageNewSheet({
path: '/enterpriseStandardLibrary/enterpriseStandardDetail',
query: {
standardNumber: record.newEnStandardNo
}
})
},
// 获取表格数据
replacePage (arg) {
if (arg === 1) {
this.ipagination.current = 1
}
const query = {
...this.queryParam,
...this.searchParam,
pageNo: this.ipagination.current,
pageSize: this.ipagination.pageSize
}
this.selectedRowKeys = []
this.loading = true
getEnterpriseStandardPlanPage(query).then((res) => {
if (res.success) {
this.dataList = res.result.records
this.ipagination.total = res.result.total
this.selectedRowKeys = this.value.split(',')
} else {
this.dataList = []
}
}).finally(() => {
this.loading = false
})
},
handleTableChange (pagination) {
// 分页、排序、筛选变化时触发
this.ipagination = pagination
this.replacePage()
},
searchQuery () {
this.replacePage(1)
},
searchReset () {
this.queryParam = {}
this.replacePage(1)
},
// 表格选择改变
onSelectChange (value, row) {
this.selectedRowKeys = value
this.selectedRowList = row
},
handleCancel () {
this.close()
},
handleSubmit () {
if (this.selectedRowKeys && this.selectedRowKeys.length > 0) {
const standardNumberList = this.selectedRowList.map(item => item.originEnStandardNo)
this.$emit('change', this.selectedRowKeys.join(','))
this.$emit('standardNumberChange', standardNumberList.join(','))
this.$emit('listChange', this.selectedRowList)
this.close()
} else {
this.$message.warning(this.$t('selectLeastOne'))
}
},
close () {
this.visible = false
this.ipagination = {
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '30', '50', '100', '150', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
}
}
}
}
</script>
<style scoped lang="less">
@import '~@assets/less/common.less';
</style>
@@ -0,0 +1,80 @@
<template>
<div class="selection-wrapper">
<div class="box-title-text">
<a-input class="box-input" :value="standardNumber" :title="standardNumber" @click="standardClick"
disabled readonly :placeholder="placeholder"/>
<a-button v-if="!disabled" type="primary" class="button-box" @click="standardClick">
{{ $t('select') }}
</a-button>
</div>
<enterprise-recheck-plan-selection-modal ref="enterpriseRecheckPlanSelectionModal" v-bind="$attrs" :value="value" @change="modalChange" @standardNumberChange="standardNumberChange" @listChange="modalListChange"></enterprise-recheck-plan-selection-modal>
</div>
</template>
<script>
import EnterpriseRecheckPlanSelectionModal from './EnterpriseRecheckPlanSelectionModal'
export default {
name: 'EnterpriseRecheckPlanSelection',
components: { EnterpriseRecheckPlanSelectionModal },
props: {
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
standardNumber: {
type: String,
default: ''
}
},
methods: {
// 点击选择标准按钮
standardClick () {
this.$refs.enterpriseRecheckPlanSelectionModal.open()
},
modalChange (value) {
this.$emit('change', value)
},
standardNumberChange (value) {
this.$emit('standardNumberChange', value)
},
modalListChange (value) {
this.$emit('listChange', value)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
.selection-wrapper {
height: 40px;
line-height: 40px;
}
.box-title-text {
height: 100%;
display: flex;
align-items: center;
.box-input {
width: 100%;
}
/deep/ .ant-input-disabled {
background: #fff;
color: rgba(0, 0, 0, 0.65);
cursor: default;
}
.button-box {
margin-left: 10px;
}
}
</style>
@@ -0,0 +1,305 @@
<template>
<a-drawer
:title="$t('enterpriseRecheckPlanSelect.title')"
:maskClosable="false"
:width="1000"
placement="right"
:closable="true"
@close="handleCancel"
:visible="visible"
class="custom-drawer-style">
<div class="custom-drawer-style-scroll">
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<!-- 企标编号 -->
<a-col :span="8">
<a-form-item :label="$t('enterpriseStandardLibrary.reviewPlan.enterpriseStandardNum')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('enterpriseStandardLibrary.reviewPlan.enterpriseStandardNum')" v-model="queryParam.standardNo"></a-input>
</a-form-item>
</a-col>
<!-- 企标名称 -->
<a-col :span="8">
<a-form-item :label="$t('enterpriseStandardLibrary.reviewPlan.enterpriseStandardName')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('enterpriseStandardLibrary.reviewPlan.enterpriseStandardName')" v-model="queryParam.standardName"></a-input>
</a-form-item>
</a-col>
<!-- 主起草人 -->
<a-col :span="8">
<a-form-item :label="$t('enterpriseStandardLibrary.reviewPlan.principalDrafter')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('enterpriseStandardLibrary.reviewPlan.principalDrafter')" v-model="queryParam.mainDraftingUser"></a-input>
</a-form-item>
</a-col>
<!-- 主起草单位 -->
<a-col :span="8">
<a-form-item :label="$t('enterpriseStandardLibrary.reviewPlan.mainDraftingUnit')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-tree-select
tree-node-filter-prop="title"
v-model="queryParam.mainDraftingUnit"
:maxTagCount="1"
:show-search="true"
:getPopupContainer="triggerNode=> triggerNode.parentNode"
class="box-input"
style="width: 100%"
:tree-data="categoryTreeList"
:placeholder="$t('pleaseSelect') + $t('enterpriseStandardLibrary.reviewPlan.mainDraftingUnit')"
/>
</a-form-item>
</a-col>
<div style="float: right;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search" style="margin-left: 8px">{{ $t('query') }}</a-button>
<a-button type="primary" ghost @click="searchReset" icon="reload" style="margin-left: 8px">{{ $t('reset') }}</a-button>
</div>
</a-row>
</a-form>
</div>
<a-table
:columns="columns"
rowKey="id"
:scroll="{x: 900}"
:data-source="dataList"
:pagination="ipagination"
:row-selection="{ type: type, selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
:loading="loading"
@change="handleTableChange">
<template slot="text" slot-scope="text">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
<!-- 企标编号/企标名称 -->
<template v-slot:toDetail="text, record">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<a v-if="text" class="link-a" @click="handleGoDetail(record)">{{ text }}</a>
<div v-else class="table-text">{{ global.emptyLine }}</div>
</a-tooltip>
</template>
</a-table>
</div>
<div class="custom-drawer-style-bottom-btn">
<a-button @click="handleCancel">{{ $t('cancel') }}</a-button>
<a-button @click="handleSubmit" type="primary" :loading="confirmLoading">{{ $t('submit') }}</a-button>
</div>
</a-drawer>
</template>
<script>
import { queryDepartTreeList } from '@/api/api'
import { getEsRecheckPlanList } from '@/api/workCenter'
export default {
name: 'EnterpriseRecheckPlanSelectionModal',
props: {
value: {
type: String,
default: ''
},
type: {
type: String,
required: false,
default: 'checkbox'
},
searchParam: { // 根据不同模块传入固定的查询参数
type: Object,
required: false,
default () {
return {}
}
}
},
data () {
return {
visible: false,
confirmLoading: false,
labelCol: {
sm: 8
},
wrapperCol: {
sm: 14
},
selectedRowKeys: [],
selectedRowList: [],
loading: false,
queryParam: {},
/* 分页参数 */
ipagination: {
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '30', '50', '100', '150', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
columns: [
{ // 企标编号
title: this.$t('enterpriseStandardLibrary.reviewPlan.enterpriseStandardNum'),
align: 'center',
width: 180,
dataIndex: 'standardNo',
scopedSlots: { customRender: 'toDetail' }
},
{ // 企标名称
title: this.$t('enterpriseStandardLibrary.reviewPlan.enterpriseStandardName'),
align: 'center',
width: 180,
dataIndex: 'standardName',
scopedSlots: { customRender: 'toDetail' }
},
{ // 发布日期
title: this.$t('enterpriseStandardLibrary.reviewPlan.publishDate'),
align: 'center',
width: 180,
dataIndex: 'releaseDate',
scopedSlots: { customRender: 'text' }
},
{ // 复审日期
title: this.$t('enterpriseStandardLibrary.reviewPlan.reviewDate'),
align: 'center',
width: 180,
dataIndex: 'recheckDate',
scopedSlots: { customRender: 'reviewDate' }
},
{ // 复审结果
title: this.$t('enterpriseStandardLibrary.reviewPlan.reviewResult'),
align: 'center',
width: 180,
dataIndex: 'recheckResult_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 主起草人
title: this.$t('enterpriseStandardLibrary.reviewPlan.principalDrafter'),
align: 'center',
width: 180,
dataIndex: 'mainDraftingUser_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 主起草单位
title: this.$t('enterpriseStandardLibrary.reviewPlan.mainDraftingUnit'),
align: 'center',
width: 180,
dataIndex: 'mainDraftingUnit_dictText',
scopedSlots: { customRender: 'text' }
}
],
dataList: [],
categoryTreeList: [] // 组织机构下拉框数据
}
},
mounted () {
this.getSysCategoryTree()
},
methods: {
open () {
this.visible = true
this.queryParam = {}
this.$nextTick(() => {
this.replacePage()
})
},
// 获取组织机构树
getSysCategoryTree () {
queryDepartTreeList().then((res) => {
if (res.success) {
this.categoryTreeList = res.result
} else {
this.categoryTreeList = []
}
})
},
// 点击跳转企标详情
handleGoDetail (record) {
this.$openPageNewSheet({
path: '/enterpriseStandardLibrary/enterpriseStandardDetail',
query: {
standardNumber: record.standardNo
}
})
},
// 获取表格数据
replacePage (arg) {
if (arg === 1) {
this.ipagination.current = 1
}
const query = {
...this.queryParam,
...this.searchParam,
pageNo: this.ipagination.current,
pageSize: this.ipagination.pageSize
}
this.selectedRowKeys = []
this.loading = true
getEsRecheckPlanList(query).then((res) => {
if (res.success) {
this.dataList = res.result.records
this.ipagination.total = res.result.total
this.selectedRowKeys = this.value.split(',')
} else {
this.dataList = []
}
}).finally(() => {
this.loading = false
})
},
handleTableChange (pagination) {
// 分页、排序、筛选变化时触发
this.ipagination = pagination
this.replacePage()
},
searchQuery () {
this.replacePage(1)
},
searchReset () {
this.queryParam = {}
this.replacePage(1)
},
// 表格选择改变
onSelectChange (value, row) {
this.selectedRowKeys = value
this.selectedRowList = row
},
handleCancel () {
this.close()
},
handleSubmit () {
if (this.selectedRowKeys && this.selectedRowKeys.length > 0) {
const standardNumberList = this.selectedRowList.map(item => item.originEnStandardNo)
this.$emit('change', this.selectedRowKeys.join(','))
this.$emit('standardNumberChange', standardNumberList.join(','))
this.$emit('listChange', this.selectedRowList)
this.close()
} else {
this.$message.warning(this.$t('selectLeastOne'))
}
},
close () {
this.visible = false
this.ipagination = {
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '30', '50', '100', '150', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
}
}
}
}
</script>
<style scoped lang="less">
@import '~@assets/less/common.less';
</style>
@@ -0,0 +1,133 @@
<template>
<div class="selection-wrapper">
<div class="box-title-text">
<a-input class="box-input"
:value="nameStr || value"
:title="value"
@input="indexClick($event)"
:disabled="disabled || selectOnly"
:max-length="500"
:placeholder="placeholder">
<a-icon v-if="(nameStr || value) && !disabled" slot="suffix" class="close-icon" type="close-circle" theme="filled" @click="clearInput" />
</a-input>
<a-button v-if="!disabled" type="primary" class="button-box" @click="standardClick">
{{ $t('standardSelect.standardSelection') }}
</a-button>
</div>
<split-standard-selection-modal ref="standardSelectionModal"
v-bind="$attrs"
:value="value"
@change="modalInput"
@nameChange="modalNameChange"
@listChange="modalListChange"></split-standard-selection-modal>
</div>
</template>
<script>
import SplitStandardSelectionModal from './SplitStandardSelectionModal'
export default {
name: 'SplitStandardSelection',
components: { SplitStandardSelectionModal },
props: {
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
// 是否只能选择
selectOnly: {
type: Boolean,
required: false,
default: false
},
// 自定义点击标准选择按钮的事件
customClickFunc: {
type: Function
},
// 回显内容的字符串
nameStr: {
type: String,
required: false,
default: null
}
},
methods: {
// 点击选择标准按钮
standardClick () {
if (this.customClickFunc && typeof this.customClickFunc === 'function') {
this.customClickFunc(() => {
this.$refs.standardSelectionModal.open()
})
return
}
this.$refs.standardSelectionModal.open()
},
// 清空输入框
clearInput () {
console.log('输入框清空了')
this.$emit('change', '')
this.$emit('nameChange', '')
this.$emit('listChange', [])
},
// 输入框输入监听
indexClick (event) {
this.$emit('change', event.target.value)
},
modalInput (value) {
this.$emit('change', value)
},
modalNameChange (value) {
this.$emit('nameChange', value)
},
modalListChange (value) {
this.$emit('listChange', value)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
@import '~@assets/less/common.less';
.selection-wrapper {
height: 40px;
line-height: 40px;
}
.box-title-text {
height: 100%;
display: flex;
align-items: center;
.box-input {
width: 100%;
}
.button-box {
margin-left: 10px;
}
}
.close-icon {
font-size: 12px;
color: rgba(0, 0, 0, 0.25);
transition: color 0.3s;
}
.close-icon:hover {
color: rgba(0, 0, 0, 0.45);
}
</style>
@@ -0,0 +1,353 @@
<template>
<a-drawer
:title="$t('standardSelect.standardSelection')"
:maskClosable="false"
:width="1000"
placement="right"
:closable="true"
@close="handleCancel"
:visible="visible"
class="custom-drawer-style">
<div class="custom-drawer-style-scroll">
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :sm="8">
<a-form-item :label="$t('standardSelect.source')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<j-dict-select-tag style="width: 100%" v-model="queryParam.standardType"
:disabled="disabledSourceSearch"
:placeholder="$t('pleaseSelect')+$t('standardSelect.source')"
:triggerChange="false"
:options="sourceOptions"
@change="handleTypeChange" />
</a-form-item>
</a-col>
<a-col :sm="8">
<a-form-item :label="$t('standardSelect.standardNumOrName')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('standardSelect.standardNumOrName')"
v-model="queryParam.standardName"></a-input>
</a-form-item>
</a-col>
<div style="float: right;overflow: hidden;margin-right: 41px;margin-bottom: 20px"
class="table-page-search-submitButtons">
<a-button style="margin-left: 8px" type="primary" icon="search" @click="searchQuery">{{ $t('query') }}</a-button>
<a-button style="margin-left: 8px" type="primary" ghost icon="reload" @click="searchReset">{{ $t('reset') }}</a-button>
</div>
</a-row>
</a-form>
</div>
<a-table
:columns="columns"
rowKey="standardNumber"
:scroll="{x: 900}"
:data-source="dataList"
:pagination="ipagination"
:row-selection="{ type: type, selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
:loading="loading"
@change="handleTableChange">
<template slot="text" slot-scope="text">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
<!-- 企标编号/企标名称 -->
<template v-slot:toDetail="text, record">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<a v-if="text" class="link-a" @click="handleGoDetail(record)">{{ text }}</a>
<div v-else class="table-text">{{ global.emptyLine }}</div>
</a-tooltip>
</template>
<!-- 标准状态 -->
<template slot="standardState" slot-scope="text, record">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ record.standardType === '3' ? (record.esStandardState_dictText || global.emptyLine) : (record.standardState_dictText || global.emptyLine) }}</template>
<div class="table-text">{{ record.standardType === '3' ? (record.esStandardState_dictText || global.emptyLine) : (record.standardState_dictText || global.emptyLine) }}</div>
</a-tooltip>
</template>
</a-table>
</div>
<div class="custom-drawer-style-bottom-btn">
<a-button @click="handleCancel">{{ $t('cancel') }}</a-button>
<a-button @click="handleSubmit" type="primary" :loading="confirmLoading">{{ $t('submit') }}</a-button>
</div>
</a-drawer>
</template>
<script>
import JDictSelectTag from '../dict/JDictSelectTag'
import { StandardSource } from '../../enums/commonEnums'
import { ajaxGetDictItems, getSplitStandardList } from '../../api/api'
export default {
name: 'SplitStandardSelectionModal',
components: { JDictSelectTag },
props: {
source: {
type: [String, Number],
default: '1'
},
// 查询条件可以选择的类型
canSelectedSource: {
type: [String, Array],
required: false,
default: () => {
return [StandardSource.DOMESTIC.value, StandardSource.OVERSEAS.value, StandardSource.ENTERPRISE.value]
}
},
value: {
type: String,
default: ''
},
// 搜索条件中的来源是否不可更改
disabledSourceSearch: {
type: Boolean,
default: false
},
type: {
type: String,
required: false,
default: 'checkbox'
},
// 列表数据不包含的标准
excludeStandardNumbers: {
type: String,
required: false,
default: null
},
// 过滤条件
filters: {
type: Object,
required: false,
default: () => {
return {}
}
}
},
data () {
return {
visible: false,
confirmLoading: false,
labelCol: {
sm: 8
},
wrapperCol: {
sm: 14
},
selectedRowKeys: [],
selectedRowList: [],
loading: false,
queryParam: {},
/* 分页参数 */
ipagination: {
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '30', '50', '100', '150', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
columns: [
{
title: this.$t('standardNumber'),
dataIndex: 'standardNumber',
ellipsis: true,
align: 'center',
width: 150,
scopedSlots: { customRender: 'toDetail' }
},
{
title: this.$t('standardName'),
dataIndex: 'standardName',
ellipsis: true,
align: 'center',
width: 150,
scopedSlots: { customRender: 'toDetail' }
},
// 发布日期
{
title: this.$t('standardSelect.releaseDate'),
dataIndex: 'releaseDate',
align: 'center',
width: 120,
scopedSlots: { customRender: 'text' }
},
{
title: this.$t('standardSelect.textState'),
dataIndex: 'standardState_dictText',
align: 'center',
width: 150,
scopedSlots: { customRender: 'standardState' }
}
],
dataList: [],
sourceOptions: []
}
},
methods: {
open () {
this.visible = true
this.queryParam = {}
this.initDict()
this.$nextTick(() => {
this.source ? this.queryParam.standardType = this.source : this.queryParam = {}
this.replacePage()
})
},
initDict () {
ajaxGetDictItems('standard_source').then(res => {
if (res.success) {
const canSelectedArr = typeof this.canSelectedSource === 'string' ? this.canSelectedSource.split(',') : this.canSelectedSource
this.sourceOptions = res.result.filter(tt => canSelectedArr.includes(tt.value))
}
})
},
// 获取表格数据
replacePage (arg) {
if (arg === 1) {
this.ipagination.current = 1
}
const query = {
...this.queryParam,
...this.filters,
pageNo: this.ipagination.current,
pageSize: this.ipagination.pageSize
}
// 清空在可选范围内进行查询
if (!query.standardType && this.canSelectedSource.length < 3) {
query.standardType = this.canSelectedSource.join(',')
}
// this.selectedRowKeys = []
this.loading = true
getSplitStandardList(query).then((res) => {
if (res.success) {
this.dataList = res.result.records
this.ipagination.total = res.result.total
this.selectedRowKeys = this.value ? this.value.split(',') : (this.selectedRowKeys || [])
} else {
this.dataList = []
}
}).finally(() => {
this.loading = false
})
},
searchQuery () {
this.replacePage(1)
},
searchReset () {
// 如果禁用来源,就不重置来源
if (this.disabledSourceSearch) {
this.queryParam = { standardType: this.source }
} else {
this.queryParam = {}
}
this.replacePage(1)
},
// 表格选择改变
onSelectChange (selectedRowKeys, selectedRows) {
this.selectedRowKeys = selectedRowKeys
// this.selectedRowList = row
if (this.type === 'checkbox') {
if (selectedRowKeys.length > this.selectedRowList.length) {
// 说明是增加了数据
for (const rowIndex in selectedRows) {
if (!this.selectedRowList.find(item => item.standardNumber === selectedRows[rowIndex].standardNumber)) {
// 不存在,追加
this.selectedRowList.push(selectedRows[rowIndex])
}
}
} else {
// 说明是删除了数据
if (selectedRowKeys && selectedRowKeys.length > 0) {
// 没有选中数据,说明这一页没有选中数据了
for (let i = 0; i < this.selectedRowList.length; i++) {
if (!selectedRowKeys.find(item => item === this.selectedRowList[i].standardNumber)) {
// 表格选中中没有找到这一条数据,说明已经被删了
this.selectedRowList.splice(i, 1)
i--
}
}
} else {
this.selectedRowList = []
}
}
console.log(this.selectedRowList)
} else {
this.selectedRowList = selectedRows
}
},
handleTableChange (pagination) {
// 分页、排序、筛选变化时触发
this.ipagination = pagination
this.replacePage()
},
handleCancel () {
this.close()
},
handleSubmit () {
const serialNumber = []
const serialNameArr = []
if (this.selectedRowKeys && this.selectedRowKeys.length > 0) {
this.selectedRowList.forEach(res => {
serialNumber.push(res.standardNumber)
serialNameArr.push(res.standardName)
})
this.$emit('change', this.selectedRowKeys.join(','))
this.$emit('nameChange', serialNameArr.join(','))
this.$emit('listChange', this.selectedRowList)
this.close()
} else {
this.$message.warning(this.$t('selectLeastOne'))
}
},
close () {
this.visible = false
this.selectedRowKeys = []
this.ipagination = {
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '30', '50', '100', '150', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
}
},
handleTypeChange () {
this.$forceUpdate()
},
// 点击跳转标准详情
handleGoDetail (record) {
let path = ''
// 需要先判断是哪种标准
if (record.standardType === '1') {
path = '/standardRegulationLibrary/DomesticStandardDetail'
} else if (record.standardType === '2') {
path = '/standardRegulationLibrary/OverseasStandardDetail'
} else if (record.standardType === '3') {
path = '/enterpriseStandardLibrary/enterpriseStandardDetail'
}
this.$openPageNewSheet({
path: path,
query: {
id: record.id
}
})
}
}
}
</script>
<style scoped lang="less">
@import '~@assets/less/common.less';
</style>
@@ -0,0 +1,133 @@
<template>
<div class="selection-wrapper">
<div class="box-title-text">
<a-input class="box-input"
:value="nameStr || value"
:title="value"
@input="indexClick($event)"
:disabled="disabled || selectOnly"
:max-length="500"
:placeholder="placeholder">
<a-icon v-if="(nameStr || value) && !disabled" slot="suffix" class="close-icon" type="close-circle" theme="filled" @click="clearInput" />
</a-input>
<a-button v-if="!disabled" type="primary" class="button-box" @click="standardClick">
{{ $t('standardSelect.standardSelection') }}
</a-button>
</div>
<standard-selection-modal ref="standardSelectionModal"
v-bind="$attrs"
:value="value"
@change="modalInput"
@nameChange="modalNameChange"
@listChange="modalListChange"></standard-selection-modal>
</div>
</template>
<script>
import StandardSelectionModal from './StandardSelectionModal'
export default {
name: 'StandardSelection',
components: { StandardSelectionModal },
props: {
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
// 是否只能选择
selectOnly: {
type: Boolean,
required: false,
default: false
},
// 自定义点击标准选择按钮的事件
customClickFunc: {
type: Function
},
// 回显内容的字符串
nameStr: {
type: String,
required: false,
default: null
}
},
methods: {
// 点击选择标准按钮
standardClick () {
if (this.customClickFunc && typeof this.customClickFunc === 'function') {
this.customClickFunc(() => {
this.$refs.standardSelectionModal.open()
})
return
}
this.$refs.standardSelectionModal.open()
},
// 清空输入框
clearInput () {
console.log('输入框清空了')
this.$emit('change', '')
this.$emit('nameChange', '')
this.$emit('listChange', [])
},
// 输入框输入监听
indexClick (event) {
this.$emit('change', event.target.value)
},
modalInput (value) {
this.$emit('change', value)
},
modalNameChange (value) {
this.$emit('nameChange', value)
},
modalListChange (value) {
this.$emit('listChange', value)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
@import '~@assets/less/common.less';
.selection-wrapper {
height: 40px;
line-height: 40px;
}
.box-title-text {
height: 100%;
display: flex;
align-items: center;
.box-input {
width: 100%;
}
.button-box {
margin-left: 10px;
}
}
.close-icon {
font-size: 12px;
color: rgba(0, 0, 0, 0.25);
transition: color 0.3s;
}
.close-icon:hover {
color: rgba(0, 0, 0, 0.45);
}
</style>
@@ -0,0 +1,354 @@
<template>
<a-drawer
:title="$t('standardSelect.standardSelection')"
:maskClosable="false"
:width="1000"
placement="right"
:closable="true"
@close="handleCancel"
:visible="visible"
class="custom-drawer-style">
<div class="custom-drawer-style-scroll">
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :sm="8">
<a-form-item :label="$t('standardSelect.source')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<j-dict-select-tag style="width: 100%" v-model="queryParam.source"
:disabled="disabledSourceSearch"
:placeholder="$t('pleaseSelect')+$t('standardSelect.source')"
:triggerChange="false"
:options="sourceOptions"
@change="handleTypeChange" />
</a-form-item>
</a-col>
<a-col :sm="8">
<a-form-item :label="$t('standardSelect.standardNumOrName')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('standardSelect.standardNumOrName')"
v-model="queryParam.standardNumberOrName"></a-input>
</a-form-item>
</a-col>
<div style="float: right;overflow: hidden;margin-right: 41px;margin-bottom: 20px"
class="table-page-search-submitButtons">
<a-button style="margin-left: 8px" type="primary" icon="search" @click="searchQuery">{{ $t('query') }}</a-button>
<a-button style="margin-left: 8px" type="primary" ghost icon="reload" @click="searchReset">{{ $t('reset') }}</a-button>
</div>
</a-row>
</a-form>
</div>
<a-table
:columns="columns"
rowKey="standardNumber"
:scroll="{x: 900}"
:data-source="dataList"
:pagination="ipagination"
:row-selection="{ type: type, selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
:loading="loading"
@change="handleTableChange">
<template slot="text" slot-scope="text">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
<!-- 企标编号/企标名称 -->
<template v-slot:toDetail="text, record">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<a v-if="text" class="link-a" @click="handleGoDetail(record)">{{ text }}</a>
<div v-else class="table-text">{{ global.emptyLine }}</div>
</a-tooltip>
</template>
<!-- 标准状态 -->
<template slot="standardState" slot-scope="text, record">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ record.source === '3' ? (record.esStandardState_dictText || global.emptyLine) : (record.standardState_dictText || global.emptyLine) }}</template>
<div class="table-text">{{ record.source === '3' ? (record.esStandardState_dictText || global.emptyLine) : (record.standardState_dictText || global.emptyLine) }}</div>
</a-tooltip>
</template>
</a-table>
</div>
<div class="custom-drawer-style-bottom-btn">
<a-button @click="handleCancel">{{ $t('cancel') }}</a-button>
<a-button @click="handleSubmit" type="primary" :loading="confirmLoading">{{ $t('submit') }}</a-button>
</div>
</a-drawer>
</template>
<script>
import { ajaxGetDictItems, getStandardList } from '@/api/api'
import JDictSelectTag from '../dict/JDictSelectTag'
import { StandardSource } from '../../enums/commonEnums'
export default {
name: 'StandardSelectionModal',
components: { JDictSelectTag },
props: {
source: {
type: [String, Number],
default: '1'
},
// 查询条件可以选择的类型
canSelectedSource: {
type: [String, Array],
required: false,
default: () => {
return [StandardSource.DOMESTIC.value, StandardSource.OVERSEAS.value, StandardSource.ENTERPRISE.value]
}
},
value: {
type: String,
default: ''
},
// 搜索条件中的来源是否不可更改
disabledSourceSearch: {
type: Boolean,
default: false
},
type: {
type: String,
required: false,
default: 'checkbox'
},
// 列表数据不包含的标准
excludeStandardNumbers: {
type: String,
required: false,
default: null
},
// 过滤条件
filters: {
type: Object,
required: false,
default: () => {
return {}
}
}
},
data () {
return {
visible: false,
confirmLoading: false,
labelCol: {
sm: 8
},
wrapperCol: {
sm: 14
},
selectedRowKeys: [],
selectedRowList: [],
loading: false,
queryParam: {},
/* 分页参数 */
ipagination: {
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '30', '50', '100', '150', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
columns: [
{
title: this.$t('standardNumber'),
dataIndex: 'standardNumber',
ellipsis: true,
align: 'center',
width: 150,
scopedSlots: { customRender: 'toDetail' }
},
{
title: this.$t('standardName'),
dataIndex: 'standardName',
ellipsis: true,
align: 'center',
width: 150,
scopedSlots: { customRender: 'toDetail' }
},
// 发布日期
{
title: this.$t('standardSelect.releaseDate'),
dataIndex: 'releaseDate',
align: 'center',
width: 120,
scopedSlots: { customRender: 'text' }
},
{
title: this.$t('standardSelect.textState'),
dataIndex: 'standardState_dictText',
align: 'center',
width: 150,
scopedSlots: { customRender: 'standardState' }
}
],
dataList: [],
sourceOptions: []
}
},
methods: {
open () {
this.visible = true
this.queryParam = {}
this.initDict()
this.$nextTick(() => {
this.source ? this.queryParam.source = this.source : this.queryParam = {}
this.replacePage()
})
},
initDict () {
ajaxGetDictItems('standard_source').then(res => {
if (res.success) {
const canSelectedArr = typeof this.canSelectedSource === 'string' ? this.canSelectedSource.split(',') : this.canSelectedSource
this.sourceOptions = res.result.filter(tt => canSelectedArr.includes(tt.value))
}
})
},
// 获取表格数据
replacePage (arg) {
if (arg === 1) {
this.ipagination.current = 1
}
const query = {
...this.queryParam,
...this.filters,
pageNo: this.ipagination.current,
pageSize: this.ipagination.pageSize,
excludeStandardNumbers: this.excludeStandardNumbers
}
// 清空在可选范围内进行查询
if (!query.source && this.canSelectedSource.length < 3) {
query.source = this.canSelectedSource.join(',')
}
// this.selectedRowKeys = []
this.loading = true
getStandardList(query).then((res) => {
if (res.success) {
this.dataList = res.result.records
this.ipagination.total = res.result.total
this.selectedRowKeys = this.value ? this.value.split(',') : (this.selectedRowKeys || [])
} else {
this.dataList = []
}
}).finally(() => {
this.loading = false
})
},
searchQuery () {
this.replacePage(1)
},
searchReset () {
// 如果禁用来源,就不重置来源
if (this.disabledSourceSearch) {
this.queryParam = { source: this.source }
} else {
this.queryParam = {}
}
this.replacePage(1)
},
// 表格选择改变
onSelectChange (selectedRowKeys, selectedRows) {
this.selectedRowKeys = selectedRowKeys
// this.selectedRowList = row
if (this.type === 'checkbox') {
if (selectedRowKeys.length > this.selectedRowList.length) {
// 说明是增加了数据
for (const rowIndex in selectedRows) {
if (!this.selectedRowList.find(item => item.standardNumber === selectedRows[rowIndex].standardNumber)) {
// 不存在,追加
this.selectedRowList.push(selectedRows[rowIndex])
}
}
} else {
// 说明是删除了数据
if (selectedRowKeys && selectedRowKeys.length > 0) {
// 没有选中数据,说明这一页没有选中数据了
for (let i = 0; i < this.selectedRowList.length; i++) {
if (!selectedRowKeys.find(item => item === this.selectedRowList[i].standardNumber)) {
// 表格选中中没有找到这一条数据,说明已经被删了
this.selectedRowList.splice(i, 1)
i--
}
}
} else {
this.selectedRowList = []
}
}
console.log(this.selectedRowList)
} else {
this.selectedRowList = selectedRows
}
},
handleTableChange (pagination) {
// 分页、排序、筛选变化时触发
this.ipagination = pagination
this.replacePage()
},
handleCancel () {
this.close()
},
handleSubmit () {
const serialNumber = []
const serialNameArr = []
if (this.selectedRowKeys && this.selectedRowKeys.length > 0) {
this.selectedRowList.forEach(res => {
serialNumber.push(res.standardNumber)
serialNameArr.push(res.standardName)
})
this.$emit('change', this.selectedRowKeys.join(','))
this.$emit('nameChange', serialNameArr.join(','))
this.$emit('listChange', this.selectedRowList)
this.close()
} else {
this.$message.warning(this.$t('selectLeastOne'))
}
},
close () {
this.visible = false
this.selectedRowKeys = []
this.ipagination = {
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '30', '50', '100', '150', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
}
},
handleTypeChange () {
this.$forceUpdate()
},
// 点击跳转标准详情
handleGoDetail (record) {
let path = ''
// 需要先判断是哪种标准
if (record.source === '1') {
path = '/standardRegulationLibrary/DomesticStandardDetail'
} else if (record.source === '2') {
path = '/standardRegulationLibrary/OverseasStandardDetail'
} else if (record.source === '3') {
path = '/enterpriseStandardLibrary/enterpriseStandardDetail'
}
this.$openPageNewSheet({
path: path,
query: {
id: record.id
}
})
}
}
}
</script>
<style scoped lang="less">
@import '~@assets/less/common.less';
</style>
@@ -0,0 +1,346 @@
<template>
<j-modal
:title="$t('userSelect.select')"
:width="width"
:visible="visible"
switchFullscreen
:maskClosable="false"
:confirmLoading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel">
<div class="modal-search-wrapper table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :span="10">
<a-form-item :label="$t('treeSelection.primaryNodeName')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter') + $t('treeSelection.primaryNodeName')" v-model="queryParam[searchField]" />
</a-form-item>
</a-col>
<a-col :span="8">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search" style="margin-left: 8px">
{{ $t('query') }}
</a-button>
<a-button type="primary" @click="searchReset" icon="reload" ghost>{{ $t('reset') }}</a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<div class="modal-content">
<a-table
:columns="columns"
rowKey="code"
bordered
:scroll="{x: '100%'}"
:data-source="dataSource"
:pagination="ipagination"
:row-selection="rowSelection"
:loading="confirmLoading"
:childrenColumnName="childrenFieldName"
@change="handleTableChange">
<template slot="text" slot-scope="text">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
</a-table>
</div>
<p class="modal-content-title">{{ $t('treeSelection.selectedData') }}</p>
<div v-if="dataSourceRight && dataSourceRight.length > 0" class="name-content">
<div v-for="(item, index) in dataSourceRight" :key="item.code" class="name-div">
{{ item.name }}
<a-icon type="close" @click="handleDelete(item, index)" />
</div>
</div>
<a-empty v-else />
</j-modal>
</template>
<script>
import { getAction, postAction } from '../../api/manage'
import { StandardSource } from '../../enums/commonEnums'
export default {
name: 'TreeSelectModal',
props: {
dictId: {
type: String,
required: false,
default: ''
},
type: {
type: String,
required: false,
default: 'checkbox'
},
// 是否校验必选
checkRequired: {
type: Boolean,
required: false,
default: false
},
// 获取数据的接口
optionsHref: {
type: String,
required: false,
default: ''
},
// 树形数据取值字段
childrenColumnName: {
type: String,
required: false,
default: 'childPartNameList'
},
// 标签库的限制,只能选第三级
isTagLibraryRestriction: {
type: Boolean,
required: false,
default: false
},
// 查询传的字段值
searchFieldName: {
type: String,
required: false,
default: 'nodeName'
}
},
computed: {
rowSelection () {
return {
selectedRowKeys: this.selectedRowKeys,
onChange: this.onSelectChange,
type: this.type,
getCheckboxProps: record => ({
props: {
disabled: this.isTagLibraryRestriction ? record.level + '' !== '3' : false
}
})
}
}
},
data () {
return {
width: 800,
visible: false,
confirmLoading: false,
queryParam: {},
labelCol: {
span: 8
},
wrapperCol: {
span: 16
},
dataSourceRight: [],
filters: {},
/* 分页参数 */
ipagination: {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30', '100', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + total + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
columns: [
{
title: this.$t('system.tag.name'),
dataIndex: 'name'
}
],
dataSource: [],
selectedRowKeys: [],
childrenFieldName: 'childPartNameList',
searchField: 'nodeName'
}
},
methods: {
open (values) {
// 处理零部件和标签的字段不一致的问题,默认的是零部件的
this.childrenFieldName = this.childrenColumnName || 'childPartNameList'
this.searchField = this.searchFieldName || 'nodeName'
this.visible = true
this.selectedRowKeys = values ? values.split(',') : []
this.loadData(1)
this.getSelectedList(values)
},
handleCancel () {
this.visible = false
},
close () {
this.visible = false
this.visible = false
this.dataSourceRight = []
this.selectedRowKeys = []
this.queryParam = {}
this.ipagination = {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30', '100', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
}
},
searchQuery () {
this.loadData(1)
},
searchReset () {
this.queryParam = {}
this.loadData(1)
},
loadData (arg) {
if (arg) {
this.ipagination.current = 1
}
this.confirmLoading = true
const params = Object.assign({}, this.queryParam, this.filters)
params.pageNo = this.ipagination.current
params.pageSize = this.ipagination.pageSize
getAction(this.optionsHref, params).then(res => {
if (res.success) {
this.dataSource = res.result.records || res.result
if (res.result.total) {
this.ipagination.total = res.result.total
} else {
this.ipagination.total = 0
}
}
}).finally(() => {
this.confirmLoading = false
})
},
onSelectChange (selectedRowKeys, selectedRows) {
this.selectedRowKeys = selectedRowKeys
if (this.type === 'checkbox') {
if (selectedRowKeys.length > this.dataSourceRight.length) {
// 说明是增加了数据
for (const rowIndex in selectedRows) {
if (!this.dataSourceRight.find(item => item.code === selectedRows[rowIndex].code)) {
// 右侧不存在,追加到右侧表格
this.dataSourceRight.push(selectedRows[rowIndex])
}
}
} else {
// 说明是删除了数据
if (selectedRowKeys && selectedRowKeys.length > 0) {
// 没有选中数据,说明这一页没有选中数据了
for (let i = 0; i < this.dataSourceRight.length; i++) {
if (!selectedRowKeys.find(item => item === this.dataSourceRight[i].code)) {
// 表格选中中没有找到这一条数据,说明已经被删了
this.dataSourceRight.splice(i, 1)
i--
}
}
} else {
this.dataSourceRight = []
}
}
} else {
this.dataSourceRight = selectedRows
}
},
handleTableChange (pagination) {
this.ipagination = pagination
this.loadData()
},
// 名字列表的删除
handleDelete (record, index) {
this.dataSourceRight.splice(index, 1)
this.selectedRowKeys = this.selectedRowKeys.filter(item => item !== record.code)
},
handleOk () {
if (this.checkRequired && (!this.selectedRowKeys || this.selectedRowKeys.length === 0)) {
this.$message.warning(this.$t('selectLeastOne'))
return
}
this.$emit('nameChange', this.dataSourceRight.map(item => item.name).join(','))
this.$emit('change', this.selectedRowKeys.filter(tt => !!tt).join(','))
this.close()
},
getSelectedList (codes) {
const params = {
selectNodeCodes: codes
}
let url
// 零部件
if (this.optionsHref === '/laws/standard/partName/') {
url = '/laws/standard/partName/echo'
} else if (this.optionsHref === '/laws/lawsLabelDatabase/queryTreeList') { // 标签库
url = '/laws/lawsLabelDatabase/queryByCodes'
}
if (!url) {
return
}
postAction(url, params).then(res => {
if (res.success) {
this.dataSourceRight = res.result || []
}
})
}
}
}
</script>
<style scoped lang="less">
.modal-content {
width: 100%;
display: flex;
justify-content: space-between;
&-left {
width: 58%;
}
&-right {
width: 40%;
}
&-title-div {
display: flex;
align-items: center;
height: 28px;
margin: 20px 0;
.modal-content-title {
color: #1D2129;
font-weight: 500;
margin-right: 12px;
margin-bottom: 0;
}
}
}
.name-content {
display: flex;
flex-wrap: wrap;
.name-div {
width: auto;
padding: 5px 16px;
margin-right: 12px;
margin-top: 8px;
background: rgba(213, 44, 38, 0.08);
border-radius: 4px 4px 4px 4px;
opacity: 1;
color: @primary-color;
white-space: nowrap;
/deep/ .anticon {
margin-left: 4px;
}
}
}
/deep/ .ant-form-item-label {
min-width: 70px !important;
}
</style>
+108
View File
@@ -0,0 +1,108 @@
<template>
<div class="user-organ-wrap">
<a-input
type="text"
v-bind="$attrs"
disabled
class="user-input"
:value="checkedValue"
@click="selectClick"
:title="checkedValue">
</a-input>
<a-button type="primary" class="button-box" @click="selectClick" :disabled="disabled">
{{ $t('userSelect.select') }}
</a-button>
<tree-select-modal ref="selectModal" v-bind="$attrs" @change="selectChange" @nameChange="nameChange" />
</div>
</template>
<script>
import TreeSelectModal from './TreeSelectModal'
import UserSelectModal from './UserSelectModal'
export default {
name: 'TreeSelection',
components: { UserSelectModal, TreeSelectModal },
props: {
disabled: {
type: Boolean,
required: false,
default: false
},
// 名字字符串
nameStr: {
type: String,
default: ''
},
// 修改的字段名
filedName: {
type: String,
default: ''
},
value: {
type: String,
default: () => {
return ''
}
}
},
watch: {
nameStr: {
immediate: true,
handler (val) {
console.log(val)
this.checkedValue = val
}
}
},
data () {
return {
checkedValue: ''
}
},
methods: {
selectClick () {
console.log(this.value)
this.$refs.selectModal.open(this.value)
},
selectChange (value) {
this.$emit('change', value)
},
nameChange (value) {
this.checkedValue = value
this.$emit('nameChange', value, this.filedName)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
.user-organ-wrap {
width: 100%;
position: relative;
display: flex;
align-items: center;
//height: 39.98px;
.user-input {
resize: none;
width: calc(100% - 70px);
}
// 因为需要加title,所以不能把鼠标事件去掉
/deep/ .ant-input-disabled {
background: #fff;
color: rgba(0, 0, 0, 0.65);
cursor: default;
}
.button-box {
margin-left: 5px;
}
}
</style>
@@ -0,0 +1,128 @@
<template>
<div>
<div class="user-organ-wrap">
<!-- <div @click="selectClick">-->
<!-- <div v-for="item in selectValue" :key="item.id">{{item.label}}</div>-->
<!-- </div>-->
<a-select
class="user-organ-select"
mode="multiple"
:open="false"
:showSearch="false"
:filterOption="false"
:placeholder="$t('pleaseSelect')"
:maxTagCount="1"
:value="checkedValue"
@click="selectClick"
>
<a-select-option v-for="(item) in selectOptions" :key="item.key">
{{ item.title }}
</a-select-option>
</a-select>
<a-button type="primary" class="button-box" @click="selectClick">
{{this.$t('userOrOrganSelect.select')}}
</a-button>
</div>
<user-organ-select-modal v-bind="$attrs" ref="selectModal" :selectType="selectType" @change="selectChange"></user-organ-select-modal>
</div>
</template>
<script>
import UserOrganSelectModal from './UserOrganSelectModal'
export default {
name: 'UserOrOrganSelection',
components: { UserOrganSelectModal },
props: {
disabled: {
type: Boolean,
default: false
},
selectType: {
type: String,
default: 'all'
},
placeholder: {
type: String,
default: ''
},
value: {
type: Object,
default: () => {
return {
organ: [],
user: []
}
}
}
},
mounted () {
this.selectOptions = this.value.organ.concat(this.value.user)
this.checkedValue = this.value.organ.concat(this.value.user).map(item => item.key)
},
data () {
return {
checkedValue: [],
selectOptions: [] // 下拉框数据,为了回显
}
},
methods: {
selectClick () {
this.$refs.selectModal.open()
},
selectChange (arrOne, arrTwo) {
console.log(arrOne, arrTwo)
if (this.selectType === 'all') {
this.selectOptions = arrOne.concat(arrTwo)
this.$emit('change', {
organ: arrOne,
user: arrTwo
})
} else {
this.selectOptions = arrOne
if (this.selectType === 'organ') {
this.$emit('change', {
organ: arrOne
})
} else {
this.$emit('change', {
user: arrOne
})
}
}
this.checkedValue = this.selectOptions.map(item => item.key)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
.user-organ-wrap {
width: 100%;
position: relative;
.user-organ-select {
width: calc(100% - 70px);
/deep/ .ant-select-selection--multiple {
height: 38px;
.ant-select-selection__rendered > ul > li {
margin-top: 6px;
}
}
/deep/ .ant-select-selection__rendered {
line-height: 38px;
height: 38px;
}
}
.button-box {
height: 38px;
margin-left: 5px;
position: absolute;
top: 0;
}
}
</style>
@@ -0,0 +1,559 @@
<template>
<a-modal
:title="$t('userOrOrganSelect.selectUserOrOrgan')"
:maskClosable="false"
:width="1000"
:closable="true"
@ok="handleOk"
@cancel="handleCancel"
:visible="visible">
<div class="modal-search-wrapper table-page-search-wrapper">
<a-form v-if="switchValue === 'organ'" layout="inline" @keyup.enter.native="searchQueryOrgan">
<a-row :gutter="24">
<a-col :sm="6">
<a-form-item :label="$t('organization')">
<a-tree-select
tree-node-filter-prop="title"
v-model="queryParamOrgan.departId"
:maxTagCount="1"
:show-search="true"
:getPopupContainer="triggerNode=> triggerNode.parentNode"
style="width: 100%"
:tree-data="categoryTreeList"
:placeholder="$t('pleaseSelect')"
/>
</a-form-item>
</a-col>
<span style="float: right;overflow: hidden;margin-right: 11px" class="table-page-search-submitButtons">
<a-button style="margin-left: 8px" @click="searchResetOrgan">{{$t('reset')}}</a-button>
<a-button style="margin-left: 8px" type="primary" @click="searchQueryOrgan">{{$t('query')}}</a-button>
</span>
</a-row>
</a-form>
<a-form v-if="switchValue === 'user'" layout="inline" @keyup.enter.native="searchQueryUser">
<a-row :gutter="24">
<a-col :sm="6">
<a-form-item :label="$t('user.workNo')">
<a-input :placeholder="$t('pleaseEnter')"
v-model="queryParamUser.username"></a-input>
</a-form-item>
</a-col>
<a-col :sm="6">
<a-form-item :label="$t('userOrOrganSelect.name')">
<a-input :placeholder="$t('pleaseEnter')"
v-model="queryParamUser.realname"></a-input>
</a-form-item>
</a-col>
<span style="float: right;overflow: hidden;margin-right: 11px" class="table-page-search-submitButtons">
<a-button style="margin-left: 8px" @click="searchResetUser">{{$t('reset')}}</a-button>
<a-button style="margin-left: 8px" type="primary" @click="searchQueryUser">{{$t('query')}}</a-button>
</span>
</a-row>
</a-form>
</div>
<div class="modal-content">
<div class="modal-content-left">
<div class="modal-content-title-div">
<p class="modal-content-title">选择</p>
<div class="table-operator-tab">
<a v-if="selectType === 'all' || selectType === 'organ'" class="switch-item" :class="switchValue === 'organ' ? 'table-operator-tab-active' : ''"
@click="switchChange('organ')">组织机构
</a>
<a v-if="selectType === 'all' || selectType === 'user'" class="switch-item" :class="switchValue === 'user' ? 'table-operator-tab-active' : ''"
@click="switchChange('user')">用户列表
</a>
</div>
</div>
<a-table
v-if="switchValue === 'organ'"
:columns="columnsOrgan"
rowKey="key"
bordered
:scroll="{x: 500}"
:data-source="dataSourceOrgan"
:pagination="ipaginationOrgan"
:row-selection="{ selectedRowKeys: selectedRowKeysOrgan, onChange: onSelectChangeOrgan, type: type }"
:loading="loadingLeft"
@change="organLeftTableChange">
</a-table>
<a-table
v-else-if="switchValue === 'user'"
:columns="columnsUser"
rowKey="id"
bordered
:scroll="{x: 500}"
:data-source="dataSourceUser"
:pagination="ipaginationUser"
:row-selection="{ selectedRowKeys: selectedRowKeysUser, onChange: onSelectChangeUser, type: type }"
:loading="loadingLeft"
@change="userLeftTableChange">
</a-table>
</div>
<div class="modal-content-right">
<div class="modal-content-title-div">
<p class="modal-content-title">选择</p>
</div>
<a-table
v-if="switchValue === 'organ'"
:columns="columnsOrganRight"
rowKey="key"
:pagination="false"
bordered
:scroll="{x: 300}"
:loading="loadingRight"
:data-source="dataSourceOrganRight">
<template slot="action" slot-scope="text, record, index">
<a @click="handleDeleteOrgan(record, index)" >{{ $t('delete') }}</a>
</template>
</a-table>
<a-table
v-else-if="switchValue === 'user'"
:columns="columnsOrganRight"
rowKey="id"
:pagination="false"
bordered
:scroll="{x: 300}"
:loading="loadingRight"
:data-source="dataSourceOrganRight">
<template slot="action" slot-scope="text, record, index">
<a @click="handleDeleteOrgan(record, index)" >{{ $t('delete') }}</a>
</template>
</a-table>
</div>
</div>
</a-modal>
</template>
<script>
import '@assets/less/common.less'
import { getAction } from '@/api/manage'
export default {
name: 'UserOrganSelectModal',
props: {
selectType: {
type: String,
default: 'all'
},
type: { // 是单选还是多选
type: String,
default: 'radio'
},
value: {
type: Object,
default: () => {
return {
organ: '',
user: ''
}
}
}
},
watch: {
value: {
immediate: true,
handler (val) {
if (this.selectType === 'all') {
if (val.organ && val.organ.length > 0) {
this.dataSourceOrganRight = val.organ
this.selectedRowKeysOrgan = val.organ.map(item => item.id)
}
if (val.user && val.user.length > 0) {
this.dataSourceUserRight = val.user
this.selectedRowKeysUser = val.user.map(item => item.id)
}
} else if (this.selectType === 'organ' && val.organ && val.organ.length > 0) {
this.dataSourceOrganRight = val.organ
this.selectedRowKeysOrgan = val.organ.map(item => item.id)
} else if (this.selectType === 'user' && val.user && val.user.length > 0) {
this.dataSourceUserRight = val.user
this.selectedRowKeysUser = val.user.map(item => item.id)
}
// if (val.organ) {
// this.loadOrganRight(val.organ, () => {
// if (val.user) {
// this.loadUserRight(val.user, () => {
// this.$emit('change', this.dataSourceOrganRight, this.dataSourceUserRight)
// })
// } else {
// this.$emit('change', this.dataSourceOrganRight, [])
// }
// })
// } else {
// this.loadUserRight(val.user, () => {
// this.$emit('change', [], this.dataSourceUserRight)
// })
// }
// } else if (this.selectType === 'organ') {
// this.loadOrganRight(val.organ, () => {
// this.$emit('change', this.dataSourceOrganRight)
// })
// } else if (this.selectType === 'user') {
// this.loadUserRight(val.user, () => {
// this.$emit('change', this.dataSourceUserRight)
// })
// }
}
}
},
data () {
return {
visible: false,
labelCol: {
sm: 4
},
wrapperCol: {
sm: 20
},
categoryTreeList: [], // 组织机构查询的组织机构树数据
switchValue: 'organ',
loadingLeft: false, // 左侧表的加载状态
loadingRight: false, // 右侧表的加载
// 组织机构左侧表相关数据
queryParamOrgan: {},
columnsOrgan: [
{
title: this.$t('organization'),
dataIndex: 'title',
align: 'center'
},
{
title: this.$t('userOrOrganSelect.secondLevel'),
dataIndex: 'secondLevel',
align: 'center'
},
{
title: this.$t('userOrOrganSelect.threeLevel'),
dataIndex: 'threeLevel',
align: 'center'
}
],
dataSourceOrgan: [],
selectedRowKeysOrgan: [],
selectedRowsOrgan: [],
ipaginationOrgan: {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
columnsOrganRight: [
{
title: this.$t('organization'),
dataIndex: 'title',
align: 'center'
},
{
title: this.$t('operation'),
dataIndex: 'action',
scopedSlots: { customRender: 'action' },
align: 'center'
}
],
dataSourceOrganRight: [],
// 用户相关数据
queryParamUser: {},
columnsUser: [
{
title: this.$t('user.workNo'),
dataIndex: 'username',
align: 'center'
},
{
title: this.$t('userOrOrganSelect.name'),
dataIndex: 'name',
align: 'center'
},
{
title: this.$t('role'),
dataIndex: 'role',
align: 'center'
},
{
title: this.$t('organization'),
dataIndex: 'organization',
align: 'center'
}
],
dataSourceUser: [],
selectedRowKeysUser: [],
selectedRowsUser: [],
ipaginationUser: {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
columnsUserRight: [
{
title: this.$t('userOrOrganSelect.name'),
dataIndex: 'title',
align: 'center'
},
{
title: this.$t('operation'),
dataIndex: 'action',
scopedSlots: { customRender: 'action' },
align: 'center'
}
],
dataSourceUserRight: [],
url: {
organList: '/sys/sysDepart/queryTreeList',
userList: '/sys/user/page'
}
}
},
mounted () {
if (this.selectType === 'all' || this.selectType === 'organ') {
this.switchValue = 'organ'
this.loadDataOrgan()
} else {
this.switchValue = 'user'
this.loadDataUser()
}
},
methods: {
open () {
this.visible = true
},
// switch改变
switchChange (value) {
this.switchValue = value
if (value === 'organ') {
this.loadDataOrgan()
} else {
this.loadDataUser()
}
},
/**
* 组织机构相关方法
*/
// 获取组织机构树
getSysCategoryTree () {
getAction(this.url.getSysCategoryTree, {}).then((res) => {
if (res.success) {
this.categoryTreeList = res.result
} else {
this.categoryTreeList = []
}
})
},
searchResetOrgan () {
this.queryParamOrgan = {}
this.loadDataOrgan()
},
searchQueryOrgan () {
this.loadDataOrgan()
},
// 获取组织机构左侧树列表
loadDataOrgan () {
const params = Object.assign({}, this.queryParamOrgan)
params.pageNo = this.ipaginationOrgan.current
params.pageSize = this.ipaginationOrgan.pageSize
this.loadingLeft = true
getAction(this.url.organList, params).then((res) => {
if (res.success) {
if (res.result.current > 1 && res.result.length === 0) {
this.ipaginationOrgan.current = res.result.current - 1
this.loadDataOrgan()
return
}
this.dataSourceOrgan = res.result.map(item => {
return {
key: item.key,
parentId: item.parentId,
title: item.title
}
}) || []
this.ipaginationOrgan.total = res.result.total
} else {
this.$message.warn(res.message)
}
}).finally(() => {
this.loadingLeft = false
})
},
// 组织机构左侧树的选择
onSelectChangeOrgan (selectedRowKeys, selectedRows) {
this.selectedRowKeysOrgan = selectedRowKeys
this.selectedRowsOrgan = selectedRows
if (this.type === 'checkbox') {
for (const rowIndex in selectedRows) {
if (!this.dataSourceOrganRight.find(item => item.key === selectedRows[rowIndex].key)) {
// 右侧不存在,追加到右侧表格
this.dataSourceOrganRight.push(selectedRows[rowIndex])
}
}
} else {
this.dataSourceOrganRight = selectedRows
}
},
// 组织结构左侧树的复选框状态
getCheckboxPropsOrgan (record) {
return {
disabled: this.selectedRowKeysOrgan.includes(record.id)
}
},
// 组织机构左侧表格改变
organLeftTableChange (pagination) {
this.ipaginationOrganLeft = pagination
this.loadDataOrgan()
},
// 组织机构右侧表的删除
handleDeleteOrgan (record, index) {
this.dataSourceOrganRight.splice(index, 1)
this.selectedRowKeysOrgan = this.selectedRowKeysOrgan.filter(item => item === record.id)
},
// 组织机构初始化右侧树列表
// loadOrganRight (ids, callback) {
// this.loadingRight = true
// getAction(this.url.organList, { ids: ids }).then((res) => {
// if (res.success) {
// this.dataSourceOrganRight = res.result.records || []
// callback && callback()
// } else {
// this.$message.warn(res.message)
// }
// }).finally(() => {
// this.loadingRight = false
// })
// },
/**
* 用户相关方法
*/
searchResetUser () {
this.queryParamUser = {}
this.loadDataUser()
},
searchQueryUser () {
this.loadDataUser()
},
// 获取用户左侧树列表
loadDataUser () {
const params = Object.assign({}, this.queryParamUser)
params.pageNo = this.ipaginationUser.current
params.pageSize = this.ipaginationUser.pageSize
this.loadingLeft = true
getAction(this.url.userList, params).then((res) => {
if (res.success) {
if (res.result.current > 1 && res.result.records.length === 0) {
this.ipaginationOrgan.current = res.result.current - 1
this.loadDataUser()
return
}
this.dataSourceUser = res.result.records || []
this.ipaginationUser.total = res.result.total
} else {
this.$message.warn(res.message)
}
}).finally(() => {
this.loadingLeft = false
})
},
// 用户左侧表的选择
onSelectChangeUser (selectedRowKeys, selectedRows) {
this.selectedRowKeysUser = selectedRowKeys
this.selectedRowsUser = selectedRows
if (this.type === 'checkbox') {
for (const rowIndex in selectedRows) {
if (!this.dataSourceUserRight.find(item => item.id === selectedRows[rowIndex].id)) {
// 右侧不存在,追加到右侧表格
this.dataSourceUserRight.push(selectedRows[rowIndex])
}
}
} else {
this.dataSourceUserRight = selectedRows
}
},
// 用户左侧表的复选框状态
getCheckboxPropsUser (record) {
return {
disabled: this.selectedRowKeysUser.includes(record.id)
}
},
// 用户左侧表格改变
userLeftTableChange (pagination) {
this.ipaginationUserLeft = pagination
this.loadDataUser()
},
// 用户右侧表的删除
handleDeleteUser (record, index) {
this.dataSourceUserRight.splice(index, 1)
this.selectedRowKeysUser = this.selectedRowKeysUser.filter(item => item === record.id)
},
// 用户初始化右侧树列表
// loadUserRight (ids, callback) {
// this.loadingRight = true
// getAction(this.url.userList, { ids: ids }).then((res) => {
// if (res.success) {
// this.dataSourceUserRight = res.result.records || []
// callback && callback()
// } else {
// this.$message.warn(res.message)
// }
// }).finally(() => {
// this.loadingRight = false
// })
// },
handleOk () {
if (this.selectType === 'all') {
this.$emit('change', this.dataSourceOrganRight, this.dataSourceUserRight)
} else if (this.selectType === 'organ') {
this.$emit('change', this.dataSourceOrganRight)
} else {
this.$emit('change', this.dataSourceUserRight)
}
this.visible = false
},
handleCancel () {
this.close()
},
close () {
this.visible = false
// this.dataSourceOrgan = []
// this.dataSourceUser = []
this.dataSourceOrganRight = []
this.dataSourceUserRight = []
this.selectedRowKeysOrgan = []
this.selectedRowKeysUser = []
}
}
}
</script>
<style scoped lang="less">
.modal-content {
width: 100%;
display: flex;
justify-content: space-between;
&-left {
width: 58%;
}
&-right {
width: 40%;
}
&-title-div {
display: flex;
align-items: center;
height: 28px;
margin: 20px 0;
.modal-content-title {
color: #1D2129;
font-weight: 500;
margin-right: 12px;
margin-bottom: 0;
}
}
}
</style>
@@ -0,0 +1,133 @@
<template>
<div>
<div class="user-organ-wrap">
<a-input
:type="inputType"
:autoSize="true"
:rows="1"
readOnly
:disabled="disabled"
:class="{
'input-readonly': !disabled,
'user-input': showBtn
}"
:placeholder="placeholder"
:value="checkedValue"
@click="selectClick"
:title="checkedValue"
>
</a-input>
<a-button type="primary" class="button-box" @click="selectClick" :disabled="disabled" v-if="showBtn && !disabled">
{{ $t('userSelect.select') }}
</a-button>
</div>
<user-select-by-contact-modal v-bind="$attrs" :nameStr="nameStr" ref="selectModal" @change="selectChange" @listChange="listChange" @nameChange="nameChange"></user-select-by-contact-modal>
</div>
</template>
<script>
import UserSelectByContactModal from './UserSelectByContactModal'
export default {
name: 'UserSelectByContact',
components: { UserSelectByContactModal },
props: {
disabled: {
type: Boolean,
default: false
},
placeholder: {
type: String,
default: ''
},
value: {
type: String,
default: () => {
return ''
}
},
// 名字字符串
nameStr: {
type: String,
default: ''
},
// 修改的字段名
filedName: {
type: [String, Number],
default: ''
},
// 回显输入框的类型,默认是input
inputType: {
type: String,
required: false,
default: 'text'
},
// 是否展示按钮
showBtn: {
type: Boolean,
required: false,
default: true
}
},
watch: {
nameStr: {
immediate: true,
handler (val) {
this.checkedValue = val
}
}
},
data () {
return {
checkedValue: ''
}
},
methods: {
selectClick () {
// 禁用后不弹框
if (this.disabled) {
return
}
this.$refs.selectModal.open(this.value)
},
selectChange (ids) {
this.$emit('change', ids)
},
listChange (value) {
this.$emit('listChange', value)
},
nameChange (value) {
this.checkedValue = value
this.$emit('nameChange', value, this.filedName)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
.user-organ-wrap {
width: 100%;
position: relative;
display: flex;
align-items: center;
//height: 39.98px;
.user-input {
resize: none;
width: calc(100% - 70px);
}
// 因为需要加title,所以不能把鼠标事件去掉
/deep/ .input-readonly.ant-input-disabled {
background: #fff;
color: rgba(0, 0, 0, 0.65);
cursor: default;
}
.button-box {
margin-left: 5px;
}
}
</style>
@@ -0,0 +1,464 @@
<template>
<j-modal
:title="$t('userSelect.selectUser')"
:maskClosable="false"
:width="1000"
:closable="true"
centered
@ok="handleOk"
@cancel="handleCancel"
switchFullscreen
:visible="visible">
<div class="modal-search-wrapper table-page-search-wrapper search-wrap">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :span="6">
<a-form-item :label="$t('system.contact.departName')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<j-input :placeholder="$t('pleaseEnter')+$t('system.contact.departName')" v-model="queryParam.departName"></j-input>
</a-form-item>
</a-col>
<a-col :span="6">
<a-form-item :label="$t('system.contact.contactPerson')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('system.contact.contactPerson')" v-model="queryParam.contact"></a-input>
</a-form-item>
</a-col>
<span style="float: right;overflow: hidden;margin-right: 11px" class="table-page-search-submitButtons">
<a-button style="margin-left: 8px" type="primary" icon="search" @click="searchQuery">{{$t('query')}}</a-button>
<a-button style="margin-left: 8px" type="primary" ghost icon="reload" @click="searchReset">{{$t('reset')}}</a-button>
</span>
</a-row>
</a-form>
<!-- 全选所有 -->
<a-checkbox v-if="type === 'checkbox'" v-model="isCheckedAll" class="modal-title-check" @change="checkedAllChange">{{ $t('checkedAll') }}</a-checkbox>
</div>
<div class="modal-content">
<a-table
:columns="columns"
rowKey="contactId"
bordered
:scroll="{x: '100%', y: '280px'}"
:data-source="dataSource"
:pagination="ipagination"
:row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange, type: type }"
:loading="loadingLeft"
@change="leftTableChange">
<template slot="text" slot-scope="text">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
</a-table>
</div>
<p class="modal-content-title">{{ $t('userSelect.selectedPersonnel') }}</p>
<div v-if="dataSourceRight && dataSourceRight.length > 0" class="name-content">
<div v-for="(item, index) in dataSourceRight" :key="item.contactId" class="name-div">
{{ item.contactId_dictText }}
<a-icon type="close" @click="handleDelete(item, index)" />
</div>
</div>
<a-empty v-else/>
</j-modal>
</template>
<script>
import { getAction, postAction } from '@/api/manage'
export default {
name: 'UserSelectByContactModal',
props: {
type: { // 是单选还是多选
type: String,
default: 'radio'
},
value: {
type: String,
default: () => {
return ''
}
},
// 是否校验必选
checkRequired: {
type: Boolean,
required: false,
default: true
}
},
watch: {
value: {
immediate: true,
handler (val) {
console.log(val)
if (val) {
this.selectedRowKeys = val ? val.split(',') : []
this.getUserListByIds(val)
}
}
},
dataSourceRight: {
immediate: true,
deep: true,
handler (val) {
console.log(this.currentQueryAllData, this.dataSourceRight)
const arrOne = this.currentQueryAllData.map(item => item.contactId)
const arrTwo = this.dataSourceRight.map(item => item.contactId)
const temp = []
for (const item of arrTwo) {
arrOne.includes(item) ? temp.push(item) : ''
}
if (val.length !== 0 && this.currentQueryAllData.length !== 0 && this.dataSourceRight.length >= this.ipagination.total && temp.length === this.currentQueryAllData.length) {
// 选中数据长度等于当前表格总长度
this.isCheckedAll = true
} else {
this.isCheckedAll = false
}
}
},
currentQueryAllData: {
immediate: true,
deep: true,
handler (val) {
console.log(this.currentQueryAllData, this.dataSourceRight)
const arrOne = this.currentQueryAllData.map(item => item.contactId)
const arrTwo = this.dataSourceRight.map(item => item.contactId)
const temp = []
for (const item of arrTwo) {
arrOne.includes(item) ? temp.push(item) : ''
}
if (this.dataSourceRight.length !== 0 && this.currentQueryAllData.length !== 0 && this.dataSourceRight.length >= this.ipagination.total && temp.length === this.currentQueryAllData.length) {
// 选中数据长度等于当前表格总长度
this.isCheckedAll = true
} else {
this.isCheckedAll = false
}
}
},
queryParam: {
deep: true,
handler (val) {
this.isClickedSearch = false
}
}
},
data () {
return {
visible: false,
queryParam: {},
labelCol: {
span: 6
},
wrapperCol: {
span: 18
},
columns: [
{ // 部门名称
title: this.$t('system.contact.departName'),
align: 'center',
width: 180,
dataIndex: 'departId_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 标准化工程师
title: this.$t('system.contact.standardizationEngineer'),
align: 'center',
width: 180,
dataIndex: 'engineerId_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 联络人
title: this.$t('system.contact.contactPerson'),
align: 'center',
width: 180,
dataIndex: 'contactId_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 部门联络人主管级领导
title: this.$t('system.contact.contactPersonSupervisorLevelLeader'),
align: 'center',
width: 240,
dataIndex: 'leaderId_dictText',
scopedSlots: { customRender: 'text' }
}
],
dataSource: [],
ipagination: {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30', '100', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
selectedRowKeys: [],
loadingLeft: false,
dataSourceRight: [],
isCheckedAll: false, // 是否选中所有
url: {
userList: '/laws/system/lawsContactManage/pageMerge',
userListByIds: '/sys/user/queryByIds'
},
isClickedSearch: false, // 改完搜索条件是否点击过搜索
oldQueryParam: {}, // 上一次的搜索条件,用于从一个搜索条件改成另一个搜索条件,但是没有点搜索,这时候全选时传旧的搜索条件
oldTotal: 0,
currentQueryAllData: [] // 当前查询条件下的所有数据
}
},
methods: {
open (value) {
this.visible = true
// this.loadData()
if (value) {
this.selectedRowKeys = value.split(',')
this.getUserListByIds(value)
}
},
// 全选所有
checkedAllChange (e) {
console.log(e.target.checked)
if (e.target.checked) {
this.checkCurrentAll()
} else {
const field = 'contactId'
this.dataSourceRight = this.dataSourceRight.filter(item => !this.currentQueryAllData.some(i => i[field] === item[field]))
this.selectedRowKeys = JSON.parse(JSON.stringify(this.dataSourceRight)).map(item => item[field])
}
},
checkCurrentAll () {
this.loadingLeft = true
let params
if (this.isClickedSearch) {
// 点击过搜索了,传搜索条件
params = Object.assign({}, this.queryParam)
} else {
// 没点击过搜索,传旧的搜索条件
params = Object.assign({}, this.oldQueryParam)
}
params.pageNo = 1
params.pageSize = this.ipagination.total + 10
params.column = 'createTime'
params.order = 'desc'
getAction(this.url.userList, params).then(res => {
if (res.success) {
const arr = this.uniqueByKey([...res.result.records || [], ...this.dataSourceRight || []], 'contactId')
this.dataSourceRight = Array.from(arr)
this.selectedRowKeys = Array.from(arr).map(item => item.contactId)
}
}).finally(() => {
this.loadingLeft = false
})
},
// 根据某个字段对对象数组去重
uniqueByKey (arr, key) {
const map = arr.reduce((acc, obj) => {
const keyValue = obj[key]
acc[keyValue] = obj
return acc
}, {})
return Object.values(map)
},
// 获取当前查询条件的所有数据
async getCurrentAllData () {
const params = Object.assign({}, this.queryParam)
params.pageNo = 1
params.pageSize = 100000000
params.column = 'createTime'
params.order = 'desc'
await getAction(this.url.userList, params).then(res => {
if (res.success) {
this.currentQueryAllData = res.result.records || []
console.log('00000000000获取完当前所有数据了', this.currentQueryAllData)
}
})
},
searchReset () {
this.queryParam = {}
this.loadData()
},
searchQuery () {
this.isClickedSearch = true
this.loadData()
},
// 获取用户左侧树列表
async loadData () {
this.loadingLeft = true
if (this.type === 'checkbox') {
await this.getCurrentAllData()
}
const params = Object.assign({}, this.queryParam)
params.pageNo = this.ipagination.current
params.pageSize = this.ipagination.pageSize
params.column = 'createTime'
params.order = 'desc'
getAction(this.url.userList, params).then((res) => {
if (res.success) {
if (res.result.current > 1 && res.result.records.length === 0) {
this.ipagination.current = res.result.current - 1
this.loadData()
return
}
this.oldQueryParam = Object.assign({}, this.queryParam)
this.dataSource = res.result.records || []
this.ipagination.total = res.result.total
} else {
this.$message.warn(res.message)
}
}).finally(() => {
this.loadingLeft = false
})
},
// 表格选择
onSelectChange (selectedRowKeys, selectedRows) {
this.selectedRowKeys = selectedRowKeys
if (this.type === 'checkbox') {
if (selectedRowKeys.length > this.dataSourceRight.length) {
// 说明是增加了数据
for (const rowIndex in selectedRows) {
if (!this.dataSourceRight.find(item => item.contactId === selectedRows[rowIndex].contactId)) {
// 右侧不存在,追加到右侧表格
this.dataSourceRight.push(selectedRows[rowIndex])
}
}
} else {
// 说明是删除了数据
if (selectedRowKeys && selectedRowKeys.length > 0) {
// 没有选中数据,说明这一页没有选中数据了
for (let i = 0; i < this.dataSourceRight.length; i++) {
if (!selectedRowKeys.find(item => item === this.dataSourceRight[i].contactId)) {
// 表格选中中没有找到这一条数据,说明已经被删了
this.dataSourceRight.splice(i, 1)
i--
}
}
} else {
this.dataSourceRight = []
}
}
console.log(this.dataSourceRight)
} else {
this.dataSourceRight = selectedRows
}
},
// 左侧表格改变
leftTableChange (pagination) {
this.ipagination = pagination
this.loadData()
},
// 根据ids获取用户列表
getUserListByIds (ids) {
const params = {}
params.userIds = ids
this.loadingRight = true
postAction(this.url.userListByIds, params).then((res) => {
if (res.success) {
this.dataSourceRight = res.result.map(item => {
return {
contactId: item.id,
contactId_dictText: item.realname + '(' + item.username + ')'
}
}) || []
} else {
this.$message.warn(res.message)
}
}).finally(() => {
this.loadingRight = false
})
},
// 名字列表的删除
handleDelete (record, index) {
this.dataSourceRight.splice(index, 1)
this.selectedRowKeys = this.selectedRowKeys.filter(item => item !== record.contactId)
},
handleOk () {
if (this.checkRequired && (!this.selectedRowKeys || this.selectedRowKeys.length === 0)) {
if (this.type === 'radio') {
this.$message.warning(this.$t('docTool.split.pleaseSelectUser'))
} else {
this.$message.warning(this.$t('pleaseAtLeastSelectOneUser'))
}
return
}
this.$emit('nameChange', this.dataSourceRight.map(item => item.contactId_dictText).join(','))
this.$emit('change', this.selectedRowKeys.join(','))
this.$emit('listChange', this.dataSourceRight)
this.close()
},
handleCancel () {
this.close()
},
close () {
this.visible = false
this.dataSourceRight = []
this.selectedRowKeys = []
this.queryParam = {}
this.ipagination = {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30', '100', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
}
}
}
}
</script>
<style scoped lang="less">
.modal-title-check {
margin-left: 25px;
margin-bottom: 10px;
}
.modal-content {
width: 100%;
display: flex;
justify-content: space-between;
&-left {
width: 58%;
}
&-right {
width: 40%;
}
&-title-div {
display: flex;
align-items: center;
height: 28px;
margin: 20px 0;
.modal-content-title {
color: #1D2129;
font-weight: 500;
margin-right: 12px;
margin-bottom: 0;
}
}
}
.name-content {
display: flex;
flex-wrap: wrap;
max-height: 200px;
overflow-y: auto;
.name-div {
width: auto;
padding: 5px 16px;
margin-right: 12px;
margin-top: 8px;
background: rgba(213, 44, 38, 0.08);
border-radius: 4px 4px 4px 4px;
opacity: 1;
color: @primary-color;
white-space: nowrap;
/deep/ .anticon {
margin-left: 4px;
}
}
}
/deep/ .ant-form-item-label{
min-width: 70px !important;
}
</style>
@@ -0,0 +1,133 @@
<template>
<div>
<div class="user-organ-wrap">
<a-input
:type="inputType"
:autoSize="true"
:rows="1"
readOnly
:disabled="disabled"
:class="{
'input-readonly': !disabled,
'user-input': showBtn
}"
:placeholder="placeholder"
:value="checkedValue"
@click="selectClick"
:title="checkedValue"
>
</a-input>
<a-button type="primary" class="button-box" @click="selectClick" :disabled="disabled" v-if="showBtn && !disabled">
{{ $t('userSelect.select') }}
</a-button>
</div>
<user-select-by-contact-no-merge-modal v-bind="$attrs" :nameStr="nameStr" ref="selectModal" @change="selectChange" @listChange="listChange" @nameChange="nameChange"></user-select-by-contact-no-merge-modal>
</div>
</template>
<script>
import UserSelectByContactNoMergeModal from './UserSelectByContactNoMergeModal'
export default {
name: 'UserSelectByContactNoMerge',
components: { UserSelectByContactNoMergeModal },
props: {
disabled: {
type: Boolean,
default: false
},
placeholder: {
type: String,
default: ''
},
value: {
type: String,
default: () => {
return ''
}
},
// 名字字符串
nameStr: {
type: String,
default: ''
},
// 修改的字段名
filedName: {
type: [String, Number],
default: ''
},
// 回显输入框的类型,默认是input
inputType: {
type: String,
required: false,
default: 'text'
},
// 是否展示按钮
showBtn: {
type: Boolean,
required: false,
default: true
}
},
watch: {
nameStr: {
immediate: true,
handler (val) {
this.checkedValue = val
}
}
},
data () {
return {
checkedValue: ''
}
},
methods: {
selectClick () {
// 禁用后不弹框
if (this.disabled) {
return
}
this.$refs.selectModal.open(this.value)
},
selectChange (ids) {
this.$emit('change', ids)
},
listChange (value) {
this.$emit('listChange', value)
},
nameChange (value) {
this.checkedValue = value
this.$emit('nameChange', value, this.filedName)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
.user-organ-wrap {
width: 100%;
position: relative;
display: flex;
align-items: center;
//height: 39.98px;
.user-input {
resize: none;
width: calc(100% - 70px);
}
// 因为需要加title,所以不能把鼠标事件去掉
/deep/ .input-readonly.ant-input-disabled {
background: #fff;
color: rgba(0, 0, 0, 0.65);
cursor: default;
}
.button-box {
margin-left: 5px;
}
}
</style>
@@ -0,0 +1,486 @@
<template>
<j-modal
:title="$t('userSelect.selectUser')"
:maskClosable="false"
:width="1000"
:closable="true"
centered
@ok="handleOk"
@cancel="handleCancel"
switchFullscreen
:visible="visible">
<div class="modal-search-wrapper table-page-search-wrapper search-wrap">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :span="6">
<a-form-item :label="$t('system.contact.departName')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<j-input :placeholder="$t('pleaseEnter')+$t('system.contact.departName')" v-model="queryParam.departName"></j-input>
</a-form-item>
</a-col>
<a-col :span="6">
<a-form-item :label="$t('system.contact.contactPerson')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('system.contact.contactPerson')" v-model="queryParam.contact"></a-input>
</a-form-item>
</a-col>
<span style="float: right;overflow: hidden;margin-right: 11px" class="table-page-search-submitButtons">
<a-button style="margin-left: 8px" type="primary" icon="search" @click="searchQuery">{{$t('query')}}</a-button>
<a-button style="margin-left: 8px" type="primary" ghost icon="reload" @click="searchReset">{{$t('reset')}}</a-button>
</span>
</a-row>
</a-form>
<!-- 全选所有 -->
<a-checkbox v-if="type === 'checkbox'" v-model="isCheckedAll" class="modal-title-check" @change="checkedAllChange">{{ $t('checkedAll') }}</a-checkbox>
</div>
<div class="modal-content">
<a-table
:columns="columns"
rowKey="id"
bordered
:scroll="{x: '100%', y: '280px'}"
:data-source="dataSource"
:pagination="ipagination"
:row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange, type: type }"
:loading="loadingLeft"
@change="leftTableChange">
<template slot="text" slot-scope="text">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
</a-table>
</div>
<p class="modal-content-title">{{ $t('userSelect.selectedPersonnel') }}</p>
<div v-if="dataSourceRight && dataSourceRight.length > 0" class="name-content">
<div v-for="(item, index) in dataSourceRight" :key="item.id + item.contactId" class="name-div">
{{ item.contactId_dictText }}
<a-icon type="close" @click="handleDelete(item, index)" />
</div>
</div>
<a-empty v-else/>
</j-modal>
</template>
<script>
import { getAction } from '@/api/manage'
export default {
name: 'UserSelectByContactNoMergeModal',
props: {
type: { // 是单选还是多选
type: String,
default: 'radio'
},
value: {
type: String,
default: () => {
return ''
}
},
list: {
type: Array,
required: false,
default: () => {
return []
}
},
// 是否校验必选
checkRequired: {
type: Boolean,
required: false,
default: true
}
},
// computed: {
// nameArr () {
// if (this.dataSourceRight && this.dataSourceRight.length > 0) {
// return this.unique(this.dataSourceRight)
// } else {
// return []
// }
// }
// },
watch: {
value: {
immediate: true,
handler (val) {
console.log(val)
if (val) {
this.selectedRowKeys = val ? val.split(',') : []
}
}
},
list: {
immediate: true,
deep: true,
handler (val) {
console.log('list改变了------------', val)
if (val && val.length > 0) {
this.dataSourceRight = JSON.parse(JSON.stringify(val))
} else {
this.dataSourceRight = []
}
}
},
dataSourceRight: {
immediate: true,
deep: true,
handler (val) {
console.log(this.currentQueryAllData)
const arrOne = this.currentQueryAllData.map(item => item.id)
const arrTwo = this.dataSourceRight.map(item => item.id)
const temp = []
for (const item of arrTwo) {
arrOne.includes(item) ? temp.push(item) : ''
}
if (val.length !== 0 && this.currentQueryAllData.length !== 0 && this.dataSourceRight.length >= this.ipagination.total && temp.length === this.currentQueryAllData.length) {
this.isCheckedAll = true
} else {
this.isCheckedAll = false
}
}
},
currentQueryAllData: {
immediate: true,
deep: true,
handler (val) {
console.log(this.currentQueryAllData)
const arrOne = this.currentQueryAllData.map(item => item.id)
const arrTwo = this.dataSourceRight.map(item => item.id)
const temp = []
for (const item of arrTwo) {
arrOne.includes(item) ? temp.push(item) : ''
}
if (this.dataSourceRight.length !== 0 && this.currentQueryAllData.length !== 0 && this.dataSourceRight.length >= this.ipagination.total && temp.length === this.currentQueryAllData.length) {
// 选中数据长度和表格总数相等或者和上次查询的总数相等
this.isCheckedAll = true
} else {
this.isCheckedAll = false
}
}
},
queryParam: {
deep: true,
handler (val) {
this.isClickedSearch = false
}
}
},
data () {
return {
visible: false,
queryParam: {},
labelCol: {
span: 6
},
wrapperCol: {
span: 18
},
columns: [
{ // 部门名称
title: this.$t('system.contact.departName'),
align: 'center',
width: 180,
dataIndex: 'departId_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 标准化工程师
title: this.$t('system.contact.standardizationEngineer'),
align: 'center',
width: 180,
dataIndex: 'engineerId_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 联络人
title: this.$t('system.contact.contactPerson'),
align: 'center',
width: 180,
dataIndex: 'contactId_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 部门联络人主管级领导
title: this.$t('system.contact.contactPersonSupervisorLevelLeader'),
align: 'center',
width: 240,
dataIndex: 'leaderId_dictText',
scopedSlots: { customRender: 'text' }
}
],
dataSource: [],
ipagination: {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30', '100', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
selectedRowKeys: [],
loadingLeft: false,
dataSourceRight: [],
isCheckedAll: false, // 是否选中所有
url: {
userList: '/laws/system/lawsContactManage/pageWP',
userListByIds: '/laws/system/lawsContactManage/queryById'
},
isClickedSearch: false, // 改完搜索条件是否点击过搜索
oldQueryParam: {}, // 上一次的搜索条件,用于从一个搜索条件改成另一个搜索条件,但是没有点搜索,这时候全选时传旧的搜索条件
oldTotal: 0,
currentQueryAllData: [] // 当前查询条件下的所有数据
}
},
methods: {
open (value) {
this.visible = true
// this.loadData()
if (value) {
this.selectedRowKeys = value.split(',')
}
if (this.list && this.list.length > 0) {
this.dataSourceRight = JSON.parse(JSON.stringify(this.list))
} else {
this.dataSourceRight = []
}
},
// 全选所有
checkedAllChange (e) {
console.log(e.target.checked)
if (e.target.checked) {
this.checkCurrentAll()
} else {
const field = 'id'
this.dataSourceRight = this.dataSourceRight.filter(item => !this.currentQueryAllData.some(i => i[field] === item[field]))
this.selectedRowKeys = JSON.parse(JSON.stringify(this.dataSourceRight)).map(item => item[field])
}
},
checkCurrentAll () {
this.loadingLeft = true
let params
if (this.isClickedSearch) {
// 点击过搜索了,传搜索条件
params = Object.assign({}, this.queryParam)
} else {
// 没点击过搜索,传旧的搜索条件
params = Object.assign({}, this.oldQueryParam)
}
params.pageNo = 1
params.pageSize = this.ipagination.total + 10
params.column = 'createTime'
params.order = 'desc'
getAction(this.url.userList, params).then(res => {
if (res.success) {
const arr = this.uniqueByKey([...res.result.records || [], ...this.dataSourceRight || []], 'id')
this.dataSourceRight = Array.from(arr)
this.selectedRowKeys = Array.from(arr).map(item => item.id)
}
}).finally(() => {
this.loadingLeft = false
})
},
// 根据某个字段对对象数组去重
uniqueByKey (arr, key) {
const map = arr.reduce((acc, obj) => {
const keyValue = obj[key]
acc[keyValue] = obj
return acc
}, {})
return Object.values(map)
},
// 获取当前查询条件的所有数据
async getCurrentAllData () {
const params = Object.assign({}, this.queryParam)
params.pageNo = 1
params.pageSize = 100000000
params.column = 'createTime'
params.order = 'desc'
await getAction(this.url.userList, params).then(res => {
if (res.success) {
this.currentQueryAllData = res.result.records || []
}
})
},
searchReset () {
this.queryParam = {}
this.loadData()
},
searchQuery () {
this.isClickedSearch = true
this.loadData()
},
// 获取用户左侧树列表
async loadData () {
this.loadingLeft = true
if (this.type === 'checkbox') {
await this.getCurrentAllData()
}
const params = Object.assign({}, this.queryParam)
params.pageNo = this.ipagination.current
params.pageSize = this.ipagination.pageSize
params.column = 'createTime'
params.order = 'desc'
getAction(this.url.userList, params).then((res) => {
if (res.success) {
if (res.result.current > 1 && res.result.records.length === 0) {
this.ipagination.current = res.result.current - 1
this.loadData()
return
}
this.oldQueryParam = Object.assign({}, this.queryParam)
this.dataSource = res.result.records || []
this.ipagination.total = res.result.total
} else {
this.$message.warn(res.message)
}
}).finally(() => {
this.loadingLeft = false
})
},
// 表格选择
onSelectChange (selectedRowKeys, selectedRows) {
this.selectedRowKeys = selectedRowKeys
if (this.type === 'checkbox') {
if (selectedRowKeys.length > this.dataSourceRight.length) {
// 说明是增加了数据
for (const rowIndex in selectedRows) {
if (!this.dataSourceRight.find(item => item.id === selectedRows[rowIndex].id)) {
// 右侧不存在,追加到右侧表格
this.dataSourceRight.push(selectedRows[rowIndex])
}
}
} else {
// 说明是删除了数据
if (selectedRowKeys && selectedRowKeys.length > 0) {
// 没有选中数据,说明这一页没有选中数据了
for (let i = 0; i < this.dataSourceRight.length; i++) {
if (!selectedRowKeys.find(item => item === this.dataSourceRight[i].id)) {
// 表格选中中没有找到这一条数据,说明已经被删了
this.dataSourceRight.splice(i, 1)
i--
}
}
} else {
this.dataSourceRight = []
}
}
console.log(this.dataSourceRight)
} else {
this.dataSourceRight = selectedRows
}
},
// 左侧表格改变
leftTableChange (pagination) {
this.ipagination = pagination
this.loadData()
},
// unique (array) {
// // 定义要返回的数组
// const resultArr = []
// // 循环遍历未去重的数组
// array.forEach(item => {
// // 如果obj中没有改元素属性
// if (!resultArr.find(i => i.contactId === item.contactId)) {
// // 说明还没有这个联络人
// resultArr.push(item)
// }
// })
// return resultArr
// },
// 名字列表的删除
handleDelete (record, index) {
this.dataSourceRight.splice(index, 1)
this.selectedRowKeys = this.selectedRowKeys.filter(item => item !== record.id)
},
handleOk () {
if (this.checkRequired && (!this.selectedRowKeys || this.selectedRowKeys.length === 0)) {
if (this.type === 'radio') {
this.$message.warning(this.$t('docTool.split.pleaseSelectUser'))
} else {
this.$message.warning(this.$t('pleaseAtLeastSelectOneUser'))
}
return
}
this.$emit('nameChange', this.dataSourceRight.map(item => item.contactId_dictText).join(','))
this.$emit('change', this.selectedRowKeys.join(','))
this.$emit('listChange', this.dataSourceRight)
this.close()
},
handleCancel () {
this.close()
},
close () {
this.visible = false
this.dataSourceRight = []
this.selectedRowKeys = []
this.queryParam = {}
this.ipagination = {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30', '100', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
}
}
}
}
</script>
<style scoped lang="less">
.modal-title-check {
margin-left: 25px;
margin-bottom: 10px;
}
.modal-content {
width: 100%;
display: flex;
justify-content: space-between;
&-left {
width: 58%;
}
&-right {
width: 40%;
}
&-title-div {
display: flex;
align-items: center;
height: 28px;
margin: 20px 0;
.modal-content-title {
color: #1D2129;
font-weight: 500;
margin-right: 12px;
margin-bottom: 0;
}
}
}
.name-content {
display: flex;
flex-wrap: wrap;
max-height: 200px;
overflow-y: auto;
.name-div {
width: auto;
padding: 5px 16px;
margin-right: 12px;
margin-top: 8px;
background: rgba(213, 44, 38, 0.08);
border-radius: 4px 4px 4px 4px;
opacity: 1;
color: @primary-color;
white-space: nowrap;
/deep/ .anticon {
margin-left: 4px;
}
}
}
/deep/ .ant-form-item-label{
min-width: 70px !important;
}
</style>
@@ -0,0 +1,130 @@
<template>
<div>
<div class="user-organ-wrap">
<a-input
:type="inputType"
:autoSize="true"
:rows="1"
readOnly
:disabled="disabled"
:class="{
'input-readonly': !disabled,
'user-input': showBtn
}"
:placeholder="placeholder"
:value="checkedValue"
@click="selectClick"
:title="checkedValue"
>
</a-input>
<a-button type="primary" class="button-box" @click="selectClick" :disabled="disabled" v-if="showBtn && !disabled">
{{ $t('userSelect.select') }}
</a-button>
</div>
<user-select-by-work-group-modal v-bind="$attrs" :nameStr="nameStr" ref="selectModal" @change="selectChange" @nameChange="nameChange"></user-select-by-work-group-modal>
</div>
</template>
<script>
import UserSelectByWorkGroupModal from './UserSelectByWorkGroupModal'
export default {
name: 'UserSelectByWorkGroup',
components: { UserSelectByWorkGroupModal },
props: {
disabled: {
type: Boolean,
default: false
},
placeholder: {
type: String,
default: ''
},
value: {
type: String,
default: () => {
return ''
}
},
// 名字字符串
nameStr: {
type: String,
default: ''
},
// 修改的字段名
filedName: {
type: [String, Number],
default: ''
},
// 回显输入框的类型,默认是input
inputType: {
type: String,
required: false,
default: 'text'
},
// 是否展示按钮
showBtn: {
type: Boolean,
required: false,
default: true
}
},
watch: {
nameStr: {
immediate: true,
handler (val) {
this.checkedValue = val
}
}
},
data () {
return {
checkedValue: ''
}
},
methods: {
selectClick () {
// 禁用后不弹框
if (this.disabled) {
return
}
this.$refs.selectModal.open(this.value)
},
selectChange (ids) {
this.$emit('change', ids)
},
nameChange (value) {
this.checkedValue = value
this.$emit('nameChange', value, this.filedName)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
.user-organ-wrap {
width: 100%;
position: relative;
display: flex;
align-items: center;
//height: 39.98px;
.user-input {
resize: none;
width: calc(100% - 70px);
}
// 因为需要加title,所以不能把鼠标事件去掉
/deep/ .input-readonly.ant-input-disabled {
background: #fff;
color: rgba(0, 0, 0, 0.65);
cursor: default;
}
.button-box {
margin-left: 5px;
}
}
</style>
@@ -0,0 +1,575 @@
<template>
<j-modal
:title="$t('userSelect.selectUser')"
:maskClosable="false"
:width="1200"
:closable="true"
centered
@ok="handleOk"
@cancel="handleCancel"
switchFullscreen
:visible="visible">
<div class="modal-top-wrapper">
<div class="modal-left-wrapper">
<a-spin :spinning="treeLoading">
<a-tree
:show-line="true"
:show-icon="true"
:tree-data="treeData"
:selectedKeys="currentTreeNode"
:replaceFields="{children: 'subset', title: 'name', key: 'id'}"
:default-expand-all="defaultExpandAll"
@select="treeSelect">
<template #custom="record">
<div class="tree-operate-node">
<a-icon class="parent-node-icon" type="folder" v-if="record.subset && record.subset.length > 0" />
<a-tooltip>
<template #title>
{{ record.name }}
</template>
<span class="tree-node-custom-title">{{ record.name }}</span>
</a-tooltip>
</div>
</template>
</a-tree>
</a-spin>
</div>
<div class="modal-right-wrapper">
<div class="modal-search-wrapper table-page-search-wrapper search-wrap">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :span="6">
<a-form-item :label="$t('system.internalWorkGroup.name')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('system.internalWorkGroup.name')" v-model="queryParam.realname"></a-input>
</a-form-item>
</a-col>
<a-col :span="6">
<a-form-item :label="$t('system.internalWorkGroup.workNo')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('system.internalWorkGroup.workNo')" v-model="queryParam.username"></a-input>
</a-form-item>
</a-col>
<a-col :span="6">
<a-form-item :label="$t('system.internalWorkGroup.role')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('system.internalWorkGroup.role')" v-model="queryParam.userRoleName"></a-input>
</a-form-item>
</a-col>
<a-col :span="6">
<a-form-item :label="$t('system.internalWorkGroup.post')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter')+$t('system.internalWorkGroup.post')" v-model="queryParam.userPostName"></a-input>
</a-form-item>
</a-col>
<!--<a-col :span="6">-->
<!-- <a-form-item :label="$t('userSelect.workGroup')" :labelCol="labelCol" :wrapperCol="wrapperCol">-->
<!-- <a-tree-select-->
<!-- tree-node-filter-prop="title"-->
<!-- v-model="queryParam.workingGroupId"-->
<!-- :maxTagCount="1"-->
<!-- :show-search="true"-->
<!-- :getPopupContainer="triggerNode=> triggerNode.parentNode"-->
<!-- style="width: 100%"-->
<!-- :tree-data="workingGroupTreeList"-->
<!-- :placeholder="$t('pleaseSelect')"-->
<!-- />-->
<!-- </a-form-item>-->
<!--</a-col>-->
<span style="float: right;overflow: hidden;margin-right: 11px" class="table-page-search-submitButtons">
<a-button style="margin-left: 8px" type="primary" icon="search" @click="searchQuery">{{$t('query')}}</a-button>
<a-button style="margin-left: 8px" type="primary" ghost icon="reload" @click="searchReset">{{$t('reset')}}</a-button>
</span>
</a-row>
</a-form>
<!-- 全选所有 -->
<a-checkbox v-if="type === 'checkbox'" v-model="isCheckedAll" class="modal-title-check" @change="checkedAllChange">{{ $t('checkedAll') }}</a-checkbox>
</div>
<div class="modal-content">
<a-table
:columns="columns"
rowKey="userId"
bordered
:scroll="{x: '100%', y: '280px'}"
:data-source="dataSource"
:pagination="ipagination"
:row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange, type: type }"
:loading="loadingLeft"
@change="leftTableChange">
<template slot="text" slot-scope="text">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
</a-table>
</div>
</div>
</div>
<p class="modal-content-title">{{ $t('userSelect.selectedPersonnel') }}</p>
<div v-if="dataSourceRight && dataSourceRight.length > 0" class="name-content">
<div v-for="(item, index) in dataSourceRight" :key="item.userId" class="name-div">
{{ item.realname + '(' + item.username + ')' }}
<a-icon type="close" @click="handleDelete(item, index)" />
</div>
</div>
<a-empty v-else/>
</j-modal>
</template>
<script>
import { getAction, postAction } from '@/api/manage'
import { getWorkGroupTreeList } from '@/api/api'
export default {
name: 'UserSelectByWorkGroupModal',
props: {
type: { // 是单选还是多选
type: String,
default: 'radio'
},
value: {
type: String,
default: () => {
return ''
}
},
// 是否校验必选
checkRequired: {
type: Boolean,
required: false,
default: true
}
},
watch: {
value: {
immediate: true,
handler (val) {
console.log(val)
if (val) {
this.selectedRowKeys = val ? val.split(',') : []
this.getUserListByIds(val)
}
}
},
dataSourceRight: {
immediate: true,
deep: true,
handler (val) {
console.log(this.currentQueryAllData)
const arrOne = this.currentQueryAllData.map(item => item.userId)
const arrTwo = this.dataSourceRight.map(item => item.userId)
const temp = []
for (const item of arrTwo) {
arrOne.includes(item) ? temp.push(item) : ''
}
if (val.length !== 0 && this.currentQueryAllData.length !== 0 && this.dataSourceRight.length >= this.ipagination.total && temp.length === this.currentQueryAllData.length) {
// 选中数据长度等于当前表格总长度
this.isCheckedAll = true
} else {
this.isCheckedAll = false
}
}
},
currentQueryAllData: {
immediate: true,
deep: true,
handler (val) {
console.log(this.currentQueryAllData)
const arrOne = this.currentQueryAllData.map(item => item.userId)
const arrTwo = this.dataSourceRight.map(item => item.userId)
const temp = []
for (const item of arrTwo) {
arrOne.includes(item) ? temp.push(item) : ''
}
if (this.dataSourceRight.length !== 0 && this.currentQueryAllData.length !== 0 && this.dataSourceRight.length >= this.ipagination.total && temp.length === this.currentQueryAllData.length) {
// 选中数据长度等于当前表格总长度
this.isCheckedAll = true
} else {
this.isCheckedAll = false
}
}
},
queryParam: {
deep: true,
handler (val) {
this.isClickedSearch = false
}
}
},
data () {
return {
visible: false,
queryParam: {},
labelCol: {
span: 6
},
wrapperCol: {
span: 18
},
treeLoading: false,
currentTreeNode: null, // 当前选中的树节点
defaultExpandAll: false, // 左侧树默认展开所有
treeData: [],
columns: [
{
title: this.$t('user.workNo'),
dataIndex: 'username',
align: 'center',
scopedSlots: { customRender: 'text' }
},
{
title: this.$t('userSelect.name'),
dataIndex: 'realname',
align: 'center',
scopedSlots: { customRender: 'text' }
},
{
title: this.$t('role'),
dataIndex: 'userRoleName',
align: 'center',
scopedSlots: { customRender: 'text' }
},
{
title: this.$t('userSelect.post'),
dataIndex: 'userPostName',
align: 'center',
scopedSlots: { customRender: 'text' }
}
],
dataSource: [],
ipagination: {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30', '100', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
selectedRowKeys: [],
loadingLeft: false,
dataSourceRight: [],
workingGroupTreeList: [], // 内部工作组下拉框数据
isCheckedAll: false, // 是否选中所有
url: {
userList: '/act/user/workGroupPage',
userListByIds: '/sys/user/queryByIds'
},
isClickedSearch: false, // 改完搜索条件是否点击过搜索
oldQueryParam: {}, // 上一次的搜索条件,用于从一个搜索条件改成另一个搜索条件,但是没有点搜索,这时候全选时传旧的搜索条件
oldTotal: 0,
currentQueryAllData: [] // 当前查询条件下的所有数据
}
},
mounted () {
this.initTreeData()
this.getWorkGroupTree()
},
methods: {
open (value) {
this.visible = true
// this.loadData()
if (value) {
this.selectedRowKeys = value.split(',')
this.getUserListByIds(value)
}
},
// 获取内部工作组树
getWorkGroupTree () {
getWorkGroupTreeList().then((res) => {
if (res.success) {
this.workingGroupTreeList = this.dealTreeData(res.result)
} else {
this.workingGroupTreeList = []
}
})
},
// 左侧树点击选中
treeSelect (selectedKeys) {
console.log(selectedKeys)
this.currentTreeNode = selectedKeys
this.queryParam.workingGroupId = selectedKeys[0]
this.loadData()
},
// 获取左侧树数据
initTreeData (params) {
this.treeLoading = true
getWorkGroupTreeList(params).then(res => {
if (res.success) {
this.treeData = this.dealTreeData(res.result)
this.treeData[0].scopedSlots = { title: 'oneCustom' }
} else {
this.treeData = []
}
}).finally(() => {
this.$nextTick(() => {
this.defaultExpandAll = true
})
this.treeLoading = false
})
},
// 处理左侧树数据结构
dealTreeData (treeData) {
return treeData.map(item => {
item.label = item.name
item.value = item.id
item.children = this.dealTreeData(item.subset)
return item
})
},
// 全选所有
checkedAllChange (e) {
console.log(e.target.checked)
if (e.target.checked) {
this.checkCurrentAll()
} else {
const field = 'userId'
this.dataSourceRight = this.dataSourceRight.filter(item => !this.currentQueryAllData.some(i => i[field] === item[field]))
this.selectedRowKeys = JSON.parse(JSON.stringify(this.dataSourceRight)).map(item => item[field])
}
},
checkCurrentAll () {
this.loadingLeft = true
let params
if (this.isClickedSearch) {
// 点击过搜索了,传搜索条件
params = Object.assign({}, this.queryParam)
} else {
// 没点击过搜索,传旧的搜索条件
params = Object.assign({}, this.oldQueryParam)
}
params.pageNo = 1
params.pageSize = this.ipagination.total + 10
getAction(this.url.userList, params).then(res => {
if (res.success) {
const arr = this.uniqueByKey([...res.result.records || [], ...this.dataSourceRight || []], 'userId')
this.dataSourceRight = Array.from(arr)
this.selectedRowKeys = Array.from(arr).map(item => item.userId)
}
}).finally(() => {
this.loadingLeft = false
})
},
// 根据某个字段对对象数组去重
uniqueByKey (arr, key) {
const map = arr.reduce((acc, obj) => {
const keyValue = obj[key]
acc[keyValue] = obj
return acc
}, {})
return Object.values(map)
},
// 获取当前查询条件的所有数据
async getCurrentAllData () {
const params = Object.assign({}, this.queryParam)
params.pageNo = 1
params.pageSize = 100000000
await getAction(this.url.userList, params).then(res => {
if (res.success) {
this.currentQueryAllData = res.result.records || []
}
})
},
searchReset () {
this.queryParam = {}
this.loadData()
},
searchQuery () {
this.isClickedSearch = true
this.loadData()
},
// 获取用户左侧树列表
async loadData () {
this.loadingLeft = true
if (this.type === 'checkbox') {
await this.getCurrentAllData()
}
const params = Object.assign({}, this.queryParam)
params.pageNo = this.ipagination.current
params.pageSize = this.ipagination.pageSize
getAction(this.url.userList, params).then((res) => {
if (res.success) {
if (res.result.current > 1 && res.result.records.length === 0) {
this.ipagination.current = res.result.current - 1
this.loadData()
return
}
this.oldQueryParam = Object.assign({}, this.queryParam)
this.dataSource = res.result.records || []
this.ipagination.total = res.result.total
} else {
this.$message.warn(res.message)
}
}).finally(() => {
this.loadingLeft = false
})
},
// 表格选择
onSelectChange (selectedRowKeys, selectedRows) {
this.selectedRowKeys = selectedRowKeys
if (this.type === 'checkbox') {
if (selectedRowKeys.length > this.dataSourceRight.length) {
// 说明是增加了数据
for (const rowIndex in selectedRows) {
if (!this.dataSourceRight.find(item => item.userId === selectedRows[rowIndex].userId)) {
// 右侧不存在,追加到右侧表格
this.dataSourceRight.push(selectedRows[rowIndex])
}
}
} else {
// 说明是删除了数据
if (selectedRowKeys && selectedRowKeys.length > 0) {
// 没有选中数据,说明这一页没有选中数据了
for (let i = 0; i < this.dataSourceRight.length; i++) {
if (!selectedRowKeys.find(item => item === this.dataSourceRight[i].userId)) {
// 表格选中中没有找到这一条数据,说明已经被删了
this.dataSourceRight.splice(i, 1)
i--
}
}
} else {
this.dataSourceRight = []
}
}
console.log(this.dataSourceRight)
} else {
this.dataSourceRight = selectedRows
}
},
// 左侧表格改变
leftTableChange (pagination) {
this.ipagination = pagination
this.loadData()
},
// 根据ids获取用户列表
getUserListByIds (ids) {
const params = {}
params.userIds = ids
this.loadingRight = true
postAction(this.url.userListByIds, params).then((res) => {
if (res.success) {
this.dataSourceRight = res.result.map(item => { return { ...item, userId: item.id } }) || []
} else {
this.$message.warn(res.message)
}
}).finally(() => {
this.loadingRight = false
})
},
// 名字列表的删除
handleDelete (record, index) {
this.dataSourceRight.splice(index, 1)
this.selectedRowKeys = this.selectedRowKeys.filter(item => item !== record.userId)
},
handleOk () {
if (this.checkRequired && (!this.selectedRowKeys || this.selectedRowKeys.length === 0)) {
if (this.type === 'radio') {
this.$message.warning(this.$t('docTool.split.pleaseSelectUser'))
} else {
this.$message.warning(this.$t('pleaseAtLeastSelectOneUser'))
}
return
}
this.$emit('change', this.selectedRowKeys.join(','))
this.$emit('nameChange', this.dataSourceRight.map(item => item.realname + '(' + item.username + ')').join(','))
this.close()
},
handleCancel () {
this.close()
},
close () {
this.visible = false
this.dataSourceRight = []
this.selectedRowKeys = []
this.queryParam = {}
this.ipagination = {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30', '100', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
}
}
}
}
</script>
<style scoped lang="less">
@import '~@assets/less/common.less';
.search-wrap {
position: relative;
}
.modal-title-check {
position: absolute;
left: 25px;
bottom: 10px;
}
.modal-top-wrapper {
display: flex;
height: 480px;
margin-bottom: 20px;
}
.modal-left-wrapper {
width: 200px;
margin-right: 20px;
height: 100%;
overflow-y: scroll;
}
.modal-right-wrapper {
flex: 1;
}
.modal-content {
width: 100%;
display: flex;
justify-content: space-between;
&-left {
width: 58%;
}
&-right {
width: 40%;
}
&-title-div {
display: flex;
align-items: center;
height: 28px;
margin: 20px 0;
.modal-content-title {
color: #1D2129;
font-weight: 500;
margin-right: 12px;
margin-bottom: 0;
}
}
}
.name-content {
display: flex;
flex-wrap: wrap;
max-height: 200px;
overflow-y: auto;
.name-div {
width: auto;
padding: 5px 16px;
margin-right: 12px;
margin-top: 8px;
background: rgba(213, 44, 38, 0.08);
border-radius: 4px 4px 4px 4px;
opacity: 1;
color: @primary-color;
white-space: nowrap;
/deep/ .anticon {
margin-left: 4px;
}
}
}
/deep/ .ant-table-content .ant-table-body{
overflow: scroll !important;
}
/deep/ .ant-form-item-label{
min-width: 70px !important;
}
</style>
@@ -0,0 +1,517 @@
<template>
<j-modal
:title="$t('userSelect.selectUser')"
:maskClosable="false"
:width="1000"
:closable="true"
centered
@ok="handleOk"
@cancel="handleCancel"
switchFullscreen
:visible="visible">
<div class="modal-search-wrapper table-page-search-wrapper search-wrap">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :span="6">
<a-form-item :label="$t('organization')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-tree-select
tree-node-filter-prop="title"
v-model="queryParam.departId"
:maxTagCount="1"
:show-search="true"
:getPopupContainer="triggerNode=> triggerNode.parentNode"
style="width: 100%"
:tree-data="categoryTreeList"
:placeholder="$t('pleaseSelect')"
/>
</a-form-item>
</a-col>
<a-col :span="6">
<a-form-item :label="$t('role')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<j-search-select-tag
:placeholder="$t('pleaseSelect') + $t('role')"
v-model="queryParam.roleId"
:dictOptions="rolesList">
</j-search-select-tag>
</a-form-item>
</a-col>
<a-col :span="6">
<a-form-item :label="$t('user.workNo')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<j-input :placeholder="$t('pleaseEnter')"
v-model="queryParam.username"></j-input>
</a-form-item>
</a-col>
<a-col :span="6">
<a-form-item :label="$t('userSelect.name')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<j-input :placeholder="$t('pleaseEnter')"
v-model="queryParam.realname"></j-input>
</a-form-item>
</a-col>
<span style="float: right;overflow: hidden;margin-right: 11px" class="table-page-search-submitButtons">
<a-button style="margin-left: 8px" type="primary" icon="search" @click="searchQuery">{{$t('query')}}</a-button>
<a-button style="margin-left: 8px" type="primary" ghost icon="reload" @click="searchReset">{{$t('reset')}}</a-button>
</span>
</a-row>
</a-form>
<!-- 全选所有 -->
<a-checkbox v-if="type === 'checkbox'" v-model="isCheckedAll" class="modal-title-check" @change="checkedAllChange">{{ $t('checkedAll') }}</a-checkbox>
</div>
<div class="modal-content">
<a-table
:columns="columns"
rowKey="id"
bordered
:scroll="{x: '100%', y: '280px'}"
:data-source="dataSource"
:pagination="ipagination"
:row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange, type: type }"
:loading="loadingLeft"
@change="leftTableChange">
<template slot="text" slot-scope="text">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
</a-table>
</div>
<p class="modal-content-title">{{ $t('userSelect.selectedPersonnel') }}</p>
<div v-if="dataSourceRight && dataSourceRight.length > 0" class="name-content">
<div v-for="(item, index) in dataSourceRight" :key="item.id" class="name-div">
{{ item.realname + '(' + item.username + ')' }}
<a-icon type="close" @click="handleDelete(item, index)" />
</div>
</div>
<a-empty v-else/>
</j-modal>
</template>
<script>
import JSearchSelectTag from '../dict/JSearchSelectTag'
import { queryall, queryDepartTreeList } from '@/api/api'
import { getAction, postAction } from '@/api/manage'
export default {
name: 'UserSelectModal',
components: { JSearchSelectTag },
props: {
type: { // 是单选还是多选
type: String,
default: 'radio'
},
value: {
type: String,
default: () => {
return ''
}
},
// 是否校验必选
checkRequired: {
type: Boolean,
required: false,
default: true
}
},
watch: {
value: {
immediate: true,
handler (val) {
console.log(val)
if (val) {
this.selectedRowKeys = val ? val.split(',') : []
this.getUserListByIds(val)
}
}
},
dataSourceRight: {
immediate: true,
deep: true,
handler (val) {
console.log(this.currentQueryAllData)
const arrOne = this.currentQueryAllData.map(item => item.id)
const arrTwo = this.dataSourceRight.map(item => item.id)
const temp = []
for (const item of arrTwo) {
arrOne.includes(item) ? temp.push(item) : ''
}
if (val.length !== 0 && this.currentQueryAllData.length !== 0 && this.dataSourceRight.length >= this.ipagination.total && temp.length === this.currentQueryAllData.length) {
// 选中数据长度等于当前表格总长度
this.isCheckedAll = true
} else {
this.isCheckedAll = false
}
}
},
currentQueryAllData: {
immediate: true,
deep: true,
handler (val) {
console.log(this.currentQueryAllData)
const arrOne = this.currentQueryAllData.map(item => item.id)
const arrTwo = this.dataSourceRight.map(item => item.id)
const temp = []
for (const item of arrTwo) {
arrOne.includes(item) ? temp.push(item) : ''
}
if (this.dataSourceRight.length !== 0 && this.currentQueryAllData.length !== 0 && this.dataSourceRight.length >= this.ipagination.total && temp.length === this.currentQueryAllData.length) {
// 选中数据长度等于当前表格总长度
this.isCheckedAll = true
} else {
this.isCheckedAll = false
}
}
},
queryParam: {
deep: true,
handler (val) {
this.isClickedSearch = false
}
}
},
data () {
return {
visible: false,
categoryTreeList: [], // 组织机构树
rolesList: [], // 角色下拉框
queryParam: {},
labelCol: {
span: 6
},
wrapperCol: {
span: 18
},
columns: [
{
title: this.$t('user.workNo'),
dataIndex: 'username',
align: 'center',
scopedSlots: { customRender: 'text' }
},
{
title: this.$t('userSelect.name'),
dataIndex: 'realname',
align: 'center',
scopedSlots: { customRender: 'text' }
},
{
title: this.$t('role'),
dataIndex: 'roleTxt',
align: 'center',
scopedSlots: { customRender: 'text' }
},
{
title: this.$t('userSelect.post'),
dataIndex: 'post',
align: 'center',
scopedSlots: { customRender: 'text' }
}
],
dataSource: [],
ipagination: {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30', '100', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
selectedRowKeys: [],
loadingLeft: false,
dataSourceRight: [],
isCheckedAll: false, // 是否选中所有
url: {
userList: '/sys/user/page',
userListByIds: '/sys/user/queryByIds'
},
isClickedSearch: false, // 改完搜索条件是否点击过搜索
oldQueryParam: {}, // 上一次的搜索条件,用于从一个搜索条件改成另一个搜索条件,但是没有点搜索,这时候全选时传旧的搜索条件
oldTotal: 0,
currentQueryAllData: [] // 当前查询条件下的所有数据
}
},
methods: {
open (value) {
this.getSysCategoryTree()
this.initRoleList()
// this.loadData()
this.visible = true
if (value) {
this.selectedRowKeys = value.split(',')
this.getUserListByIds(value)
}
},
// 获取组织机构树
getSysCategoryTree () {
queryDepartTreeList().then((res) => {
if (res.success) {
this.categoryTreeList = res.result
} else {
this.categoryTreeList = []
}
})
},
// 初始化角色字典
initRoleList () {
queryall().then((res) => {
if (res.success) {
this.rolesList = res.result.map((item) => {
return { text: item.roleName, value: item.id }
})
}
})
},
// 全选所有
checkedAllChange (e) {
console.log(e.target.checked)
if (e.target.checked) {
this.checkCurrentAll()
} else {
const field = 'id'
this.dataSourceRight = this.dataSourceRight.filter(item => !this.currentQueryAllData.some(i => i[field] === item[field]))
this.selectedRowKeys = JSON.parse(JSON.stringify(this.dataSourceRight)).map(item => item[field])
}
},
checkCurrentAll () {
this.loadingLeft = true
let params
if (this.isClickedSearch) {
// 点击过搜索了,传搜索条件
params = Object.assign({}, this.queryParam)
} else {
// 没点击过搜索,传旧的搜索条件
params = Object.assign({}, this.oldQueryParam)
}
params.pageNo = 1
params.pageSize = this.ipagination.total + 10
params.field = 'id,avatar,username,realname,sex_dictText,phone,orgCodeTxt,roleTxt,status_dictText'
params.column = 'createTime'
params.order = 'desc'
getAction(this.url.userList, params).then(res => {
if (res.success) {
const arr = this.uniqueByKey([...res.result.records || [], ...this.dataSourceRight || []], 'id')
this.dataSourceRight = Array.from(arr)
this.selectedRowKeys = Array.from(arr).map(item => item.id)
this.oldTotal = res.result.total
}
}).finally(() => {
this.loadingLeft = false
})
},
// 根据某个字段对对象数组去重
uniqueByKey (arr, key) {
const map = arr.reduce((acc, obj) => {
const keyValue = obj[key]
acc[keyValue] = obj
return acc
}, {})
return Object.values(map)
},
// 获取当前查询条件的所有数据
async getCurrentAllData () {
const params = Object.assign({}, this.queryParam)
params.pageNo = 1
params.pageSize = 100000000
params.field = 'id,avatar,username,realname,sex_dictText,phone,orgCodeTxt,roleTxt,status_dictText'
params.column = 'createTime'
params.order = 'desc'
await getAction(this.url.userList, params).then(res => {
if (res.success) {
this.currentQueryAllData = res.result.records || []
}
})
},
searchReset () {
this.queryParam = {}
this.loadData(1)
},
searchQuery () {
this.isClickedSearch = true
this.loadData(1)
},
// 获取用户左侧树列表
async loadData (arg) {
this.loadingLeft = true
if (this.type === 'checkbox') {
await this.getCurrentAllData()
}
if (arg) {
this.ipagination.current = 1
}
const params = Object.assign({}, this.queryParam)
params.pageNo = this.ipagination.current
params.pageSize = this.ipagination.pageSize
params.field = 'id,avatar,username,realname,sex_dictText,phone,orgCodeTxt,roleTxt,status_dictText'
params.column = 'createTime'
params.order = 'desc'
getAction(this.url.userList, params).then((res) => {
if (res.success) {
if (res.result.current > 1 && res.result.records.length === 0) {
this.ipagination.current = res.result.current - 1
this.loadData()
return
}
this.oldQueryParam = Object.assign({}, this.queryParam)
this.dataSource = res.result.records || []
this.ipagination.total = res.result.total
} else {
this.$message.warn(res.message)
}
}).finally(() => {
this.loadingLeft = false
})
},
// 表格选择
onSelectChange (selectedRowKeys, selectedRows) {
this.selectedRowKeys = selectedRowKeys
if (this.type === 'checkbox') {
if (selectedRowKeys.length > this.dataSourceRight.length) {
// 说明是增加了数据
for (const rowIndex in selectedRows) {
if (!this.dataSourceRight.find(item => item.id === selectedRows[rowIndex].id)) {
// 右侧不存在,追加到右侧表格
this.dataSourceRight.push(selectedRows[rowIndex])
}
}
} else {
// 说明是删除了数据
if (selectedRowKeys && selectedRowKeys.length > 0) {
// 没有选中数据,说明这一页没有选中数据了
for (let i = 0; i < this.dataSourceRight.length; i++) {
if (!selectedRowKeys.find(item => item === this.dataSourceRight[i].id)) {
// 表格选中中没有找到这一条数据,说明已经被删了
this.dataSourceRight.splice(i, 1)
i--
}
}
} else {
this.dataSourceRight = []
}
}
console.log(this.dataSourceRight)
} else {
this.dataSourceRight = selectedRows
}
},
// 左侧表格改变
leftTableChange (pagination) {
this.ipagination = pagination
this.loadData()
},
// 根据ids获取用户列表
getUserListByIds (ids) {
const params = {}
params.userIds = ids
this.loadingRight = true
postAction(this.url.userListByIds, params).then((res) => {
if (res.success) {
this.dataSourceRight = res.result || []
} else {
this.$message.warn(res.message)
}
}).finally(() => {
this.loadingRight = false
})
},
// 名字列表的删除
handleDelete (record, index) {
this.dataSourceRight.splice(index, 1)
this.selectedRowKeys = this.selectedRowKeys.filter(item => item !== record.id)
},
handleOk () {
if (this.checkRequired && (!this.selectedRowKeys || this.selectedRowKeys.length === 0)) {
if (this.type === 'radio') {
this.$message.warning(this.$t('docTool.split.pleaseSelectUser'))
} else {
this.$message.warning(this.$t('pleaseAtLeastSelectOneUser'))
}
return
}
this.$emit('nameChange', this.dataSourceRight.map(item => item.realname + '(' + item.username + ')').join(','))
this.$emit('change', this.selectedRowKeys.join(','))
this.$emit('listChange', this.dataSourceRight)
this.close()
},
handleCancel () {
this.close()
},
close () {
this.visible = false
this.dataSourceRight = []
this.selectedRowKeys = []
this.queryParam = {}
this.ipagination = {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30', '100', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
}
}
}
}
</script>
<style scoped lang="less">
.search-wrap {
position: relative;
}
.modal-title-check {
position: absolute;
left: 25px;
bottom: 10px;
}
.modal-content {
width: 100%;
display: flex;
justify-content: space-between;
&-left {
width: 58%;
}
&-right {
width: 40%;
}
&-title-div {
display: flex;
align-items: center;
height: 28px;
margin: 20px 0;
.modal-content-title {
color: #1D2129;
font-weight: 500;
margin-right: 12px;
margin-bottom: 0;
}
}
}
.name-content {
display: flex;
flex-wrap: wrap;
max-height: 200px;
overflow-y: auto;
.name-div {
width: auto;
padding: 5px 16px;
margin-right: 12px;
margin-top: 8px;
background: rgba(213, 44, 38, 0.08);
border-radius: 4px 4px 4px 4px;
opacity: 1;
color: @primary-color;
white-space: nowrap;
/deep/ .anticon {
margin-left: 4px;
}
}
}
/deep/ .ant-form-item-label{
min-width: 70px !important;
}
</style>
+145
View File
@@ -0,0 +1,145 @@
<template>
<div class="wrapper-box">
<div class="user-organ-wrap">
<a-input
:type="inputType"
:autoSize="true"
:rows="1"
readOnly
:disabled="disabled"
:class="{
'input-readonly': !disabled,
'user-input': showBtn
}"
:placeholder="placeholder"
:value="checkedValue"
@click="selectClick"
:title="checkedValue">
</a-input>
<a-button type="primary" class="button-box" @click="selectClick" :disabled="disabled" v-if="showBtn && !disabled">
{{ $t('userSelect.select') }}
</a-button>
</div>
<user-select-modal v-bind="$attrs"
:nameStr="nameStr"
ref="selectModal"
@change="selectChange"
@nameChange="nameChange"
@listChange="listChange" />
</div>
</template>
<script>
import UserSelectModal from './UserSelectModal'
export default {
name: 'UserSelection',
components: { UserSelectModal },
props: {
disabled: {
type: Boolean,
default: false
},
placeholder: {
type: String,
default: ''
},
value: {
type: String,
default: () => {
return ''
}
},
// 名字字符串
nameStr: {
type: String,
default: ''
},
// 修改的字段名
filedName: {
type: [String, Number],
default: ''
},
// 回显输入框的类型,默认是input
inputType: {
type: String,
required: false,
default: 'text'
},
// 是否展示按钮
showBtn: {
type: Boolean,
required: false,
default: true
}
},
watch: {
nameStr: {
immediate: true,
handler (val) {
this.checkedValue = val
}
}
},
data () {
return {
checkedValue: ''
}
},
methods: {
selectClick () {
console.log('点击了')
// 禁用后不弹框
if (this.disabled) {
return
}
this.$refs.selectModal.open(this.value)
},
selectChange (ids) {
this.$emit('change', ids, this.filedName)
},
nameChange (value) {
this.checkedValue = value
this.$emit('nameChange', value, this.filedName)
},
listChange (list) {
this.$emit('listChange', list)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
.wrapper-box {
display: flex;
}
.user-organ-wrap {
width: 100%;
flex: 1;
position: relative;
display: flex;
align-items: center;
//height: 39.98px;
.user-input {
resize: none;
//width: calc(100% - 70px);
}
// 因为需要加title,所以不能把鼠标事件去掉
/deep/ .input-readonly.ant-input-disabled {
background: #fff;
color: rgba(0, 0, 0, 0.65);
cursor: default;
}
.button-box {
margin-left: 5px;
}
}
</style>
@@ -0,0 +1,110 @@
<template>
<div class="selection-wrapper">
<div class="box-title-text">
<a-input class="box-input"
:value="checkedValue"
:title="checkedValue"
disabled
:max-length="500"
:placeholder="placeholder" />
<a-button v-if="!disabled" type="primary" class="button-box" @click="handleClick">
{{ $t('projectLibrary.noncoincidenceItem.projectSelection') }}
</a-button>
</div>
<vehicle-project-selection-drawer ref="projectSelectModal" @listChange="handleListChange" />
</div>
</template>
<script>
import VehicleProjectSelectionDrawer from './VehicleProjectSelectionDrawer'
export default {
name: 'VehicleProjectSelection',
components: { VehicleProjectSelectionDrawer },
props: {
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
// 是否只能选择
selectOnly: {
type: Boolean,
required: false,
default: false
},
// 名字字符串
nameStr: {
type: String,
required: false,
default: ''
},
// 回显取哪个字段的值
echoFieldName: {
type: String,
required: false,
default: 'projectName'
}
},
data () {
return {
checkedValue: null
}
},
watch: {
nameStr: {
immediate: true,
handler (val) {
this.checkedValue = val
}
}
},
methods: {
// 点击选择标准按钮
handleClick () {
this.$refs.projectSelectModal.open()
},
handleListChange (list) {
const ids = list.map(tt => tt.id).join(',')
this.checkedValue = list.map(tt => tt[this.echoFieldName]).join(',')
this.$emit('change', ids)
this.$emit('listChange', list)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
@import '~@assets/less/common.less';
.selection-wrapper {
height: 40px;
line-height: 40px;
}
.box-title-text {
height: 100%;
display: flex;
align-items: center;
.box-input {
width: 100%;
}
.button-box {
margin-left: 10px;
}
}
</style>
@@ -0,0 +1,158 @@
<template>
<a-drawer
:title="title"
:width="width"
placement="right"
:closable="true"
@close="onClose"
:visible="visible"
:maskClosable="false"
destroyOnClose
class="custom-drawer-style">
<div class="custom-drawer-style-scroll">
<!--查询区域-->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<!--项目名称-->
<a-col :md="6" :sm="12">
<a-form-item :label="$t('projectLibrary.projectName')">
<j-input :placeholder="$t('pleaseEnter') + $t('projectLibrary.projectName')" v-model="queryParam.projectName"></j-input>
</a-form-item>
</a-col>
<!--工作令编号-->
<a-col :md="6" :sm="12">
<a-form-item :label="$t('projectLibrary.workOrderNumber')">
<j-input :placeholder="$t('pleaseEnter') + $t('projectLibrary.workOrderNumber')" v-model="queryParam.workNumber"></j-input>
</a-form-item>
</a-col>
<!--项目健康状态-->
<a-col :md="6" :sm="12">
<a-form-item :label="$t('projectLibrary.projectHealthStatus')">
<j-dict-select-tag
class="box-input"
v-model="queryParam.projectHealth"
:placeholder="$t('pleaseSelect') + $t('projectLibrary.projectHealthStatus')"
:type="'select'"
:triggerChange="false"
:dictCode="'project_health'" />
</a-form-item>
</a-col>
<a-col :md="6" :sm="8">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchReset" icon="reload" ghost>{{ $t('reset') }}</a-button>
<a-button type="primary" @click="searchQuery" icon="search" style="margin-left: 8px" v-has="'vehicleItemLibrary:search'">
{{ $t('query') }}
</a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<j-table
:columns="columns"
:dataSource="dataSource"
:can-drag="true"
rowKey="id"
:row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
:pagination="ipagination"
:scroll="{x: '100%'}"
:loading="loading"
@change="handleTableChange">
</j-table>
</div>
<div class="custom-drawer-style-bottom-btn">
<a-button @click="handleCancel" style="margin-bottom: 0;" :loading="loading">{{ $t('close') }}</a-button>
<a-button @click="handleOk" type="primary" style="margin-bottom: 0;" :loading="loading">
{{ $t('preservation') }}
</a-button>
</div>
</a-drawer>
</template>
<script>
import JTable from '../jero/JTable'
import { JeroListMixin } from '../../mixins/JeroListMixin'
export default {
name: 'VehicleProjectSelectionDrawer',
components: { JTable },
mixins: [JeroListMixin],
data () {
return {
visible: false,
title: this.$t('projectLibrary.selectProject'),
width: 1100,
// 存储表单的数据
form: {},
isEdit: false,
columns: [
// 项目来源
{
dataIndex: 'projectSource_dictText',
title: this.$t('projectLibrary.vehicleItemLibrary.projectSource'),
width: 110
},
// 项目名称
{
dataIndex: 'projectName',
title: this.$t('projectLibrary.projectName'),
sorter: true,
width: 150
},
// 工作令编号
{
dataIndex: 'workNumber',
title: this.$t('projectLibrary.workOrderNumber'),
sorter: true,
width: 150
},
// 项目负责人
{
dataIndex: 'projectLeader_dictText',
title: this.$t('projectLibrary.vehicleItemLibrary.projectLeader'),
width: 150
},
// 项目健康状态
{
dataIndex: 'projectHealth_dictText',
title: this.$t('projectLibrary.projectHealthStatus'),
width: 120
}
],
disableMixinCreated: true,
url: {
list: '/projectLibrary/lawsProjectLibrary/page'
}
}
},
methods: {
open () {
this.visible = true
this.loadData(1)
},
onClose () {
this.visible = false
this.onClearSelected()
},
handleCancel () {
this.onClose()
},
handleOk () {
this.$emit('change', this.selectedRowKeys.join(','))
this.$emit('listChange', this.selectionRows)
this.onClose()
}
}
}
</script>
<style scoped lang="less">
/deep/ .table-page-search-wrapper .ant-form-inline .ant-form-item > .ant-form-item-label {
min-width: 80px;
}
</style>
@@ -0,0 +1,210 @@
<template>
<div class="selection-wrapper">
<div class="box-title-text">
<a-input class="box-input" :value="value" :title="value" @input="indexClick"
:disabled="disabledInput" :placeholder="placeholder">
<a-icon v-show="value" slot="suffix" type="close-circle" @click="handleEmpty" title="清空"/>
</a-input>
<a-button v-if="!disabled" type="primary" class="button-box" @click="workGroupClick">
{{this.$t('workGroupSelect.select')}}
</a-button>
</div>
<work-group-selection-modal ref="workGroupSelectionModal" v-bind="$attrs"
:modal-width="modalWidth"
:multi="multi"
:rootOpened="rootOpened"
:depart-id="value"
:store="storeField"
:text="textField"
:treeOpera="treeOpera"
@ok="handleOK"
@initComp="initComp"/>
</div>
</template>
<script>
import WorkGroupSelectionModal from '@comp/selection/WorkGroupSelectionModal'
import { underLinetoHump } from '@comp/_util/StringUtil'
export default {
name: 'WorkGroupSelection',
components: { WorkGroupSelectionModal },
props: {
value: {
type: String,
default: ''
},
placeholder: {
type: String,
default: ''
},
disabled: {
type: Boolean,
required: false,
default: false
},
// 只禁用输入框
disabledInput: {
type: Boolean,
default: false
},
modalWidth: {
type: Number,
default: 500,
required: false
},
multi: {
type: Boolean,
default: false,
required: false
},
rootOpened: {
type: Boolean,
default: true,
required: false
},
// 自定义返回字段,默认返回 name
customReturnField: {
type: String,
default: 'name'
},
backDepart: {
type: Boolean,
default: false,
required: false
},
// 存储字段 [key field]
store: {
type: String,
default: 'id',
required: false
},
// 显示字段 [label field]
text: {
type: String,
default: 'name',
required: false
},
treeOpera: {
type: Boolean,
default: false,
required: false
}
},
data () {
return {
visible: false,
confirmLoading: false,
storeVals: '', // [key values]
textVals: '' // [label values]
}
},
computed: {
storeField () {
let field = this.customReturnField
if (!field) {
field = this.store
}
return underLinetoHump(field)
},
textField () {
return underLinetoHump(this.text)
}
},
mounted () {
this.storeVals = this.value
},
watch: {
value (val) {
this.storeVals = val
}
},
methods: {
initComp (textVals) {
this.textVals = textVals
},
// 返回选中的部门信息
backDepartInfo () {
if (this.backDepart === true) {
if (this.storeVals && this.storeVals.length > 0) {
const arr1 = this.storeVals.split(',')
const arr2 = this.textVals.split(',')
const info = []
for (let i = 0; i < arr1.length; i++) {
info.push({
value: arr1[i],
text: arr2[i]
})
}
this.$emit('back', info)
}
}
},
handleOK (rows) {
if (!rows && rows.length <= 0) {
this.textVals = ''
this.storeVals = ''
} else {
const arr1 = []
const arr2 = []
for (const dep of rows) {
arr1.push(dep[this.storeField])
arr2.push(dep[this.textField])
}
this.storeVals = arr1.join(',')
this.textVals = arr2.join(',')
}
this.$emit('change', this.storeVals)
this.backDepartInfo()
},
handleEmpty () {
this.handleOK('')
},
// 点击选择按钮
workGroupClick () {
this.$refs.workGroupSelectionModal.show(this.textVals)
},
// 输入框输入监听
indexClick (event) {
this.$emit('change', event.target.value)
},
modalInput (value) {
this.$emit('change', value)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
@import '~@assets/less/common.less';
.selection-wrapper {
height: 40px;
line-height: 40px;
}
.box-title-text {
height: 100%;
display: flex;
align-items: center;
.box-input {
width: 100%;
}
.button-box {
margin-left: 5px;
}
}
.selection-wrapper .anticon-close-circle {
cursor: pointer;
color: #ccc;
transition: color 0.3s;
font-size: 12px;
}
.selection-wrapper .anticon-close-circle:hover {
color: #f5222d;
}
.selection-wrapper .anticon-close-circle:active {
color: #666;
}
</style>
@@ -0,0 +1,376 @@
<template>
<j-modal
:title="$t('workGroupSelect.selectWorkGroup')"
:width="modalWidth"
:visible="visible"
:confirmLoading="confirmLoading"
@ok="handleSubmit"
@cancel="handleCancel"
@update:fullscreen="isFullscreen"
wrapClassName="j-depart-select-modal"
switchFullscreen
:cancelText="$t('close')">
<a-spin tip="Loading..." :spinning="false">
<a-input-search style="margin-bottom: 1px" :placeholder="$t('workGroupSelect.enterWorkGroupPressEnter')" @search="onSearch" />
<a-tree
:checkable="true"
:class="treeScreenClass"
class="select-work-group-tree"
:treeData="treeData"
:checkStrictly="checkStrictly"
@check="onCheck"
@select="onSelect"
@expand="onExpand"
:autoExpandParent="autoExpandParent"
:expandedKeys="expandedKeys"
:selectedKeys.sync="selectedKeys"
:checkedKeys="checkedKeys">
<template slot="title" slot-scope="{title}">
<span v-if="title.indexOf(searchValue) > -1">
{{title.substr(0, title.indexOf(searchValue))}}
<span style="color: #f50">{{searchValue}}</span>
{{title.substr(title.indexOf(searchValue) + searchValue.length)}}
</span>
<span v-else>{{title}}</span>
</template>
</a-tree>
</a-spin>
<!--底部父子关联操作和确认取消按钮-->
<template slot="footer" v-if="treeOpera && multi">
<div class="drawer-bootom-button">
<a-dropdown style="float: left" :trigger="['click']" placement="topCenter">
<a-menu slot="overlay">
<a-menu-item key="1" @click="switchCheckStrictly(1)">{{ $t('parentChildConnection') }}</a-menu-item>
<a-menu-item key="2" @click="switchCheckStrictly(2)">{{ $t('cancelConnection') }}</a-menu-item>
</a-menu>
<a-button>
{{ $t('treeOperation') }} <a-icon type="up" />
</a-button>
</a-dropdown>
<a-button @click="handleCancel" type="primary" style="margin-right: 0.8rem">{{ $t('close') }}</a-button>
<a-button @click="handleSubmit" type="primary" >{{ $t('confirm') }}</a-button>
</div>
</template>
</j-modal>
</template>
<script>
import { getWorkGroupTreeList } from '@api/api'
export default {
name: 'WorkGroupSelectionModal',
props: ['modalWidth', 'multi', 'rootOpened', 'departId', 'store', 'text', 'treeOpera'],
data () {
return {
visible: false,
confirmLoading: false,
treeData: [],
autoExpandParent: true,
expandedKeys: [],
dataList: [],
checkedKeys: [],
checkedRows: [],
searchValue: '',
checkStrictly: true,
fullscreen: false,
selectedKeys: []
}
},
created () {
this.loadWorkGroup()
},
watch: {
departId () {
this.initDepartComponent()
},
visible: {
handler () {
this.initDepartComponent(true)
}
}
},
computed: {
treeScreenClass () {
return {
'my-dept-select-tree': true,
fullscreen: this.fullscreen,
'radio-tree': !this.multi
}
}
},
methods: {
show (textVals) {
this.visible = true
this.checkedRows = []
this.checkedKeys = []
if (textVals) {
this.$nextTick(() => {
// 如果是多选就以逗号分开查找,否则就直接查找
const nodes = this.findKeysByNodes(this.multi ? textVals.split(',') : textVals)
this.checkedRows = nodes
this.checkedKeys = nodes.map(item => item.key)
this.selectedKeys = [...this.checkedKeys]
})
}
},
findKeysByNodes (titles) {
const _this = this
const nodes = []
function searchTree (node) {
// 如果是单选模式已经找到一个,就不继续查找了
if (!_this.multi && nodes.length) {
return
}
if (titles.includes(node.title)) {
nodes.push(node)
}
if (node.children) {
for (const child of node.children) {
searchTree(child)
}
}
}
this.treeData.forEach(data => {
searchTree(data)
})
return nodes
},
// 处理工作组树数据结构
dealTreeData (treeData) {
return treeData.map(item => {
item.title = item.name
item.value = item.id
item.key = item.id
item.disabled = !!(item.subset && item.subset.length)
item.children = this.dealTreeData(item.subset)
return item
})
},
loadWorkGroup () {
getWorkGroupTreeList().then(res => {
if (res.success) {
console.log(res.result)
const arr = this.dealTreeData(res.result)
this.reWriterWithSlot(arr)
this.treeData = arr
this.initDepartComponent()
if (this.rootOpened) {
this.initExpandedKeys(res.result)
}
}
})
},
initDepartComponent (flag) {
const arr = []
// 该方法两个地方用 1.visible改变事件重新设置选中项 2.组件编辑页面回显
const fieldName = flag === true ? 'key' : this.text
if (this.departId) {
const arr2 = this.departId.split(',')
for (const item of this.dataList) {
if (arr2.indexOf(item[this.store]) >= 0) {
arr.push(item[fieldName])
}
}
}
if (flag === true) {
this.checkedKeys = [...arr]
} else {
this.$emit('initComp', arr.join(','))
}
},
reWriterWithSlot (arr) {
for (const item of arr) {
if (item.children && item.children.length > 0) {
this.reWriterWithSlot(item.children)
const temp = Object.assign({}, item)
temp.children = {}
this.dataList.push(temp)
} else {
this.dataList.push(item)
item.scopedSlots = { title: 'title' }
}
}
},
initExpandedKeys (arr) {
if (arr && arr.length > 0) {
const keys = []
for (const item of arr) {
if (item.children && item.children.length > 0) {
keys.push(item.id)
}
}
this.expandedKeys = [...keys]
} else {
this.expandedKeys = []
}
},
onCheck (checkedKeys, info) {
if (!this.multi) {
const arr = checkedKeys.checked.filter(item => this.checkedKeys.indexOf(item) < 0)
this.checkedKeys = [...arr]
this.checkedRows = (this.checkedKeys.length === 0) ? [] : [info.node.dataRef]
} else {
if (this.checkStrictly) {
this.checkedKeys = checkedKeys.checked
} else {
this.checkedKeys = checkedKeys
}
this.checkedRows = this.getCheckedRows(this.checkedKeys)
}
},
onSelect (selectedKeys, info) {
// 取消关联的情况下才走onSelect的逻辑
if (this.checkStrictly) {
const keys = []
keys.push(selectedKeys[0])
if (!this.checkedKeys || this.checkedKeys.length === 0 || !this.multi) {
this.checkedKeys = [...keys]
this.checkedRows = [info.node.dataRef]
} else {
const currKey = info.node.dataRef.key
if (this.checkedKeys.indexOf(currKey) >= 0) {
this.checkedKeys = this.checkedKeys.filter(item => item !== currKey)
} else {
this.checkedKeys.push(...keys)
}
}
this.checkedRows = this.getCheckedRows(this.checkedKeys)
}
},
onExpand (expandedKeys) {
this.expandedKeys = expandedKeys
this.autoExpandParent = false
},
handleSubmit () {
if (!this.checkedKeys || this.checkedKeys.length === 0) {
this.$emit('ok', '')
} else {
const checkRow = this.getCheckedRows(this.checkedKeys)
const keyStr = this.checkedKeys.join(',')
this.$emit('ok', checkRow, keyStr)
}
this.handleClear()
},
handleCancel () {
this.handleClear()
},
handleClear () {
this.visible = false
this.checkedKeys = []
},
getParentKey (currKey, treeData) {
let parentKey
for (let i = 0; i < treeData.length; i++) {
const node = treeData[i]
if (node.children) {
if (node.children.some(item => item.key === currKey)) {
parentKey = node.key
} else if (this.getParentKey(currKey, node.children)) {
parentKey = this.getParentKey(currKey, node.children)
}
}
}
return parentKey
},
onSearch (value) {
const expandedKeys = this.dataList.map((item) => {
if (item.title.indexOf(value) > -1) {
return this.getParentKey(item.key, this.treeData)
}
return null
}).filter((item, i, self) => item && self.indexOf(item) === i)
Object.assign(this, {
expandedKeys,
searchValue: value,
autoExpandParent: true
})
},
// 根据 checkedKeys 获取 rows
getCheckedRows (checkedKeys) {
const forChildren = (list, key) => {
for (const item of list) {
if (item.id === key) {
return item
}
if (Array.isArray(item.children)) {
const value = forChildren(item.children, key)
if (value != null) {
return value
}
}
}
return null
}
const rows = []
for (const key of checkedKeys) {
const row = forChildren(this.treeData, key)
if (row != null) {
rows.push(row)
}
}
return rows
},
switchCheckStrictly (v) {
if (v === 1) {
this.checkStrictly = false
} else if (v === 2) {
this.checkStrictly = true
}
},
isFullscreen (val) {
this.fullscreen = val
}
}
}
</script>
<style lang="less" scoped>
// 限制部门选择树高度,避免部门太多时点击确定不便
.my-dept-select-tree{
height:350px;
&.fullscreen{
height: calc(100vh - 250px);
}
overflow-y: scroll;
}
.drawer-bootom-button {
position: absolute;
bottom: 0;
width: 100%;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
text-align: right;
left: 0;
background: #fff;
border-radius: 0 0 2px 2px;
}
// 禁用的不需要显示选择框
.select-work-group-tree {
/deep/.ant-tree-checkbox-disabled {
display: none;
}
/deep/li.ant-tree-treenode-disabled > .ant-tree-node-content-wrapper span {
color: rgba(0, 0, 0, .65)
}
}
// 单选不显示选择框
.select-work-group-tree.radio-tree {
/deep/.ant-tree-checkbox {
//display: none;
opacity: 0;
position: absolute;
}
}
// 单选鼠标悬浮时宽度调整
.ant-tree.radio-tree /deep/ li .ant-tree-node-content-wrapper:hover {
margin-left: 0;
padding-left: 5px;
}
</style>