123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 |
- <script>
- import { Switch, Modal } from 'ant-design-vue'
- import qs from 'qs'
- import axios from '@/common/services/axios-instance'
- import crossWindowWatcher from '@/common/services/cross-window-watcher'
- import sdDataTableMixin from '@/common/components/sd-table/sd-data-table-mixin'
- import SdDataTable from './xm-data-table'
- import SdDetailModal from '@/common/components/sd-detail-modal'
- import form from '@/common/components/sd-icon-library/icons/outline/form'
- import { message } from '@/common/one-ui'
- import booleanUtil from '@/common/services/boolean-util'
- /**
- * <p>为了项目上能快速实现一个增删查改的模块,我们提供了组件 SdDataTableEx</p>
- * <p>该组件需要配合固定格式的接口实现</p>
- * <ul>
- * <li>获取列表 <pre>api/framework/v1/page/businessList</pre></li>
- * <li>获取详情 <pre>api/framework/v1/page/wp/${pageId}?id={beanId}</pre></li>
- * <li>保存数据 <pre>api/framework/v1/page/handleData</pre></li>
- * <li>删除数据 <pre>api/framework/v1/page/${formId}?ids={beanId1},{beanId2}</pre></li>
- * <li>权限控制 <pre>api/framework/v1/form-perm/my-authed-perms</pre></li>
- * </ul>
- * @displayName SdDataTableEx 高级数据表格
- * @since 8.0.12
- */
- export default {
- name: 'XmDataTableEx',
- mixins: [sdDataTableMixin],
- inheritAttrs: false,
- props: {
- projectlist: {
- type: Boolean,
- default: false,
- },
- /**
- * framework/v1/page/businessList 接口中的 formId
- */
- formId: {
- type: String,
- required: true,
- },
- /**
- * framework/v1/page/wp 接口中的 pageId
- */
- pageId: {
- type: String,
- default: function() {
- return this.formId
- },
- },
- /**
- * framework/v1/page/wp 接口中的 extParams
- * @since 8.1.0.29
- */
- extParams: {
- type: Object,
- default: undefined,
- },
- /**
- * 获取表格数据 API的url
- */
- dataUrl: {
- type: String,
- default: 'api/xcoa-mobile/v1/iam-page/businessList',
- },
- /**
- * 传给详情 modal 的 props,可以用于设置样式等
- */
- modalProps: {
- type: Object,
- default: undefined,
- },
- /***
- * 请求过滤方法
- */
- processReq: {
- type: Function,
- default: undefined,
- },
- /**
- * 选择列表单选或者复选 add by zzb 20220224
- */
- checkType: {
- type: String,
- default: 'checkbox',
- },
- /***
- * 是否显示高级搜索按钮
- */
- showAdvanceQuery: {
- type: Boolean,
- default: false,
- },
- /***
- * 当前页面是否显示操作按钮
- */
- editnode: {
- type: Boolean,
- default: true,
- },
- /**
- * 自定义删除方法
- */
- customDeleteFun: {
- type: Function,
- requier: false,
- },
- /** 自定义行 */
- customRow: {
- type: Function,
- requier: false,
- },
- // 加载样式
- fnonloadsum: {
- type: Function,
- default: null,
- },
- },
- data() {
- return {
- recordId: undefined,
- localPageId: this.pageId,
- loadingSwitchs: [],
- isWindowOpen: false,
- }
- },
- computed: {
- // 把新建和删除按钮转换为标准格式
- computedActions() {
- const actions = this.actions.map((act) => {
- const action = { ...act }
- if (action.type === 'delete') {
- action.type = 'batch'
- if (this.customDeleteFun) {
- action.callback = this.customDeleteFun
- } else {
- action.callback = this.deleteRows
- action.permission = 'delete'
- }
- } else if (action.type === 'create') {
- action.type = 'primary'
- action.permission = 'create'
- action.callback = this.create
- }
- if (action.permission) {
- if (action.permission.startsWith(this.formId + '-')) {
- // eslint-disable-next-line no-console
- console.warn(
- `按钮 "${act.label}" 的 permission 属性请去掉 "${this.formId}-" 部分,formId 会自动添加`
- )
- } else {
- if (!action.permission.includes('-')) {
- action.permission = `${this.formId}-${action.permission}`
- }
- }
- }
- return action
- })
- return actions
- },
- formatedColumns() {
- const columns = this.columns.map((col) => {
- if (col.sdRender === 'switch') {
- // 行内的切换按钮
- col.customRender = (text, record, index, column) => {
- return (
- <Switch
- checked={booleanUtil.isTruthy(text)}
- loading={this.loadingSwitchs.indexOf(record.id) > -1}
- onChange={() => this.onSwitchChange(record, column)}
- />
- )
- }
- }
- return col
- })
- return columns
- },
- },
- // 加载分级授权获取部门下拉框 add by zzb
- mounted() {
- this.isWindowOpen = !this.$scopedSlots.form
- let tree = this.$parent.$children.find((item) => {
- return item.$options._componentTag === 'audit-tree'
- })
- if (!tree) {
- tree = this.$parent.$parent.$children.find((item) => {
- return (
- (item.$options._componentTag === 'audit-tree') |
- (item.$options._componentTag === 'audit-matters-catalog-tree') |
- (item.$options._componentTag === 'mtx-process-catalog-tree') |
- (item.$options._componentTag === 'mtx-version-catalog-tree') |
- (item.$options._componentTag === 'risk-category-tree')
- )
- })
- }
- // 如果还是找不到树组件,则直接退出
- if (!tree) {
- if (tree?.initTreeData) {
- tree.initTreeData()
- }
- return
- }
- const table = this.$parent.$children.find((item) => {
- return (
- (item.$options._componentTag === 'sd-data-table-ex') |
- (item.$options._componentTag === 'sd-oa-table')
- )
- })
- if (!table) {
- const acard = this.$parent.$children.find((item) => {
- return item.$options._componentTag === 'a-card'
- })
- let intable
- if (acard) {
- intable = acard.$parent.$children.find((item) => {
- return item.$options._componentTag === 'sd-data-table-ex'
- })
- } else {
- intable = this.$parent.$children.find((item) => {
- return item.$options._componentTag === 'sd-data-table-ex'
- })
- }
- // 显示下拉框才初始化
- if (tree.isSelectDep) {
- tree.initDeptList(intable.formId)
- } else if (tree.checkNodeEdit) {
- // 如果需要检查节点权限
- if (tree?.beforeInitTreeData) {
- tree.beforeInitTreeData(intable.formId)
- }
- } else {
- // 正常加载
- tree.initTreeData()
- }
- } else {
- // 显示下拉框才初始化
- if (tree.isSelectDep) {
- tree.initDeptList(table.formId)
- } else if (tree.checkNodeEdit) {
- // 如果需要检查节点权限
- if (tree?.beforeInitTreeData) {
- tree.beforeInitTreeData(table.formId)
- }
- } else {
- // 正常加载
- tree.initTreeData()
- }
- }
- },
- methods: {
- addMonitor() {
- window.addEventListener('message', this.eventListener, false)
- },
- removeMonitor() {
- window.removeEventListener('message', this.eventListener, false)
- },
- eventListener(event) {
- // 格式为{type:'', data: {}}
- if (event.data?.type === 'recordSaved') {
- const data = event.data.data
- if (data.formId === this.formId) {
- this.refresh()
- this.$emit('recordSaved', data.recordId)
- }
- }
- },
- rowClick(record) {
- this.showDetailModal(record.id, this.pageId)
- },
- create() {
- this.showDetailModal(null, this.pageId)
- },
- showDetailWindow(recordId = null, pageId = this.pageId) {
- crossWindowWatcher.subscribeChange({
- url:
- '/sd-webform?' +
- qs.stringify({
- id: recordId,
- pageId,
- // 新建时,传extParams,用于设置默认值
- extParams: !recordId && this.extParams ? JSON.stringify(this.extParams) : undefined,
- }),
- callback: (data) => {
- this.refresh()
- this.$emit('recordSaved', recordId || data?.pageFormData?.beanId)
- },
- })
- },
- /**
- * 获取详情对话框,可以通过它调用操作字段的API
- * 详情信息以Modal方式打开时有效
- * @public
- */
- getDetailModal() {
- return this.$refs.detail
- },
- /**
- * 隐藏详情对话框
- * 详情信息以Modal方式打开时有效
- * @public
- */
- hideDetailModal() {
- this.$refs.detail.hide()
- },
- /**
- * 显示详情对话框(Modal或新窗口方式)
- * @public
- * @param {string} recordId 要显示的记录ID,不传此参数表示新建
- * @param {string} pageId 用哪个page显示,默认为组件pageId prop的值
- */
- showDetailModal(recordId = null, pageId = this.pageId) {
- if (this.isWindowOpen) {
- this.showDetailWindow(recordId, pageId)
- } else {
- this.recordId = recordId
- this.localPageId = pageId
- this.$refs.detail.show()
- }
- /**
- * 详情对话框显示时触发8.1.0.27添加纪录id
- */
- this.$emit('detailModalShow', recordId)
- },
- deleteRows(selectedRowKeys) {
- return new Promise((resolve) => {
- // 判断是否起草环节
- const rows = this.$refs.dataTable.getSelectedRows()
- let flag = true
- let surl = 'api/framework/v1/page/' + this.formId
- if (rows[0].instId === undefined || rows[0].instId === null) {
- surl = 'api/xcoa-mobile/v1/iam-page/' + this.formId
- } else {
- // 流程类的 判断是否是起草环节
- rows.forEach((r) => {
- if (r.endType) {
- if (r.endType !== 0) {
- flag = false
- }
- }
- })
- }
- if (!flag) {
- Modal.error({
- title: '删除失败:存在不是起草状态的数据',
- })
- resolve()
- } else {
- Modal.confirm({
- title: '您确定删除这项内容吗?',
- content: '删除这条数据后,就无法恢复初始的状态。',
- okText: '删除',
- cancelText: '取消',
- okType: 'danger',
- onOk: () => {
- axios({
- // url: 'api/framework/v1/page/' + this.formId,
- url: surl,
- method: 'delete',
- params: {
- ids: selectedRowKeys.join(','),
- },
- })
- .then((res) => {
- if (res.status === 200) {
- this.clearSelection()
- this.refresh()
- message.success('删除成功')
- /**
- * 数据删除成功后触发
- * @property {Array} rowKeys 已删除的记录ids
- */
- this.$emit('recordsDeleted', selectedRowKeys)
- } else {
- if (res.errors) {
- message.error(res.errors)
- } else {
- message.error('删除失败,请联系管理员')
- }
- }
- })
- .catch((e) => {
- let messageinfo = '删除失败,请联系管理员'
- if (e.response?.data?.code === '-1') {
- messageinfo = e.response?.data?.message
- } else if (['403', '401'].includes(e.response?.data?.code)) {
- messageinfo = '您没有访问权限'
- } else if (e.response?.data?.code === '405') {
- if (e.response.data && e.response.data.errors) {
- messageinfo = e.response.data.errors
- }
- } else {
- messageinfo = '处理失败,请联系管理员'
- }
- message.error(messageinfo)
- })
- .finally(resolve)
- },
- onCancel: () => {
- resolve()
- },
- })
- }
- })
- },
- /**
- * 获取当前选中的记录(仅包含rowKey)
- * @public
- * @returns {Array}
- */
- getSelectedRowKeys() {
- return this.$refs.dataTable.getSelectedRowKeys()
- },
- /**
- * 获取当前选中的记录
- * @public
- * @returns {Object[]}
- */
- getSelectedRows() {
- return this.$refs.dataTable.getSelectedRows()
- },
- /**
- * 刷新表格
- * @public
- * @param {boolean} toFirstPage 是否返回第一页
- */
- refresh(toFirstPage) {
- return this.$refs.dataTable.refresh(toFirstPage)
- },
- clearSelection() {
- this.$refs.dataTable.clearSelection()
- },
- // 行内的切换按钮。先读取详情,再保存
- onSwitchChange(record, column) {
- this.loadingSwitchs.push(record.id)
- axios({
- url: 'api/framework/v1/page/wp/' + this.pageId,
- method: 'get',
- params: {
- id: record.id,
- },
- })
- .then((res) => {
- const resJson = res.data
- const data = {
- eventId: 'save',
- inputs: resJson.pageFormData.pageFieldInfos.map((v) => ({
- name: v.name,
- value: v.name === column.dataIndex ? booleanUtil.getOppositeValue(v.value) : v.value,
- })),
- pageFlowId: resJson.attrs.pageflowId,
- pagePath: resJson.attrs.pagePath,
- }
- return axios({
- url: 'api/framework/v1/page/handleData',
- method: 'post',
- data,
- })
- })
- .then((res) => {
- this.refresh()
- /**
- * 数据保存成功后触发
- * @property {String} rowKey 已保存的记录id
- */
- this.$emit('recordSaved', record.id)
- })
- .finally(() => {
- const index = this.loadingSwitchs.indexOf(record.id)
- if (index > -1) {
- this.loadingSwitchs.splice(index, 1)
- }
- })
- },
- /**
- * 导出Excel
- * @public
- * @since 0.15
- * @returns {Promise}
- */
- exportExcel() {
- return this.$refs.dataTable.exportExcel()
- },
- /**
- * 重新计算各列的宽度,容器宽度发生变化时,可以调用
- * @public
- * @since 0.15
- */
- handleResize() {
- return this.$refs.dataTable.handleResize()
- },
- },
- /**
- * 详情表单内容
- * @slot form
- * @binding {object} model 整个表单的数据,可用于 v-model 绑定
- * @binding {object} fields 后台返回的字段定义
- * @binding {string} pageId 当前显示详情页使用的pageId,可以为不同pageId画不同的表单
- * @binding {object} formData 当前显示详情页的整个formData(8.1.0.24新增)
- */
- render() {
- const { form: formSlot, ...columnSlots } = this.$scopedSlots
- const { columns, ...restProps } = this.$props
- return (
- <div>
- <SdDataTable
- {...{
- attrs: {
- ...restProps,
- projectlist: this.projectlist,
- editnode: this.editnode,
- columns: this.formatedColumns,
- dataUrl: this.dataUrl,
- actions: this.computedActions,
- processReq: (req) => {
- req.data.formId = this.formId
- if (this.processReq) {
- req = this.processReq(req)
- }
- return req
- },
- },
- ref: 'dataTable',
- on: {
- rowClick: this.rowClick,
- dataLoaded: (pagination) => {
- /**
- * 表格数据加载完成时触发
- * @property {Object} pagination 分页信息{current,pageSize,total}
- */
- this.$emit('tableDataLoaded', pagination)
- },
- onChange: (pagination, filters, sorter) => {
- this.$emit('onChange', pagination, filters, sorter)
- },
- searchbtnClick: () => {
- this.$emit('searchbtnClick')
- },
- selectedRowsChanged: (selectedRows) => {
- this.$emit('selectedRowsChanged', selectedRows)
- },
- fnonloadsum: () => {
- if (this.fnonloadsum !== null) {
- this.fnonloadsum()
- }
- },
- },
- scopedSlots: { ...columnSlots },
- }}
- ></SdDataTable>
- {formSlot ? (
- <SdDetailModal
- ref='detail'
- pageId={this.localPageId}
- recordId={this.recordId}
- extParams={this.extParams}
- onSaved={(data) => {
- this.refresh()
- message.success('保存成功')
- this.$emit('recordSaved', this.recordId || data?.pageFormData?.beanId)
- }}
- onActionBtnClick={(evt, btn) => {
- /**
- * 详情表单内的操作按钮点击时触发
- *
- * @property {event} evt 事件对象,可以用来取消默认操作等
- * @property {object} btn 点击的按钮
- * @property {object} context 上下文信息,其中包括:
- * form:详情对话框
- * recordId:当前记录ID
- */
- this.$emit('formBtnClick', evt, btn, {
- form: this.$refs.detail,
- recordId: this.recordId,
- })
- }}
- scopedSlots={{ default: formSlot }}
- modalProps={this.modalProps}
- />
- ) : (
- ''
- )}
- </div>
- )
- },
- }
- </script>
- <style module lang="scss">
- @use '@/common/design' as *;
- </style>
|