<template>
  <div v-if="Object.is(editorType, 'linkonly')" class="app-picker">
    <a @click="openLinkView">{{ curvalue }}</a>
  </div>
  <div v-else-if="!Object.is(editorType, 'pickup-no-ac') && !Object.is(editorType, 'dropdown')" class="app-picker">
    <div class="app-picker">
      <el-autocomplete class="text-value" :value-key="deMajorField" :disabled="disabled" v-model="curvalue" size="small"
        :trigger-on-focus="true" :fetch-suggestions="
          (query, callback) => {
            this.onSearch(query, callback, true);
          }
        " @select="onACSelect" @input="onInput" @blur="onBlur" style="width: 100%" :placeholder="placeholder" ref="autocomplete" :popper-class="popperClass">
        <template v-slot:default="{ item }">
          <template v-if="item.$uIActionKey && item.$uIActionKey === $uIActionKey">
            <div :class="['app-picker-ui-action',itemClass]" @click.stop @mousedown.prevent>
                <div v-if="items.length === 1" class="app-picker-ui-action__text">{{ emptyText || '暂无数据' }}</div>
                <div v-if="uIActions.length" class="app-picker-ui-action__split"></div>
                <div v-if="uIActions.length" class="app-picker-ui-action-content">
                  <div class="app-picker-ui-action-item" v-for="(uiAction, index) in uIActions" :key="index" :title="uiAction.M.caption" @click="handleUiActionClick(uiAction, $event)">
                    <menu-icon v-if="uiAction.showIcon" class="app-picker-ui-action-item__icon" :item='uiAction.M' />
                    <a v-if="uiAction.showCaption">{{ uiAction.M.caption || '' }}</a>
                  </div>
                </div>
            </div>
          </template>
          <template v-else>
            <template v-if="item.tag">
            <div v-if="acItemPlugin" @click="clickAction(item.tag)"  :class='itemClass'>
              <slot name="acItemPlugin" :item="item"></slot>
            </div>
            <div v-else @click="clickAction(item.tag)" :title="item[deMajorField]"  :class='itemClass'>{{ item[deMajorField] }}</div>
          </template>
          <slot v-else-if="acItemPlugin" name="acItemPlugin" :item="item"></slot>
          <slot v-else name="default">
            <div :title="item[deMajorField]" :class='itemClass'>{{ item[deMajorField] }}</div>
          </slot>
          </template>
        </template>
        <template v-slot:suffix>
          <i v-if="curvalue && !disabled" class="el-icon-circle-close" @click="onClear"></i>
          <i v-if="!Object.is(editorType, 'ac') && showButton" class="el-icon-search" @click="openView"></i>
          <icon v-if="linkview" type="ios-open-outline" @click="openLinkView" />
        </template>
      </el-autocomplete>
    </div>
  </div>
  <div v-else-if="Object.is(editorType, 'pickup-no-ac')" class="app-picker">
    <div class="app-picker">
      <el-input class="text-value" :placeholder="placeholder" :value="curvalue" readonly size="small"
        :disabled="disabled">
        <template slot="suffix">
          <i v-if="curvalue && !disabled" class="el-icon-circle-close" @click="onClear"></i>
          <i class="el-icon-search" @click="openView"></i>
          <icon v-if="linkview" type="ios-open-outline" @click="openLinkView" />
        </template>
      </el-input>
    </div>
  </div>
  <div v-else-if="Object.is(editorType, 'dropdown')" class="app-picker">
    <el-select ref="appPicker" remote :remote-method="query => this.onSearch(query, null, true)"
      :value="showSelectVal ? refvalue : undefined" size="small" :loading="loading" filterable @change="onSelect"
      :disabled="disabled" style="width: 100%" clearable popper-class="app-picker-dropdown" @clear="onClear"
      @visible-change="onSelectOpen" :placeholder="placeholder">
      <template v-if="loading" slot="empty">
        <li class="loading">
          <i class="el-icon-loading"></i>
        </li>
      </template>
      <template v-if="items">
        <template v-for="(_item, index) in items">
          <el-option :title="_item[deMajorField]" v-if="!_item.tag"
            :key="`${_item[deKeyField]}${index}${parentCodeName}`" :value="_item[deKeyField]"
            :label="_item[deMajorField]" :disabled="_item.disabled" :class="itemClass">
            <slot v-if="acItemPlugin" name="acItemPlugin" :item="_item"></slot>
            <span v-else>{{ _item[deMajorField] }}</span>
          </el-option>
          <el-option v-else :key="`${_item[deKeyField]}${index}${parentCodeName}`" value="action" :class="itemClass">
            <span @click="clickAction(_item.tag)" style="float: left; width: 100%" :title="_item[deMajorField]">
              <slot v-if="acItemPlugin" name="acItemPlugin" :item="_item"></slot>
              <span v-else>{{ _item[deMajorField] }}</span>
            </span>
          </el-option>
        </template>
      </template>
      <div v-if="items.length === 0" class="app-picker-nodata">{{emptyText || '暂无数据'}}</div>
      <div v-if="uIActions.length" class="app-picker-uiaction-split"></div>
      <template v-if="uIActions.length">
        <el-option value="action" :class="['app-picker-uiaction',itemClass]">
          <template v-for="(uiaction, index) in uIActions">
            <div  @click="uiActionClick(uiaction, $event)"  class="app-picker-uiaction-item" :key="index" :title="uiaction.getPSUIAction().caption">
              <menu-icon v-if="uiaction.showIcon" :item='uiaction._data' />
              <a v-if="uiaction.showCaption">{{uiaction.getPSUIAction().caption}}</a>
            </div>
          </template>
        </el-option>
      </template>
    </el-select>
    <span style="position: absolute; right: 5px; color: #c0c4cc; top: 0; font-size: 13px">
      <i v-show="open" class="el-icon-arrow-up" @click="closeDropdown"></i>
      <i v-show="!open" class="el-icon-arrow-down" @click="openDropdown"></i>
    </span>
  </div>
</template>

<script lang = 'ts'>
import { Component, Vue, Prop, Model, Watch, Inject } from 'vue-property-decorator';
import { Subject, Subscription } from 'rxjs';
import { Util, ModelTool, ViewTool, IPSUIActionGroupDetail } from '@ibizstudio/runtime';
import {
  IPSAppDataEntity,
  IPSAppDERedirectView,
  IPSAppDEView,
  IPSAppViewRef,
  IPSNavigateContext,
  IPSAppView,
  IPSPicker,
} from '@ibizstudio/runtime';
import { UIServiceRegister } from '@ibizstudio/runtime';
import { winMsg } from '../../../ibz-studio-plugins';
import { isNilOrEmpty, notNilEmpty } from 'qx-util';
import { AppViewLogicService } from '../../..';
import { calcEditorDropdownWidth } from '../utils';

@Component({})
export default class AppPicker extends Vue {
  /**
   * 视图上下文
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop() context!: any;

  /**
   * 视图参数
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop() viewparams!: any;

  /**
   * AC参数
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop({ default: () => { } }) acParams?: any;

  /**
   * 外键值附加数据
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop() pickUpData?: string;

  /**
   * 表单服务
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop() service?: any;

  /**
   * 应用实体主信息属性名称
   *
   * @type {string}
   * @memberof AppPicker
   */
  @Prop({ default: 'srfmajortext' }) deMajorField!: string;

  /**
   * 应用实体主键属性名称
   *
   * @type {string}
   * @memberof AppPicker
   */
  @Prop({ default: 'srfkey' }) deKeyField!: string;

  /**
   * 表单数据
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop() data!: any;

  /**
   * 属性项名称
   *
   * @type {string}
   * @memberof AppPicker
   */
  @Prop() name!: string;

  /**
   * 是否启用
   *
   * @type {boolean}
   * @memberof AppPicker
   */
  @Prop() disabled?: boolean;

  /**
   * 是否显示按钮
   *
   * @type {boolean}
   * @memberof AppPicker
   */
  @Prop({ default: true }) showButton?: boolean;

  /**
   * 类型
   *
   * @type {string}
   * @memberof AppPicker
   */
  @Prop() editorType?: string;

  /**
   * 视图参数（如：视图name，title，width，height）
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop() pickupView?: any;

  /**
   * 数据链接参数
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop() linkview?: any;

  /**
   * 局部上下文导航参数
   *
   * @type {any}
   * @memberof AppPicker
   */
  @Prop() localContext!: any;

  /**
   * 局部导航参数
   *
   * @type {any}
   * @memberof AppPicker
   */
  @Prop() localParam!: any;

  /**
   * 值项名称
   *
   * @type {string}
   * @memberof AppPicker
   */
  @Prop() valueitem!: string;

  /**
   * 排序
   *
   * @type {string}
   * @memberof AppPicker
   */
  @Prop() sort?: string;

  /**
   * 行为组
   *
   * @type {Array<any>}
   * @memberof AppPicker
   */
  @Prop() actionDetails?: Array<any>;

  /**
   * 值
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Model('change') value?: any;

  /**
   * 占位提示
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop() placeholder?: string;

  /**
   * 编辑器模型
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop() editorInstance?: any;

  /**
   * 父容器标识
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop() parentCodeName?: string;

  /**
   * 值格式化
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop() valFormat?: any;

  /**
   * 自填项插件是否存在
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Prop({ default: false }) acItemPlugin!: boolean;

  /**
   * 数据项
   *
   * @type {Array<any>}
   * @memberof AppPicker
   */
  @Prop() dataItems?: Array<any>;  
    
/**
 * 是否支持分页
 *
 * @type {boolean}
 * @memberof AppPicker
 */
  @Prop({ default: false }) enablePagingBar?: boolean;    
    
/**
 * 分页条数
 *
 * @type {boolean}
 * @memberof AppPicker
 */
  @Prop({ default: 100 }) limit?: number;    

  /**
   * 表单状态对象
   *
   * @type {*}
   * @memberof AppPicker
   */
  @Inject('formState')
  formState!: Subject<any>

  /**
   * 订阅对象
   *
   * @type {*}
   * @memberof AppPicker
   */
  protected formStateEvent: Subscription | undefined;

  /**
   * 下拉远程加载状态
   *
   * @type {boolean}
   * @memberof AppPicker
   */
  loading: boolean = false;

  /**
   * 是否显示select的值
   *
   * @type {boolean}
   * @memberof AppPicker
   */
  showSelectVal: boolean = true;

  /**
   * 当前值
   *
   * @type {string}
   * @memberof AppPicker
   */
  curvalue: string = '';

  /**
   * 下拉数组
   * @type {any[]}
   * @memberof AppPicker
   */
  items: any[] = [];

  /**
   * 下拉图标指向状态管理
   * @type {boolean}
   * @memberof AppPicker
   */
  open: boolean = false;

  /**
   * 输入状态
   *
   * @type {boolean}
   * @memberof AppPicker
   */
  inputState: boolean = false;

  /**
   * 当前选择的值
   *
   * @type {string}
   * @memberof AppPicker
   */
  selectValue = null;

  /**
   * 下拉列表节点元素
   *
   * @type {*}
   * @memberof AppPicker
   */
  dropdownDom: any = {};

  /**
   * 自动填充
   *
   * @type {*}
   * @memberof AppPicker
   */
  autocomplete: any = {};


  /**
   * 加载完毕前阻止搜索请求
   *
   * @type {*}
   * @memberof AppPicker
   */
   isOk: boolean = false;

  /**
   * 界面行为组
   *
   * @type {*}
   * @memberof AppPicker
   */
   uIActions: any[] = [];

  /**
   * 无值显示内容
   *
   * @type {*}
   * @memberof AppPicker
   */
   emptyText: string = '';

  /**
   * 选项行样式名
   *
   * @type {string}
   * @memberof DropDownList
   */    
   itemClass: string = ''
    
  /**
    * 选项组样式名
    *
    * @type {string}
    * @memberof DropDownList
    */    
   transferClass: string = 'transferDropdownWidth'


  /**
   * 界面行为组项key
   *
   * @type {string}
   * @memberof AppPicker
   */
  $uIActionKey: string = '';

  
  /**
   * loading宽度
   *
   * @type {string}
   * @memberof AppPicker
   */
  loadingWidth: number = 0;


  /**
   * 弹出框class类名
   *
   * @type {string}
   * @memberof AppPicker
   */
  get popperClass() {
    return 'app-picker-ui-action-popper transferDropdownWidth';
  }

  /**
   * 获取关联数据项值
   *
   * @readonly
   * @memberof AppPicker
   */
  get refvalue() {
    if (this.valueitem && this.data) {
      const key = this.data[this.valueitem];
      if (this.valFormat) {
        const format = eval('(' + this.valFormat + ')');
        if (format.hasOwnProperty(key)) {
          if (!Util.isEmpty(this.curvalue)) {
            return format[key];
          } else {
            return '';
          }
        }
      }
      if (!Util.isEmpty(this.curvalue)) {
        return key;
      } else {
        return '';
      }
    }
    return this.curvalue;
  }

  /**
   * 值变化
   *
   * @param {*} newVal
   * @param {*} oldVal
   * @memberof AppPicker
   */
  @Watch('value', { immediate: true })
  onValueChange(newVal: any, oldVal: any) {
    this.curvalue = newVal;
    this.selectValue = newVal;
    if (Object.is(this.editorType, 'dropdown') && this.valueitem) {
      const value = this.data[this.valueitem];
      const index = this.items.findIndex((item: any) => Object.is(item[this.deKeyField], value));
      if (index !== -1) {
        return;
      }
      // items里匹配不到当前值项值时，生成自身的选项
      this.items = [];
      if (!Util.isEmpty(newVal) && !Util.isEmpty(value)) {
        this.items.push({ [this.deMajorField]: newVal, [this.deKeyField]: value });
      }
    }
  }

  /**
   * 值项值变化
   *
   * @param {*} newVal
   * @param {*} oldVal
   * @memberof AppPicker
   */
  @Watch('refvalue', { immediate: true })
  onRefValueChange(newVal: any, oldVal: any) {
    // 空值和值不变，不进行处理
    if (isNilOrEmpty(newVal) || newVal == oldVal) {
      return;
    }
    // 当值项的值与选项不匹配时重新加载选项数据
    const index = this.items.findIndex((item: any) => Object.is(item[this.deKeyField], newVal));
    if (index !== -1) {
      return;
    }

    // 重新加载选项数据,先隐藏select的值，否则在选项加载变更之前，会因为匹配不到选项而短暂的显示value值。
    if(!this.isOk){
      return;   
    }
    this.showSelectVal = false;
    this.onSearch(this.curvalue, () => {
      this.showSelectVal = true;
    }, true);
  }

  /**
   * vue 生命周期
   *
   * @memberof AppPicker
   */
  created() {
    if (!Object.is(this.editorType, 'pickup-no-ac')) {
      this.curvalue = this.value;
    }
    if (this.formState) {
      this.formStateEvent = this.formState.subscribe(({ type, data }) => {
        if (Object.is('load', type)) {
          this.initDropDownData();
          this.isOk = true;
        }
      });
    }
    this.$uIActionKey = Util.createUUID();
  }

  /**
   * vue 生命周期
   *
   * @memberof AppPicker
   */
  mounted() {
    const dropdownDom: any = this.$el.getElementsByClassName('app-picker-dropdown')[0];
    this.dropdownDom = dropdownDom;
    this.autocomplete =  this.$refs.autocomplete as any;
    const uIActions = this.editorInstance?.getPSUIActionGroup()?.getPSUIActionGroupDetails();
    this.emptyText = this.editorInstance?.getPSAppDEACMode()?.emptyText;
    if (uIActions) {
      this.uIActions = uIActions;
    } 
      
  }

  /**
   * 组件销毁
   *
   * @memberof AppPicker
   */
  destroyed(): void {
    if (this.formStateEvent) {
      this.formStateEvent.unsubscribe();
    }
  }

  /**
   * 界面行为
   *
   * @param {*} detail 界面行为
   * @param {*} $event 事件源
   * @memberof AppPicker
   */
  uiActionClick(detail: any, $event: any) {
    AppViewLogicService.getInstance().executeViewLogic(`${this.name}_editor_${detail.name}_click`, $event, this, null, this.service.controlInstance?.getPSAppViewLogics() as any);
  }

    /**
   * 初始化下拉列表数据
   *
   * @memberof AppPicker
   */
  async initDropDownData() {
    if (Object.is(this.editorType, 'dropdown') && this.valueitem) {
      const value = this.data[this.valueitem];
      const name = this.data[this.name];
      if (notNilEmpty(value) && isNilOrEmpty(name)) {
        this.items = [];
        const index = await this.FindMoreItem(-1,0,value)
        if (index !== -1 && !this.curvalue) {
          this.onACSelect(this.items[index]);
        }
      }
    }
  }


  async FindMoreItem(index:number,page:number,value:any):Promise<any>{
    if(index !== -1){
     return index
    }
    if(page>9){
     return -1
    }
    await this.onSearch(this.curvalue, null, true, page);
    const index1 = this.items.findIndex((item: any) => Object.is(item[this.deKeyField], value));
    return await this.FindMoreItem(index1,page+1,value)
  }

  /**
   * 下拉切换回调
   * @param flag
   */
  onSelectOpen(flag: boolean): void {
    this.open = flag;
    if (this.open) {
      this.items = [];
      //设置下拉列表的最大宽度
      // this.setDropdownWidth();
      if (this.dropdownDom) {
        const el = this.$el as HTMLElement;
        if (el) {
          this.dropdownDom.style.minWidth = `${el.offsetWidth}px`;
          this.dropdownDom.style.maxWidth = `${el.offsetWidth > 700 ? el.offsetWidth : 700}px`;
        }
      }
      this.onSearch(this.curvalue, null, true);
    }
  }

  /**
   * 设置下拉列表最大宽度使下拉列表宽度和编辑器宽度一致
   *
   * @memberof AppPicker
   */
  setDropdownWidth() {
    const elInput: any = this.$el.getElementsByClassName('el-input__inner')[0];
    this.dropdownDom.style.maxWidth = elInput.offsetWidth + 'px';
  }

  /**
   * 关闭弹出框
   *
   * @memberof AppPicker
   */
  closePopper() {
    const el = this.$refs.autocomplete as unknown as { close: () => void };
    if (el) {
      el.close();
    }
  }

  /**
   * 处理界面行为点击
   *
   * @memberof AppPicker
   */
  handleUiActionClick(item: IPSUIActionGroupDetail, e: MouseEvent) {
    e.stopPropagation();
    this.closePopper();
    this.uiActionClick(item, e);
  }

  /**
   * 执行搜索数据
   * @param query
   * @param callback
   */
  async onSearch(query: any, callback: any, other: boolean, page = 0): Promise<void> {
    // 公共参数处理
    if (this.autocomplete) {
      const suggestions = this.autocomplete.$refs.suggestions?.$el as HTMLElement;
      const el = this.$el as HTMLElement;
      if (suggestions && el) {
        suggestions.style.minWidth = `${el.offsetWidth}px`;
        suggestions.style.maxWidth = `${el.offsetWidth > 700 ? el.offsetWidth : 700}px`;
      }
    }
    const data: any = {};
    const bcancel: boolean = this.handlePublicParams(data);
    if (!bcancel || !this.acParams) {
      return;
    }
    if (!this.acParams) {
      console.log(this.name, '未配置 acParams 参数');
      return;
    }
    // 处理搜索参数
    let _context = data.context;
    let _param = data.param;
    query = !query ? '' : query.trim();
    if (!this.inputState && other && Object.is(query, this.value)) {
      query = '';
    }
    this.inputState = false;
    Object.assign(_param, { query: query});
    if (this.sort && !Object.is(this.sort, '')) {
      Object.assign(_param, { sort: this.sort });
    }
    if (this.enablePagingBar) {
      Object.assign(_param, { size: this.limit , page : page });
    }
    if (this.service && this.acParams.serviceName && this.acParams.interfaceName) {
      this.loading = true;
      const response = await this.service.getItems(this.acParams.serviceName, this.acParams.interfaceName, _context, _param);
      this.loading = false;
      if(page === 0 && response){
        this.items = [...response];
      }else{
        this.items = [...response,...this.items];
      }
      if (this.acParams && this.actionDetails && this.actionDetails.length > 0) {
        this.items = [...this.items, ...this.actionDetails];
      }
      // 处理自填模式数据项
      this.items = this.handleDataItems(this.items);
    }
    if (callback) {
      if (this.editorType !== 'pickup-no-ac' && this.editorType !== 'dropdown') {
        this.items.push({ [this.deMajorField]: '', [this.deKeyField]: this.$uIActionKey, $uIActionKey: this.$uIActionKey });
      }
      callback(this.items);
      this.$nextTick(() => {
        setTimeout(() => {
          if (this.autocomplete) {
            this.autocomplete.$refs.suggestions?.updatePopper();
          }
        }, 0)
      })
    }
  }

    /**
     * 处理数据项转化
     *
     * @memberof AppPicker
     */
    handleDataItems(data: any) {
        const opts = Util.deepCopy(data);
        if (this.dataItems && this.dataItems.length > 0) {
            if (opts && opts.length > 0) {
                for(let element  of opts){
                    for (let item of this.dataItems as Array<any>) {
                        if (!item.customCode) {
                            const value = element[item.name]
                            if (item.getPSAppDEField()?.codeName && isNilOrEmpty(value)) {
                                element[item.name] = element[item.getPSAppDEField().codeName.toLowerCase()];
                            }
                        }
                    }
                    // 先计算非脚本的数据项，防止数据有误
                    for (let item of this.dataItems as Array<any>) {
                        const value = element[item.name]
                        if (item.customCode && isNilOrEmpty(value)) {
                            element[item.name] = eval(`${item.scriptCode}`);
                        }
                    }
                }
            }
        }
        return opts;
    }  

  /**
   * 选中数据回调
   * @param item
   */
  onACSelect(item: any): void {
    if (this.valueitem) {
      this.$emit('formitemvaluechange', { name: this.valueitem, value: item[this.deKeyField] });
    }
    if (this.name) {
      this.$emit('formitemvaluechange', { name: this.name, value: item[this.deMajorField] });
    }
    this.fillPickUpData(item);
  }

  /**
   * 下拉选中
   *
   * @param {string} val
   * @memberof AppPicker
   */
  onSelect(val: string) {
    let index = this.items.findIndex(item => Object.is(item[this.deKeyField], val));
    if (index >= 0) {
      this.onACSelect(this.items[index]);
    }
  }

  /**
   * 失去焦点事件
   * @param e
   */
  onBlur(e: any): void {
    this.curvalue = this.value;
  }

  /**
   * 清除
   */
  onClear($event: any): void {
    if (this.valueitem) {
      this.$emit('formitemvaluechange', { name: this.valueitem, value: null });
    }
    if (this.name) {
      this.$emit('formitemvaluechange', { name: this.name, value: null });
    }
    this.fillPickUpData();
    this.$forceUpdate();
  }

  /**
   * 打开视图
   */
  openView($event: any): void {
    if (this.disabled) {
      return;
    }
    // 公共参数处理
    let data: any = {};
    const bcancel: boolean = this.handlePublicParams(data);
    if (!bcancel) {
      return;
    }
    // 参数处理
    const view = { ...this.pickupView };
    let _context = data.context;
    let _param = data.param;
    if (this.valueitem && this.data && this.data[this.valueitem] && this.curvalue) {
      _param.selectedData = [{ srfkey: this.data[this.valueitem], srfmajortext: this.curvalue }];
    }
    // 判断打开方式
    view.placement = view.placement || '';
    if (view.placement === 'POPOVER') {
      this.openPopOver($event, view, _context, _param);
    } else if (view.placement.indexOf('DRAWER') !== -1) {
      this.openDrawer(view, _context, _param);
    } else {
      this.openPopupModal(view, _context, _param);
    }
    this.closePopper();
  }

  /**
   * 路由模式打开视图
   *
   * @private
   * @param {*} view
   * @param {*} context
   * @param {*} param
   * @memberof AppPicker
   */
  private openIndexViewTab(view: any, context: any, param: any): void {
    if (context.srfdynainstid) {
      Object.assign(param, { srfdynainstid: context.srfdynainstid });
    }
    const routePath = this.$viewTool.buildUpRoutePath(
      this.$route,
      context,
      view.deResParameters,
      view.parameters,
      [this.data],
      param,
    );
    this.$router.push(routePath);
  }

  /**
   * 模态模式打开视图
   *
   * @private
   * @param {*} view
   * @param {*} data
   * @memberof AppPicker
   */
  private openPopupModal(view: any, context: any, param: any): void {
    if (view.viewpath) {
      Object.assign(context, { viewpath: view.viewpath });
    }
    let container: Subject<any> = this.$appmodal.openModal(view, context, param);
    container.subscribe((result: any) => {
      if (!result || !Object.is(result.ret, 'OK')) {
        return;
      }
      this.openViewClose(result);
    });
  }

  /**
   * 抽屉模式打开视图
   *
   * @private
   * @param {*} view
   * @param {*} data
   * @memberof AppPicker
   */
  private openDrawer(view: any, context: any, param: any): void {
    if (view.viewpath) {
      Object.assign(context, { viewpath: view.viewpath });
    }
    let container: Subject<any> = this.$appdrawer.openDrawer(view, Util.getViewProps(context, param));
    container.subscribe((result: any) => {
      if (!result || !Object.is(result.ret, 'OK')) {
        return;
      }
      this.openViewClose(result);
    });
  }

  /**
   * 气泡卡片模式打开
   *
   * @private
   * @param {*} $event
   * @param {*} view
   * @param {*} data
   * @memberof AppPicker
   */
  private openPopOver($event: any, view: any, context: any, param: any): void {
    if (view.viewpath) {
      Object.assign(context, { viewpath: view.viewpath });
    }
    let container: Subject<any> = this.$apppopover.openPop($event, view, context, param);
    container.subscribe((result: any) => {
      if (!result || !Object.is(result.ret, 'OK')) {
        return;
      }
      this.openViewClose(result);
    });
  }

  /**
   * 独立里面弹出
   *
   * @private
   * @param {string} url
   * @memberof AppPicker
   */
  private openPopupApp(url: string): void {
    window.open(url, '_blank');
  }

  /**
   * 打开重定向视图
   *
   * @private
   * @param {*} $event
   * @param {*} view
   * @param {*} data
   * @memberof AppPicker
   */
  private async openRedirectView($event: any, context: any, params: any) {
    const targetRedirectView: IPSAppDERedirectView = this.linkview.viewModel;
    await targetRedirectView.fill(true);
    if (
      targetRedirectView.getRedirectPSAppViewRefs() &&
      targetRedirectView.getRedirectPSAppViewRefs()?.length === 0
    ) {
      return;
    }
    const redirectUIService: any = await UIServiceRegister.getService(
      context,
      (ModelTool.getViewAppEntityCodeName(targetRedirectView) as string)?.toLowerCase(),
    );
    await redirectUIService.loaded();
    const redirectAppEntity: IPSAppDataEntity | null = targetRedirectView.getPSAppDataEntity();
    await ViewTool.calcRedirectContext(context, this.data, redirectAppEntity);
    if (targetRedirectView.codeName === 'PSSysAppLinkRedirectView' || targetRedirectView.codeName === 'PSAppViewDesignRedirectView') {
      let type = '';
      if (this.localContext.LINKID) {
        context[this.localContext.LINKID] = this.data[this.valueitem];
      }
      const linkType: string = this.localParam.linktype;
      if (linkType) {
        if (linkType.indexOf('static:') !== -1) {
          type = linkType.substring(7);
        } else {
          type = this.data[linkType];
        }
      } else {
        const pModel = targetRedirectView.getParentPSModelObject() as IPSPicker;
        const entity = pModel.getPSAppDataEntity()!;
        if (entity) {
          if (!entity.isFill) {
            await entity.fill(true);
          }
          const deName = entity.codeName.toLowerCase();
          context[deName] = context[deName + 'id'];
          type = deName.toUpperCase();
        }
      }
      if (notNilEmpty(type)) {
        winMsg.openView(type, context, params, [this.data]);
      } else {
        console.warn('未找到对应实体类型，暂时无法打开iframe级别视图跳转!');
      }
      return;
    }
    const tag = await this.calcDERdTag(redirectAppEntity!, targetRedirectView, '', this.data);
    const targetOpenViewRef = targetRedirectView.getRedirectPSAppViewRefs()?.find((item: IPSAppViewRef) => item.name === tag);
    if (!targetOpenViewRef) {
      return;
    }
    if (
      targetOpenViewRef.getPSNavigateContexts() &&
      (targetOpenViewRef.getPSNavigateContexts() as IPSNavigateContext[]).length > 0
    ) {
      const localContextRef: any = Util.formatNavParam(targetOpenViewRef.getPSNavigateContexts(), true);
      const _context: any = Util.computedNavData(this.data, context, params, localContextRef);
      Object.assign(context, _context);
    }
    const targetOpenView: IPSAppView | null = targetOpenViewRef.getRefPSAppView();
    if (!targetOpenView) {
      return;
    }
    await targetOpenView.fill(true);
    const view: any = {
      viewname: Util.srfFilePath2(targetOpenView.codeName),
      height: targetOpenView.height,
      width: targetOpenView.width,
      title: this.$tl(targetOpenView.getCapPSLanguageRes()?.lanResTag, targetOpenView.title),
      placement: targetOpenView.openMode ? targetOpenView.openMode : '',
      viewpath: targetOpenView.modelFilePath,
    };
    if (!targetOpenView.openMode || targetOpenView.openMode == 'INDEXVIEWTAB') {
      if (targetOpenView.getPSAppDataEntity()) {
        view.deResParameters = Util.formatAppDERSPath(
          context,
          (targetOpenView as IPSAppDEView).getPSAppDERSPaths(),
        );
        view.parameters = [
          {
            pathName: Util.srfpluralize(
              (targetOpenView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName,
            ).toLowerCase(),
            parameterName: (
              targetOpenView.getPSAppDataEntity() as IPSAppDataEntity
            )?.codeName.toLowerCase(),
          },
          {
            pathName: 'views',
            parameterName: ((targetOpenView as IPSAppDEView).getPSDEViewCodeName() as string).toLowerCase(),
          },
        ];
      } else {
        view.parameters = [
          {
            pathName: targetOpenView.codeName.toLowerCase(),
            parameterName: targetOpenView.codeName.toLowerCase(),
          },
        ];
      }
    } else {
      if (targetOpenView.getPSAppDataEntity()) {
        view.parameters = [
          {
            pathName: Util.srfpluralize(
              (targetOpenView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName,
            ).toLowerCase(),
            parameterName: (
              targetOpenView.getPSAppDataEntity() as IPSAppDataEntity
            )?.codeName.toLowerCase(),
          },
        ];
      }
      if (targetOpenView && targetOpenView.modelPath) {
        Object.assign(context, { viewpath: targetOpenView.modelPath });
      }
    }
    if (Object.is(view.placement, 'INDEXVIEWTAB') || Util.isEmpty(view.placement)) {
      this.openIndexViewTab(view, context, params);
    } else if (Object.is(view.placement, 'POPOVER')) {
      this.openPopOver($event, view, context, params);
    } else if (Object.is(view.placement, 'POPUPMODAL')) {
      this.openPopupModal(view, context, params);
    } else if (view.placement.startsWith('DRAWER')) {
      this.openDrawer(view, context, params);
    }
  }


  /**
   * 计算重定向标识
   *
   * @author chitanda
   * @date 2022-10-25 16:10:48
   * @export
   * @param {IPSAppDataEntity} entity 重定向视图所在应用实体
   * @param {IPSAppDERedirectView} rdView 重定向视图
   * @param {string} wfStep 流程步骤
   * @param {*} data 当前数据
   * @return {*}  {Promise<string>}
   */
  async calcDERdTag(
    entity: IPSAppDataEntity,
    rdView: IPSAppDERedirectView,
    wfStep: string,
    data: any,
  ): Promise<string> {
    let rdTag = '';
    // 重定向视图自定义类别属性
    const typeField = rdView.getTypePSAppDEField();
    // 自定义重定向
    if (typeField) {
      const value = data[typeField.codeName.toLowerCase()];
      if (notNilEmpty(value)) {
        return value;
      }
    }
    // 如果流程步骤存在，按照工作流优先
    if (notNilEmpty(wfStep)) {
      return `EDITVIEW:${wfStep.toUpperCase()}`;
    }
    let typeValue = '';
    // 从索引属性获取重定向视图类型
    const indexTypeField = entity.getIndexTypePSAppDEField();
    if (indexTypeField) {
      typeValue = data[indexTypeField.codeName.toLowerCase()];
    }
    if (isNilOrEmpty(typeValue)) {
      // 从多表单属性判断重定向视图类型
      const multiFormField = entity.getFormTypePSAppDEField();
      if (multiFormField) {
        typeValue = data[multiFormField.codeName.toLowerCase()];
      }
    }
    if (notNilEmpty(typeValue)) {
      rdTag = `EDITVIEW:${typeValue}`;
    } else {
      rdTag = `EDITVIEW`;
    }
    return rdTag;
  }

  /**
   * 打开链接视图
   *
   * @memberof AppPicker
   */
  openLinkView($event: any): void {
    if (!this.data || !this.valueitem || !this.data[this.valueitem]) {
      this.$throw(this.$t('components.apppicker.valueitemexception') as any, 'openLinkView');
      return;
    }
    // 公共参数处理
    let data: any = {};
    const bcancel: boolean = this.handlePublicParams(data);
    if (!bcancel) {
      return;
    }
    // 参数处理
    let _context = data.context;
    let _param = data.param;
    Object.assign(_context, { [this.deKeyField]: this.data[this.valueitem] });
    const view = { ...this.linkview };
    const viewname2: string = view.viewname;
    view.viewname = viewname2;
    if (view.isRedirectView) {
      this.openRedirectView($event, _context, _param);
    } else if (Object.is(view.placement, 'INDEXVIEWTAB') || Util.isEmpty(view.placement)) {
      this.openIndexViewTab(view, _context, _param);
    } else if (Object.is(view.placement, 'POPOVER')) {
      this.openPopOver($event, view, _context, _param);
    } else if (view.placement.startsWith('DRAWER')) {
      this.openDrawer(view, _context, _param);
    } else if (Object.is(view.placement, 'POPUPMODAL')) {
      this.openPopupModal(view, _context, _param);
    }
    this.closePopper();
  }

  /**
   * 打开页面关闭
   *
   * @param {*} result
   * @memberof AppPicker
   */
  openViewClose(result: any) {
    let item: any = {};
    if (result.datas && Array.isArray(result.datas)) {
      Object.assign(item, result.datas[0]);
    }

    if (this.data) {
      if (this.valueitem) {
        this.$emit('formitemvaluechange', {
          name: this.valueitem,
          value: item[this.deKeyField] ? item[this.deKeyField] : item['srfkey'],
        });
      }
      if (this.name) {
        this.$emit('formitemvaluechange', {
          name: this.name,
          value: item[this.deMajorField] ? item[this.deMajorField] : item['srfmajortext'],
        });
      }
      this.fillPickUpData(item);
    }
  }

  /**
   * 公共参数处理
   *
   * @param {*} arg
   * @returns
   * @memberof AppPicker
   */
  handlePublicParams(arg: any): boolean {
    if (!this.data) {
      this.$throw(this.$t('components.apppicker.formdataexception') as any, 'handlePublicParams');
      return false;
    }
    // 合并表单参数
    arg.param = this.viewparams ? JSON.parse(JSON.stringify(this.viewparams)) : {};
    arg.context = this.context ? JSON.parse(JSON.stringify(this.context)) : {};
    // 附加参数处理
    if (this.localContext && Object.keys(this.localContext).length > 0) {
      let _context = this.$util.computedNavData(this.data, arg.context, arg.param, this.localContext);
      Object.assign(arg.context, _context);
    }
    if (this.localParam && Object.keys(this.localParam).length > 0) {
      let _param = this.$util.computedNavData(this.data, arg.context, arg.param, this.localParam);
      Object.assign(arg.param, _param);
    }
    return true;
  }

  /**
   * 触发界面行为
   *
   * @param {*} arg
   * @returns
   * @memberof AppPicker
   */
  clickAction(arg: any) {
    this.$emit('editoractionclick', arg);
  }

  /**
   * 创建并编辑
   *
   * @param {*} arg
   * @returns
   * @memberof AppPicker
   */
  newAndEdit($event: any) {
    if (this.disabled) {
      return;
    }
    // 公共参数处理
    let data: any = {};
    const bcancel: boolean = this.handlePublicParams(data);
    if (!bcancel) {
      return;
    }
    // 参数处理
    const view = { ...this.linkview };
    view.viewname = this.$util.srfFilePath2(view.viewname);
    let _context = data.context;
    delete _context[this.deKeyField];
    let _param = data.param;
    // 判断打开方式
    if (view.placement && !Util.isEmpty(view.placement)) {
      if (Object.is(view.placement, 'POPOVER')) {
        this.openPopOver($event, view, _context, _param);
      } else {
        this.openDrawer(view, _context, _param);
      }
    } else {
      this.openPopupModal(view, _context, _param);
    }
  }

  /**
   * 输入过程中
   *
   * @memberof AppPicker
   */
  onInput($event: any) {
    if (Object.is($event, this.value)) {
      this.inputState = true;
    }
  }

  /**
   * 展开下拉
   *
   * @memberof AppPicker
   */
  openDropdown() {
    const appPicker: any = this.$refs.appPicker;
    if (appPicker) {
      appPicker.focus();
    }
  }

  /**
   * 收起下拉
   *
   * @memberof AppPicker
   */
  closeDropdown() {
    const appPicker: any = this.$refs.appPicker;
    if (appPicker) {
      appPicker.blur();
    }
  }

  /**
   * 填充外键值附加数据
   *
   * @param {item} 数据集
   * @memberof AppPicker
   */
  fillPickUpData(item?: any) {
    if (this.pickUpData) {
      let pickUpDataArray: Array<any> = this.pickUpData.split(';');
      if (pickUpDataArray && pickUpDataArray.length > 0) {
        for (let i = 0; i < pickUpDataArray.length; i++) {
          if (item) {
            this.$emit('formitemvaluechange', {
              name: pickUpDataArray[i],
              value: item[pickUpDataArray[i]],
            });
          } else {
            this.$emit('formitemvaluechange', {
              name: pickUpDataArray[i],
              value: '',
            });
          }
        }
      }
    }
  }
}
</script>
<style lang="less">
@import './app-picker.less';
</style>