feat: 添加下拉远程搜索并完善登录会话
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
e785a99b7d
commit
55f13bb47b
15
src/App.vue
15
src/App.vue
@ -6,6 +6,7 @@ import { audioManager } from '@/utils/audioManager'
|
||||
|
||||
import util from '@/common/util.js';
|
||||
import md5 from '@/common/md5.js';
|
||||
import { restoreUserSession } from '@/common/userSession.js';
|
||||
export default {
|
||||
globalData: {
|
||||
AppName: '',
|
||||
@ -25,6 +26,7 @@ import { audioManager } from '@/utils/audioManager'
|
||||
|
||||
onLaunch() {
|
||||
console.log('App Launch');
|
||||
restoreUserSession();
|
||||
|
||||
// 初始化音频管理器
|
||||
audioManager.init();
|
||||
@ -374,4 +376,17 @@ import { audioManager } from '@/utils/audioManager'
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.u-select__search,
|
||||
.u-action-sheet-search,
|
||||
.u-dropdown-item__search {
|
||||
height: 88rpx !important;
|
||||
}
|
||||
|
||||
.u-select__search__input,
|
||||
.u-action-sheet-search__input,
|
||||
.u-dropdown-item__search__input {
|
||||
font-size: 32rpx !important;
|
||||
height: 88rpx !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -142,6 +142,8 @@ const install = (Vue, vm) => {
|
||||
// PDA登录接口
|
||||
pdaLogin: (params = {}) => vm.$u.postJson('/login', params),
|
||||
pdaLogout: (params = {}) => vm.$u.postJson('/logout', params),
|
||||
// 登录后获取当前用户信息、菜单与按钮权限
|
||||
pdaGetInformation: (params = {}) => vm.$u.get('/information', params),
|
||||
// 获取配布单列表
|
||||
getFpmArrangeOrderList: (params = {}) => vm.$u.get('/product/fpmArrangeOrder/getFpmArrangeOrderList', params),
|
||||
// 获取成品配布单详情
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
||||
*/
|
||||
// 此处第二个参数vm,就是我们在页面使用的this,你可以通过vm获取vuex等操作
|
||||
import { clearUserSession } from '@/common/userSession.js';
|
||||
|
||||
const install = (Vue, vm) => {
|
||||
// 通用请求头设定
|
||||
const ajaxHeader = 'x-ajax';
|
||||
@ -43,8 +45,9 @@ const install = (Vue, vm) => {
|
||||
}
|
||||
|
||||
// 设定传递 Token 认证参数 aidex
|
||||
if (!req.header[sessionIdHeader] && vm.vuex_token){
|
||||
req.header[sessionIdHeader] = vm.vuex_token;
|
||||
if (!req.header[sessionIdHeader]){
|
||||
const loginData = uni.getStorageSync('RemoteTokenData');
|
||||
req.header[sessionIdHeader] = vm.vuex_token || (loginData && loginData.token) || '';
|
||||
}
|
||||
|
||||
// 为节省流量,记住我数据不是每次都发送的,当会话失效后,尝试重试登录 aidex
|
||||
@ -65,11 +68,7 @@ const install = (Vue, vm) => {
|
||||
// 处理401未授权状态码
|
||||
if (res.statusCode === 401) {
|
||||
vm.$u.toast('登录已过期,请重新登录');
|
||||
// 清除token和用户信息
|
||||
uni.removeStorageSync('token');
|
||||
vm.$u.vuex('vuex_token', '');
|
||||
vm.$u.vuex('vuex_user', {});
|
||||
// 跳转到登录页面
|
||||
clearUserSession();
|
||||
uni.reLaunch({
|
||||
url: '/pages/sys/login/index'
|
||||
});
|
||||
|
||||
46
src/common/remoteSelect.js
Normal file
46
src/common/remoteSelect.js
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 从往来单位等列表接口中取出数组。
|
||||
* 兼容拦截器解包后的 { list, total },以及完整响应
|
||||
* { data: { code, data: { list, total } } }。
|
||||
*/
|
||||
export function extractList(data, depth = 0) {
|
||||
if (!data || depth > 6) return [];
|
||||
if (Array.isArray(data)) return data;
|
||||
if (Array.isArray(data.list)) return data.list;
|
||||
if (Array.isArray(data.items)) return data.items;
|
||||
if (Array.isArray(data.records)) return data.records;
|
||||
if (data.data && typeof data.data === 'object') return extractList(data.data, depth + 1);
|
||||
return [];
|
||||
}
|
||||
|
||||
/** 将下拉/列表接口响应转为 u-select 所需的 { value, label } */
|
||||
export function mapToSelectOptions(data) {
|
||||
return extractList(data).filter((item) => item && typeof item === 'object').map((item) => ({
|
||||
value: item.id != null ? item.id : item.value,
|
||||
label: item.name || item.label || item.code || (item.id != null ? String(item.id) : ''),
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉远程搜索:把关键字写入接口常用的 name 参数。
|
||||
* 空关键字时不带 name,让后端返回默认列表。
|
||||
*/
|
||||
export function withNameParam(params, keyword) {
|
||||
const next = Object.assign({}, params || {});
|
||||
const name = String(keyword || '').trim();
|
||||
if (name) next.name = name;
|
||||
else delete next.name;
|
||||
return next;
|
||||
}
|
||||
|
||||
export const REMOTE_SELECT_TYPES = [
|
||||
'染厂',
|
||||
'加工单位',
|
||||
'供应商',
|
||||
'仓库名称',
|
||||
'营销体系',
|
||||
];
|
||||
|
||||
export function isRemoteSelectType(type) {
|
||||
return REMOTE_SELECT_TYPES.indexOf(type) !== -1;
|
||||
}
|
||||
54
src/common/remoteSelectMixin.js
Normal file
54
src/common/remoteSelectMixin.js
Normal file
@ -0,0 +1,54 @@
|
||||
import { isRemoteSelectType } from '@/common/remoteSelect';
|
||||
|
||||
/**
|
||||
* 表单页远程下拉搜索。
|
||||
* 使用方需实现 fetchRemoteSelectOptions(type, keyword),返回 { value, label }[]。
|
||||
*
|
||||
* 注意:不要用 `_` / `$` 前缀的 data 字段名——Vue2 不会代理到 this,
|
||||
* `++this._xxx` 会得到 NaN,导致列表不更新、loading 不关。
|
||||
*/
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
selectSearching: false,
|
||||
selectSearchSeq: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isRemoteSelect() {
|
||||
return isRemoteSelectType(this.selectType);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isRemoteSelectType,
|
||||
openSelectPicker(type, cachedList) {
|
||||
this.selectType = type;
|
||||
this.selectList = Array.isArray(cachedList) ? cachedList.slice() : [];
|
||||
this.selectShow = true;
|
||||
},
|
||||
onSelectSearch(keyword) {
|
||||
if (!isRemoteSelectType(this.selectType)) return;
|
||||
if (typeof this.fetchRemoteSelectOptions !== 'function') return;
|
||||
const seq = ++this.selectSearchSeq;
|
||||
this.selectSearching = true;
|
||||
const finish = () => {
|
||||
if (seq === this.selectSearchSeq) this.selectSearching = false;
|
||||
};
|
||||
Promise.resolve()
|
||||
.then(() => this.fetchRemoteSelectOptions(this.selectType, keyword))
|
||||
.then((list) => {
|
||||
if (seq !== this.selectSearchSeq) return;
|
||||
this.selectList = Array.isArray(list) ? list.slice() : [];
|
||||
})
|
||||
.catch((e) => {
|
||||
if (seq !== this.selectSearchSeq) return;
|
||||
if (typeof this.showError === 'function') {
|
||||
this.showError((e && e.message) || '搜索失败');
|
||||
} else {
|
||||
uni.showToast({ title: (e && e.message) || '搜索失败', icon: 'none' });
|
||||
}
|
||||
})
|
||||
.then(finish, finish);
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -80,14 +80,7 @@ export function getStatusOptions() {
|
||||
}));
|
||||
}
|
||||
|
||||
/** 将下拉/列表接口响应转为 u-select 所需的 { value, label } */
|
||||
export function mapToSelectOptions(data) {
|
||||
const list = Array.isArray(data) ? data : (data && (data.list || data.items || data.records)) || [];
|
||||
return list.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name || item.label || item.code || String(item.id),
|
||||
}));
|
||||
}
|
||||
export { mapToSelectOptions } from '@/common/remoteSelect';
|
||||
|
||||
// 匹数:后端以 0.01 匹存储(乘以100的整数),展示需除以100
|
||||
export function formatRoll(value) {
|
||||
|
||||
@ -74,13 +74,7 @@ export function getStatusOptions() {
|
||||
}));
|
||||
}
|
||||
|
||||
export function mapToSelectOptions(data) {
|
||||
const list = Array.isArray(data) ? data : (data && (data.list || data.items || data.records)) || [];
|
||||
return list.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name || item.label || item.code || String(item.id),
|
||||
}));
|
||||
}
|
||||
export { mapToSelectOptions } from '@/common/remoteSelect';
|
||||
|
||||
/** 匹数:后端 ×100 存储 */
|
||||
export function formatRoll(value) {
|
||||
|
||||
@ -59,13 +59,7 @@ export function getStatusOptions() {
|
||||
}));
|
||||
}
|
||||
|
||||
export function mapToSelectOptions(data) {
|
||||
const list = Array.isArray(data) ? data : (data && (data.list || data.items || data.records)) || [];
|
||||
return list.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name || item.label || item.code || String(item.id),
|
||||
}));
|
||||
}
|
||||
export { mapToSelectOptions } from '@/common/remoteSelect';
|
||||
|
||||
/** 匹数:后端 ×100 存储 */
|
||||
export function formatRoll(value) {
|
||||
|
||||
@ -55,13 +55,7 @@ export function getStatusOptions() {
|
||||
}));
|
||||
}
|
||||
|
||||
export function mapToSelectOptions(data) {
|
||||
const list = Array.isArray(data) ? data : (data && (data.list || data.items || data.records)) || [];
|
||||
return list.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name || item.label || item.code || String(item.id),
|
||||
}));
|
||||
}
|
||||
export { mapToSelectOptions } from '@/common/remoteSelect';
|
||||
|
||||
/** 匹数:后端 ×100 存储 */
|
||||
export function formatRoll(value) {
|
||||
|
||||
@ -87,13 +87,7 @@ export function getStatusOptions() {
|
||||
}));
|
||||
}
|
||||
|
||||
export function mapToSelectOptions(data) {
|
||||
const list = Array.isArray(data) ? data : (data && (data.list || data.items || data.records)) || [];
|
||||
return list.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name || item.label || item.code || String(item.id),
|
||||
}));
|
||||
}
|
||||
export { mapToSelectOptions } from '@/common/remoteSelect';
|
||||
|
||||
/** 匹数:后端 ×100 存储 */
|
||||
export function formatRoll(value) {
|
||||
|
||||
155
src/common/userSession.js
Normal file
155
src/common/userSession.js
Normal file
@ -0,0 +1,155 @@
|
||||
/**
|
||||
* 登录会话:token、用户信息、菜单/按钮权限
|
||||
*/
|
||||
import store from '@/store/index.js';
|
||||
|
||||
const TOKEN_KEY = 'RemoteTokenData';
|
||||
const USER_TOKEN_KEY = 'userToken';
|
||||
const INFORMATION_KEY = 'PdaUserInformation';
|
||||
|
||||
function commitVuex(name, value) {
|
||||
store.commit('$uStore', { name, value });
|
||||
}
|
||||
|
||||
function applyGlobalData(patch) {
|
||||
try {
|
||||
const app = getApp();
|
||||
if (!app || !app.globalData) {
|
||||
return;
|
||||
}
|
||||
Object.keys(patch).forEach((key) => {
|
||||
app.globalData[key] = patch[key];
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('applyGlobalData error', e);
|
||||
}
|
||||
}
|
||||
|
||||
export function getLoginData() {
|
||||
return uni.getStorageSync(TOKEN_KEY) || null;
|
||||
}
|
||||
|
||||
export function getUserInformation() {
|
||||
return uni.getStorageSync(INFORMATION_KEY) || null;
|
||||
}
|
||||
|
||||
export function applyLoginData(loginData) {
|
||||
if (!loginData) {
|
||||
return;
|
||||
}
|
||||
uni.setStorageSync(TOKEN_KEY, loginData);
|
||||
uni.setStorageSync(USER_TOKEN_KEY, { Token: loginData.token });
|
||||
if (loginData.token) {
|
||||
commitVuex('vuex_token', loginData.token);
|
||||
}
|
||||
applyGlobalData({
|
||||
Token: loginData.token || '',
|
||||
EmployeeID: loginData.employee_id != null ? loginData.employee_id : (loginData.user_id || 0),
|
||||
LoginID: loginData.user_id || 0,
|
||||
LoginName: loginData.user_name || '',
|
||||
UserName: loginData.user_name || '',
|
||||
PlanDepartmentID: loginData.default_sale_system_id || 0,
|
||||
PlanDepartmentName: loginData.default_sale_system_name || '',
|
||||
StoreNameID: loginData.default_physical_warehouse_id || 0,
|
||||
StoreName: loginData.default_physical_warehouse_name || '',
|
||||
IsSaleUserStatus: 0,
|
||||
UserGroup: '',
|
||||
StoreTypeNo: ''
|
||||
});
|
||||
}
|
||||
|
||||
export function applyUserInformation(info) {
|
||||
if (!info) {
|
||||
return;
|
||||
}
|
||||
uni.setStorageSync(INFORMATION_KEY, info);
|
||||
const profile = {
|
||||
userName: info.user_name || '',
|
||||
user_id: info.user_id,
|
||||
user_name: info.user_name || '',
|
||||
avatar: info.avatar_url || '',
|
||||
avatar_url: info.avatar_url || '',
|
||||
employee_id: info.employee_id,
|
||||
department_id: info.department_id,
|
||||
department_name: info.department_name || '',
|
||||
phone: info.phone || '',
|
||||
default_sale_system_id: info.default_sale_system_id,
|
||||
default_sale_system_name: info.default_sale_system_name || '',
|
||||
default_customer_id: info.default_customer_id,
|
||||
default_customer_name: info.default_customer_name || '',
|
||||
role_id: info.role_id || []
|
||||
};
|
||||
commitVuex('vuex_user', profile);
|
||||
applyGlobalData({
|
||||
EmployeeID: info.employee_id != null ? info.employee_id : (info.user_id || 0),
|
||||
LoginID: info.user_id || 0,
|
||||
LoginName: info.user_name || '',
|
||||
UserName: info.user_name || '',
|
||||
PlanDepartmentID: info.default_sale_system_id || 0,
|
||||
PlanDepartmentName: info.default_sale_system_name || ''
|
||||
});
|
||||
}
|
||||
|
||||
export function restoreUserSession() {
|
||||
const loginData = getLoginData();
|
||||
if (loginData && loginData.token) {
|
||||
applyLoginData(loginData);
|
||||
}
|
||||
const info = getUserInformation();
|
||||
if (info) {
|
||||
applyUserInformation(info);
|
||||
}
|
||||
}
|
||||
|
||||
export function clearUserSession() {
|
||||
uni.removeStorageSync(TOKEN_KEY);
|
||||
uni.removeStorageSync(USER_TOKEN_KEY);
|
||||
uni.removeStorageSync(INFORMATION_KEY);
|
||||
uni.removeStorageSync('token');
|
||||
commitVuex('vuex_token', '');
|
||||
commitVuex('vuex_user', {});
|
||||
applyGlobalData({
|
||||
Token: '',
|
||||
EmployeeID: 0,
|
||||
LoginID: 0,
|
||||
LoginName: '',
|
||||
UserName: '',
|
||||
PlanDepartmentID: 0,
|
||||
PlanDepartmentName: '',
|
||||
StoreNameID: 0,
|
||||
StoreName: '',
|
||||
IsSaleUserStatus: 0,
|
||||
UserGroup: '',
|
||||
StoreTypeNo: ''
|
||||
});
|
||||
}
|
||||
|
||||
export function hasResourceRouter(name) {
|
||||
if (!name) {
|
||||
return true;
|
||||
}
|
||||
const info = getUserInformation();
|
||||
if (!info) {
|
||||
return true;
|
||||
}
|
||||
const names = info.resource_router_names;
|
||||
if (!Array.isArray(names)) {
|
||||
return true;
|
||||
}
|
||||
return names.indexOf(name) !== -1;
|
||||
}
|
||||
|
||||
export function hasButtonCode(code) {
|
||||
if (!code) {
|
||||
return true;
|
||||
}
|
||||
const info = getUserInformation();
|
||||
if (!info) {
|
||||
return true;
|
||||
}
|
||||
const codes = info.button_codes;
|
||||
if (!Array.isArray(codes)) {
|
||||
return true;
|
||||
}
|
||||
return codes.indexOf(code) !== -1;
|
||||
}
|
||||
247
src/components/u-action-sheet/u-action-sheet.vue
Normal file
247
src/components/u-action-sheet/u-action-sheet.vue
Normal file
@ -0,0 +1,247 @@
|
||||
<template>
|
||||
<u-popup mode="bottom" :border-radius="borderRadius" :popup="false" v-model="value" :maskCloseAble="maskCloseAble"
|
||||
length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="popupClose" :z-index="uZIndex">
|
||||
<view class="u-tips u-border-bottom" v-if="tips.text" :style="[tipsStyle]">
|
||||
{{tips.text}}
|
||||
</view>
|
||||
<view class="u-action-sheet-search" v-if="showSearch" @tap.stop>
|
||||
<u-icon name="search" size="32" color="#909399"></u-icon>
|
||||
<input
|
||||
class="u-action-sheet-search__input"
|
||||
:value="keyword"
|
||||
:placeholder="searchPlaceholder"
|
||||
confirm-type="search"
|
||||
:adjust-position="true"
|
||||
@input="onSearchInput"
|
||||
/>
|
||||
<u-icon
|
||||
v-if="keyword"
|
||||
name="close-circle-fill"
|
||||
size="28"
|
||||
color="#c0c4cc"
|
||||
@tap.stop="clearSearch"
|
||||
></u-icon>
|
||||
</view>
|
||||
<scroll-view scroll-y class="u-action-sheet-scroll">
|
||||
<view
|
||||
v-for="(item, index) in displayList"
|
||||
:key="item._originIndex"
|
||||
@touchmove.stop.prevent
|
||||
@tap="itemClick(item._originIndex)"
|
||||
:style="[itemStyle(item._originIndex)]"
|
||||
class="u-action-sheet-item u-line-1"
|
||||
:class="[index < displayList.length - 1 ? 'u-border-bottom' : '']"
|
||||
:hover-stay-time="150"
|
||||
>
|
||||
<text>{{item.text}}</text>
|
||||
<text class="u-action-sheet-item__subtext u-line-1" v-if="item.subText">{{item.subText}}</text>
|
||||
</view>
|
||||
<view v-if="!displayList.length" class="u-action-sheet-empty">无匹配选项</view>
|
||||
</scroll-view>
|
||||
<view class="u-gab" v-if="cancelBtn">
|
||||
</view>
|
||||
<view @touchmove.stop.prevent class="u-actionsheet-cancel u-action-sheet-item" hover-class="u-hover-class"
|
||||
:hover-stay-time="150" v-if="cancelBtn" @tap="close">{{cancelText}}</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* actionSheet 操作菜单(本地覆盖:选项支持搜索)
|
||||
* @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。
|
||||
* @tutorial https://www.uviewui.com/components/actionSheet.html
|
||||
* @property {Array<Object>} list 按钮的文字数组,见官方文档示例
|
||||
* @property {Boolean} show-search 是否显示搜索框(默认true)
|
||||
* @property {String} search-placeholder 搜索框占位文字
|
||||
* @event {Function} click 点击ActionSheet列表项时触发,返回原始列表下标
|
||||
* @example <u-action-sheet :list="list" @click="click" v-model="show"></u-action-sheet>
|
||||
*/
|
||||
export default {
|
||||
name: "u-action-sheet",
|
||||
props: {
|
||||
maskCloseAble: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
tips: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
text: '',
|
||||
color: '',
|
||||
fontSize: '26'
|
||||
}
|
||||
}
|
||||
},
|
||||
cancelBtn: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
safeAreaInsetBottom: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
borderRadius: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
zIndex: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: '取消'
|
||||
},
|
||||
showSearch: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
searchPlaceholder: {
|
||||
type: String,
|
||||
default: '搜索'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
keyword: ''
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
if (val) this.keyword = '';
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tipsStyle() {
|
||||
let style = {};
|
||||
if (this.tips.color) style.color = this.tips.color;
|
||||
if (this.tips.fontSize) style.fontSize = this.tips.fontSize + 'rpx';
|
||||
return style;
|
||||
},
|
||||
itemStyle() {
|
||||
return (index) => {
|
||||
let style = {};
|
||||
const item = this.list[index];
|
||||
if (!item) return style;
|
||||
if (item.color) style.color = item.color;
|
||||
if (item.fontSize) style.fontSize = item.fontSize + 'rpx';
|
||||
if (item.disabled) style.color = '#c0c4cc';
|
||||
return style;
|
||||
}
|
||||
},
|
||||
uZIndex() {
|
||||
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
|
||||
},
|
||||
displayList() {
|
||||
const keyword = (this.keyword || '').trim().toLowerCase();
|
||||
return (this.list || []).reduce((arr, item, index) => {
|
||||
const text = String((item && item.text) || '');
|
||||
const subText = String((item && item.subText) || '');
|
||||
if (!keyword || text.toLowerCase().indexOf(keyword) !== -1 || subText.toLowerCase().indexOf(keyword) !== -1) {
|
||||
arr.push(Object.assign({}, item, { _originIndex: index }));
|
||||
}
|
||||
return arr;
|
||||
}, []);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSearchInput(e) {
|
||||
this.keyword = e && e.detail && e.detail.value != null ? e.detail.value : '';
|
||||
},
|
||||
clearSearch() {
|
||||
this.keyword = '';
|
||||
},
|
||||
close() {
|
||||
this.popupClose();
|
||||
this.$emit('close');
|
||||
},
|
||||
popupClose() {
|
||||
this.keyword = '';
|
||||
this.$emit('input', false);
|
||||
},
|
||||
itemClick(index) {
|
||||
if(this.list[index] && this.list[index].disabled) return;
|
||||
this.$emit('click', index);
|
||||
this.$emit('input', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~uview-ui/libs/css/style.components.scss";
|
||||
|
||||
.u-tips {
|
||||
font-size: 26rpx;
|
||||
text-align: center;
|
||||
padding: 34rpx 0;
|
||||
line-height: 1;
|
||||
color: $u-tips-color;
|
||||
}
|
||||
|
||||
.u-action-sheet-search {
|
||||
@include vue-flex;
|
||||
align-items: center;
|
||||
margin: 16rpx 24rpx;
|
||||
padding: 0 24rpx;
|
||||
height: 80rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 12rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
&__input {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
margin-left: 12rpx;
|
||||
font-size: 30rpx;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
.u-action-sheet-scroll {
|
||||
max-height: 600rpx;
|
||||
}
|
||||
|
||||
.u-action-sheet-empty {
|
||||
text-align: center;
|
||||
padding: 60rpx 0;
|
||||
font-size: 30rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.u-action-sheet-item {
|
||||
@include vue-flex;
|
||||
line-height: 1;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
padding: 34rpx 0;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.u-action-sheet-item__subtext {
|
||||
font-size: 24rpx;
|
||||
color: $u-tips-color;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.u-gab {
|
||||
height: 12rpx;
|
||||
background-color: rgb(234, 234, 236);
|
||||
}
|
||||
|
||||
.u-actionsheet-cancel {
|
||||
color: $u-main-color;
|
||||
}
|
||||
</style>
|
||||
186
src/components/u-dropdown-item/u-dropdown-item.vue
Normal file
186
src/components/u-dropdown-item/u-dropdown-item.vue
Normal file
@ -0,0 +1,186 @@
|
||||
<template>
|
||||
<view class="u-dropdown-item" v-if="active" @touchmove.stop.prevent="() => {}" @tap.stop.prevent="() => {}">
|
||||
<block v-if="!$slots.default && !$slots.$default">
|
||||
<view class="u-dropdown-item__search" v-if="showSearch" @tap.stop>
|
||||
<u-icon name="search" size="28" color="#909399"></u-icon>
|
||||
<input
|
||||
class="u-dropdown-item__search__input"
|
||||
:value="keyword"
|
||||
:placeholder="searchPlaceholder"
|
||||
confirm-type="search"
|
||||
:adjust-position="true"
|
||||
@input="onSearchInput"
|
||||
/>
|
||||
<u-icon
|
||||
v-if="keyword"
|
||||
name="close-circle-fill"
|
||||
size="28"
|
||||
color="#c0c4cc"
|
||||
@tap.stop="clearSearch"
|
||||
></u-icon>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" :style="{
|
||||
height: $u.addUnit(height)
|
||||
}">
|
||||
<view class="u-dropdown-item__options">
|
||||
<u-cell-group>
|
||||
<u-cell-item @click="cellClick(item.value)" :arrow="false" :title="item.label" v-for="(item, index) in filteredOptions"
|
||||
:key="index" :title-style="{
|
||||
color: value == item.value ? activeColor : inactiveColor
|
||||
}">
|
||||
<u-icon v-if="value == item.value" name="checkbox-mark" :color="activeColor" size="32"></u-icon>
|
||||
</u-cell-item>
|
||||
</u-cell-group>
|
||||
<view v-if="!filteredOptions.length" class="u-dropdown-item__empty">无匹配选项</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</block>
|
||||
<slot v-else />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* dropdown-item 下拉菜单(本地覆盖:选项支持搜索)
|
||||
* @description 该组件一般用于向下展开菜单,同时可切换多个选项卡的场景
|
||||
* @tutorial http://uviewui.com/components/dropdown.html
|
||||
* @property {String | Number} v-model 双向绑定选项卡选择值
|
||||
* @property {String} title 菜单项标题
|
||||
* @property {Array[Object]} options 选项数据,如果传入了默认slot,此参数无效
|
||||
* @property {Boolean} show-search 是否显示搜索框(默认true)
|
||||
* @property {String} search-placeholder 搜索框占位文字
|
||||
* @example <u-dropdown-item title="标题"></u-dropdown-item>
|
||||
*/
|
||||
export default {
|
||||
name: 'u-dropdown-item',
|
||||
props: {
|
||||
value: {
|
||||
type: [Number, String, Array],
|
||||
default: ''
|
||||
},
|
||||
title: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
height: {
|
||||
type: [Number, String],
|
||||
default: 'auto'
|
||||
},
|
||||
showSearch: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
searchPlaceholder: {
|
||||
type: String,
|
||||
default: '搜索'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
active: false,
|
||||
activeColor: '#2979ff',
|
||||
inactiveColor: '#606266',
|
||||
keyword: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
propsChange() {
|
||||
return `${this.title}-${this.disabled}`;
|
||||
},
|
||||
filteredOptions() {
|
||||
const keyword = (this.keyword || '').trim().toLowerCase();
|
||||
const list = this.options || [];
|
||||
if (!keyword) return list;
|
||||
return list.filter(item => {
|
||||
const label = String(item && item.label != null ? item.label : '');
|
||||
const value = String(item && item.value != null ? item.value : '');
|
||||
return label.toLowerCase().indexOf(keyword) !== -1 || value.toLowerCase().indexOf(keyword) !== -1;
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
propsChange() {
|
||||
if (this.parent) this.parent.init();
|
||||
},
|
||||
active(val) {
|
||||
if (!val) this.keyword = '';
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.parent = false;
|
||||
},
|
||||
methods: {
|
||||
onSearchInput(e) {
|
||||
this.keyword = e && e.detail && e.detail.value != null ? e.detail.value : '';
|
||||
},
|
||||
clearSearch() {
|
||||
this.keyword = '';
|
||||
},
|
||||
init() {
|
||||
let parent = this.$u.$parent.call(this, 'u-dropdown');
|
||||
if (parent) {
|
||||
this.parent = parent;
|
||||
this.activeColor = parent.activeColor;
|
||||
this.inactiveColor = parent.inactiveColor;
|
||||
let exist = parent.children.find(val => {
|
||||
return this === val;
|
||||
})
|
||||
if (!exist) parent.children.push(this);
|
||||
if (parent.children.length == 1) this.active = true;
|
||||
parent.menuList.push({
|
||||
title: this.title,
|
||||
disabled: this.disabled
|
||||
});
|
||||
}
|
||||
},
|
||||
cellClick(value) {
|
||||
this.$emit('input', value);
|
||||
this.parent.close();
|
||||
this.$emit('change', value);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~uview-ui/libs/css/style.components.scss";
|
||||
|
||||
.u-dropdown-item__search {
|
||||
@include vue-flex;
|
||||
align-items: center;
|
||||
margin: 16rpx 24rpx 0;
|
||||
padding: 0 24rpx;
|
||||
height: 72rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 12rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
&__input {
|
||||
flex: 1;
|
||||
height: 72rpx;
|
||||
margin-left: 12rpx;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
.u-dropdown-item__empty {
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
font-size: 28rpx;
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
538
src/components/u-select/u-select.vue
Normal file
538
src/components/u-select/u-select.vue
Normal file
@ -0,0 +1,538 @@
|
||||
<template>
|
||||
<view class="u-select">
|
||||
<u-popup :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex">
|
||||
<view class="u-select">
|
||||
<view class="u-select__header" @touchmove.stop.prevent="">
|
||||
<view
|
||||
class="u-select__header__cancel u-select__header__btn"
|
||||
:style="{ color: cancelColor }"
|
||||
hover-class="u-hover-class"
|
||||
:hover-stay-time="150"
|
||||
@tap="getResult('cancel')"
|
||||
>
|
||||
{{cancelText}}
|
||||
</view>
|
||||
<view class="u-select__header__title">
|
||||
{{title}}
|
||||
</view>
|
||||
<view
|
||||
class="u-select__header__confirm u-select__header__btn"
|
||||
:style="{ color: moving ? cancelColor : confirmColor }"
|
||||
hover-class="u-hover-class"
|
||||
:hover-stay-time="150"
|
||||
@touchmove.stop=""
|
||||
@tap.stop="getResult('confirm')"
|
||||
>
|
||||
{{confirmText}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-select__search" v-if="showSearch" @tap.stop>
|
||||
<u-icon name="search" size="32" color="#909399"></u-icon>
|
||||
<input
|
||||
class="u-select__search__input"
|
||||
:value="keyword"
|
||||
:placeholder="searchPlaceholder"
|
||||
confirm-type="search"
|
||||
:adjust-position="true"
|
||||
@input="onSearchInput"
|
||||
@confirm="onSearchConfirm"
|
||||
/>
|
||||
<u-icon
|
||||
v-if="keyword"
|
||||
name="close-circle-fill"
|
||||
size="28"
|
||||
color="#c0c4cc"
|
||||
@tap.stop="clearSearch"
|
||||
></u-icon>
|
||||
</view>
|
||||
<view v-if="loading" class="u-select__loading">搜索中...</view>
|
||||
<view class="u-select__body">
|
||||
<view v-if="isColumnEmpty && !loading" class="u-select__empty">无匹配选项</view>
|
||||
<picker-view
|
||||
v-else-if="value && !isColumnEmpty"
|
||||
:key="pickerKey"
|
||||
@change="columnChange"
|
||||
class="u-select__body__picker-view"
|
||||
:value="defaultSelector"
|
||||
@pickstart="pickstart"
|
||||
@pickend="pickend"
|
||||
>
|
||||
<picker-view-column v-for="(item, index) in columnData" :key="'col-' + pickerKey + '-' + index">
|
||||
<view class="u-select__body__picker-view__item" v-for="(item1, index1) in item" :key="item1[valueName] != null ? item1[valueName] : index1">
|
||||
<view class="u-line-1">{{ item1[labelName] }}</view>
|
||||
</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* select 列选择器(本地覆盖:选项支持搜索)
|
||||
* @description 此选择器用于单列,多列,多列联动的选择场景。
|
||||
* @tutorial http://uviewui.com/components/select.html
|
||||
* @property {String} mode 模式选择,"single-column"-单列模式,"mutil-column"-多列模式,"mutil-column-auto"-多列联动模式
|
||||
* @property {Array} list 列数据,数组形式,见官网说明
|
||||
* @property {Boolean} v-model 布尔值变量,用于控制选择器的弹出与收起
|
||||
* @property {Boolean} show-search 是否显示搜索框(默认true)
|
||||
* @property {String} search-placeholder 搜索框占位文字
|
||||
* @event {Function} confirm 点击确定按钮,返回当前选择的值
|
||||
* @example <u-select v-model="show" :list="list"></u-select>
|
||||
*/
|
||||
|
||||
export default {
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
cancelColor: {
|
||||
type: String,
|
||||
default: '#606266'
|
||||
},
|
||||
confirmColor: {
|
||||
type: String,
|
||||
default: '#2979ff'
|
||||
},
|
||||
zIndex: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
safeAreaInsetBottom: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
maskCloseAble: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
defaultValue: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [0];
|
||||
}
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'single-column'
|
||||
},
|
||||
valueName: {
|
||||
type: String,
|
||||
default: 'value'
|
||||
},
|
||||
labelName: {
|
||||
type: String,
|
||||
default: 'label'
|
||||
},
|
||||
childName: {
|
||||
type: String,
|
||||
default: 'children'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: '取消'
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确认'
|
||||
},
|
||||
showSearch: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
searchPlaceholder: {
|
||||
type: String,
|
||||
default: '搜索'
|
||||
},
|
||||
remote: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
debounce: {
|
||||
type: Number,
|
||||
default: 400
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultSelector: [0],
|
||||
columnData: [],
|
||||
selectValue: [],
|
||||
lastSelectIndex: [],
|
||||
columnNum: 0,
|
||||
moving: false,
|
||||
keyword: '',
|
||||
pickerKey: 0,
|
||||
// 勿用 _ 前缀:Vue2 不会把 data 代理到 this
|
||||
searchTimer: null,
|
||||
lastSearchEmit: '',
|
||||
lastSearchAt: 0
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if (val) {
|
||||
this.keyword = '';
|
||||
this.applyPickerData();
|
||||
if (this.remote) this.emitRemoteSearch('');
|
||||
} else {
|
||||
this.clearSearchTimer();
|
||||
this.lastSearchEmit = '';
|
||||
this.lastSearchAt = 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
list: {
|
||||
handler() {
|
||||
if (!this.value) return;
|
||||
this.applyPickerData();
|
||||
},
|
||||
},
|
||||
loading(val) {
|
||||
// loading 从 true→false 时再刷一次滚轮,避免原生 picker-view 漏更
|
||||
if (!val && this.value && this.remote) this.applyPickerData();
|
||||
},
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.clearSearchTimer();
|
||||
},
|
||||
computed: {
|
||||
uZIndex() {
|
||||
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
|
||||
},
|
||||
isColumnEmpty() {
|
||||
return !this.columnData || !this.columnData.length || !this.columnData[0] || !this.columnData[0].length;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
pickstart() {
|
||||
// #ifdef MP-WEIXIN
|
||||
this.moving = true;
|
||||
// #endif
|
||||
},
|
||||
pickend() {
|
||||
// #ifdef MP-WEIXIN
|
||||
this.moving = false;
|
||||
// #endif
|
||||
},
|
||||
readInputValue(e) {
|
||||
if (typeof e === 'string' || typeof e === 'number') return String(e);
|
||||
if (e && e.detail && e.detail.value != null) return String(e.detail.value);
|
||||
if (e && e.target && e.target.value != null) return String(e.target.value);
|
||||
return '';
|
||||
},
|
||||
clearSearchTimer() {
|
||||
if (this.searchTimer) {
|
||||
clearTimeout(this.searchTimer);
|
||||
this.searchTimer = null;
|
||||
}
|
||||
},
|
||||
emitRemoteSearch(keyword) {
|
||||
this.clearSearchTimer();
|
||||
const key = keyword == null ? '' : String(keyword).trim();
|
||||
const now = Date.now();
|
||||
if (key === this.lastSearchEmit && now - this.lastSearchAt < 80) return;
|
||||
this.lastSearchEmit = key;
|
||||
this.lastSearchAt = now;
|
||||
this.$emit('search', key);
|
||||
},
|
||||
scheduleRemoteSearch() {
|
||||
this.clearSearchTimer();
|
||||
this.searchTimer = setTimeout(() => {
|
||||
this.emitRemoteSearch(this.keyword);
|
||||
}, this.debounce);
|
||||
},
|
||||
onSearchInput(e) {
|
||||
this.keyword = this.readInputValue(e);
|
||||
if (this.remote) this.scheduleRemoteSearch();
|
||||
else this.applyFilter();
|
||||
},
|
||||
onSearchConfirm(e) {
|
||||
this.keyword = this.readInputValue(e);
|
||||
if (this.remote) this.emitRemoteSearch(this.keyword);
|
||||
else this.applyFilter();
|
||||
},
|
||||
clearSearch() {
|
||||
this.keyword = '';
|
||||
if (this.remote) this.emitRemoteSearch('');
|
||||
else this.applyFilter();
|
||||
},
|
||||
matchKeyword(text) {
|
||||
const keyword = (this.keyword || '').trim().toLowerCase();
|
||||
if (!keyword) return true;
|
||||
return String(text == null ? '' : text).toLowerCase().indexOf(keyword) !== -1;
|
||||
},
|
||||
filterItems(list) {
|
||||
if (!Array.isArray(list)) return [];
|
||||
if (this.remote) return list.slice();
|
||||
const keyword = (this.keyword || '').trim();
|
||||
if (!keyword) return list.slice();
|
||||
return list.filter(item => {
|
||||
return this.matchKeyword(item && item[this.labelName]) || this.matchKeyword(item && item[this.valueName]);
|
||||
});
|
||||
},
|
||||
applyPickerData() {
|
||||
this.init();
|
||||
this.pickerKey += 1;
|
||||
},
|
||||
applyFilter() {
|
||||
this.applyPickerData();
|
||||
},
|
||||
init() {
|
||||
this.setColumnNum();
|
||||
this.setDefaultSelector();
|
||||
this.setColumnData();
|
||||
this.setSelectValue();
|
||||
},
|
||||
setDefaultSelector() {
|
||||
this.defaultSelector = Array(this.columnNum || 1).fill(0);
|
||||
this.lastSelectIndex = this.defaultSelector.slice();
|
||||
},
|
||||
setColumnNum() {
|
||||
if(this.mode == 'single-column') this.columnNum = 1;
|
||||
else if(this.mode == 'mutil-column') this.columnNum = this.list.length;
|
||||
else if(this.mode == 'mutil-column-auto') {
|
||||
let num = 1;
|
||||
let column = this.list;
|
||||
while(column[0] && column[0][this.childName]) {
|
||||
column = column[0] ? column[0][this.childName] : {};
|
||||
num ++;
|
||||
}
|
||||
this.columnNum = num;
|
||||
}
|
||||
},
|
||||
setColumnData() {
|
||||
let data = [];
|
||||
this.selectValue = [];
|
||||
if(this.mode == 'mutil-column-auto') {
|
||||
const sourceList = this.filterItems(this.list);
|
||||
if (!sourceList.length) {
|
||||
this.columnData = [[]];
|
||||
return;
|
||||
}
|
||||
let selector = this.defaultSelector.length ? this.defaultSelector[0] : 0;
|
||||
if (selector >= sourceList.length) selector = 0;
|
||||
let column = sourceList[selector];
|
||||
for (let i = 0; i < this.columnNum; i++) {
|
||||
if (i == 0) {
|
||||
data[i] = sourceList;
|
||||
column = column ? column[this.childName] : [];
|
||||
} else {
|
||||
data[i] = column || [];
|
||||
const nextIndex = this.defaultSelector[i] || 0;
|
||||
column = (column && column[nextIndex]) ? column[nextIndex][this.childName] : [];
|
||||
}
|
||||
}
|
||||
} else if(this.mode == 'single-column') {
|
||||
data[0] = this.filterItems(this.list);
|
||||
} else {
|
||||
data = (this.list || []).map(col => this.filterItems(Array.isArray(col) ? col : []));
|
||||
}
|
||||
this.columnData = data.slice();
|
||||
},
|
||||
setSelectValue() {
|
||||
let tmp = null;
|
||||
for(let i = 0; i < this.columnNum; i++) {
|
||||
const col = this.columnData[i] || [];
|
||||
tmp = col[this.defaultSelector[i]];
|
||||
let data = {
|
||||
value: tmp ? tmp[this.valueName] : null,
|
||||
label: tmp ? tmp[this.labelName] : null
|
||||
};
|
||||
if(tmp && tmp.extra !== undefined) data.extra = tmp.extra;
|
||||
this.selectValue.push(data)
|
||||
}
|
||||
},
|
||||
columnChange(e) {
|
||||
let index = null;
|
||||
let columnIndex = e.detail.value;
|
||||
this.selectValue = [];
|
||||
this.defaultSelector = columnIndex;
|
||||
if(this.mode == 'mutil-column-auto') {
|
||||
this.lastSelectIndex.map((val, idx) => {
|
||||
if (val != columnIndex[idx]) index = idx;
|
||||
});
|
||||
|
||||
for (let i = index + 1; i < this.columnNum; i++) {
|
||||
this.columnData[i] = this.columnData[i - 1][i - 1 == index ? columnIndex[index] : 0][this.childName];
|
||||
this.defaultSelector[i] = 0;
|
||||
}
|
||||
columnIndex.map((item, idx) => {
|
||||
let data = this.columnData[idx][columnIndex[idx]];
|
||||
let tmp = {
|
||||
value: data ? data[this.valueName] : null,
|
||||
label: data ? data[this.labelName] : null,
|
||||
};
|
||||
if(data && data.extra !== undefined) tmp.extra = data.extra;
|
||||
this.selectValue.push(tmp);
|
||||
|
||||
})
|
||||
this.lastSelectIndex = columnIndex;
|
||||
} else if(this.mode == 'single-column') {
|
||||
let data = this.columnData[0][columnIndex[0]];
|
||||
let tmp = {
|
||||
value: data ? data[this.valueName] : null,
|
||||
label: data ? data[this.labelName] : null,
|
||||
};
|
||||
if(data && data.extra !== undefined) tmp.extra = data.extra;
|
||||
this.selectValue.push(tmp);
|
||||
} else if(this.mode == 'mutil-column') {
|
||||
columnIndex.map((item, idx) => {
|
||||
let data = this.columnData[idx][columnIndex[idx]];
|
||||
let tmp = {
|
||||
value: data ? data[this.valueName] : null,
|
||||
label: data ? data[this.labelName] : null,
|
||||
};
|
||||
if(data && data.extra !== undefined) tmp.extra = data.extra;
|
||||
this.selectValue.push(tmp);
|
||||
})
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.$emit('input', false);
|
||||
this.$set(this, 'defaultSelector', [0]);
|
||||
this.keyword = '';
|
||||
this.lastSearchEmit = '';
|
||||
this.lastSearchAt = 0;
|
||||
},
|
||||
getResult(event = null) {
|
||||
// #ifdef MP-WEIXIN
|
||||
if (this.moving) return;
|
||||
// #endif
|
||||
if (event === 'confirm' && this.isColumnEmpty) {
|
||||
this.$u.toast && this.$u.toast('无匹配选项');
|
||||
return;
|
||||
}
|
||||
if (event) this.$emit(event, this.selectValue);
|
||||
this.close();
|
||||
},
|
||||
selectHandler() {
|
||||
this.$emit('click');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "~uview-ui/libs/css/style.components.scss";
|
||||
|
||||
.u-select {
|
||||
|
||||
&__action {
|
||||
position: relative;
|
||||
line-height: $u-form-item-height;
|
||||
height: $u-form-item-height;
|
||||
|
||||
&__icon {
|
||||
position: absolute;
|
||||
right: 20rpx;
|
||||
top: 50%;
|
||||
transition: transform .4s;
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
|
||||
&--reverse {
|
||||
transform: rotate(-180deg) translateY(50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__hader {
|
||||
&__title {
|
||||
color: $u-content-color;
|
||||
}
|
||||
}
|
||||
|
||||
&--border {
|
||||
border-radius: 6rpx;
|
||||
border-radius: 4px;
|
||||
border: 1px solid $u-form-item-border-color;
|
||||
}
|
||||
|
||||
&__header {
|
||||
@include vue-flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 80rpx;
|
||||
padding: 0 40rpx;
|
||||
}
|
||||
|
||||
&__search {
|
||||
@include vue-flex;
|
||||
align-items: center;
|
||||
margin: 0 24rpx 16rpx;
|
||||
padding: 0 24rpx;
|
||||
height: 80rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 12rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
&__input {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
margin-left: 12rpx;
|
||||
font-size: 30rpx;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
&__loading {
|
||||
padding: 0 24rpx 8rpx;
|
||||
font-size: 26rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
&__empty {
|
||||
@include vue-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
font-size: 30rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
&__body {
|
||||
width: 100%;
|
||||
height: 500rpx;
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
|
||||
&__picker-view {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
&__item {
|
||||
@include vue-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
color: $u-main-color;
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,5 +1,8 @@
|
||||
{
|
||||
"easycom": {
|
||||
"^u-select$": "@/components/u-select/u-select.vue",
|
||||
"^u-action-sheet$": "@/components/u-action-sheet/u-action-sheet.vue",
|
||||
"^u-dropdown-item$": "@/components/u-dropdown-item/u-dropdown-item.vue",
|
||||
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
|
||||
},
|
||||
"pages": [
|
||||
|
||||
@ -122,7 +122,7 @@
|
||||
|
||||
|
||||
|
||||
<u-select v-model="selectShow" :list="selectList" @confirm="selectConfirmFun"></u-select>
|
||||
<u-select v-model="selectShow" :list="selectList" :remote="isRemoteSelect" :loading="selectSearching" @search="onSelectSearch" @confirm="selectConfirmFun"></u-select>
|
||||
|
||||
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@
|
||||
|
||||
<FabricOutFooter :buttons="statusActionButtons" @action="handleStatusAction" />
|
||||
|
||||
<u-select v-model="selectShow" :list="selectList" @confirm="selectConfirmFun"></u-select>
|
||||
<u-select v-model="selectShow" :list="selectList" :remote="isRemoteSelect" :loading="selectSearching" @search="onSelectSearch" @confirm="selectConfirmFun"></u-select>
|
||||
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
||||
<FineCodePopup :show.sync="fineCodeShow" :list="currentFineCodes" :readonly="false" @delete="onDeleteFineCode" />
|
||||
</view>
|
||||
|
||||
@ -59,7 +59,7 @@
|
||||
</u-popup>
|
||||
|
||||
<u-select v-model="statusSelectShow" :list="statusSelectList" @confirm="onStatusConfirm"></u-select>
|
||||
<u-select v-model="unitSelectShow" :list="unitSelectList" @confirm="onUnitConfirm"></u-select>
|
||||
<u-select v-model="unitSelectShow" :list="unitSelectList" remote :loading="selectSearching" @search="onUnitSearch" @confirm="onUnitConfirm"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -75,6 +75,7 @@ import {
|
||||
mapToSelectOptions,
|
||||
fetchAllOrderList,
|
||||
} from '@/common/storeFabricBusinessOut';
|
||||
import { withNameParam } from '@/common/remoteSelect';
|
||||
|
||||
export default {
|
||||
components: { addBtn, FabricOutItem },
|
||||
@ -90,6 +91,9 @@ export default {
|
||||
deliveryUnitOptions: [],
|
||||
businessUnitOptions: [],
|
||||
unitOptionsLoading: false,
|
||||
selectSearching: false,
|
||||
unitSearchSeq: 0,
|
||||
unitSelectList: [{ value: '', label: '全部' }],
|
||||
billTypeName: (BILL_TYPES[0] || {}).label || '坯布其他出货单',
|
||||
filters: {
|
||||
order_no: '',
|
||||
@ -118,10 +122,6 @@ export default {
|
||||
businessUnitLabel() {
|
||||
return this.filters.business_unit_name || '';
|
||||
},
|
||||
unitSelectList() {
|
||||
const options = this.unitSelectType === 'delivery' ? this.deliveryUnitOptions : this.businessUnitOptions;
|
||||
return [{ value: '', label: '全部' }, ...options];
|
||||
},
|
||||
},
|
||||
onLoad() {
|
||||
uni.setNavigationBarTitle({ title: '坯布出库列表' });
|
||||
@ -160,21 +160,40 @@ export default {
|
||||
return this.businessUnitOptions;
|
||||
});
|
||||
},
|
||||
applyUnitSelectList(list) {
|
||||
const rows = Array.isArray(list) ? list.slice() : [];
|
||||
this.unitSelectList = [{ value: '', label: '全部' }].concat(rows);
|
||||
},
|
||||
openUnitSelect(type) {
|
||||
if (this.unitOptionsLoading) return;
|
||||
this.unitOptionsLoading = true;
|
||||
const loadFn = type === 'delivery' ? this.loadDeliveryUnitOptions : this.loadBusinessUnitOptions;
|
||||
loadFn.call(this)
|
||||
.then((list) => {
|
||||
if (!list.length) {
|
||||
uni.showToast({ title: '暂无可选单位', icon: 'none' });
|
||||
return;
|
||||
this.unitSelectType = type;
|
||||
const cache = type === 'delivery' ? this.deliveryUnitOptions : this.businessUnitOptions;
|
||||
this.applyUnitSelectList(cache);
|
||||
this.unitSelectShow = true;
|
||||
},
|
||||
onUnitSearch(keyword) {
|
||||
const seq = ++this.unitSearchSeq;
|
||||
const isDelivery = this.unitSelectType === 'delivery';
|
||||
const empty = !String(keyword || '').trim();
|
||||
this.selectSearching = true;
|
||||
const params = isDelivery ? {} : { unit_type_id: BUSINESS_UNIT_TYPE_DYE_FACTORY };
|
||||
this.$u.api.businessUnit.list(withNameParam(params, keyword))
|
||||
.then((res) => {
|
||||
if (seq !== this.unitSearchSeq) return;
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) {
|
||||
if (isDelivery) this.deliveryUnitOptions = list;
|
||||
else this.businessUnitOptions = list;
|
||||
}
|
||||
this.unitSelectType = type;
|
||||
this.unitSelectShow = true;
|
||||
this.applyUnitSelectList(list);
|
||||
})
|
||||
.finally(() => {
|
||||
this.unitOptionsLoading = false;
|
||||
.catch((e) => {
|
||||
if (seq !== this.unitSearchSeq) return;
|
||||
uni.showToast({ title: (e && e.message) || '搜索失败', icon: 'none' });
|
||||
})
|
||||
.then(() => {
|
||||
if (seq === this.unitSearchSeq) this.selectSearching = false;
|
||||
}, () => {
|
||||
if (seq === this.unitSearchSeq) this.selectSearching = false;
|
||||
});
|
||||
},
|
||||
openDeliveryUnitSelect() {
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
*/
|
||||
import util from '@/common/util';
|
||||
import scanMixin from '@/common/scanMixin.js';
|
||||
import remoteSelectMixin from '@/common/remoteSelectMixin.js';
|
||||
import { withNameParam } from '@/common/remoteSelect';
|
||||
import { initTts, speak } from '@/common/tts.js';
|
||||
import {
|
||||
AUDIT_STATUS_MAP,
|
||||
@ -36,7 +38,7 @@ import {
|
||||
} from '@/common/storeFabricBusinessOut';
|
||||
|
||||
export default {
|
||||
mixins: [scanMixin],
|
||||
mixins: [scanMixin, remoteSelectMixin],
|
||||
data() {
|
||||
return {
|
||||
pageMode: 'add',
|
||||
@ -145,6 +147,15 @@ export default {
|
||||
return this.businessUnitOptions;
|
||||
});
|
||||
},
|
||||
fetchRemoteSelectOptions(type, keyword) {
|
||||
if (type !== '染厂') return Promise.resolve([]);
|
||||
return this.$u.api.businessUnit.list(withNameParam({ unit_type_id: BUSINESS_UNIT_TYPE_DYE_FACTORY }, keyword))
|
||||
.then((res) => {
|
||||
const list = mapToSelectOptions(res);
|
||||
if (!String(keyword || '').trim()) this.businessUnitOptions = list;
|
||||
return list;
|
||||
});
|
||||
},
|
||||
getEmptyForm() {
|
||||
return {
|
||||
order_no: '',
|
||||
@ -185,19 +196,9 @@ export default {
|
||||
},
|
||||
pickerSelectFun(type) {
|
||||
if (!this.headerEditable) return;
|
||||
this.selectType = type;
|
||||
const openPicker = (list) => {
|
||||
if (!list.length) {
|
||||
this.showError('暂无可选数据');
|
||||
return;
|
||||
}
|
||||
this.selectList = list;
|
||||
this.selectShow = true;
|
||||
};
|
||||
if (type === '染厂') {
|
||||
this.ensureBusinessUnitOptions()
|
||||
.then(openPicker)
|
||||
.catch((e) => this.showError(e.message || '加载单位列表失败'));
|
||||
this.openSelectPicker(type, this.businessUnitOptions);
|
||||
return;
|
||||
}
|
||||
},
|
||||
selectConfirmFun(e) {
|
||||
|
||||
@ -107,7 +107,7 @@
|
||||
@action="handleStatusAction"
|
||||
/>
|
||||
|
||||
<u-select v-model="selectShow" :list="selectList" @confirm="selectConfirmFun"></u-select>
|
||||
<u-select v-model="selectShow" :list="selectList" :remote="isRemoteSelect" :loading="selectSearching" @search="onSelectSearch" @confirm="selectConfirmFun"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@ -85,7 +85,7 @@
|
||||
|
||||
<FabricOutFooter :buttons="statusActionButtons" @action="handleStatusAction" />
|
||||
|
||||
<u-select v-model="selectShow" :list="selectList" @confirm="selectConfirmFun"></u-select>
|
||||
<u-select v-model="selectShow" :list="selectList" :remote="isRemoteSelect" :loading="selectSearching" @search="onSelectSearch" @confirm="selectConfirmFun"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
</u-popup>
|
||||
|
||||
<u-select v-model="statusSelectShow" :list="statusSelectList" @confirm="onStatusConfirm"></u-select>
|
||||
<u-select v-model="unitSelectShow" :list="unitSelectList" @confirm="onUnitConfirm"></u-select>
|
||||
<u-select v-model="unitSelectShow" :list="unitSelectList" remote :loading="selectSearching" @search="onUnitSearch" @confirm="onUnitConfirm"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -63,6 +63,7 @@ import {
|
||||
mapToSelectOptions,
|
||||
fetchAllOrderList,
|
||||
} from '@/common/storeGoodsProcessIn';
|
||||
import { withNameParam } from '@/common/remoteSelect';
|
||||
|
||||
export default {
|
||||
components: { addBtn, ProcessInItem },
|
||||
@ -79,6 +80,9 @@ export default {
|
||||
processUnitOptions: [],
|
||||
warehouseOptions: [],
|
||||
unitOptionsLoading: false,
|
||||
selectSearching: false,
|
||||
unitSearchSeq: 0,
|
||||
unitSelectList: [{ value: '', label: '全部' }],
|
||||
filters: {
|
||||
order_no: '',
|
||||
process_unit_id: '',
|
||||
@ -104,10 +108,6 @@ export default {
|
||||
warehouseLabel() {
|
||||
return this.filters.warehouse_name || '';
|
||||
},
|
||||
unitSelectList() {
|
||||
const options = this.unitSelectType === 'warehouse' ? this.warehouseOptions : this.processUnitOptions;
|
||||
return [{ value: '', label: '全部' }, ...options];
|
||||
},
|
||||
},
|
||||
onLoad() {
|
||||
uni.setNavigationBarTitle({ title: '加工进仓列表' });
|
||||
@ -145,22 +145,40 @@ export default {
|
||||
return this.warehouseOptions;
|
||||
});
|
||||
},
|
||||
applyUnitSelectList(list) {
|
||||
const rows = Array.isArray(list) ? list.slice() : [];
|
||||
this.unitSelectList = [{ value: '', label: '全部' }].concat(rows);
|
||||
},
|
||||
openUnitSelect(type) {
|
||||
if (this.unitOptionsLoading) return;
|
||||
this.unitOptionsLoading = true;
|
||||
const loadFn = type === 'warehouse' ? this.loadWarehouseOptions : this.loadProcessUnitOptions;
|
||||
loadFn.call(this)
|
||||
.then((list) => {
|
||||
if (!list.length) {
|
||||
uni.showToast({ title: '暂无可选数据', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.unitSelectType = type;
|
||||
this.unitSelectShow = true;
|
||||
})
|
||||
.finally(() => {
|
||||
this.unitOptionsLoading = false;
|
||||
});
|
||||
this.unitSelectType = type;
|
||||
const cache = type === 'warehouse' ? this.warehouseOptions : this.processUnitOptions;
|
||||
this.applyUnitSelectList(cache);
|
||||
this.unitSelectShow = true;
|
||||
},
|
||||
onUnitSearch(keyword) {
|
||||
const seq = ++this.unitSearchSeq;
|
||||
const type = this.unitSelectType;
|
||||
const empty = !String(keyword || '').trim();
|
||||
this.selectSearching = true;
|
||||
const req = type === 'warehouse'
|
||||
? this.$u.api.physicalWarehouse.getDropdownList(withNameParam({ warehouse_type_id: WAREHOUSE_TYPE_FINISHED }, keyword))
|
||||
: this.$u.api.businessUnit.list(withNameParam({ unit_type_id: BUSINESS_UNIT_TYPE_PROCESS }, keyword));
|
||||
req.then((res) => {
|
||||
if (seq !== this.unitSearchSeq) return;
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) {
|
||||
if (type === 'warehouse') this.warehouseOptions = list;
|
||||
else this.processUnitOptions = list;
|
||||
}
|
||||
this.applyUnitSelectList(list);
|
||||
}).catch((e) => {
|
||||
if (seq !== this.unitSearchSeq) return;
|
||||
uni.showToast({ title: (e && e.message) || '搜索失败', icon: 'none' });
|
||||
}).then(() => {
|
||||
if (seq === this.unitSearchSeq) this.selectSearching = false;
|
||||
}, () => {
|
||||
if (seq === this.unitSearchSeq) this.selectSearching = false;
|
||||
});
|
||||
},
|
||||
openProcessUnitSelect() {
|
||||
this.openUnitSelect('process');
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
*/
|
||||
import util from '@/common/util';
|
||||
import scanMixin from '@/common/scanMixin.js';
|
||||
import remoteSelectMixin from '@/common/remoteSelectMixin.js';
|
||||
import { withNameParam } from '@/common/remoteSelect';
|
||||
import { initTts, speak } from '@/common/tts.js';
|
||||
import {
|
||||
AUDIT_STATUS_MAP,
|
||||
@ -36,7 +38,7 @@ import {
|
||||
} from '@/common/storeGoodsProcessIn';
|
||||
|
||||
export default {
|
||||
mixins: [scanMixin],
|
||||
mixins: [scanMixin, remoteSelectMixin],
|
||||
data() {
|
||||
return {
|
||||
pageMode: 'add',
|
||||
@ -309,6 +311,34 @@ export default {
|
||||
return this.saleSystemOptions;
|
||||
});
|
||||
},
|
||||
fetchRemoteSelectOptions(type, keyword) {
|
||||
const empty = !String(keyword || '').trim();
|
||||
if (type === '加工单位') {
|
||||
return this.$u.api.businessUnit.list(withNameParam({ unit_type_id: BUSINESS_UNIT_TYPE_PROCESS }, keyword))
|
||||
.then((res) => {
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) this.processUnitOptions = list;
|
||||
return list;
|
||||
});
|
||||
}
|
||||
if (type === '仓库名称') {
|
||||
return this.$u.api.physicalWarehouse.getDropdownList(withNameParam({ warehouse_type_id: WAREHOUSE_TYPE_FINISHED }, keyword))
|
||||
.then((res) => {
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) this.warehouseOptions = list;
|
||||
return list;
|
||||
});
|
||||
}
|
||||
if (type === '营销体系') {
|
||||
return this.$u.api.saleSystem.getDropdownList(withNameParam({}, keyword))
|
||||
.then((res) => {
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) this.saleSystemOptions = list;
|
||||
return list;
|
||||
});
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
},
|
||||
applyDefaultWarehouse() {
|
||||
const app = getApp();
|
||||
const picked = pickDefaultWarehouse(
|
||||
@ -390,30 +420,22 @@ export default {
|
||||
},
|
||||
pickerSelectFun(type) {
|
||||
if (!this.headerEditable) return;
|
||||
this.selectType = type;
|
||||
const openPicker = (list) => {
|
||||
if (!list.length) {
|
||||
if (type === '进仓类型') {
|
||||
this.selectType = type;
|
||||
if (!this.inOrderTypeOptions.length) {
|
||||
this.showError('暂无可选数据');
|
||||
return;
|
||||
}
|
||||
this.selectList = list;
|
||||
this.selectList = this.inOrderTypeOptions;
|
||||
this.selectShow = true;
|
||||
};
|
||||
if (type === '进仓类型') {
|
||||
openPicker(this.inOrderTypeOptions);
|
||||
} else if (type === '加工单位') {
|
||||
this.ensureProcessUnitOptions()
|
||||
.then(openPicker)
|
||||
.catch((e) => this.showError(e.message || '加载加工单位失败'));
|
||||
} else if (type === '仓库名称') {
|
||||
this.ensureWarehouseOptions()
|
||||
.then(openPicker)
|
||||
.catch((e) => this.showError(e.message || '加载仓库失败'));
|
||||
} else if (type === '营销体系') {
|
||||
this.ensureSaleSystemOptions()
|
||||
.then(openPicker)
|
||||
.catch((e) => this.showError(e.message || '加载营销体系失败'));
|
||||
return;
|
||||
}
|
||||
const cache = {
|
||||
'加工单位': this.processUnitOptions,
|
||||
'仓库名称': this.warehouseOptions,
|
||||
'营销体系': this.saleSystemOptions,
|
||||
};
|
||||
if (cache[type]) this.openSelectPicker(type, cache[type]);
|
||||
},
|
||||
selectConfirmFun(e) {
|
||||
const item = e[0];
|
||||
|
||||
@ -64,7 +64,7 @@
|
||||
@action="handleStatusAction"
|
||||
/>
|
||||
|
||||
<u-select v-model="selectShow" :list="selectList" @confirm="selectConfirmFun"></u-select>
|
||||
<u-select v-model="selectShow" :list="selectList" :remote="isRemoteSelect" :loading="selectSearching" @search="onSelectSearch" @confirm="selectConfirmFun"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
|
||||
<FabricOutFooter :buttons="statusActionButtons" @action="handleStatusAction" />
|
||||
|
||||
<u-select v-model="selectShow" :list="selectList" @confirm="selectConfirmFun"></u-select>
|
||||
<u-select v-model="selectShow" :list="selectList" :remote="isRemoteSelect" :loading="selectSearching" @search="onSelectSearch" @confirm="selectConfirmFun"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
</u-popup>
|
||||
|
||||
<u-select v-model="statusSelectShow" :list="statusSelectList" @confirm="onStatusConfirm"></u-select>
|
||||
<u-select v-model="unitSelectShow" :list="unitSelectList" @confirm="onUnitConfirm"></u-select>
|
||||
<u-select v-model="unitSelectShow" :list="unitSelectList" remote :loading="selectSearching" @search="onUnitSearch" @confirm="onUnitConfirm"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -63,6 +63,7 @@ import {
|
||||
mapToSelectOptions,
|
||||
fetchAllOrderList,
|
||||
} from '@/common/storeGoodsProcessOut';
|
||||
import { withNameParam } from '@/common/remoteSelect';
|
||||
|
||||
export default {
|
||||
components: { addBtn, ProcessOutItem },
|
||||
@ -79,6 +80,9 @@ export default {
|
||||
processUnitOptions: [],
|
||||
warehouseOptions: [],
|
||||
unitOptionsLoading: false,
|
||||
selectSearching: false,
|
||||
unitSearchSeq: 0,
|
||||
unitSelectList: [{ value: '', label: '全部' }],
|
||||
filters: {
|
||||
order_no: '',
|
||||
process_unit_id: '',
|
||||
@ -104,10 +108,6 @@ export default {
|
||||
warehouseLabel() {
|
||||
return this.filters.warehouse_name || '';
|
||||
},
|
||||
unitSelectList() {
|
||||
const options = this.unitSelectType === 'warehouse' ? this.warehouseOptions : this.processUnitOptions;
|
||||
return [{ value: '', label: '全部' }, ...options];
|
||||
},
|
||||
},
|
||||
onLoad() {
|
||||
uni.setNavigationBarTitle({ title: '加工出仓列表' });
|
||||
@ -145,22 +145,40 @@ export default {
|
||||
return this.warehouseOptions;
|
||||
});
|
||||
},
|
||||
applyUnitSelectList(list) {
|
||||
const rows = Array.isArray(list) ? list.slice() : [];
|
||||
this.unitSelectList = [{ value: '', label: '全部' }].concat(rows);
|
||||
},
|
||||
openUnitSelect(type) {
|
||||
if (this.unitOptionsLoading) return;
|
||||
this.unitOptionsLoading = true;
|
||||
const loadFn = type === 'warehouse' ? this.loadWarehouseOptions : this.loadProcessUnitOptions;
|
||||
loadFn.call(this)
|
||||
.then((list) => {
|
||||
if (!list.length) {
|
||||
uni.showToast({ title: '暂无可选数据', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.unitSelectType = type;
|
||||
this.unitSelectShow = true;
|
||||
})
|
||||
.finally(() => {
|
||||
this.unitOptionsLoading = false;
|
||||
});
|
||||
this.unitSelectType = type;
|
||||
const cache = type === 'warehouse' ? this.warehouseOptions : this.processUnitOptions;
|
||||
this.applyUnitSelectList(cache);
|
||||
this.unitSelectShow = true;
|
||||
},
|
||||
onUnitSearch(keyword) {
|
||||
const seq = ++this.unitSearchSeq;
|
||||
const type = this.unitSelectType;
|
||||
const empty = !String(keyword || '').trim();
|
||||
this.selectSearching = true;
|
||||
const req = type === 'warehouse'
|
||||
? this.$u.api.physicalWarehouse.getDropdownList(withNameParam({ warehouse_type_id: WAREHOUSE_TYPE_FINISHED }, keyword))
|
||||
: this.$u.api.businessUnit.list(withNameParam({ unit_type_id: BUSINESS_UNIT_TYPE_PROCESS }, keyword));
|
||||
req.then((res) => {
|
||||
if (seq !== this.unitSearchSeq) return;
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) {
|
||||
if (type === 'warehouse') this.warehouseOptions = list;
|
||||
else this.processUnitOptions = list;
|
||||
}
|
||||
this.applyUnitSelectList(list);
|
||||
}).catch((e) => {
|
||||
if (seq !== this.unitSearchSeq) return;
|
||||
uni.showToast({ title: (e && e.message) || '搜索失败', icon: 'none' });
|
||||
}).then(() => {
|
||||
if (seq === this.unitSearchSeq) this.selectSearching = false;
|
||||
}, () => {
|
||||
if (seq === this.unitSearchSeq) this.selectSearching = false;
|
||||
});
|
||||
},
|
||||
openProcessUnitSelect() {
|
||||
this.openUnitSelect('process');
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
*/
|
||||
import util from '@/common/util';
|
||||
import scanMixin from '@/common/scanMixin.js';
|
||||
import remoteSelectMixin from '@/common/remoteSelectMixin.js';
|
||||
import { withNameParam } from '@/common/remoteSelect';
|
||||
import { initTts, speak } from '@/common/tts.js';
|
||||
import {
|
||||
AUDIT_STATUS_MAP,
|
||||
@ -32,7 +34,7 @@ import {
|
||||
} from '@/common/storeGoodsProcessOut';
|
||||
|
||||
export default {
|
||||
mixins: [scanMixin],
|
||||
mixins: [scanMixin, remoteSelectMixin],
|
||||
data() {
|
||||
return {
|
||||
pageMode: 'add',
|
||||
@ -211,6 +213,26 @@ export default {
|
||||
return this.warehouseOptions;
|
||||
});
|
||||
},
|
||||
fetchRemoteSelectOptions(type, keyword) {
|
||||
const empty = !String(keyword || '').trim();
|
||||
if (type === '加工单位') {
|
||||
return this.$u.api.businessUnit.list(withNameParam({ unit_type_id: BUSINESS_UNIT_TYPE_PROCESS }, keyword))
|
||||
.then((res) => {
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) this.processUnitOptions = list;
|
||||
return list;
|
||||
});
|
||||
}
|
||||
if (type === '仓库名称') {
|
||||
return this.$u.api.physicalWarehouse.getDropdownList(withNameParam({ warehouse_type_id: WAREHOUSE_TYPE_FINISHED }, keyword))
|
||||
.then((res) => {
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) this.warehouseOptions = list;
|
||||
return list;
|
||||
});
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
},
|
||||
applyDefaultWarehouse() {
|
||||
const app = getApp();
|
||||
const picked = pickDefaultWarehouse(
|
||||
@ -264,28 +286,26 @@ export default {
|
||||
},
|
||||
pickerSelectFun(type) {
|
||||
if (!this.headerEditable) return;
|
||||
this.selectType = type;
|
||||
const openPicker = (list) => {
|
||||
if (!list.length) {
|
||||
this.showError('暂无可选数据');
|
||||
return;
|
||||
}
|
||||
this.selectList = list;
|
||||
this.selectShow = true;
|
||||
};
|
||||
if (type === '出仓类型') {
|
||||
this.selectType = type;
|
||||
const openPicker = (list) => {
|
||||
if (!list.length) {
|
||||
this.showError('暂无可选数据');
|
||||
return;
|
||||
}
|
||||
this.selectList = list;
|
||||
this.selectShow = true;
|
||||
};
|
||||
this.ensureOutOrderTypeOptions()
|
||||
.then(openPicker)
|
||||
.catch((e) => this.showError(e.message || '加载出仓类型失败'));
|
||||
} else if (type === '加工单位') {
|
||||
this.ensureProcessUnitOptions()
|
||||
.then(openPicker)
|
||||
.catch((e) => this.showError(e.message || '加载加工单位失败'));
|
||||
} else if (type === '仓库名称') {
|
||||
this.ensureWarehouseOptions()
|
||||
.then(openPicker)
|
||||
.catch((e) => this.showError(e.message || '加载仓库失败'));
|
||||
return;
|
||||
}
|
||||
const cache = {
|
||||
'加工单位': this.processUnitOptions,
|
||||
'仓库名称': this.warehouseOptions,
|
||||
};
|
||||
if (cache[type]) this.openSelectPicker(type, cache[type]);
|
||||
},
|
||||
selectConfirmFun(e) {
|
||||
const item = e[0];
|
||||
|
||||
@ -72,7 +72,7 @@
|
||||
@action="handleStatusAction"
|
||||
/>
|
||||
|
||||
<u-select v-model="selectShow" :list="selectList" @confirm="selectConfirmFun"></u-select>
|
||||
<u-select v-model="selectShow" :list="selectList" :remote="isRemoteSelect" :loading="selectSearching" @search="onSelectSearch" @confirm="selectConfirmFun"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@
|
||||
|
||||
<FabricOutFooter :buttons="statusActionButtons" @action="handleStatusAction" />
|
||||
|
||||
<u-select v-model="selectShow" :list="selectList" @confirm="selectConfirmFun"></u-select>
|
||||
<u-select v-model="selectShow" :list="selectList" :remote="isRemoteSelect" :loading="selectSearching" @search="onSelectSearch" @confirm="selectConfirmFun"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
</u-popup>
|
||||
|
||||
<u-select v-model="statusSelectShow" :list="statusSelectList" @confirm="onStatusConfirm"></u-select>
|
||||
<u-select v-model="unitSelectShow" :list="unitSelectList" @confirm="onUnitConfirm"></u-select>
|
||||
<u-select v-model="unitSelectShow" :list="unitSelectList" remote :loading="selectSearching" @search="onUnitSearch" @confirm="onUnitConfirm"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -63,6 +63,7 @@ import {
|
||||
mapToSelectOptions,
|
||||
fetchAllOrderList,
|
||||
} from '@/common/storeGoodsProcessReturnIn';
|
||||
import { withNameParam } from '@/common/remoteSelect';
|
||||
|
||||
export default {
|
||||
components: { addBtn, ProcessReturnInItem },
|
||||
@ -79,6 +80,9 @@ export default {
|
||||
processUnitOptions: [],
|
||||
warehouseOptions: [],
|
||||
unitOptionsLoading: false,
|
||||
selectSearching: false,
|
||||
unitSearchSeq: 0,
|
||||
unitSelectList: [{ value: '', label: '全部' }],
|
||||
filters: {
|
||||
order_no: '',
|
||||
process_unit_id: '',
|
||||
@ -104,10 +108,6 @@ export default {
|
||||
warehouseLabel() {
|
||||
return this.filters.warehouse_name || '';
|
||||
},
|
||||
unitSelectList() {
|
||||
const options = this.unitSelectType === 'warehouse' ? this.warehouseOptions : this.processUnitOptions;
|
||||
return [{ value: '', label: '全部' }, ...options];
|
||||
},
|
||||
},
|
||||
onLoad() {
|
||||
uni.setNavigationBarTitle({ title: '加工退货进仓列表' });
|
||||
@ -145,22 +145,40 @@ export default {
|
||||
return this.warehouseOptions;
|
||||
});
|
||||
},
|
||||
applyUnitSelectList(list) {
|
||||
const rows = Array.isArray(list) ? list.slice() : [];
|
||||
this.unitSelectList = [{ value: '', label: '全部' }].concat(rows);
|
||||
},
|
||||
openUnitSelect(type) {
|
||||
if (this.unitOptionsLoading) return;
|
||||
this.unitOptionsLoading = true;
|
||||
const loadFn = type === 'warehouse' ? this.loadWarehouseOptions : this.loadProcessUnitOptions;
|
||||
loadFn.call(this)
|
||||
.then((list) => {
|
||||
if (!list.length) {
|
||||
uni.showToast({ title: '暂无可选数据', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.unitSelectType = type;
|
||||
this.unitSelectShow = true;
|
||||
})
|
||||
.finally(() => {
|
||||
this.unitOptionsLoading = false;
|
||||
});
|
||||
this.unitSelectType = type;
|
||||
const cache = type === 'warehouse' ? this.warehouseOptions : this.processUnitOptions;
|
||||
this.applyUnitSelectList(cache);
|
||||
this.unitSelectShow = true;
|
||||
},
|
||||
onUnitSearch(keyword) {
|
||||
const seq = ++this.unitSearchSeq;
|
||||
const type = this.unitSelectType;
|
||||
const empty = !String(keyword || '').trim();
|
||||
this.selectSearching = true;
|
||||
const req = type === 'warehouse'
|
||||
? this.$u.api.physicalWarehouse.getDropdownList(withNameParam({ warehouse_type_id: WAREHOUSE_TYPE_FINISHED }, keyword))
|
||||
: this.$u.api.businessUnit.list(withNameParam({ unit_type_id: BUSINESS_UNIT_TYPE_PROCESS }, keyword));
|
||||
req.then((res) => {
|
||||
if (seq !== this.unitSearchSeq) return;
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) {
|
||||
if (type === 'warehouse') this.warehouseOptions = list;
|
||||
else this.processUnitOptions = list;
|
||||
}
|
||||
this.applyUnitSelectList(list);
|
||||
}).catch((e) => {
|
||||
if (seq !== this.unitSearchSeq) return;
|
||||
uni.showToast({ title: (e && e.message) || '搜索失败', icon: 'none' });
|
||||
}).then(() => {
|
||||
if (seq === this.unitSearchSeq) this.selectSearching = false;
|
||||
}, () => {
|
||||
if (seq === this.unitSearchSeq) this.selectSearching = false;
|
||||
});
|
||||
},
|
||||
openProcessUnitSelect() {
|
||||
this.openUnitSelect('process');
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
*/
|
||||
import util from '@/common/util';
|
||||
import scanMixin from '@/common/scanMixin.js';
|
||||
import remoteSelectMixin from '@/common/remoteSelectMixin.js';
|
||||
import { withNameParam } from '@/common/remoteSelect';
|
||||
import { initTts, speak } from '@/common/tts.js';
|
||||
import {
|
||||
AUDIT_STATUS_MAP,
|
||||
@ -31,7 +33,7 @@ import {
|
||||
} from '@/common/storeGoodsProcessReturnIn';
|
||||
|
||||
export default {
|
||||
mixins: [scanMixin],
|
||||
mixins: [scanMixin, remoteSelectMixin],
|
||||
data() {
|
||||
return {
|
||||
pageMode: 'add',
|
||||
@ -284,6 +286,26 @@ export default {
|
||||
return this.warehouseOptions;
|
||||
});
|
||||
},
|
||||
fetchRemoteSelectOptions(type, keyword) {
|
||||
const empty = !String(keyword || '').trim();
|
||||
if (type === '加工单位') {
|
||||
return this.$u.api.businessUnit.list(withNameParam({ unit_type_id: BUSINESS_UNIT_TYPE_PROCESS }, keyword))
|
||||
.then((res) => {
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) this.processUnitOptions = list;
|
||||
return list;
|
||||
});
|
||||
}
|
||||
if (type === '仓库名称') {
|
||||
return this.$u.api.physicalWarehouse.getDropdownList(withNameParam({ warehouse_type_id: WAREHOUSE_TYPE_FINISHED }, keyword))
|
||||
.then((res) => {
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) this.warehouseOptions = list;
|
||||
return list;
|
||||
});
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
},
|
||||
applyDefaultWarehouse() {
|
||||
const app = getApp();
|
||||
const picked = pickDefaultWarehouse(
|
||||
@ -336,24 +358,11 @@ export default {
|
||||
},
|
||||
pickerSelectFun(type) {
|
||||
if (!this.headerEditable) return;
|
||||
this.selectType = type;
|
||||
const openPicker = (list) => {
|
||||
if (!list.length) {
|
||||
this.showError('暂无可选数据');
|
||||
return;
|
||||
}
|
||||
this.selectList = list;
|
||||
this.selectShow = true;
|
||||
const cache = {
|
||||
'加工单位': this.processUnitOptions,
|
||||
'仓库名称': this.warehouseOptions,
|
||||
};
|
||||
if (type === '加工单位') {
|
||||
this.ensureProcessUnitOptions()
|
||||
.then(openPicker)
|
||||
.catch((e) => this.showError(e.message || '加载加工单位失败'));
|
||||
} else if (type === '仓库名称') {
|
||||
this.ensureWarehouseOptions()
|
||||
.then(openPicker)
|
||||
.catch((e) => this.showError(e.message || '加载仓库失败'));
|
||||
}
|
||||
if (cache[type]) this.openSelectPicker(type, cache[type]);
|
||||
},
|
||||
selectConfirmFun(e) {
|
||||
const item = e[0];
|
||||
|
||||
@ -107,7 +107,7 @@
|
||||
@action="handleStatusAction"
|
||||
/>
|
||||
|
||||
<u-select v-model="selectShow" :list="selectList" @confirm="selectConfirmFun"></u-select>
|
||||
<u-select v-model="selectShow" :list="selectList" :remote="isRemoteSelect" :loading="selectSearching" @search="onSelectSearch" @confirm="selectConfirmFun"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@ -85,7 +85,7 @@
|
||||
|
||||
<FabricOutFooter :buttons="statusActionButtons" @action="handleStatusAction" />
|
||||
|
||||
<u-select v-model="selectShow" :list="selectList" @confirm="selectConfirmFun"></u-select>
|
||||
<u-select v-model="selectShow" :list="selectList" :remote="isRemoteSelect" :loading="selectSearching" @search="onSelectSearch" @confirm="selectConfirmFun"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
</u-popup>
|
||||
|
||||
<u-select v-model="statusSelectShow" :list="statusSelectList" @confirm="onStatusConfirm"></u-select>
|
||||
<u-select v-model="unitSelectShow" :list="unitSelectList" @confirm="onUnitConfirm"></u-select>
|
||||
<u-select v-model="unitSelectShow" :list="unitSelectList" remote :loading="selectSearching" @search="onUnitSearch" @confirm="onUnitConfirm"></u-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -63,6 +63,7 @@ import {
|
||||
mapToSelectOptions,
|
||||
fetchAllOrderList,
|
||||
} from '@/common/storeGoodsPurchaseIn';
|
||||
import { withNameParam } from '@/common/remoteSelect';
|
||||
|
||||
export default {
|
||||
components: { addBtn, PurchaseInItem },
|
||||
@ -79,6 +80,9 @@ export default {
|
||||
supplierOptions: [],
|
||||
warehouseOptions: [],
|
||||
unitOptionsLoading: false,
|
||||
selectSearching: false,
|
||||
unitSearchSeq: 0,
|
||||
unitSelectList: [{ value: '', label: '全部' }],
|
||||
filters: {
|
||||
order_no: '',
|
||||
supplier_id: '',
|
||||
@ -104,10 +108,6 @@ export default {
|
||||
warehouseLabel() {
|
||||
return this.filters.warehouse_name || '';
|
||||
},
|
||||
unitSelectList() {
|
||||
const options = this.unitSelectType === 'warehouse' ? this.warehouseOptions : this.supplierOptions;
|
||||
return [{ value: '', label: '全部' }, ...options];
|
||||
},
|
||||
},
|
||||
onLoad() {
|
||||
uni.setNavigationBarTitle({ title: '成品采购进仓' });
|
||||
@ -145,22 +145,40 @@ export default {
|
||||
return this.warehouseOptions;
|
||||
});
|
||||
},
|
||||
applyUnitSelectList(list) {
|
||||
const rows = Array.isArray(list) ? list.slice() : [];
|
||||
this.unitSelectList = [{ value: '', label: '全部' }].concat(rows);
|
||||
},
|
||||
openUnitSelect(type) {
|
||||
if (this.unitOptionsLoading) return;
|
||||
this.unitOptionsLoading = true;
|
||||
const loadFn = type === 'warehouse' ? this.loadWarehouseOptions : this.loadSupplierOptions;
|
||||
loadFn.call(this)
|
||||
.then((list) => {
|
||||
if (!list.length) {
|
||||
uni.showToast({ title: '暂无可选数据', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.unitSelectType = type;
|
||||
this.unitSelectShow = true;
|
||||
})
|
||||
.finally(() => {
|
||||
this.unitOptionsLoading = false;
|
||||
});
|
||||
this.unitSelectType = type;
|
||||
const cache = type === 'warehouse' ? this.warehouseOptions : this.supplierOptions;
|
||||
this.applyUnitSelectList(cache);
|
||||
this.unitSelectShow = true;
|
||||
},
|
||||
onUnitSearch(keyword) {
|
||||
const seq = ++this.unitSearchSeq;
|
||||
const type = this.unitSelectType;
|
||||
const empty = !String(keyword || '').trim();
|
||||
this.selectSearching = true;
|
||||
const req = type === 'warehouse'
|
||||
? this.$u.api.physicalWarehouse.getDropdownList(withNameParam({ warehouse_type_id: WAREHOUSE_TYPE_FINISHED }, keyword))
|
||||
: this.$u.api.businessUnit.list(withNameParam({ unit_type_id: BUSINESS_UNIT_TYPE_PRODUCT_SUPPLIER }, keyword));
|
||||
req.then((res) => {
|
||||
if (seq !== this.unitSearchSeq) return;
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) {
|
||||
if (type === 'warehouse') this.warehouseOptions = list;
|
||||
else this.supplierOptions = list;
|
||||
}
|
||||
this.applyUnitSelectList(list);
|
||||
}).catch((e) => {
|
||||
if (seq !== this.unitSearchSeq) return;
|
||||
uni.showToast({ title: (e && e.message) || '搜索失败', icon: 'none' });
|
||||
}).then(() => {
|
||||
if (seq === this.unitSearchSeq) this.selectSearching = false;
|
||||
}, () => {
|
||||
if (seq === this.unitSearchSeq) this.selectSearching = false;
|
||||
});
|
||||
},
|
||||
openSupplierSelect() {
|
||||
this.openUnitSelect('supplier');
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
*/
|
||||
import util from '@/common/util';
|
||||
import scanMixin from '@/common/scanMixin.js';
|
||||
import remoteSelectMixin from '@/common/remoteSelectMixin.js';
|
||||
import { withNameParam } from '@/common/remoteSelect';
|
||||
import { initTts, speak } from '@/common/tts.js';
|
||||
import {
|
||||
AUDIT_STATUS_MAP,
|
||||
@ -38,7 +40,7 @@ import {
|
||||
} from '@/common/storeGoodsPurchaseIn';
|
||||
|
||||
export default {
|
||||
mixins: [scanMixin],
|
||||
mixins: [scanMixin, remoteSelectMixin],
|
||||
data() {
|
||||
return {
|
||||
pageMode: 'add',
|
||||
@ -311,6 +313,34 @@ export default {
|
||||
return this.saleSystemOptions;
|
||||
});
|
||||
},
|
||||
fetchRemoteSelectOptions(type, keyword) {
|
||||
const empty = !String(keyword || '').trim();
|
||||
if (type === '供应商') {
|
||||
return this.$u.api.businessUnit.list(withNameParam({ unit_type_id: BUSINESS_UNIT_TYPE_PRODUCT_SUPPLIER }, keyword))
|
||||
.then((res) => {
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) this.supplierOptions = list;
|
||||
return list;
|
||||
});
|
||||
}
|
||||
if (type === '仓库名称') {
|
||||
return this.$u.api.physicalWarehouse.getDropdownList(withNameParam({ warehouse_type_id: WAREHOUSE_TYPE_FINISHED }, keyword))
|
||||
.then((res) => {
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) this.warehouseOptions = list;
|
||||
return list;
|
||||
});
|
||||
}
|
||||
if (type === '营销体系') {
|
||||
return this.$u.api.saleSystem.getDropdownList(withNameParam({}, keyword))
|
||||
.then((res) => {
|
||||
const list = mapToSelectOptions(res);
|
||||
if (empty) this.saleSystemOptions = list;
|
||||
return list;
|
||||
});
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
},
|
||||
applyDefaultWarehouse() {
|
||||
const app = getApp();
|
||||
const picked = pickDefaultWarehouse(
|
||||
@ -394,30 +424,22 @@ export default {
|
||||
},
|
||||
pickerSelectFun(type) {
|
||||
if (!this.headerEditable) return;
|
||||
this.selectType = type;
|
||||
const openPicker = (list) => {
|
||||
if (!list.length) {
|
||||
if (type === '订单类型') {
|
||||
this.selectType = type;
|
||||
if (!this.saleModeOptions.length) {
|
||||
this.showError('暂无可选数据');
|
||||
return;
|
||||
}
|
||||
this.selectList = list;
|
||||
this.selectList = this.saleModeOptions;
|
||||
this.selectShow = true;
|
||||
};
|
||||
if (type === '供应商') {
|
||||
this.ensureSupplierOptions()
|
||||
.then(openPicker)
|
||||
.catch((e) => this.showError(e.message || '加载供应商失败'));
|
||||
} else if (type === '仓库名称') {
|
||||
this.ensureWarehouseOptions()
|
||||
.then(openPicker)
|
||||
.catch((e) => this.showError(e.message || '加载仓库失败'));
|
||||
} else if (type === '营销体系') {
|
||||
this.ensureSaleSystemOptions()
|
||||
.then(openPicker)
|
||||
.catch((e) => this.showError(e.message || '加载营销体系失败'));
|
||||
} else if (type === '订单类型') {
|
||||
openPicker(this.saleModeOptions);
|
||||
return;
|
||||
}
|
||||
const cache = {
|
||||
'供应商': this.supplierOptions,
|
||||
'仓库名称': this.warehouseOptions,
|
||||
'营销体系': this.saleSystemOptions,
|
||||
};
|
||||
if (cache[type]) this.openSelectPicker(type, cache[type]);
|
||||
},
|
||||
selectConfirmFun(e) {
|
||||
const item = e[0];
|
||||
|
||||
@ -105,8 +105,8 @@
|
||||
<!-- </view>-->
|
||||
<!-- </view>-->
|
||||
<!-- </div>-->
|
||||
<u-picker v-model="showApiUrlPicker" mode="selector" :range="apiUrlList" range-key="label"
|
||||
@confirm="onApiUrlConfirm" @cancel="showApiUrlPicker = false"></u-picker>
|
||||
<u-select v-model="showApiUrlPicker" :list="apiUrlList" title="选择服务器"
|
||||
@confirm="onApiUrlConfirm" @cancel="showApiUrlPicker = false"></u-select>
|
||||
<!-- 版本信息显示 -->
|
||||
<view class="version-info">
|
||||
<text class="version-text">版本: {{ appVersion }}</text>
|
||||
@ -125,6 +125,7 @@ import md5 from '@/common/md5.js';
|
||||
import manifest from '@/manifest.json';
|
||||
import { mapState } from 'vuex'
|
||||
import app_upgrade from '@/uni_modules/app-upgrade/js_sdk/index.js'
|
||||
import { applyLoginData, applyUserInformation } from '@/common/userSession.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@ -218,9 +219,8 @@ export default {
|
||||
},
|
||||
|
||||
onApiUrlConfirm(e) {
|
||||
console.log('e', JSON.stringify(e));
|
||||
const selectedValue = this.apiUrlList[e[0]].value;
|
||||
console.log('selectedValue', selectedValue)
|
||||
const selectedValue = e && e[0] && e[0].value;
|
||||
if (selectedValue == null) return;
|
||||
this.selectedApiUrl = selectedValue;
|
||||
this.showApiUrlPicker = false;
|
||||
|
||||
@ -334,11 +334,10 @@ export default {
|
||||
this.$u.api.pdaLogin({
|
||||
'phone': this.login.username,
|
||||
'password': this.login.password,
|
||||
}).then((res) => {
|
||||
}).then(async (res) => {
|
||||
console.log('login res', res)
|
||||
var aLoginUserData = res;
|
||||
|
||||
//console.log('--aLoginUserData->>' + JSON.stringify(aLoginUserData));
|
||||
// 只在开发环境保存 apiurl 到本地存储
|
||||
if (config.isDevelopment) {
|
||||
uni.setStorage({
|
||||
@ -347,27 +346,17 @@ export default {
|
||||
});
|
||||
util.updateApiUrl(currentApiUrl);
|
||||
}
|
||||
// 保存 token 到本地存储
|
||||
uni.setStorageSync('RemoteTokenData', aLoginUserData);
|
||||
|
||||
uni.setStorage({
|
||||
key: 'userToken',
|
||||
data: {
|
||||
Token: aLoginUserData.token,
|
||||
}
|
||||
});
|
||||
applyLoginData(aLoginUserData);
|
||||
|
||||
try {
|
||||
const userInfo = await this.$u.api.pdaGetInformation();
|
||||
console.log('information res', userInfo);
|
||||
applyUserInformation(userInfo);
|
||||
} catch (infoError) {
|
||||
console.log('information error', infoError);
|
||||
}
|
||||
|
||||
getApp().globalData.Token = aLoginUserData.token;
|
||||
getApp().globalData.EmployeeID = aLoginUserData.user_id;
|
||||
getApp().globalData.IsSaleUserStatus = 0;
|
||||
getApp().globalData.LoginID = aLoginUserData.user_id;
|
||||
getApp().globalData.LoginName = aLoginUserData.user_name;
|
||||
getApp().globalData.PlanDepartmentID = aLoginUserData.default_sale_system_id;
|
||||
getApp().globalData.PlanDepartmentName = aLoginUserData.default_sale_system_name;
|
||||
getApp().globalData.UserGroup = '';
|
||||
getApp().globalData.StoreNameID = aLoginUserData.default_physical_warehouse_id;
|
||||
getApp().globalData.StoreName = aLoginUserData.default_physical_warehouse_name;
|
||||
getApp().globalData.StoreTypeNo = '';
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({
|
||||
url: '/pages/sys/workbench/index'
|
||||
|
||||
@ -69,7 +69,7 @@ export default {
|
||||
};
|
||||
},
|
||||
onLoad(e) {
|
||||
this.loginUserName = getApp().globalData.UserName;
|
||||
this.loginUserName = getApp().globalData.UserName || (this.vuex_user && this.vuex_user.user_name) || '';
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
import app_upgrade from '@/uni_modules/app-upgrade/js_sdk/index.js'
|
||||
import util from '@/common/util.js';
|
||||
import config from '../../../common/config';
|
||||
import { clearUserSession } from '@/common/userSession.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -84,27 +85,17 @@ export default {
|
||||
// #endif
|
||||
},
|
||||
logout() {
|
||||
this.$u.api.pdaLogout().then(res => {
|
||||
console.log('res',res)
|
||||
if (res.code != 0) {
|
||||
// this.$u.toast('退出登录失败');
|
||||
uni.reLaunch({
|
||||
url: '/pages/sys/login/index'
|
||||
});
|
||||
return
|
||||
}
|
||||
// 清除token和用户信息
|
||||
uni.removeStorageSync('token');
|
||||
this.$store.dispatch('updateUserInfo', null);
|
||||
const goLogin = () => {
|
||||
clearUserSession();
|
||||
uni.reLaunch({
|
||||
url: '/pages/sys/login/index'
|
||||
});
|
||||
};
|
||||
this.$u.api.pdaLogout().then(() => {
|
||||
goLogin();
|
||||
}).catch(error => {
|
||||
console.log('error',error)
|
||||
// 即使退出登录失败,也要清除本地token和用户信息
|
||||
uni.removeStorageSync('token');
|
||||
this.$store.dispatch('updateUserInfo', null);
|
||||
// this.$u.toast('退出登录失败');
|
||||
goLogin();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,57 +7,31 @@
|
||||
</view>
|
||||
</template>
|
||||
</common-navbar>
|
||||
<view class="workbench-title">销售管理</view>
|
||||
<view class="toolbar">
|
||||
<u-grid class="grid" :col="4" :border="false">
|
||||
<u-grid-item :index="0" @click="navTo('/pages/saleship/salepickscan')">
|
||||
<view class="home-icon icon-color05">
|
||||
<i class="iconfont icon-hetongguanli"></i>
|
||||
</view>
|
||||
<view class="grid-text">成品配布</view>
|
||||
</u-grid-item>
|
||||
<!-- <u-grid-item :index="1" @click="navTo('/pages/storegoods/QRBarCodeReview')"> -->
|
||||
<!-- <view class="home-icon icon-color02"> -->
|
||||
<!-- <i class="iconfont icon-mall-bag"></i>-->
|
||||
<!-- </view>-->
|
||||
<!-- <view class="grid-text">标签检测</view>-->
|
||||
<!-- </u-grid-item>-->
|
||||
</u-grid>
|
||||
</view>
|
||||
<view class="workbench-title">成品管理</view>
|
||||
<view class="toolbar">
|
||||
<u-grid class="grid" :col="4" :border="false">
|
||||
<u-grid-item :index="2" @click="navTo('/pages/storegoods/storeGoodsProcessInList')">
|
||||
<view class="home-icon icon-color04">
|
||||
<i class="iconfont icon-hetongguanli"></i>
|
||||
</view>
|
||||
<view class="grid-text">加工进仓</view>
|
||||
</u-grid-item>
|
||||
<u-grid-item :index="3" @click="navTo('/pages/storegoods/storeGoodsProcessOutList')">
|
||||
<view class="home-icon icon-color05">
|
||||
<i class="iconfont icon-hetongguanli"></i>
|
||||
</view>
|
||||
<view class="grid-text">加工出仓</view>
|
||||
</u-grid-item>
|
||||
<u-grid-item :index="4" @click="navTo('/pages/storegoods/storeGoodsProcessReturnInList')">
|
||||
<view class="home-icon icon-color02">
|
||||
<i class="iconfont icon-hetongguanli"></i>
|
||||
</view>
|
||||
<view class="grid-text">加工退货进仓</view>
|
||||
</u-grid-item>
|
||||
<u-grid-item :index="5" @click="navTo('/pages/storegoods/storeGoodsPurchaseInList')">
|
||||
<view class="home-icon icon-color03">
|
||||
<i class="iconfont icon-hetongguanli"></i>
|
||||
</view>
|
||||
<view class="grid-text">采购进仓</view>
|
||||
</u-grid-item>
|
||||
</u-grid>
|
||||
</view>
|
||||
<view v-for="group in visibleMenuGroups" :key="group.title">
|
||||
<view class="workbench-title">{{ group.title }}</view>
|
||||
<view class="toolbar">
|
||||
<u-grid class="grid" :col="4" :border="false">
|
||||
<u-grid-item
|
||||
v-for="(item, index) in group.items"
|
||||
:key="item.router"
|
||||
:index="index"
|
||||
@click="navTo(item.url)"
|
||||
>
|
||||
<view class="home-icon" :class="item.color">
|
||||
<i class="iconfont" :class="item.icon"></i>
|
||||
</view>
|
||||
<view class="grid-text">{{ item.name }}</view>
|
||||
</u-grid-item>
|
||||
</u-grid>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="!visibleMenuGroups.length" class="textCenter">暂无可用功能</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import CommonNavbar from "@/components/common-navbar/index";
|
||||
import scanMixin from '@/common/scanMixin.js';
|
||||
import { hasResourceRouter } from '@/common/userSession.js';
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
||||
*/
|
||||
@ -76,7 +50,53 @@ export default {
|
||||
//{image: '/static/aidex/banner/banner03.png'}
|
||||
],
|
||||
todoCount: 3,
|
||||
// scanReceiver 和 isPageActive 已由 scanMixin 提供
|
||||
menuGroups: [
|
||||
{
|
||||
title: '销售管理',
|
||||
items: [
|
||||
{
|
||||
name: '成品配布',
|
||||
url: '/pages/saleship/salepickscan',
|
||||
router: 'CashCommodityClothOrder',
|
||||
icon: 'icon-hetongguanli',
|
||||
color: 'icon-color05'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '成品管理',
|
||||
items: [
|
||||
{
|
||||
name: '加工进仓',
|
||||
url: '/pages/storegoods/storeGoodsProcessInList',
|
||||
router: 'FpProcessingEntryOrder',
|
||||
icon: 'icon-hetongguanli',
|
||||
color: 'icon-color04'
|
||||
},
|
||||
{
|
||||
name: '加工出仓',
|
||||
url: '/pages/storegoods/storeGoodsProcessOutList',
|
||||
router: 'FpProcessingDeliverFromGodownOrder',
|
||||
icon: 'icon-hetongguanli',
|
||||
color: 'icon-color05'
|
||||
},
|
||||
{
|
||||
name: '加工退货进仓',
|
||||
url: '/pages/storegoods/storeGoodsProcessReturnInList',
|
||||
router: 'FpProcessingReturnEntryOrder',
|
||||
icon: 'icon-hetongguanli',
|
||||
color: 'icon-color02'
|
||||
},
|
||||
{
|
||||
name: '采购进仓',
|
||||
url: '/pages/storegoods/storeGoodsPurchaseInList',
|
||||
router: 'FinishPurchaseWarehouseEntry',
|
||||
icon: 'icon-hetongguanli',
|
||||
color: 'icon-color03'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
@ -92,6 +112,14 @@ export default {
|
||||
height: `${navHeight}px`,
|
||||
};
|
||||
},
|
||||
visibleMenuGroups() {
|
||||
return this.menuGroups
|
||||
.map((group) => ({
|
||||
...group,
|
||||
items: group.items.filter((item) => hasResourceRouter(item.router))
|
||||
}))
|
||||
.filter((group) => group.items.length > 0);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 自定义扫码处理回调 - 处理本页面特有的扫码逻辑
|
||||
|
||||
@ -255,7 +255,19 @@ const store = new Vuex.Store({
|
||||
},
|
||||
updateApiUrl({ commit }, url) {
|
||||
commit('SET_API_URL', url)
|
||||
}
|
||||
},
|
||||
updateUserInfo({ commit }, info) {
|
||||
commit('$uStore', {
|
||||
name: 'vuex_user',
|
||||
value: info || {}
|
||||
});
|
||||
if (!info) {
|
||||
commit('$uStore', {
|
||||
name: 'vuex_token',
|
||||
value: ''
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
apiurl: state => state.apiurl
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
const path = require('path');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
// // Load environment variables from .env file
|
||||
@ -5,6 +6,10 @@ dotenv.config();
|
||||
|
||||
module.exports = {
|
||||
chainWebpack: (config) => {
|
||||
config.resolve.alias
|
||||
.set('uview-ui/components/u-select/u-select.vue', path.resolve(__dirname, 'src/components/u-select/u-select.vue'))
|
||||
.set('uview-ui/components/u-action-sheet/u-action-sheet.vue', path.resolve(__dirname, 'src/components/u-action-sheet/u-action-sheet.vue'))
|
||||
.set('uview-ui/components/u-dropdown-item/u-dropdown-item.vue', path.resolve(__dirname, 'src/components/u-dropdown-item/u-dropdown-item.vue'));
|
||||
config.plugin('define').tap((definitions) => {
|
||||
console.log('VUE_APP_UPGRADE_NAME',JSON.stringify(process.env.VUE_APP_UPGRADE_NAME))
|
||||
console.log('VUE_APP_PRODUCTION_API_URL',JSON.stringify(process.env.VUE_APP_PRODUCTION_API_URL))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user