Compare commits
53
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1648bcb30 | ||
|
|
c0067e3b89 | ||
|
|
706fcda5b9 | ||
|
|
fdbd06f5f5 | ||
|
|
0e630d0fb0 | ||
|
|
4d3f767e16 | ||
|
|
5b6690b4d8 | ||
|
|
db12e1a249 | ||
|
|
870f857be8 | ||
|
|
c390b9f72b | ||
|
|
8315222788 | ||
|
|
59e699b4f6 | ||
|
|
fdacdfbda0 | ||
|
|
569b671b7b | ||
|
|
804e1a8f2b | ||
|
|
61bb43f759 | ||
|
|
7adec1b960 | ||
|
|
640dcf3493 | ||
|
|
b1404fdd89 | ||
|
|
a4dbcbe504 | ||
|
|
39e8393fde | ||
|
|
35fb587e22 | ||
|
|
83645ccbf6 | ||
|
|
232a3e179a | ||
|
|
1c434a608a | ||
|
|
f8ec49c79d | ||
|
|
7b10d36361 | ||
|
|
e8ae05b87b | ||
|
|
c4d5db056b | ||
|
|
7b199ba559 | ||
|
|
322ada8428 | ||
|
|
3e9b0fd1a8 | ||
|
|
b734f50f0a | ||
|
|
b04f890664 | ||
|
|
304d7ccde0 | ||
|
|
45a8928564 | ||
|
|
f6f85ed8ce | ||
|
|
3e936b064d | ||
|
|
7c6c7a1b32 | ||
|
|
c8ce45ae38 | ||
|
|
bff563b444 | ||
|
|
63755eab5c | ||
|
|
26c7085ab2 | ||
|
|
53a059f16b | ||
|
|
e0ee8d8c8d | ||
|
|
fa0ff1614b | ||
|
|
3f2481d1eb | ||
|
|
162e10a6fc | ||
|
|
26ff443107 | ||
|
|
02f192cac6 | ||
|
|
530ca0c3ad | ||
|
|
b3ecd77fb2 | ||
|
|
36c0f9a3a0 |
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
description: PDA 小屏界面字号与排版标准(以手动进仓页为准)
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# PDA 字号标准
|
||||||
|
|
||||||
|
本项目面向工业 PDA 小屏。新增/改版业务页时,**以后台手动进仓页**(`storeFabricManualIn.vue`)的字号为准,不要用偏小的默认字号。
|
||||||
|
|
||||||
|
共用变量:`@import '@/common/pda-typography.scss';`(或等价路径)。
|
||||||
|
|
||||||
|
## 字号(rpx)
|
||||||
|
|
||||||
|
| 用途 | 字号 | 变量 |
|
||||||
|
|------|------|------|
|
||||||
|
| 表单标签 / 正文 / 输入值 | **36** | `$pda-font-body` |
|
||||||
|
| 扫码输入框 | **36** | `$pda-font-body` |
|
||||||
|
| 占位提示 | **34** | `$pda-font-placeholder` |
|
||||||
|
| 行内操作(取消/修改) | **34** | `$pda-font-action` |
|
||||||
|
| 单位角标(如 KG) | **32** | `$pda-font-unit` |
|
||||||
|
| 顶栏次要文字(设置等) | **32** | `$pda-font-nav-sub` |
|
||||||
|
| 主按钮文字 | **36** | `$pda-font-button` |
|
||||||
|
| 弹层标题 / 选项 | **36** | `$pda-font-popup-title` / `$pda-font-popup-item` |
|
||||||
|
| 弹层取消 / 空态 | **34** | `$pda-font-popup-sub` |
|
||||||
|
|
||||||
|
## 行高与触控
|
||||||
|
|
||||||
|
- 列表行最小高度约 **100rpx**,可略加上下 padding
|
||||||
|
- 扫码输入框高度约 **100rpx**
|
||||||
|
- 主按钮高度约 **92rpx**
|
||||||
|
- 标签列宽约 **200rpx**(中文四字标签)
|
||||||
|
|
||||||
|
## 注意
|
||||||
|
|
||||||
|
- 登录环境选择、出仓明细等已放大过的页面,新改动保持不低于上表
|
||||||
|
- 不要为了“好看”再缩小字号;宁可少露内容、可滚动,也要可读
|
||||||
|
- 选择类弹层(如 `SearchSelectPopup`)与表单页使用同一套字号
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
NODE_ENV = development
|
NODE_ENV = production
|
||||||
VUE_APP_ENV_NAME = 默认环境
|
VUE_APP_ENV_NAME = zhoushang环境
|
||||||
VUE_APP_UPGRADE_NAME = erp_pda
|
VUE_APP_UPGRADE_NAME = erp_pda_zhoushang_zhichang
|
||||||
VUE_APP_PRODUCTION_API_URL = https://www.haotopai.com/hcscm_weave/mes/server/pda/v1
|
VUE_APP_UPGRADE_CDN_PREFIX = https://zsfzcdn.yushangfangzhi.com/version/erp_pda_zhoushang_zhichang
|
||||||
VUE_APP_DEV_API_URL = https://www.haotopai.com/hcscm_weave/mes/server/pda/v1
|
VUE_APP_PRODUCTION_API_URL = https://zszc.yushangfangzhi.com/hcscm_weave/pda/v1
|
||||||
|
VUE_APP_DEV_API_URL = https://zszc.yushangfangzhi.com/hcscm_weave/pda/v1
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
NODE_ENV = production
|
||||||
|
VUE_APP_ENV_NAME = zhoushang环境
|
||||||
|
VUE_APP_UPGRADE_NAME = erp_pda_zhoushang_zhichang
|
||||||
|
VUE_APP_UPGRADE_CDN_PREFIX = https://zsfzcdn.yushangfangzhi.com/version/erp_pda_zhoushang_zhichang
|
||||||
|
VUE_APP_PRODUCTION_API_URL = https://zszc.yushangfangzhi.com/hcscm_weave/pda/v1
|
||||||
|
VUE_APP_DEV_API_URL = https://zszc.yushangfangzhi.com/hcscm_weave/pda/v1
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
"build": "npm run build:h5",
|
"build": "npm run build:h5",
|
||||||
"build:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build",
|
"build:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build",
|
||||||
"build:app-plus:zhisheng": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build --mode zhisheng",
|
"build:app-plus:zhisheng": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build --mode zhisheng",
|
||||||
|
"build:app-plus:zhoushang": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build --mode zhoushang",
|
||||||
"build:app-plus:mes": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build --mode mes",
|
"build:app-plus:mes": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build --mode mes",
|
||||||
"build:custom": "cross-env NODE_ENV=production uniapp-cli custom",
|
"build:custom": "cross-env NODE_ENV=production uniapp-cli custom",
|
||||||
"build:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build",
|
"build:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build",
|
||||||
@@ -47,6 +48,7 @@
|
|||||||
"dev:quickapp-webview-huawei": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build --watch",
|
"dev:quickapp-webview-huawei": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build --watch",
|
||||||
"dev:quickapp-webview-union": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview-union vue-cli-service uni-build --watch",
|
"dev:quickapp-webview-union": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview-union vue-cli-service uni-build --watch",
|
||||||
"info": "node node_modules/@dcloudio/vue-cli-plugin-uni/commands/info.js",
|
"info": "node node_modules/@dcloudio/vue-cli-plugin-uni/commands/info.js",
|
||||||
|
"upload:apk": "node scripts/upload-apk.js",
|
||||||
"serve:quickapp-native": "node node_modules/@dcloudio/uni-quickapp-native/bin/serve.js",
|
"serve:quickapp-native": "node node_modules/@dcloudio/uni-quickapp-native/bin/serve.js",
|
||||||
"test:android": "cross-env UNI_PLATFORM=app-plus UNI_OS_NAME=android jest -i",
|
"test:android": "cross-env UNI_PLATFORM=app-plus UNI_OS_NAME=android jest -i",
|
||||||
"test:h5": "cross-env UNI_PLATFORM=h5 jest -i",
|
"test:h5": "cross-env UNI_PLATFORM=h5 jest -i",
|
||||||
|
|||||||
@@ -0,0 +1,333 @@
|
|||||||
|
/**
|
||||||
|
* 上传已打包的 PDA APK,等价于 ERP「开发者资源上传」里的安装包上传。
|
||||||
|
*
|
||||||
|
* 用法:
|
||||||
|
* npm run upload:apk -- --file D:\path\app.apk --target test
|
||||||
|
* npm run upload:apk -- --file D:\path\app.apk --target prod
|
||||||
|
* npm run upload:apk -- --file D:\path\app.apk --target test --mode zhisheng
|
||||||
|
*
|
||||||
|
* --target 只决定 APK 放到哪套 CDN:
|
||||||
|
* test 测试 CDN
|
||||||
|
* prod 正式 CDN
|
||||||
|
* 两者没有别的差别。生产环境的 PDA 也可以从测试 CDN 下载并安装。
|
||||||
|
*
|
||||||
|
* 版本号取 src/manifest.json 的 versionName。
|
||||||
|
* 场景值取对应 .env 的 VUE_APP_UPGRADE_NAME,拼成 /version/{upgradeName}/{version}.apk。
|
||||||
|
* 版本包上传成功后,再把同一份安装包上传为 /version/{upgradeName}/latest.apk。
|
||||||
|
* 运行时输入 ERP 手机号和密码获取 token。多个账套时再选择一次。
|
||||||
|
*/
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const readline = require('readline');
|
||||||
|
|
||||||
|
const ROOT = path.resolve(__dirname, '..');
|
||||||
|
const UPYUN_API = 'https://v0.api.upyun.com';
|
||||||
|
const DEFAULT_API_BASE = 'https://hcscmtest.zzfzyc.com/hcscm_weave';
|
||||||
|
const DEFAULT_CDN_HOST = {
|
||||||
|
test: 'https://testhcscm.cdn.zzfzyc.com',
|
||||||
|
prod: 'https://hcscm.cdn.zzfzyc.com',
|
||||||
|
};
|
||||||
|
/** 织厂环境签到 zhoushang 空间,下载域名与 ERP 相同 */
|
||||||
|
const MODE_UPLOAD = {
|
||||||
|
zhoushang: {
|
||||||
|
apiBase: 'https://zszc.yushangfangzhi.com/hcscm_weave',
|
||||||
|
cdnHost: 'https://zsfzcdn.yushangfangzhi.com',
|
||||||
|
status: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const MODE_ENV = {
|
||||||
|
zhoushang: '.env.zhoushang',
|
||||||
|
zhisheng: '.env.zhisheng',
|
||||||
|
mes: '.env.mes',
|
||||||
|
cjt: '.env.cjt',
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseArgs(argv) {
|
||||||
|
const args = { mode: 'zhoushang' };
|
||||||
|
for (let i = 0; i < argv.length; i += 1) {
|
||||||
|
const key = argv[i];
|
||||||
|
const value = argv[i + 1];
|
||||||
|
if (key === '--file' || key === '--target' || key === '--mode' || key === '--version' || key === '--phone' || key === '--password' || key === '--tenant') {
|
||||||
|
args[key.slice(2)] = value;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readEnvValue(filePath, name) {
|
||||||
|
const text = fs.readFileSync(filePath, 'utf8');
|
||||||
|
const line = text.split(/\r?\n/).find((item) => item.trim().startsWith(`${name}`));
|
||||||
|
if (!line) return '';
|
||||||
|
const raw = line.slice(line.indexOf('=') + 1).trim();
|
||||||
|
return raw.replace(/^['"]|['"]$/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function readManifestVersion() {
|
||||||
|
const manifest = JSON.parse(fs.readFileSync(path.join(ROOT, 'src/manifest.json'), 'utf8'));
|
||||||
|
return String(manifest.versionName || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
function ask(question) {
|
||||||
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
rl.question(question, (answer) => {
|
||||||
|
rl.close();
|
||||||
|
resolve(String(answer || '').trim());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function askPassword(question) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const stdin = process.stdin;
|
||||||
|
const stdout = process.stdout;
|
||||||
|
if (!stdin.isTTY || typeof stdin.setRawMode !== 'function') {
|
||||||
|
ask(question).then(resolve);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stdout.write(question);
|
||||||
|
stdin.setRawMode(true);
|
||||||
|
stdin.resume();
|
||||||
|
stdin.setEncoding('utf8');
|
||||||
|
let value = '';
|
||||||
|
const onData = (char) => {
|
||||||
|
switch (char) {
|
||||||
|
case '\n':
|
||||||
|
case '\r':
|
||||||
|
case '\u0004':
|
||||||
|
stdin.setRawMode(false);
|
||||||
|
stdin.pause();
|
||||||
|
stdin.removeListener('data', onData);
|
||||||
|
stdout.write('\n');
|
||||||
|
resolve(value);
|
||||||
|
break;
|
||||||
|
case '\u0003':
|
||||||
|
process.exit();
|
||||||
|
break;
|
||||||
|
case '\u007f':
|
||||||
|
case '\b':
|
||||||
|
value = value.slice(0, -1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
value += char;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
stdin.on('data', onData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function apiJson(apiBase, urlPath, { method = 'GET', token, body } = {}) {
|
||||||
|
const headers = { Platform: '1' };
|
||||||
|
if (token) headers.Authorization = token;
|
||||||
|
if (body) headers['Content-Type'] = 'application/json';
|
||||||
|
const res = await fetch(`${apiBase}${urlPath}`, {
|
||||||
|
method,
|
||||||
|
headers,
|
||||||
|
body: body ? JSON.stringify(body) : undefined,
|
||||||
|
});
|
||||||
|
const data = await res.json().catch(() => ({}));
|
||||||
|
if (!res.ok || data.code !== 0) {
|
||||||
|
throw new Error(data.msg || `请求失败(HTTP ${res.status})`);
|
||||||
|
}
|
||||||
|
return data.data || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function login(apiBase, { phone: phoneArg, password: passwordArg, tenant: tenantArg } = {}) {
|
||||||
|
const phone = phoneArg || await ask('手机号: ');
|
||||||
|
const password = passwordArg || await askPassword('密码: ');
|
||||||
|
if (!phone || !password) {
|
||||||
|
throw new Error('请输入手机号和密码');
|
||||||
|
}
|
||||||
|
console.log('正在登录...');
|
||||||
|
const first = await apiJson(apiBase, '/admin/v1/login', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { phone, password },
|
||||||
|
});
|
||||||
|
const tempToken = first.token;
|
||||||
|
if (!tempToken) throw new Error('登录未返回 token');
|
||||||
|
|
||||||
|
const dropdown = await apiJson(apiBase, '/admin/v1/tenantManagement/dropdownList', {
|
||||||
|
token: tempToken,
|
||||||
|
});
|
||||||
|
const tenants = dropdown.list || [];
|
||||||
|
if (!tenants.length) return tempToken;
|
||||||
|
|
||||||
|
let tenant = tenants[0];
|
||||||
|
if (tenants.length > 1) {
|
||||||
|
if (tenantArg) {
|
||||||
|
const picked = Number(tenantArg);
|
||||||
|
tenant = tenants[picked - 1];
|
||||||
|
if (!tenant) throw new Error('账套序号无效');
|
||||||
|
} else {
|
||||||
|
console.log('请选择账套:');
|
||||||
|
tenants.forEach((item, index) => {
|
||||||
|
const name = item.company_name || item.database_name || item.tenant_contacts || item.tenant_management_id;
|
||||||
|
console.log(` ${index + 1}. ${name}`);
|
||||||
|
});
|
||||||
|
const picked = Number(await ask('序号: '));
|
||||||
|
tenant = tenants[picked - 1];
|
||||||
|
if (!tenant) throw new Error('账套序号无效');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const second = await apiJson(apiBase, '/admin/v1/login', {
|
||||||
|
method: 'POST',
|
||||||
|
token: tempToken,
|
||||||
|
body: {
|
||||||
|
token: tempToken,
|
||||||
|
tenant_management_id: tenant.tenant_management_id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!second.token) throw new Error('选择账套后未返回 token');
|
||||||
|
return second.token;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getCdnSign({ apiBase, token, saveKey, status }) {
|
||||||
|
const url = new URL(`${apiBase}/admin/v1/cdn/token`);
|
||||||
|
url.searchParams.set('method', 'post');
|
||||||
|
url.searchParams.set('save_key', saveKey);
|
||||||
|
url.searchParams.set('status', String(status));
|
||||||
|
const res = await fetch(url, {
|
||||||
|
headers: {
|
||||||
|
Authorization: token,
|
||||||
|
Platform: '1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const body = await res.json();
|
||||||
|
if (!res.ok || body.code !== 0) {
|
||||||
|
throw new Error(body.msg || `获取签名失败(HTTP ${res.status})`);
|
||||||
|
}
|
||||||
|
return body.data || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function uploadToUpyun({ bucket, authorization, policy, filePath, fileName }) {
|
||||||
|
const buf = fs.readFileSync(filePath);
|
||||||
|
const form = new FormData();
|
||||||
|
form.append('authorization', authorization);
|
||||||
|
form.append('policy', policy);
|
||||||
|
form.append('file', new Blob([buf], { type: 'application/vnd.android.package-archive' }), fileName);
|
||||||
|
const res = await fetch(`${UPYUN_API}/${bucket}`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: form,
|
||||||
|
});
|
||||||
|
const text = await res.text();
|
||||||
|
let body = {};
|
||||||
|
try {
|
||||||
|
body = JSON.parse(text);
|
||||||
|
} catch (e) {
|
||||||
|
body = { raw: text };
|
||||||
|
}
|
||||||
|
if (!res.ok || (body.code != null && Number(body.code) !== 200)) {
|
||||||
|
throw new Error(body.message || body.msg || body.raw || `上传失败(HTTP ${res.status})`);
|
||||||
|
}
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toPublicUrl(cdnHost, saveKey, uploaded) {
|
||||||
|
if (uploaded.url && String(uploaded.url).startsWith('http')) return uploaded.url;
|
||||||
|
return `${cdnHost}${saveKey}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function uploadApkFile({ apiBase, token, apkPath, saveKey, fileName, status }) {
|
||||||
|
console.log(`场景路径: ${saveKey}`);
|
||||||
|
console.log('正在获取签名...');
|
||||||
|
const sign = await getCdnSign({
|
||||||
|
apiBase,
|
||||||
|
token,
|
||||||
|
saveKey,
|
||||||
|
status,
|
||||||
|
});
|
||||||
|
if (!sign.bucket || !sign.authorization || !sign.policy) {
|
||||||
|
throw new Error('签名返回缺少 bucket、authorization 或 policy');
|
||||||
|
}
|
||||||
|
console.log(`空间: ${sign.bucket}`);
|
||||||
|
console.log(`正在上传 ${fileName}...`);
|
||||||
|
const uploaded = await uploadToUpyun({
|
||||||
|
bucket: sign.bucket,
|
||||||
|
authorization: sign.authorization,
|
||||||
|
policy: sign.policy,
|
||||||
|
filePath: apkPath,
|
||||||
|
fileName,
|
||||||
|
});
|
||||||
|
console.log('上传成功');
|
||||||
|
return uploaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const args = parseArgs(process.argv.slice(2));
|
||||||
|
if (!args.file || !args.target) {
|
||||||
|
console.error('用法: npm run upload:apk -- --file <apk路径> --target test|prod [--mode zhoushang]');
|
||||||
|
console.error('--target 只切换 APK 的 CDN:test 测试 CDN,prod 正式 CDN。生产环境也可以从测试 CDN 下载安装。');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
if (args.target !== 'test' && args.target !== 'prod') {
|
||||||
|
console.error('--target 只能是 test 或 prod。两者只是 APK 的 CDN 环境不同,生产环境也可以从测试 CDN 下载安装。');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
const envFile = MODE_ENV[args.mode];
|
||||||
|
if (!envFile) {
|
||||||
|
console.error(`不支持的 --mode:${args.mode},可选 zhoushang、zhisheng、mes、cjt`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
const apkPath = path.resolve(args.file);
|
||||||
|
if (!fs.existsSync(apkPath)) {
|
||||||
|
console.error(`找不到 APK:${apkPath}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const version = args.version || readManifestVersion();
|
||||||
|
if (!version) {
|
||||||
|
console.error('manifest.json 里没有 versionName');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
const upgradeName = readEnvValue(path.join(ROOT, envFile), 'VUE_APP_UPGRADE_NAME');
|
||||||
|
if (!upgradeName) {
|
||||||
|
console.error(`${envFile} 里没有 VUE_APP_UPGRADE_NAME`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const modeUpload = MODE_UPLOAD[args.mode];
|
||||||
|
const status = modeUpload ? modeUpload.status : (args.target === 'prod' ? 2 : 1);
|
||||||
|
const fileName = `${version}.apk`;
|
||||||
|
const saveKey = `/version/${upgradeName}/${fileName}`;
|
||||||
|
const latestFileName = 'latest.apk';
|
||||||
|
const latestSaveKey = `/version/${upgradeName}/${latestFileName}`;
|
||||||
|
const apiBase = modeUpload ? modeUpload.apiBase : DEFAULT_API_BASE;
|
||||||
|
const cdnHost = modeUpload ? modeUpload.cdnHost : DEFAULT_CDN_HOST[args.target];
|
||||||
|
const token = await login(apiBase, {
|
||||||
|
phone: args.phone,
|
||||||
|
password: args.password,
|
||||||
|
tenant: args.tenant,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`版本号: ${version}`);
|
||||||
|
console.log(`签名接口: ${apiBase}`);
|
||||||
|
console.log(`CDN: ${cdnHost}`);
|
||||||
|
const uploaded = await uploadApkFile({
|
||||||
|
apiBase,
|
||||||
|
token,
|
||||||
|
apkPath,
|
||||||
|
saveKey,
|
||||||
|
fileName,
|
||||||
|
status,
|
||||||
|
});
|
||||||
|
console.log(toPublicUrl(cdnHost, saveKey, uploaded));
|
||||||
|
|
||||||
|
const latestUploaded = await uploadApkFile({
|
||||||
|
apiBase,
|
||||||
|
token,
|
||||||
|
apkPath,
|
||||||
|
saveKey: latestSaveKey,
|
||||||
|
fileName: latestFileName,
|
||||||
|
status,
|
||||||
|
});
|
||||||
|
console.log(toPublicUrl(cdnHost, latestSaveKey, latestUploaded));
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((error) => {
|
||||||
|
console.error(error.message || error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
@@ -6,6 +6,7 @@ import { audioManager } from '@/utils/audioManager'
|
|||||||
|
|
||||||
import util from '@/common/util.js';
|
import util from '@/common/util.js';
|
||||||
import md5 from '@/common/md5.js';
|
import md5 from '@/common/md5.js';
|
||||||
|
import { ensureScanConfigAfterLogin } from '@/common/scanAutoConfig.js';
|
||||||
export default {
|
export default {
|
||||||
globalData: {
|
globalData: {
|
||||||
AppName: '',
|
AppName: '',
|
||||||
@@ -30,6 +31,14 @@ import { audioManager } from '@/utils/audioManager'
|
|||||||
audioManager.init();
|
audioManager.init();
|
||||||
// 初始化通知系统
|
// 初始化通知系统
|
||||||
this.$store.dispatch('initNotification');
|
this.$store.dispatch('initNotification');
|
||||||
|
|
||||||
|
// 已登录且本地无扫码配置时,自动匹配一次
|
||||||
|
const loginData = uni.getStorageSync('RemoteTokenData');
|
||||||
|
if (loginData && loginData.token && this.$u && this.$u.api) {
|
||||||
|
ensureScanConfigAfterLogin(this.$u.api).catch((error) => {
|
||||||
|
console.log('启动时自动匹配扫码设置失败', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
+22
-5
@@ -7,6 +7,7 @@ export const isDevelopment = process.env.NODE_ENV === 'development'
|
|||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
upgradeName: process.env.VUE_APP_UPGRADE_NAME || 'erp_pda',
|
upgradeName: process.env.VUE_APP_UPGRADE_NAME || 'erp_pda',
|
||||||
|
upgradeCdnPrefix: process.env.VUE_APP_UPGRADE_CDN_PREFIX || '',
|
||||||
|
|
||||||
// 产品名称
|
// 产品名称
|
||||||
productName: '浩拓技术',
|
productName: '浩拓技术',
|
||||||
@@ -21,19 +22,35 @@ const config = {
|
|||||||
isDevelopment: isDevelopment,
|
isDevelopment: isDevelopment,
|
||||||
|
|
||||||
// 生产环境API URL(服务名段 hcscm_weave)
|
// 生产环境API URL(服务名段 hcscm_weave)
|
||||||
productionApiUrl: process.env.VUE_APP_PRODUCTION_API_URL || 'https://www.haotopai.com/hcscm_weave/mes/server/pda/v1',
|
productionApiUrl: process.env.VUE_APP_PRODUCTION_API_URL,
|
||||||
|
|
||||||
// 开发环境API URL选项(仅替换 //域名/ 后第一个路径段 hcscm → hcscm_weave,不改域名)
|
// 开发环境API URL选项(仅替换 //域名/ 后第一个路径段 hcscm → hcscm_weave,不改域名)
|
||||||
devApiUrlOptions: [
|
devApiUrlOptions: [
|
||||||
{ label: '测试环境', value: 'https://hcscmtest.zzfzyc.com/hcscm_weave/pda/v1' },
|
{ label: '测试环境', value: 'https://hcscmtest.zzfzyc.com/hcscm_weave/pda/v1' },
|
||||||
{ label: '本地环境', value: 'http://192.168.1.66:7010/hcscm_weave/pda/v1' },
|
{ label: '正式环境', value: process.env.VUE_APP_PRODUCTION_API_URL },
|
||||||
{ label: '正式环境', value: process.env.VUE_APP_DEV_API_URL || 'https://www.haotopai.com/hcscm_weave/mes/server/pda/v1' },
|
{ label: '本地环境', value: 'http://192.168.1.97:7010/hcscm_weave/pda/v1' },
|
||||||
{ label: '自定义', value: 'custom' }
|
{ label: '自定义', value: 'custom' }
|
||||||
]
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置后台接口服务的基础地址 - 使用动态API URL
|
export function resolveUpgradeDownloadUrl(downloadUrl) {
|
||||||
// config.baseUrl = 'https://aidex.vip/api'; // 注释掉固定的baseUrl
|
const raw = String(downloadUrl || '').trim();
|
||||||
|
const prefix = String(config.upgradeCdnPrefix || '').trim().replace(/\/+$/, '');
|
||||||
|
if (!raw || !prefix) {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
const path = raw.split('?')[0].split('#')[0];
|
||||||
|
const fileName = path.split('/').filter(Boolean).pop() || '';
|
||||||
|
if (!fileName || !/\.apk$/i.test(fileName)) {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
return `${prefix}/${fileName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDefaultApiUrl() {
|
||||||
|
const prod = config.devApiUrlOptions.find(item => item.label === '正式环境');
|
||||||
|
return (prod && prod.value) || config.productionApiUrl || 'https://zszc.yushangfangzhi.com/server/hcscm_weave/pda/v1';
|
||||||
|
}
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|||||||
+12
-1
@@ -46,6 +46,12 @@ const install = (Vue, vm) => {
|
|||||||
detailList: (params = {}) => vm.$u.get(gfmWarehouseUrl('getGfmWarehouseList'), params),
|
detailList: (params = {}) => vm.$u.get(gfmWarehouseUrl('getGfmWarehouseList'), params),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// PDA 生产进仓(排产单细码扫码进仓)
|
||||||
|
productionScheduleOrder: {
|
||||||
|
getScanFineCodeDetail: (params = {}) => vm.$u.get('/produce/productionScheduleOrder/getScanFineCodeDetail', params),
|
||||||
|
scanInWarehouseFineCode: (params = {}) => vm.$u.putJson('/produce/productionScheduleOrder/scanInWarehouseFineCode', params),
|
||||||
|
},
|
||||||
|
|
||||||
// 营销体系下拉(路径相对 apiurl:.../pda/v1/saleSystem/getSaleSystemDropdownList)
|
// 营销体系下拉(路径相对 apiurl:.../pda/v1/saleSystem/getSaleSystemDropdownList)
|
||||||
saleSystem: {
|
saleSystem: {
|
||||||
getDropdownList: (params = {}) => vm.$u.get('/saleSystem/getSaleSystemDropdownList', params),
|
getDropdownList: (params = {}) => vm.$u.get('/saleSystem/getSaleSystemDropdownList', params),
|
||||||
@@ -56,6 +62,11 @@ const install = (Vue, vm) => {
|
|||||||
list: (params = {}) => vm.$u.get('/business_unit/list', params),
|
list: (params = {}) => vm.$u.get('/business_unit/list', params),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 员工枚举(路径相对 apiurl:.../pda/v1/employee/list_enum)
|
||||||
|
employee: {
|
||||||
|
listEnum: (params = {}) => vm.$u.get('/employee/list_enum', params),
|
||||||
|
},
|
||||||
|
|
||||||
// 字典明细枚举(路径相对 apiurl:.../pda/v1/dictionaryDetail/getDictionaryDetailEnumList)
|
// 字典明细枚举(路径相对 apiurl:.../pda/v1/dictionaryDetail/getDictionaryDetailEnumList)
|
||||||
dictionary: {
|
dictionary: {
|
||||||
getDetailEnumList: (params = {}) => vm.$u.get('/dictionaryDetail/getDictionaryDetailEnumList', params),
|
getDetailEnumList: (params = {}) => vm.$u.get('/dictionaryDetail/getDictionaryDetailEnumList', params),
|
||||||
@@ -103,7 +114,7 @@ const install = (Vue, vm) => {
|
|||||||
// 个人信息修改
|
// 个人信息修改
|
||||||
user: {
|
user: {
|
||||||
saveUserInfo: (params = {}) => vm.$u.post(config.productionApiUrl+'/mobile/user/saveUserInfo', params),
|
saveUserInfo: (params = {}) => vm.$u.post(config.productionApiUrl+'/mobile/user/saveUserInfo', params),
|
||||||
infoSavePwd: (params = {}) => vm.$u.put(config.productionApiUrl+'/system/user/profile/updatePwd', params),
|
infoSavePwd: (params = {}) => vm.$u.put('/system/user/profile/updatePwd', params),
|
||||||
infoSavePqa: (params = {}) => vm.$u.post(config.productionApiUrl+'/sys/user/infoSavePqa', params),
|
infoSavePqa: (params = {}) => vm.$u.post(config.productionApiUrl+'/sys/user/infoSavePqa', params),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ const install = (Vue, vm) => {
|
|||||||
console.log('request', req);
|
console.log('request', req);
|
||||||
console.log('baseUrl', vm.$store.state.apiurl);
|
console.log('baseUrl', vm.$store.state.apiurl);
|
||||||
console.log('完整URL', vm.$store.state.apiurl + req.url);
|
console.log('完整URL', vm.$store.state.apiurl + req.url);
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
// Android 5.x 等老 PDA 不信任 Let's Encrypt 新证书链,关闭校验证书
|
||||||
|
req.sslVerify = false;
|
||||||
|
// #endif
|
||||||
if (!req.header){
|
if (!req.header){
|
||||||
req.header = [];
|
req.header = [];
|
||||||
}
|
}
|
||||||
@@ -69,14 +73,33 @@ const install = (Vue, vm) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
console.log('res',res)
|
console.log('res',res)
|
||||||
if (!(res.data)){
|
const rejectWithMessage = (message) => {
|
||||||
vm.$u.toast('未连接到服务器')
|
const text = String(message || '请求失败').trim() || '请求失败';
|
||||||
return Promise.reject(new Error('未连接到服务器'));
|
vm.$u.toast(text);
|
||||||
|
return Promise.reject(new Error(text));
|
||||||
|
};
|
||||||
|
// HTTP 非 200(如 404)时直接报错,避免把字符串/HTML 当业务 data 解析
|
||||||
|
if (res.statusCode && res.statusCode !== 200) {
|
||||||
|
let message = `请求失败(${res.statusCode})`;
|
||||||
|
if (typeof res.data === 'string' && res.data.trim()) {
|
||||||
|
message = res.data.trim().slice(0, 120);
|
||||||
|
} else if (res.data && typeof res.data === 'object') {
|
||||||
|
message = res.data.msg || res.data.message || message;
|
||||||
|
}
|
||||||
|
return rejectWithMessage(message);
|
||||||
|
}
|
||||||
|
if (res.data === undefined || res.data === null || res.data === '') {
|
||||||
|
const errMsg = String((res && res.errMsg) || '');
|
||||||
|
const isNetworkError = res.statusCode === -1
|
||||||
|
|| /Unable to resolve host|Failed to connect|request:fail|timeout|网络/i.test(errMsg);
|
||||||
|
const message = isNetworkError ? '当前没有网络,请检查网络后重试' : '未连接到服务器';
|
||||||
|
return rejectWithMessage(message);
|
||||||
|
}
|
||||||
|
if (typeof res.data !== 'object') {
|
||||||
|
return rejectWithMessage(String(res.data).slice(0, 120));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.data.code !== 0) {
|
if (res.data.code !== 0) {
|
||||||
vm.$u.toast(res.data.msg)
|
return rejectWithMessage(res.data.msg || res.data.message || '请求失败');
|
||||||
return Promise.reject(new Error(res.data.msg))
|
|
||||||
}
|
}
|
||||||
let data = res.data.data;
|
let data = res.data.data;
|
||||||
console.log('data',data)
|
console.log('data',data)
|
||||||
@@ -159,6 +182,9 @@ const install = (Vue, vm) => {
|
|||||||
uni.request({
|
uni.request({
|
||||||
url,
|
url,
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
sslVerify: false,
|
||||||
|
// #endif
|
||||||
header: {
|
header: {
|
||||||
...header,
|
...header,
|
||||||
'Platform': 2,
|
'Platform': 2,
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* PDA 小屏字号标准(以手动进仓页为准)
|
||||||
|
* 业务页请优先引用这些变量,避免字号再次变小。
|
||||||
|
*/
|
||||||
|
|
||||||
|
$pda-font-body: 36rpx;
|
||||||
|
$pda-font-placeholder: 34rpx;
|
||||||
|
$pda-font-action: 34rpx;
|
||||||
|
$pda-font-unit: 32rpx;
|
||||||
|
$pda-font-nav-sub: 32rpx;
|
||||||
|
$pda-font-button: 36rpx;
|
||||||
|
$pda-font-popup-title: 36rpx;
|
||||||
|
$pda-font-popup-item: 36rpx;
|
||||||
|
$pda-font-popup-sub: 34rpx;
|
||||||
|
|
||||||
|
$pda-row-min-height: 100rpx;
|
||||||
|
$pda-scan-input-height: 100rpx;
|
||||||
|
$pda-button-height: 92rpx;
|
||||||
|
$pda-label-width: 200rpx;
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* 登录后 / 冷启动:拉取扫码字典并在本地无配置时自动匹配写入
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
DICTIONARY_TYPE_SCANNER,
|
||||||
|
autoConfigureScanSettings,
|
||||||
|
} from '@/common/scanConfig.js';
|
||||||
|
|
||||||
|
function extractDictionaryList(res) {
|
||||||
|
if (Array.isArray(res)) return res;
|
||||||
|
if (res && Array.isArray(res.list)) return res.list;
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {object} api - this.$u.api
|
||||||
|
* @returns {Promise<{saved:boolean,skipped:boolean,config:object|null,reason?:string}>}
|
||||||
|
*/
|
||||||
|
export async function ensureScanConfigAfterLogin(api) {
|
||||||
|
if (!api || !api.dictionary || !api.dictionary.getDetailEnumList) {
|
||||||
|
return autoConfigureScanSettings({ remoteConfigs: [] });
|
||||||
|
}
|
||||||
|
|
||||||
|
let remoteConfigs = [];
|
||||||
|
try {
|
||||||
|
const res = await api.dictionary.getDetailEnumList({
|
||||||
|
dictionary_id: DICTIONARY_TYPE_SCANNER,
|
||||||
|
});
|
||||||
|
remoteConfigs = extractDictionaryList(res);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('拉取扫码字典失败,改用内置配置自动匹配', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = autoConfigureScanSettings({ remoteConfigs });
|
||||||
|
if (result.skipped) {
|
||||||
|
console.log('本地已有扫码设置,跳过自动匹配', result.config && result.config.name);
|
||||||
|
} else if (result.saved) {
|
||||||
|
if (result.reason === 'rematch_n5s_from_seuic') {
|
||||||
|
console.log('N5S 误识别为东集,已纠正为', result.config && result.config.name);
|
||||||
|
} else {
|
||||||
|
console.log('已自动写入扫码设置', result.config && result.config.name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('自动匹配扫码设置未写入', result.reason);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
+421
-6
@@ -2,8 +2,156 @@ export const STORAGE_KEY = 'pda_scan_config';
|
|||||||
|
|
||||||
export const DICTIONARY_TYPE_SCANNER = 10046;
|
export const DICTIONARY_TYPE_SCANNER = 10046;
|
||||||
|
|
||||||
|
export const PHONE_SCAN_BRAND = 'phone';
|
||||||
|
|
||||||
|
// 历史误用 brand=newland 表示东集;真正的新大陆是 nlscan
|
||||||
|
const LEGACY_SEUIC_BRANDS = ['newland', '东集', 'idata'];
|
||||||
|
|
||||||
|
export const PHONE_SCAN_CONFIG = {
|
||||||
|
brand: PHONE_SCAN_BRAND,
|
||||||
|
name: '手机扫码',
|
||||||
|
isPhoneScan: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 内置扫码配置:补 needSetup,并在字典拉不到时兜底 */
|
||||||
|
export const BUILTIN_SCANNER_CONFIGS = [
|
||||||
|
{
|
||||||
|
brand: 'seuic',
|
||||||
|
name: '东大集成(AUTOID)',
|
||||||
|
action: 'com.android.server.scannerservice.broadcast',
|
||||||
|
dataKey: 'scannerdata',
|
||||||
|
needSetup: true,
|
||||||
|
setupAction: 'com.android.scanner.service_settings',
|
||||||
|
setupParams: {
|
||||||
|
barcode_send_mode: 'BROADCAST',
|
||||||
|
action_barcode_broadcast: 'com.android.server.scannerservice.broadcast',
|
||||||
|
key_barcode_broadcast: 'scannerdata',
|
||||||
|
endchar: 'NONE',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
brand: 'sunmi',
|
||||||
|
name: '商米',
|
||||||
|
action: 'com.sunmi.scanner.ACTION_DATA_CODE_RECEIVED',
|
||||||
|
dataKey: 'data',
|
||||||
|
needSetup: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
brand: 'urovo',
|
||||||
|
name: '优博讯',
|
||||||
|
action: 'android.intent.ACTION_DECODE_DATA',
|
||||||
|
dataKey: 'barcode_string',
|
||||||
|
needSetup: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
brand: 'nlscan',
|
||||||
|
name: '新大陆',
|
||||||
|
action: 'nlscan.action.SCANNER_RESULT',
|
||||||
|
dataKey: 'SCAN_BARCODE1',
|
||||||
|
needSetup: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// N5S 部分固件走智联天地兼容广播,而不是 nlscan.action
|
||||||
|
brand: 'nlscan_compat',
|
||||||
|
name: '新大陆(兼容广播)',
|
||||||
|
action: 'android.intent.action.RECEIVE_SCANDATA_BROADCAST',
|
||||||
|
dataKey: 'android.intent.extra.SCAN_BROADCAST_DATA',
|
||||||
|
needSetup: false,
|
||||||
|
},
|
||||||
|
{ ...PHONE_SCAN_CONFIG },
|
||||||
|
];
|
||||||
|
|
||||||
|
/** 设备关键词 / 常见扫码相关包名,用于自动识别 */
|
||||||
|
const DETECT_RULES = [
|
||||||
|
{
|
||||||
|
matchNames: ['商米'],
|
||||||
|
matchActions: ['com.sunmi.scanner.ACTION_DATA_CODE_RECEIVED'],
|
||||||
|
keywords: ['sunmi'],
|
||||||
|
packages: ['com.sunmi.scanner', 'woyou.aidlservice.jiuiv5'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matchNames: ['新大陆', '新大陆(兼容广播)'],
|
||||||
|
matchActions: [
|
||||||
|
'nlscan.action.SCANNER_RESULT',
|
||||||
|
'android.intent.action.RECEIVE_SCANDATA_BROADCAST',
|
||||||
|
],
|
||||||
|
// N5S 机型常标成 alps/zltd,不能只靠 newland 关键字
|
||||||
|
keywords: ['newland', 'nls', 'nlscan', 'n5s', 'zltd'],
|
||||||
|
models: ['n5s', 'n5'],
|
||||||
|
packages: [
|
||||||
|
'com.nlscan.barcodescanner',
|
||||||
|
'com.newland',
|
||||||
|
'com.nlscan.android.scan.service',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matchNames: ['优博讯'],
|
||||||
|
matchActions: ['android.intent.ACTION_DECODE_DATA'],
|
||||||
|
keywords: ['urovo', 'ubx'],
|
||||||
|
packages: ['com.urovo', 'com.ubx'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matchNames: ['盈达'],
|
||||||
|
matchActions: ['android.intent.action.SCANRESULT'],
|
||||||
|
keywords: ['idata', 'yingda'],
|
||||||
|
packages: ['com.idata'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matchNames: ['海雅达'],
|
||||||
|
matchActions: ['com.android.scanner.broadcast'],
|
||||||
|
keywords: ['haiyada'],
|
||||||
|
packages: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matchNames: ['东大集成(AUTOID)', '东大集成', '东集'],
|
||||||
|
matchActions: ['com.android.server.scannerservice.broadcast'],
|
||||||
|
keywords: ['seuic', 'autoid', 'eastcom', '东集', '东大'],
|
||||||
|
packages: ['com.seuic.scanner'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const PDA_DEVICE_KEYWORDS = [
|
||||||
|
'newland', 'nls', 'nlscan', 'n5s', 'zltd', 'sunmi', 'urovo', 'ubx', 'zebra', 'honeywell',
|
||||||
|
'idata', 'seuic', 'autoid', '东集', '东大',
|
||||||
|
];
|
||||||
|
|
||||||
|
/** 明确机型 → 优先品牌,避免通用东集广播抢分 */
|
||||||
|
const MODEL_PREFERRED_BRANDS = [
|
||||||
|
{
|
||||||
|
models: ['n5s'],
|
||||||
|
brands: ['nlscan', 'nlscan_compat'],
|
||||||
|
score: 220,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const NO_SETUP_HINT_KEY = 'pda_scan_config_hint_shown';
|
const NO_SETUP_HINT_KEY = 'pda_scan_config_hint_shown';
|
||||||
|
|
||||||
|
export function isPhoneScanConfig(config) {
|
||||||
|
return !!(config && (config.isPhoneScan || config.brand === PHONE_SCAN_BRAND));
|
||||||
|
}
|
||||||
|
|
||||||
|
function migrateLegacySeuicBrand(config) {
|
||||||
|
if (!config || isPhoneScanConfig(config)) {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
const brand = String(config.brand || '');
|
||||||
|
const name = String(config.name || '');
|
||||||
|
const action = String(config.action || '');
|
||||||
|
// 历史内置配置把东集误标成 brand=newland;真正的新大陆是 nlscan
|
||||||
|
const isLegacySeuicLabel = LEGACY_SEUIC_BRANDS.includes(brand) || name === '东集';
|
||||||
|
if (!isLegacySeuicLabel) {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
if (action.includes('nlscan')) {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
brand: 'seuic',
|
||||||
|
name: (!name || name === '东集') ? '东大集成(AUTOID)' : name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function enrichFromBuiltinConfig(config, builtinConfigs = []) {
|
function enrichFromBuiltinConfig(config, builtinConfigs = []) {
|
||||||
if (!config || !builtinConfigs.length) {
|
if (!config || !builtinConfigs.length) {
|
||||||
return config;
|
return config;
|
||||||
@@ -12,7 +160,13 @@ function enrichFromBuiltinConfig(config, builtinConfigs = []) {
|
|||||||
const builtin = builtinConfigs.find((item) => {
|
const builtin = builtinConfigs.find((item) => {
|
||||||
return item.action === config.action
|
return item.action === config.action
|
||||||
|| item.name === config.name
|
|| item.name === config.name
|
||||||
|| item.brand === config.brand;
|
|| item.brand === config.brand
|
||||||
|
|| (item.brand === 'seuic' && (
|
||||||
|
String(config.name || '').includes('东大')
|
||||||
|
|| String(config.name || '').includes('东集')
|
||||||
|
|| String(config.name || '').includes('AUTOID')
|
||||||
|
|| String(config.action || '').includes('scannerservice.broadcast')
|
||||||
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!builtin) {
|
if (!builtin) {
|
||||||
@@ -30,15 +184,25 @@ function enrichFromBuiltinConfig(config, builtinConfigs = []) {
|
|||||||
export function normalizeConfig(raw, builtinConfigs = []) {
|
export function normalizeConfig(raw, builtinConfigs = []) {
|
||||||
if (!raw || typeof raw !== 'object') return null;
|
if (!raw || typeof raw !== 'object') return null;
|
||||||
|
|
||||||
const config = enrichFromBuiltinConfig({
|
const brand = String(raw.brand || raw.id || raw.dictionary_detail_id || raw.name || '');
|
||||||
brand: String(raw.brand || raw.id || raw.dictionary_detail_id || raw.name || ''),
|
const isPhoneScan = raw.isPhoneScan === true || brand === PHONE_SCAN_BRAND;
|
||||||
|
|
||||||
|
if (isPhoneScan) {
|
||||||
|
return { ...PHONE_SCAN_CONFIG };
|
||||||
|
}
|
||||||
|
|
||||||
|
let config = {
|
||||||
|
brand,
|
||||||
name: raw.name || '',
|
name: raw.name || '',
|
||||||
action: raw.action || raw.code || '',
|
action: raw.action || raw.code || '',
|
||||||
dataKey: raw.dataKey || raw.data_key || raw.remark || '',
|
dataKey: raw.dataKey || raw.data_key || raw.remark || '',
|
||||||
needSetup: raw.needSetup != null ? raw.needSetup : !!raw.need_setup,
|
needSetup: raw.needSetup != null ? raw.needSetup : !!raw.need_setup,
|
||||||
setupAction: raw.setupAction || raw.setup_action || '',
|
setupAction: raw.setupAction || raw.setup_action || '',
|
||||||
setupParams: raw.setupParams || raw.setup_params || null,
|
setupParams: raw.setupParams || raw.setup_params || null,
|
||||||
}, builtinConfigs);
|
};
|
||||||
|
|
||||||
|
config = migrateLegacySeuicBrand(config);
|
||||||
|
config = enrichFromBuiltinConfig(config, builtinConfigs);
|
||||||
|
|
||||||
if (!config.brand || !config.action || !config.dataKey) {
|
if (!config.brand || !config.action || !config.dataKey) {
|
||||||
return null;
|
return null;
|
||||||
@@ -51,10 +215,19 @@ export function mapDictionaryToScannerConfig(raw, builtinConfigs = []) {
|
|||||||
return normalizeConfig(raw, builtinConfigs);
|
return normalizeConfig(raw, builtinConfigs);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getScanConfig() {
|
export function getScanConfig(builtinConfigs = []) {
|
||||||
try {
|
try {
|
||||||
const data = uni.getStorageSync(STORAGE_KEY);
|
const data = uni.getStorageSync(STORAGE_KEY);
|
||||||
return normalizeConfig(data);
|
const normalized = normalizeConfig(data, builtinConfigs);
|
||||||
|
// 旧 brand=newland(东集) 迁移后写回,避免下次仍读到错误 brand
|
||||||
|
if (normalized && data && String(data.brand || '') !== String(normalized.brand || '')) {
|
||||||
|
try {
|
||||||
|
uni.setStorageSync(STORAGE_KEY, normalized);
|
||||||
|
} catch (e) {
|
||||||
|
console.log('迁移扫码枪配置写回失败', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return normalized;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('读取扫码枪配置失败', e);
|
console.log('读取扫码枪配置失败', e);
|
||||||
return null;
|
return null;
|
||||||
@@ -90,3 +263,245 @@ export function markNoConfigHintShown() {
|
|||||||
console.log('记录扫码枪提示状态失败', e);
|
console.log('记录扫码枪提示状态失败', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function mergeScannerConfigs(remoteConfigs = []) {
|
||||||
|
const configMap = new Map();
|
||||||
|
BUILTIN_SCANNER_CONFIGS.forEach((item) => {
|
||||||
|
if (!isPhoneScanConfig(item)) {
|
||||||
|
configMap.set(item.action || item.brand, item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
(remoteConfigs || []).forEach((raw) => {
|
||||||
|
const normalized = mapDictionaryToScannerConfig(raw, BUILTIN_SCANNER_CONFIGS);
|
||||||
|
if (!normalized || isPhoneScanConfig(normalized)) return;
|
||||||
|
configMap.set(normalized.action || normalized.brand, normalized);
|
||||||
|
});
|
||||||
|
const list = Array.from(configMap.values());
|
||||||
|
list.push({ ...PHONE_SCAN_CONFIG });
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDeviceIdentity() {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
try {
|
||||||
|
const Build = plus.android.importClass('android.os.Build');
|
||||||
|
return {
|
||||||
|
manufacturer: String(Build.MANUFACTURER || '').toLowerCase(),
|
||||||
|
model: String(Build.MODEL || '').toLowerCase(),
|
||||||
|
brand: String(Build.BRAND || '').toLowerCase(),
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
console.log('读取设备信息失败', e);
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
return { manufacturer: '', model: '', brand: '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isPdaDevice() {
|
||||||
|
const identity = getDeviceIdentity();
|
||||||
|
const text = `${identity.manufacturer} ${identity.model} ${identity.brand}`;
|
||||||
|
return PDA_DEVICE_KEYWORDS.some((keyword) => text.includes(String(keyword).toLowerCase()));
|
||||||
|
}
|
||||||
|
|
||||||
|
function findDetectRule(config) {
|
||||||
|
return DETECT_RULES.find((rule) => {
|
||||||
|
if (rule.matchNames.includes(config.name)) return true;
|
||||||
|
if (rule.matchActions.includes(config.action)) return true;
|
||||||
|
return false;
|
||||||
|
}) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPackageInstalled(packageName) {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
try {
|
||||||
|
const main = plus.android.runtimeMainActivity();
|
||||||
|
const pm = main.getPackageManager();
|
||||||
|
plus.android.importClass(pm);
|
||||||
|
pm.getPackageInfo(packageName, 0);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function canResolveBroadcast(action) {
|
||||||
|
if (!action) return false;
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
try {
|
||||||
|
const main = plus.android.runtimeMainActivity();
|
||||||
|
const Intent = plus.android.importClass('android.content.Intent');
|
||||||
|
const pm = main.getPackageManager();
|
||||||
|
plus.android.importClass(pm);
|
||||||
|
const intent = new Intent(action);
|
||||||
|
const list = pm.queryBroadcastReceivers(intent, 0);
|
||||||
|
return !!(list && list.size && list.size() > 0);
|
||||||
|
} catch (e) {
|
||||||
|
console.log('探测广播接收方失败', action, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isModelMatch(identity, models = []) {
|
||||||
|
const model = String((identity && identity.model) || '').toLowerCase();
|
||||||
|
if (!model) return false;
|
||||||
|
return (models || []).some((item) => model === item || model.includes(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getModelPreferredBoost(config, identity) {
|
||||||
|
if (!config || isPhoneScanConfig(config)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const brand = String(config.brand || '');
|
||||||
|
for (let i = 0; i < MODEL_PREFERRED_BRANDS.length; i += 1) {
|
||||||
|
const rule = MODEL_PREFERRED_BRANDS[i];
|
||||||
|
if (!isModelMatch(identity, rule.models)) continue;
|
||||||
|
if ((rule.brands || []).includes(brand)) {
|
||||||
|
return Number(rule.score) || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新大陆 N5S / 智联天地 N5S:机型名常为 n5s,厂商可能是 newland/zltd/alps */
|
||||||
|
export function isNewlandN5sDevice(identity = getDeviceIdentity()) {
|
||||||
|
const model = String((identity && identity.model) || '').toLowerCase();
|
||||||
|
const text = `${identity.manufacturer || ''} ${identity.brand || ''} ${model}`.toLowerCase();
|
||||||
|
if (model === 'n5s' || model.includes('n5s')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return text.includes('n5s') && (
|
||||||
|
text.includes('newland')
|
||||||
|
|| text.includes('zltd')
|
||||||
|
|| text.includes('nlscan')
|
||||||
|
|| text.includes('alps')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isWrongSeuicOnNewlandDevice(config, identity = getDeviceIdentity()) {
|
||||||
|
if (!config || isPhoneScanConfig(config)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!isNewlandN5sDevice(identity) && !isModelMatch(identity, ['n5s'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const brand = String(config.brand || '');
|
||||||
|
const action = String(config.action || '');
|
||||||
|
return brand === 'seuic'
|
||||||
|
|| action.includes('scannerservice.broadcast')
|
||||||
|
|| String(config.name || '').includes('东集')
|
||||||
|
|| String(config.name || '').includes('东大');
|
||||||
|
}
|
||||||
|
|
||||||
|
function scoreScannerConfig(config, identity) {
|
||||||
|
if (!config || isPhoneScanConfig(config)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let score = 0;
|
||||||
|
const rule = findDetectRule(config);
|
||||||
|
const deviceText = `${identity.manufacturer} ${identity.model} ${identity.brand}`;
|
||||||
|
|
||||||
|
if (canResolveBroadcast(config.action)) {
|
||||||
|
score += 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule) {
|
||||||
|
if ((rule.packages || []).some((pkg) => isPackageInstalled(pkg))) {
|
||||||
|
score += 60;
|
||||||
|
}
|
||||||
|
if ((rule.keywords || []).some((keyword) => deviceText.includes(String(keyword).toLowerCase()))) {
|
||||||
|
score += 40;
|
||||||
|
}
|
||||||
|
if (isModelMatch(identity, rule.models || [])) {
|
||||||
|
score += 80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
score += getModelPreferredBoost(config, identity);
|
||||||
|
|
||||||
|
// 明确是 N5S 时,压低东集通用广播抢分
|
||||||
|
if (isNewlandN5sDevice(identity) && (
|
||||||
|
config.brand === 'seuic'
|
||||||
|
|| String(config.action || '').includes('scannerservice.broadcast')
|
||||||
|
)) {
|
||||||
|
score = Math.min(score, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在候选配置中选出最匹配当前设备的一项;非 PDA 且无命中则回落手机扫码
|
||||||
|
*/
|
||||||
|
export function matchBestScanConfig(candidateConfigs = []) {
|
||||||
|
const configs = (candidateConfigs || [])
|
||||||
|
.map((item) => normalizeConfig(item, BUILTIN_SCANNER_CONFIGS))
|
||||||
|
.filter(Boolean);
|
||||||
|
const pdaConfigs = configs.filter((item) => !isPhoneScanConfig(item));
|
||||||
|
const identity = getDeviceIdentity();
|
||||||
|
|
||||||
|
let best = null;
|
||||||
|
let bestScore = 0;
|
||||||
|
pdaConfigs.forEach((config) => {
|
||||||
|
const score = scoreScannerConfig(config, identity);
|
||||||
|
if (score > bestScore) {
|
||||||
|
bestScore = score;
|
||||||
|
best = config;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (best && bestScore > 0) {
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPdaDevice()) {
|
||||||
|
return { ...PHONE_SCAN_CONFIG };
|
||||||
|
}
|
||||||
|
|
||||||
|
return pdaConfigs[0] || { ...PHONE_SCAN_CONFIG };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仅本地没有有效配置时,自动匹配并写入扫描设置。
|
||||||
|
* 若本地误把 N5S 识别成东集,则强制重配。
|
||||||
|
* @returns {{ saved: boolean, config: object|null, skipped: boolean, reason?: string }}
|
||||||
|
*/
|
||||||
|
export function autoConfigureScanSettings({ remoteConfigs = [] } = {}) {
|
||||||
|
const existing = getScanConfig(BUILTIN_SCANNER_CONFIGS);
|
||||||
|
const identity = getDeviceIdentity();
|
||||||
|
const forceRematch = !!(existing && isWrongSeuicOnNewlandDevice(existing, identity));
|
||||||
|
|
||||||
|
if (existing && !forceRematch) {
|
||||||
|
return {
|
||||||
|
saved: false,
|
||||||
|
skipped: true,
|
||||||
|
config: existing,
|
||||||
|
reason: 'local_exists',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const candidates = mergeScannerConfigs(remoteConfigs);
|
||||||
|
const matched = matchBestScanConfig(candidates);
|
||||||
|
if (!matched) {
|
||||||
|
return {
|
||||||
|
saved: false,
|
||||||
|
skipped: false,
|
||||||
|
config: existing || null,
|
||||||
|
reason: 'no_match',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const saved = saveScanConfig(matched);
|
||||||
|
return {
|
||||||
|
saved,
|
||||||
|
skipped: false,
|
||||||
|
config: matched,
|
||||||
|
reason: saved
|
||||||
|
? (forceRematch ? 'rematch_n5s_from_seuic' : 'saved')
|
||||||
|
: 'save_failed',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
+183
-28
@@ -1,10 +1,14 @@
|
|||||||
// common/scanMixin.js
|
// common/scanMixin.js
|
||||||
// 多厂商PDA扫码器兼容方案 - 策略模式 + 配置表驱动
|
// 多厂商PDA扫码器兼容方案 - 策略模式 + 配置表驱动
|
||||||
import {
|
import {
|
||||||
|
BUILTIN_SCANNER_CONFIGS,
|
||||||
getScanConfig,
|
getScanConfig,
|
||||||
hasShownNoConfigHint,
|
hasShownNoConfigHint,
|
||||||
|
isPdaDevice as detectPdaDevice,
|
||||||
|
isPhoneScanConfig,
|
||||||
markNoConfigHintShown,
|
markNoConfigHintShown,
|
||||||
normalizeConfig,
|
normalizeConfig,
|
||||||
|
PHONE_SCAN_CONFIG,
|
||||||
} from '@/common/scanConfig.js';
|
} from '@/common/scanConfig.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -14,33 +18,34 @@ export default {
|
|||||||
isPageActive: false,
|
isPageActive: false,
|
||||||
registeredBrands: [],
|
registeredBrands: [],
|
||||||
remoteScannerConfigs: [],
|
remoteScannerConfigs: [],
|
||||||
|
usePhoneScanFallback: false,
|
||||||
|
_scanCallback: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
getScannerConfigs() {
|
getScannerConfigs() {
|
||||||
return [
|
return BUILTIN_SCANNER_CONFIGS;
|
||||||
{
|
},
|
||||||
brand: 'newland',
|
|
||||||
name: '东集',
|
getPhoneScanConfig() {
|
||||||
action: 'com.android.server.scannerservice.broadcast',
|
return { ...PHONE_SCAN_CONFIG };
|
||||||
dataKey: 'scannerdata',
|
},
|
||||||
needSetup: true,
|
|
||||||
setupAction: 'com.android.scanner.service_settings',
|
isPdaDevice() {
|
||||||
setupParams: {
|
return detectPdaDevice();
|
||||||
action_barcode_broadcast: 'com.android.server.scannerservice.broadcast',
|
},
|
||||||
key_barcode_broadcast: 'scannerdata',
|
|
||||||
endchar: 'ENTER'
|
shouldUsePhoneScan() {
|
||||||
|
const builtinConfigs = this.getScannerConfigs();
|
||||||
|
const activeConfig = getScanConfig(builtinConfigs);
|
||||||
|
if (activeConfig && isPhoneScanConfig(activeConfig)) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
},
|
if (!activeConfig && !this.isPdaDevice()) {
|
||||||
{
|
return true;
|
||||||
brand: 'sunmi',
|
}
|
||||||
name: '商米',
|
return false;
|
||||||
action: 'com.sunmi.scanner.ACTION_DATA_CODE_RECEIVED',
|
|
||||||
dataKey: 'data',
|
|
||||||
needSetup: false
|
|
||||||
},
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getAllScannerConfigs() {
|
getAllScannerConfigs() {
|
||||||
@@ -52,23 +57,155 @@ export default {
|
|||||||
const configMap = new Map();
|
const configMap = new Map();
|
||||||
builtinConfigs.forEach((item) => configMap.set(item.brand, item));
|
builtinConfigs.forEach((item) => configMap.set(item.brand, item));
|
||||||
this.remoteScannerConfigs.forEach((item) => configMap.set(item.brand, item));
|
this.remoteScannerConfigs.forEach((item) => configMap.set(item.brand, item));
|
||||||
|
if (!configMap.has(PHONE_SCAN_CONFIG.brand)) {
|
||||||
|
configMap.set(PHONE_SCAN_CONFIG.brand, { ...PHONE_SCAN_CONFIG });
|
||||||
|
}
|
||||||
return Array.from(configMap.values());
|
return Array.from(configMap.values());
|
||||||
},
|
},
|
||||||
|
|
||||||
getActiveScanConfig() {
|
getActiveScanConfig() {
|
||||||
return getScanConfig();
|
return getScanConfig(this.getScannerConfigs());
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultScanConfig() {
|
getDefaultScanConfig() {
|
||||||
const configs = this.getAllScannerConfigs();
|
const configs = this.getAllScannerConfigs().filter((item) => !isPhoneScanConfig(item));
|
||||||
return configs.length ? configs[0] : null;
|
return configs.length ? configs[0] : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
registerScanBroadcast(scanCallback) {
|
/** 停止手机连续扫码(含 Ba-Scanner) */
|
||||||
|
stopPhoneScanContinuous() {
|
||||||
|
this._phoneScanContinuousActive = false;
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
|
try {
|
||||||
|
const scanner = uni.requireNativePlugin('Ba-Scanner');
|
||||||
|
if (scanner && typeof scanner.onClose === 'function') {
|
||||||
|
scanner.onClose();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// 未购买/未打包原生插件时忽略
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开手机扫码
|
||||||
|
* @param {{ continuous?: boolean, callback?: Function, fail?: Function, scanType?: string[], hintText?: string, scanTimeSpace?: number }} options
|
||||||
|
* continuous=true 时优先用 Ba-Scanner 连续扫;无插件则扫完自动再开相机
|
||||||
|
*/
|
||||||
|
openPhoneScan(options = {}) {
|
||||||
|
const callback = options.callback || this._scanCallback;
|
||||||
|
const continuous = !!options.continuous;
|
||||||
|
this._phoneScanContinuousActive = continuous;
|
||||||
|
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
if (continuous && this.openBaScannerContinuous(options, callback)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef APP-PLUS || MP-WEIXIN
|
||||||
|
uni.scanCode({
|
||||||
|
scanType: options.scanType || ['qrCode', 'barCode'],
|
||||||
|
success: (res) => {
|
||||||
|
const result = this.handleScanResult(res.result, callback);
|
||||||
|
if (!continuous || !this._phoneScanContinuousActive) return;
|
||||||
|
Promise.resolve(result)
|
||||||
|
.catch(() => null)
|
||||||
|
.then(() => {
|
||||||
|
if (!this._phoneScanContinuousActive || !this.isPageActive) return;
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!this._phoneScanContinuousActive || !this.isPageActive) return;
|
||||||
|
this.openPhoneScan(options);
|
||||||
|
}, Number(options.scanTimeSpace) > 0 ? Number(options.scanTimeSpace) : 400);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('手机扫码失败:', err);
|
||||||
|
this._phoneScanContinuousActive = false;
|
||||||
|
if (options.fail) {
|
||||||
|
options.fail(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 用户取消不打扰
|
||||||
|
const msg = (err && (err.errMsg || err.message)) || '';
|
||||||
|
if (/cancel|取消/i.test(msg)) return;
|
||||||
|
uni.showToast({
|
||||||
|
title: '扫码失败',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef H5
|
||||||
|
uni.showToast({
|
||||||
|
title: 'H5环境不支持扫码功能',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ba-Scanner 连续扫码(插件市场 id=9669)
|
||||||
|
* @returns {boolean} 是否已成功唤起原生连续扫
|
||||||
|
*/
|
||||||
|
openBaScannerContinuous(options = {}, callback) {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
try {
|
||||||
|
const scanner = uni.requireNativePlugin('Ba-Scanner');
|
||||||
|
if (!scanner || typeof scanner.onScan !== 'function') return false;
|
||||||
|
scanner.onScan(
|
||||||
|
{
|
||||||
|
isContinuous: true,
|
||||||
|
scanTimeSpace: Number(options.scanTimeSpace) > 0 ? Number(options.scanTimeSpace) : 1500,
|
||||||
|
isShowVibrate: options.isShowVibrate !== false,
|
||||||
|
isShowBeep: !!options.isShowBeep,
|
||||||
|
isShowToast: false,
|
||||||
|
isShowPhotoAlbum: options.isShowPhotoAlbum !== false,
|
||||||
|
hintText: options.hintText || '扫二维码/条形码,可连续扫',
|
||||||
|
barcodeFormats: options.barcodeFormats || ['QR Code', 'Code 128', 'Code 39', 'EAN-13', 'EAN-8'],
|
||||||
|
},
|
||||||
|
(ret) => {
|
||||||
|
if (!ret || !ret.result) return;
|
||||||
|
if (!this._phoneScanContinuousActive) return;
|
||||||
|
this.handleScanResult(ret.result, callback);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Ba-Scanner 不可用,回退 uni.scanCode', e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
triggerScan() {
|
||||||
|
if (this.usePhoneScanFallback) {
|
||||||
|
this.openPhoneScan();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
registerScanBroadcast(scanCallback) {
|
||||||
|
this._scanCallback = scanCallback;
|
||||||
|
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
this.usePhoneScanFallback = true;
|
||||||
|
return true;
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
if (this.shouldUsePhoneScan()) {
|
||||||
|
this.usePhoneScanFallback = true;
|
||||||
|
console.log('使用手机扫码模式');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.usePhoneScanFallback = false;
|
||||||
const activeConfig = this.getActiveScanConfig();
|
const activeConfig = this.getActiveScanConfig();
|
||||||
|
|
||||||
if (activeConfig) {
|
if (activeConfig && !isPhoneScanConfig(activeConfig)) {
|
||||||
return this.registerScanBroadcastByConfig(activeConfig, scanCallback);
|
return this.registerScanBroadcastByConfig(activeConfig, scanCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,21 +238,34 @@ export default {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isPhoneScanConfig(config)) {
|
||||||
|
this._scanCallback = scanCallback;
|
||||||
|
this.usePhoneScanFallback = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return this.registerScanBroadcastByConfig(config, scanCallback);
|
return this.registerScanBroadcastByConfig(config, scanCallback);
|
||||||
// #endif
|
// #endif
|
||||||
},
|
},
|
||||||
|
|
||||||
registerScanBroadcastByConfig(config, scanCallback) {
|
registerScanBroadcastByConfig(config, scanCallback) {
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
const normalizedConfig = normalizeConfig(config);
|
const normalizedConfig = normalizeConfig(config, this.getScannerConfigs());
|
||||||
if (!normalizedConfig) {
|
if (!normalizedConfig) {
|
||||||
console.error('扫码枪配置无效');
|
console.error('扫码枪配置无效');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isPhoneScanConfig(normalizedConfig)) {
|
||||||
|
this._scanCallback = scanCallback;
|
||||||
|
this.usePhoneScanFallback = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.registerSingleBroadcast(normalizedConfig, scanCallback);
|
this.registerSingleBroadcast(normalizedConfig, scanCallback);
|
||||||
this.registeredBrands.push(normalizedConfig.brand);
|
this.registeredBrands.push(normalizedConfig.brand);
|
||||||
|
this.usePhoneScanFallback = false;
|
||||||
console.log(`${normalizedConfig.name}扫码广播注册成功`);
|
console.log(`${normalizedConfig.name}扫码广播注册成功`);
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -158,7 +308,8 @@ export default {
|
|||||||
if (!self.isPageActive) return;
|
if (!self.isPageActive) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
plus.android.importClass('android.content.Intent');
|
// 广播回调里的 intent 需要按实例导入,否则 getStringExtra 不可用
|
||||||
|
plus.android.importClass(intent);
|
||||||
const scanResult = intent.getStringExtra(config.dataKey);
|
const scanResult = intent.getStringExtra(config.dataKey);
|
||||||
|
|
||||||
console.log(`${config.name}扫码结果:`, scanResult);
|
console.log(`${config.name}扫码结果:`, scanResult);
|
||||||
@@ -188,11 +339,12 @@ export default {
|
|||||||
console.log("扫码结果:", cleanCode);
|
console.log("扫码结果:", cleanCode);
|
||||||
|
|
||||||
if (scanCallback) {
|
if (scanCallback) {
|
||||||
scanCallback(cleanCode);
|
return scanCallback(cleanCode);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("处理扫码结果时出错:", error);
|
console.error("处理扫码结果时出错:", error);
|
||||||
}
|
}
|
||||||
|
return undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
unregisterScanBroadcast() {
|
unregisterScanBroadcast() {
|
||||||
@@ -244,10 +396,13 @@ export default {
|
|||||||
|
|
||||||
onHide() {
|
onHide() {
|
||||||
this.isPageActive = false;
|
this.isPageActive = false;
|
||||||
|
// 不在 onHide 里关 Ba-Scanner:打开原生扫码页也会触发 hide,误关会打断连续扫
|
||||||
|
// 无插件回退模式靠 isPageActive 控制是否自动再开相机
|
||||||
},
|
},
|
||||||
|
|
||||||
onUnload() {
|
onUnload() {
|
||||||
this.isPageActive = false;
|
this.isPageActive = false;
|
||||||
|
this.stopPhoneScanContinuous();
|
||||||
this.unregisterScanBroadcast();
|
this.unregisterScanBroadcast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,12 +46,12 @@ export const FABRIC_INFO_FIELDS = [
|
|||||||
|
|
||||||
/** 细码表格列(不含操作列) */
|
/** 细码表格列(不含操作列) */
|
||||||
export const FINE_CODE_TABLE_COLUMNS = [
|
export const FINE_CODE_TABLE_COLUMNS = [
|
||||||
{ label: '序号', key: 'seq', width: 70 },
|
{ label: '序号', key: 'seq', width: 90 },
|
||||||
{ label: '卷号', key: 'roll_no', width: 90 },
|
{ label: '卷号', key: 'roll_no', width: 110 },
|
||||||
{ label: '匹数', key: 'roll', width: 90 },
|
{ label: '匹数', key: 'roll', width: 100 },
|
||||||
{ label: '数量(重量)', key: 'weight', width: 120 },
|
{ label: '数量(重量)', key: 'weight', width: 160 },
|
||||||
{ label: '条码', key: 'bar_code', width: 260 },
|
{ label: '条码', key: 'bar_code', width: 280 },
|
||||||
{ label: '仓位', key: 'position', width: 110 },
|
{ label: '仓位', key: 'position', width: 140 },
|
||||||
];
|
];
|
||||||
|
|
||||||
/** 审核状态变更操作配置(apiKey 对应 gfmOtherDeliveryOrder 下的方法名) */
|
/** 审核状态变更操作配置(apiKey 对应 gfmOtherDeliveryOrder 下的方法名) */
|
||||||
@@ -61,6 +61,19 @@ export const STATUS_ACTION_CONFIG = {
|
|||||||
unapprove: { status: AUDIT_STATUS.PENDING, msg: '确认消审该单据?', apiKey: 'statusWait' },
|
unapprove: { status: AUDIT_STATUS.PENDING, msg: '确认消审该单据?', apiKey: 'statusWait' },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 审核 / 消审 / 作废成功后播放的语音文案 */
|
||||||
|
export const STATUS_ACTION_VOICE = {
|
||||||
|
approve: '审核成功',
|
||||||
|
unapprove: '消审成功',
|
||||||
|
void: '作废成功',
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 将接口状态统一为数字,避免字符串导致按钮判断失效 */
|
||||||
|
export function toAuditStatus(status) {
|
||||||
|
const n = Number(status);
|
||||||
|
return Number.isFinite(n) ? n : DRAFT_AUDIT_STATUS;
|
||||||
|
}
|
||||||
|
|
||||||
// 出仓类型:当前后端仅提供「坯布其他出货单」一种类型的接口
|
// 出仓类型:当前后端仅提供「坯布其他出货单」一种类型的接口
|
||||||
export const BILL_TYPES = [
|
export const BILL_TYPES = [
|
||||||
{ value: 'other', label: '坯布其他出货单' },
|
{ value: 'other', label: '坯布其他出货单' },
|
||||||
@@ -69,6 +82,9 @@ export const BILL_TYPES = [
|
|||||||
/** 列表分页拉取每页条数 */
|
/** 列表分页拉取每页条数 */
|
||||||
export const LIST_PAGE_SIZE = 100;
|
export const LIST_PAGE_SIZE = 100;
|
||||||
|
|
||||||
|
/** 往来单位类型:染厂(接收单位下拉筛选) */
|
||||||
|
export const BUSINESS_UNIT_TYPE_DYEING_FACTORY = 12;
|
||||||
|
|
||||||
export function getStatusOptions() {
|
export function getStatusOptions() {
|
||||||
return Object.keys(AUDIT_STATUS_MAP).map((value) => ({
|
return Object.keys(AUDIT_STATUS_MAP).map((value) => ({
|
||||||
value,
|
value,
|
||||||
@@ -116,12 +132,14 @@ export function getFineCodeDisplayWeight(fineCode) {
|
|||||||
*/
|
*/
|
||||||
export function normalizeOrder(order) {
|
export function normalizeOrder(order) {
|
||||||
if (!order) return null;
|
if (!order) return null;
|
||||||
const itemData = groupItemData((order.item_data || []).map((item) => normalizeItem(item)));
|
const normalizedItems = (order.item_data || []).map((item) => normalizeItem(item));
|
||||||
|
const itemData = groupItemData(normalizedItems);
|
||||||
|
const auditStatus = toAuditStatus(order.audit_status);
|
||||||
return {
|
return {
|
||||||
id: order.id,
|
id: order.id,
|
||||||
order_no: order.order_no || '',
|
order_no: order.order_no || '',
|
||||||
audit_status: order.audit_status,
|
audit_status: auditStatus,
|
||||||
audit_status_name: order.audit_status_name || AUDIT_STATUS_MAP[order.audit_status] || '',
|
audit_status_name: order.audit_status_name || AUDIT_STATUS_MAP[auditStatus] || '',
|
||||||
// 表头
|
// 表头
|
||||||
sale_system_id: order.sale_system_id || '',
|
sale_system_id: order.sale_system_id || '',
|
||||||
sale_system_name: order.sale_system_name || '',
|
sale_system_name: order.sale_system_name || '',
|
||||||
@@ -140,21 +158,53 @@ export function normalizeOrder(order) {
|
|||||||
total_roll: formatRoll(order.total_roll),
|
total_roll: formatRoll(order.total_roll),
|
||||||
total_weight: formatWeightKg(order.total_weight),
|
total_weight: formatWeightKg(order.total_weight),
|
||||||
item_data: itemData,
|
item_data: itemData,
|
||||||
|
summary_rows: buildSummaryRows(normalizedItems),
|
||||||
_raw: order,
|
_raw: order,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 扫码详情区表格列 */
|
/** 扫码区下方汇总表列(与出仓明细表一致,可横向滑动) */
|
||||||
export const SCAN_DETAIL_TABLE_COLUMNS = [
|
export const SUMMARY_TABLE_COLUMNS = [
|
||||||
{ label: '坯布编号', key: 'grey_fabric_code', width: 140 },
|
{ label: '坯布编号', key: 'grey_fabric_code', width: 200 },
|
||||||
{ label: '坯布名称', key: 'grey_fabric_name', width: 140 },
|
{ label: '坯布名称', key: 'grey_fabric_name', width: 240 },
|
||||||
{ label: '纱批', key: 'yarn_batch', width: 120 },
|
{ label: '纱批', key: 'yarn_batch', width: 180 },
|
||||||
{ label: '机号', key: 'machine_number', width: 100 },
|
{ label: '机台号', key: 'machine_number', width: 160 },
|
||||||
{ label: '条数', key: 'roll', width: 80 },
|
{ label: '条数', key: 'roll', width: 140 },
|
||||||
{ label: '重量', key: 'weight', width: 100 },
|
{ label: '重量', key: 'weight', width: 160 },
|
||||||
];
|
];
|
||||||
|
|
||||||
/** 扫码详情区汇总维度(勾选后参与表格分组;带 lock 的维度会随扫码请求传给后端) */
|
/** 汇总行归类:坯布编号 + 名称 + 纱批 + 机台号 */
|
||||||
|
export function getSummaryGroupKey(item) {
|
||||||
|
return [
|
||||||
|
item.grey_fabric_code || '',
|
||||||
|
item.grey_fabric_name || '',
|
||||||
|
item.yarn_batch || '',
|
||||||
|
item.machine_number || '',
|
||||||
|
].join('|');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 按坯布、纱批、机台号汇总条数和重量,供扫码区表格展示 */
|
||||||
|
export function buildSummaryRows(items) {
|
||||||
|
const grouped = new Map();
|
||||||
|
(items || []).forEach((item) => {
|
||||||
|
const groupKey = getSummaryGroupKey(item);
|
||||||
|
const existing = grouped.get(groupKey);
|
||||||
|
if (!existing) {
|
||||||
|
grouped.set(groupKey, {
|
||||||
|
...item,
|
||||||
|
group_key: groupKey,
|
||||||
|
fine_codes: [...(item.fine_codes || [])],
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
existing.fine_codes.push(...(item.fine_codes || []));
|
||||||
|
existing.roll = Number((Number(existing.roll || 0) + Number(item.roll || 0)).toFixed(2));
|
||||||
|
existing.weight = Number((Number(existing.weight || 0) + Number(item.weight || 0)).toFixed(2));
|
||||||
|
});
|
||||||
|
return Array.from(grouped.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 扫码详情区汇总维度(勾选后随扫码请求把对应 lock 字段传给后端) */
|
||||||
export const SCAN_GROUP_OPTIONS = [
|
export const SCAN_GROUP_OPTIONS = [
|
||||||
{ key: 'produce_order_no', label: '合同' },
|
{ key: 'produce_order_no', label: '合同' },
|
||||||
{ key: 'grey_fabric_code', label: '布编' },
|
{ key: 'grey_fabric_code', label: '布编' },
|
||||||
@@ -297,56 +347,6 @@ export function buildScanDetailFromContext(context, order) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function aggregateScanTableRows(rows, keys) {
|
|
||||||
const map = new Map();
|
|
||||||
rows.forEach((row) => {
|
|
||||||
const groupId = keys.map((k) => row[k] || '').join('|');
|
|
||||||
const existing = map.get(groupId);
|
|
||||||
if (!existing) {
|
|
||||||
map.set(groupId, { ...row, roll: 0, raw_weight: 0 });
|
|
||||||
}
|
|
||||||
const agg = map.get(groupId);
|
|
||||||
agg.roll = Number((agg.roll + Number(row.roll || 0)).toFixed(2));
|
|
||||||
agg.raw_weight = Number(agg.raw_weight || 0) + Number(row.raw_weight || 0);
|
|
||||||
});
|
|
||||||
return Array.from(map.values()).map((row) => ({
|
|
||||||
...row,
|
|
||||||
weight: formatWeightKg(row.raw_weight),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 构建扫码详情区汇总表格数据 */
|
|
||||||
export function buildScanDetailTableRows(itemData, groupKeys = []) {
|
|
||||||
const rows = [];
|
|
||||||
(itemData || []).forEach((item) => {
|
|
||||||
(item.fine_codes || []).forEach((fc) => {
|
|
||||||
rows.push({
|
|
||||||
customer_name: item.customer_name || '',
|
|
||||||
produce_order_no: item.produce_order_no || item.contract_no || '',
|
|
||||||
grey_fabric_code: item.grey_fabric_code || '',
|
|
||||||
grey_fabric_name: item.grey_fabric_name || '',
|
|
||||||
yarn_batch: item.yarn_batch || '',
|
|
||||||
machine_number: item.machine_number || '',
|
|
||||||
volume_number: fc.roll_no || fc.fabric_piece_code || '',
|
|
||||||
grey_fabric_level_name: item.grey_fabric_level_name || '',
|
|
||||||
roll: fc.roll || 0,
|
|
||||||
raw_weight: fc.raw_weight != null ? fc.raw_weight : 0,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
if (!rows.length) return [];
|
|
||||||
const keys = (groupKeys || []).filter(Boolean);
|
|
||||||
if (!keys.length) {
|
|
||||||
return aggregateScanTableRows(rows, ['grey_fabric_code', 'grey_fabric_name', 'yarn_batch', 'machine_number']);
|
|
||||||
}
|
|
||||||
return aggregateScanTableRows(rows, keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getScanDetailTableWidth(columns) {
|
|
||||||
const total = (columns || []).reduce((sum, col) => sum + (col.width || 120), 0);
|
|
||||||
return `${total}rpx`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function normalizeItem(item) {
|
export function normalizeItem(item) {
|
||||||
const machineStockRaw = item.machine_stock_roll ?? item.machine_stock ?? item.machine_inventory_roll;
|
const machineStockRaw = item.machine_stock_roll ?? item.machine_stock ?? item.machine_inventory_roll;
|
||||||
return {
|
return {
|
||||||
@@ -440,11 +440,13 @@ export function formatDisplayTime(value, format = 'YYYY-MM-DD') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function canScanAtStatus(status) {
|
export function canScanAtStatus(status) {
|
||||||
return [AUDIT_STATUS.PENDING, AUDIT_STATUS.REJECTED].includes(status);
|
const s = toAuditStatus(status);
|
||||||
|
return s === AUDIT_STATUS.PENDING || s === AUDIT_STATUS.REJECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isLockedOrderStatus(status) {
|
export function isLockedOrderStatus(status) {
|
||||||
return [AUDIT_STATUS.APPROVED, AUDIT_STATUS.VOIDED].includes(status);
|
const s = toAuditStatus(status);
|
||||||
|
return s === AUDIT_STATUS.APPROVED || s === AUDIT_STATUS.VOIDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 分页拉取全部列表(直至末页) */
|
/** 分页拉取全部列表(直至末页) */
|
||||||
@@ -459,9 +461,14 @@ export function fetchAllOrderList(listFn, params = {}, pageSize = LIST_PAGE_SIZE
|
|||||||
return loadPage(1, []);
|
return loadPage(1, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增/编辑页底部:审核、作废 */
|
/** 新增/编辑页底部:审核、作废 / 已审核时消审 */
|
||||||
export function getFormStatusActionButtons(headerSaved, orderId, status) {
|
export function getFormStatusActionButtons(headerSaved, orderId, status) {
|
||||||
if (!headerSaved || !orderId || !canScanAtStatus(status)) return [];
|
if (!headerSaved || !orderId) return [];
|
||||||
|
const s = toAuditStatus(status);
|
||||||
|
if (s === AUDIT_STATUS.APPROVED) {
|
||||||
|
return [{ label: '消审', action: 'unapprove' }];
|
||||||
|
}
|
||||||
|
if (!canScanAtStatus(s)) return [];
|
||||||
return [
|
return [
|
||||||
{ label: '审核', action: 'approve' },
|
{ label: '审核', action: 'approve' },
|
||||||
{ label: '作废', action: 'void' },
|
{ label: '作废', action: 'void' },
|
||||||
@@ -470,14 +477,15 @@ export function getFormStatusActionButtons(headerSaved, orderId, status) {
|
|||||||
|
|
||||||
/** 查看页底部:编辑、审核、作废 / 消审 */
|
/** 查看页底部:编辑、审核、作废 / 消审 */
|
||||||
export function getViewStatusActionButtons(status) {
|
export function getViewStatusActionButtons(status) {
|
||||||
if (status === AUDIT_STATUS.PENDING || status === AUDIT_STATUS.REJECTED) {
|
const s = toAuditStatus(status);
|
||||||
|
if (s === AUDIT_STATUS.PENDING || s === AUDIT_STATUS.REJECTED) {
|
||||||
return [
|
return [
|
||||||
{ label: '编辑', action: 'edit' },
|
{ label: '编辑', action: 'edit' },
|
||||||
{ label: '审核', action: 'approve' },
|
{ label: '审核', action: 'approve' },
|
||||||
{ label: '作废', action: 'void' },
|
{ label: '作废', action: 'void' },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
if (status === AUDIT_STATUS.APPROVED) {
|
if (s === AUDIT_STATUS.APPROVED) {
|
||||||
return [{ label: '消审', action: 'unapprove' }];
|
return [{ label: '消审', action: 'unapprove' }];
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
@@ -492,12 +500,14 @@ export function orderToFormFields(order) {
|
|||||||
delivery_time: order.delivery_time,
|
delivery_time: order.delivery_time,
|
||||||
remark: order.remark,
|
remark: order.remark,
|
||||||
item_data: order.item_data,
|
item_data: order.item_data,
|
||||||
|
summary_rows: order.summary_rows || [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFineCodeTableColumns(readonly) {
|
export function getFineCodeTableColumns(readonly) {
|
||||||
const cols = [...FINE_CODE_TABLE_COLUMNS];
|
const cols = [...FINE_CODE_TABLE_COLUMNS];
|
||||||
if (!readonly) cols.push({ label: '操作', key: 'action', width: 90 });
|
// 操作列放前面,避免 PDA 小屏横向滚动后才看到删除
|
||||||
|
if (!readonly) cols.splice(1, 0, { label: '操作', key: 'action', width: 160 });
|
||||||
return cols;
|
return cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,7 +533,7 @@ export function getFineCodeTableWidth(columns) {
|
|||||||
* @param {Vue} vm 页面实例,需有 $u.api 与 showError
|
* @param {Vue} vm 页面实例,需有 $u.api 与 showError
|
||||||
* @param {{ orderId: number, action: string, onSuccess?: Function }} options
|
* @param {{ orderId: number, action: string, onSuccess?: Function }} options
|
||||||
*/
|
*/
|
||||||
export function confirmOrderStatusAction(vm, { orderId, action, onSuccess }) {
|
export function confirmOrderStatusAction(vm, { orderId, action, onSuccess, onCancel }) {
|
||||||
const cfg = STATUS_ACTION_CONFIG[action];
|
const cfg = STATUS_ACTION_CONFIG[action];
|
||||||
if (!cfg || !orderId) return;
|
if (!cfg || !orderId) return;
|
||||||
const api = vm.$u.api.gfmOtherDeliveryOrder;
|
const api = vm.$u.api.gfmOtherDeliveryOrder;
|
||||||
@@ -533,7 +543,10 @@ export function confirmOrderStatusAction(vm, { orderId, action, onSuccess }) {
|
|||||||
title: '提示',
|
title: '提示',
|
||||||
content: cfg.msg,
|
content: cfg.msg,
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (!res.confirm) return;
|
if (!res.confirm) {
|
||||||
|
if (typeof onCancel === 'function') onCancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
uni.showLoading({ title: '处理中...' });
|
uni.showLoading({ title: '处理中...' });
|
||||||
requestFn(buildStatusParam(orderId, cfg.status))
|
requestFn(buildStatusParam(orderId, cfg.status))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ export function request(options) {
|
|||||||
url: apiurl + options.url,
|
url: apiurl + options.url,
|
||||||
method: options.method || 'GET',
|
method: options.method || 'GET',
|
||||||
data: options.data,
|
data: options.data,
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
sslVerify: false,
|
||||||
|
// #endif
|
||||||
header: {
|
header: {
|
||||||
'Platform': 2,
|
'Platform': 2,
|
||||||
'Authorization': token,
|
'Authorization': token,
|
||||||
@@ -363,6 +366,58 @@ function playErrorAudio() {
|
|||||||
errorAudio.play();
|
errorAudio.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 固定中文提示语音
|
||||||
|
const SPEAK_AUDIO = {
|
||||||
|
'扫码出仓成功': '/static/audio/scan_out_ok.mp3',
|
||||||
|
'删除成功': '/static/audio/delete_ok.mp3',
|
||||||
|
'提交成功': '/static/audio/submit_ok.mp3',
|
||||||
|
'审核成功': '/static/audio/audit_ok.mp3',
|
||||||
|
'作废成功': '/static/audio/void_ok.mp3',
|
||||||
|
'扫码成功': '/static/audio/scan_ok.wav',
|
||||||
|
'进仓成功': '/static/audio/in_ok.wav',
|
||||||
|
};
|
||||||
|
|
||||||
|
const speakAudioMap = {};
|
||||||
|
|
||||||
|
function stopOtherSpeak(exceptText) {
|
||||||
|
Object.keys(speakAudioMap).forEach((key) => {
|
||||||
|
if (key === exceptText || !speakAudioMap[key]) return;
|
||||||
|
try {
|
||||||
|
speakAudioMap[key].stop();
|
||||||
|
} catch (e) {}
|
||||||
|
});
|
||||||
|
if (successAudio) {
|
||||||
|
try {
|
||||||
|
successAudio.stop();
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function playSpeak(text) {
|
||||||
|
const src = SPEAK_AUDIO[text];
|
||||||
|
if (!src) return;
|
||||||
|
stopOtherSpeak(text);
|
||||||
|
const prev = speakAudioMap[text];
|
||||||
|
if (prev) {
|
||||||
|
try {
|
||||||
|
prev.stop();
|
||||||
|
prev.destroy();
|
||||||
|
} catch (e) {}
|
||||||
|
speakAudioMap[text] = undefined;
|
||||||
|
}
|
||||||
|
const audio = uni.createInnerAudioContext();
|
||||||
|
audio.autoplay = true;
|
||||||
|
audio.src = src;
|
||||||
|
audio.onError((res) => {
|
||||||
|
console.log('语音播放失败', text, res && res.errMsg);
|
||||||
|
try {
|
||||||
|
audio.destroy();
|
||||||
|
} catch (e) {}
|
||||||
|
if (speakAudioMap[text] === audio) speakAudioMap[text] = undefined;
|
||||||
|
});
|
||||||
|
speakAudioMap[text] = audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
get apiurl() {
|
get apiurl() {
|
||||||
@@ -375,4 +430,5 @@ export default {
|
|||||||
parGetData,
|
parGetData,
|
||||||
playSuccessAudio,
|
playSuccessAudio,
|
||||||
playErrorAudio,
|
playErrorAudio,
|
||||||
|
playSpeak,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,259 @@
|
|||||||
|
<template>
|
||||||
|
<view v-show="visible" class="plus-barcode-panel">
|
||||||
|
<view class="plus-barcode-panel__toolbar">
|
||||||
|
<text class="plus-barcode-panel__tip">{{ tipText }}</text>
|
||||||
|
<text class="plus-barcode-panel__close" @click.stop="close">收起</text>
|
||||||
|
</view>
|
||||||
|
<!-- #ifdef APP-PLUS -->
|
||||||
|
<view :id="holderId" class="plus-barcode-panel__holder" />
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef APP-PLUS -->
|
||||||
|
<view class="plus-barcode-panel__fallback">
|
||||||
|
<text>当前环境不支持半屏扫码,请使用输入框或系统扫码</text>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const DEFAULT_FILTERS = [0, 1, 2, 8, 10]; // QR EAN13 EAN8 CODE39 CODE128
|
||||||
|
let barcodeSeq = 0;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'PlusBarcodePanel',
|
||||||
|
props: {
|
||||||
|
visible: { type: Boolean, default: false },
|
||||||
|
hintText: { type: String, default: '将条码放入框内,可连续扫' },
|
||||||
|
scanTimeSpace: { type: Number, default: 1200 },
|
||||||
|
filters: { type: Array, default: () => DEFAULT_FILTERS.slice() },
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
barcodeSeq += 1;
|
||||||
|
return {
|
||||||
|
holderId: `plusBarcodeHolder_${barcodeSeq}`,
|
||||||
|
barcodeViewId: `plusBarcodeView_${barcodeSeq}`,
|
||||||
|
_barcode: null,
|
||||||
|
_restartTimer: null,
|
||||||
|
_active: false,
|
||||||
|
_creating: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
tipText() {
|
||||||
|
return this.hintText || '将条码放入框内,可连续扫';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
visible(val) {
|
||||||
|
if (val) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.openNative();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.destroyNative();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.destroyNative();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
open() {
|
||||||
|
if (this.visible) {
|
||||||
|
this.$nextTick(() => this.openNative());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$emit('update:visible', true);
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.destroyNative();
|
||||||
|
if (this.visible) {
|
||||||
|
this.$emit('update:visible', false);
|
||||||
|
}
|
||||||
|
this.$emit('close');
|
||||||
|
},
|
||||||
|
getCurrentWebview() {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
try {
|
||||||
|
const pages = getCurrentPages();
|
||||||
|
const page = pages[pages.length - 1];
|
||||||
|
if (page && typeof page.$getAppWebview === 'function') {
|
||||||
|
return page.$getAppWebview();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('PlusBarcodePanel getCurrentWebview failed', e);
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
openNative() {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
if (!this.visible || this._creating) return;
|
||||||
|
if (this._barcode) {
|
||||||
|
this.resumeScan();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._creating = true;
|
||||||
|
this._active = true;
|
||||||
|
// 等占位区域完成布局后再量位置,避免 Android 上 rect 为 0
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!this.visible || !this._active) {
|
||||||
|
this._creating = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uni.createSelectorQuery()
|
||||||
|
.in(this)
|
||||||
|
.select('.plus-barcode-panel__holder')
|
||||||
|
.boundingClientRect((rect) => {
|
||||||
|
this._creating = false;
|
||||||
|
if (!this.visible || !this._active) return;
|
||||||
|
if (!rect || !rect.width || !rect.height) {
|
||||||
|
uni.showToast({ title: '扫码区域未就绪', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.createBarcode(rect);
|
||||||
|
})
|
||||||
|
.exec();
|
||||||
|
}, 80);
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
createBarcode(rect) {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
const webview = this.getCurrentWebview();
|
||||||
|
if (!webview || typeof plus === 'undefined' || !plus.barcode) {
|
||||||
|
uni.showToast({ title: '当前环境不支持扫码', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.destroyNative(false);
|
||||||
|
try {
|
||||||
|
const barcode = plus.barcode.create(
|
||||||
|
this.barcodeViewId,
|
||||||
|
this.filters && this.filters.length ? this.filters : DEFAULT_FILTERS,
|
||||||
|
{
|
||||||
|
top: `${Math.round(rect.top)}px`,
|
||||||
|
left: `${Math.round(rect.left)}px`,
|
||||||
|
width: `${Math.round(rect.width)}px`,
|
||||||
|
height: `${Math.round(rect.height)}px`,
|
||||||
|
position: 'absolute',
|
||||||
|
background: '#000000',
|
||||||
|
frameColor: '#2979ff',
|
||||||
|
scanbarColor: '#2979ff',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
barcode.onmarked = (type, code) => {
|
||||||
|
this.onMarked(type, code);
|
||||||
|
};
|
||||||
|
barcode.onerror = (err) => {
|
||||||
|
console.error('PlusBarcodePanel onerror', err);
|
||||||
|
};
|
||||||
|
webview.append(barcode);
|
||||||
|
this._barcode = barcode;
|
||||||
|
this._active = true;
|
||||||
|
barcode.start({
|
||||||
|
vibrate: true,
|
||||||
|
sound: 'default',
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error('PlusBarcodePanel create failed', e);
|
||||||
|
uni.showToast({ title: '打开扫码失败', icon: 'none' });
|
||||||
|
this._barcode = null;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
onMarked(type, code) {
|
||||||
|
const result = String(code || '').trim();
|
||||||
|
if (!result || !this._active) return;
|
||||||
|
try {
|
||||||
|
if (this._barcode) this._barcode.cancel();
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
this.$emit('success', result, type);
|
||||||
|
clearTimeout(this._restartTimer);
|
||||||
|
const gap = Number(this.scanTimeSpace) > 0 ? Number(this.scanTimeSpace) : 1200;
|
||||||
|
this._restartTimer = setTimeout(() => {
|
||||||
|
this.resumeScan();
|
||||||
|
}, gap);
|
||||||
|
},
|
||||||
|
resumeScan() {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
if (!this.visible || !this._active || !this._barcode) return;
|
||||||
|
try {
|
||||||
|
this._barcode.start({
|
||||||
|
vibrate: true,
|
||||||
|
sound: 'default',
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('PlusBarcodePanel resume failed', e);
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
destroyNative(clearActive = true) {
|
||||||
|
clearTimeout(this._restartTimer);
|
||||||
|
this._restartTimer = null;
|
||||||
|
if (clearActive) this._active = false;
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
const barcode = this._barcode;
|
||||||
|
this._barcode = null;
|
||||||
|
if (!barcode) return;
|
||||||
|
try {
|
||||||
|
barcode.cancel();
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
barcode.close();
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import '@/common/pda-typography.scss';
|
||||||
|
|
||||||
|
.plus-barcode-panel {
|
||||||
|
background: #000;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
}
|
||||||
|
.plus-barcode-panel__toolbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
min-height: 72rpx;
|
||||||
|
padding: 12rpx 26rpx;
|
||||||
|
background: #1f1f1f;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.plus-barcode-panel__tip {
|
||||||
|
flex: 1;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: $pda-font-action;
|
||||||
|
padding-right: 16rpx;
|
||||||
|
}
|
||||||
|
.plus-barcode-panel__close {
|
||||||
|
color: #2979ff;
|
||||||
|
font-size: $pda-font-action;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.plus-barcode-panel__holder {
|
||||||
|
width: 100%;
|
||||||
|
height: 420rpx;
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
.plus-barcode-panel__fallback {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 420rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: #333;
|
||||||
|
color: #fff;
|
||||||
|
font-size: $pda-font-body;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<view class="fabric-out-sectionTitle">{{ title }}</view>
|
<view v-if="title" class="fabric-out-sectionTitle">{{ title }}</view>
|
||||||
<slot name="before-list" />
|
<slot name="before-list" />
|
||||||
<view class="fabric-out-detailList">
|
<view class="fabric-out-detailList">
|
||||||
<view
|
<view
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
list: { type: Array, default: () => [] },
|
list: { type: Array, default: () => [] },
|
||||||
title: { type: String, default: '出仓细码' },
|
title: { type: String, default: '' },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -10,6 +10,20 @@
|
|||||||
@input="$emit('input', $event.detail.value)"
|
@input="$emit('input', $event.detail.value)"
|
||||||
@confirm="$emit('scan')"
|
@confirm="$emit('scan')"
|
||||||
/>
|
/>
|
||||||
|
<view
|
||||||
|
v-if="scanning"
|
||||||
|
class="fabric-out-scanClose"
|
||||||
|
@click.stop="$emit('phone-scan')"
|
||||||
|
>
|
||||||
|
关闭扫码
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
v-else
|
||||||
|
class="fabric-out-toolbarIcon"
|
||||||
|
@click.stop="$emit('phone-scan')"
|
||||||
|
>
|
||||||
|
<u-icon name="scan" size="44" color="#595959" />
|
||||||
|
</view>
|
||||||
<checkbox-group @change="$emit('delete-mode-change', $event)">
|
<checkbox-group @change="$emit('delete-mode-change', $event)">
|
||||||
<label class="fabric-out-delCheck">
|
<label class="fabric-out-delCheck">
|
||||||
<checkbox :checked="deleteMode" />删除
|
<checkbox :checked="deleteMode" />删除
|
||||||
@@ -29,10 +43,40 @@ export default {
|
|||||||
deleteMode: { type: Boolean, default: false },
|
deleteMode: { type: Boolean, default: false },
|
||||||
message: { type: String, default: '' },
|
message: { type: String, default: '' },
|
||||||
disabledTip: { type: String, default: '当前状态不可扫码' },
|
disabledTip: { type: String, default: '当前状态不可扫码' },
|
||||||
|
scanning: { type: Boolean, default: false },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '@/pages/storefabric/storeFabricBusinessOutPage.scss';
|
@import '@/pages/storefabric/storeFabricBusinessOutPage.scss';
|
||||||
|
@import '@/common/pda-typography.scss';
|
||||||
|
|
||||||
|
.fabric-out-toolbarIcon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
margin-left: 8rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
border: 1rpx solid #d9d9d9;
|
||||||
|
background: #f7f7f7;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.fabric-out-scanClose {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 8rpx;
|
||||||
|
padding: 0 16rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
border: 1rpx solid #2979ff;
|
||||||
|
background: #eaf2ff;
|
||||||
|
color: #2979ff;
|
||||||
|
font-size: $pda-font-action;
|
||||||
|
flex-shrink: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -12,12 +12,14 @@
|
|||||||
<text class="fabric-out-scanDetailLabel">客户:</text>
|
<text class="fabric-out-scanDetailLabel">客户:</text>
|
||||||
<text class="fabric-out-scanDetailValue">{{ detail.customer_name || '' }}</text>
|
<text class="fabric-out-scanDetailValue">{{ detail.customer_name || '' }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="fabric-out-scanDetailRow fabric-out-scanDetailRow--2col">
|
<view class="fabric-out-scanDetailRow">
|
||||||
<view class="fabric-out-scanDetailCheck" @click="toggleGroup('produce_order_no')">
|
<view class="fabric-out-scanDetailCheck" @click="toggleGroup('produce_order_no')">
|
||||||
<checkbox :checked="isGroupChecked('produce_order_no')" />
|
<checkbox :checked="isGroupChecked('produce_order_no')" />
|
||||||
<text class="fabric-out-scanDetailLabel">生产通知单:</text>
|
<text class="fabric-out-scanDetailLabel">生产通知单:</text>
|
||||||
<text class="fabric-out-scanDetailValue">{{ detail.produce_order_no || '' }}</text>
|
<text class="fabric-out-scanDetailValue">{{ detail.produce_order_no || '' }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fabric-out-scanDetailRow">
|
||||||
<view class="fabric-out-scanDetailCheck" @click="toggleGroup('grey_fabric_code')">
|
<view class="fabric-out-scanDetailCheck" @click="toggleGroup('grey_fabric_code')">
|
||||||
<checkbox :checked="isGroupChecked('grey_fabric_code')" />
|
<checkbox :checked="isGroupChecked('grey_fabric_code')" />
|
||||||
<text class="fabric-out-scanDetailLabel">布编:</text>
|
<text class="fabric-out-scanDetailLabel">布编:</text>
|
||||||
@@ -58,67 +60,16 @@
|
|||||||
<text class="fabric-out-scanDetailValue">{{ formatWeight(detail.weight) }}Kg</text>
|
<text class="fabric-out-scanDetailValue">{{ formatWeight(detail.weight) }}Kg</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<scroll-view scroll-x class="fabric-out-scanDetailTableScroll">
|
|
||||||
<view class="fabric-out-scanDetailTable" :style="{ width: tableWidth }">
|
|
||||||
<view class="fabric-out-scanDetailTableRow fabric-out-scanDetailTableHead">
|
|
||||||
<view
|
|
||||||
v-for="col in columns"
|
|
||||||
:key="col.key"
|
|
||||||
class="fabric-out-scanDetailTableCell"
|
|
||||||
:style="cellStyle(col)"
|
|
||||||
>{{ col.label }}</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="!tableRows.length" class="fabric-out-scanDetailEmpty">暂无数据~~</view>
|
|
||||||
<view
|
|
||||||
v-for="(row, rowIndex) in tableRows"
|
|
||||||
:key="rowIndex"
|
|
||||||
class="fabric-out-scanDetailTableRow"
|
|
||||||
>
|
|
||||||
<view
|
|
||||||
v-for="col in columns"
|
|
||||||
:key="col.key"
|
|
||||||
class="fabric-out-scanDetailTableCell"
|
|
||||||
:style="cellStyle(col)"
|
|
||||||
>{{ formatCell(row, col.key) }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
|
||||||
SCAN_DETAIL_TABLE_COLUMNS,
|
|
||||||
getScanDetailTableWidth,
|
|
||||||
buildScanDetailTableRows,
|
|
||||||
} from '@/common/storeFabricBusinessOut';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
detail: { type: Object, default: () => ({}) },
|
detail: { type: Object, default: () => ({}) },
|
||||||
itemData: { type: Array, default: () => [] },
|
|
||||||
groupKeys: { type: Array, default: () => [] },
|
groupKeys: { type: Array, default: () => [] },
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
columns() {
|
|
||||||
return SCAN_DETAIL_TABLE_COLUMNS;
|
|
||||||
},
|
|
||||||
tableWidth() {
|
|
||||||
return getScanDetailTableWidth(this.columns);
|
|
||||||
},
|
|
||||||
tableRows() {
|
|
||||||
return buildScanDetailTableRows(this.itemData, this.groupKeys);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
cellStyle(col) {
|
|
||||||
return {
|
|
||||||
width: `${col.width}rpx`,
|
|
||||||
minWidth: `${col.width}rpx`,
|
|
||||||
maxWidth: `${col.width}rpx`,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
isGroupChecked(key) {
|
isGroupChecked(key) {
|
||||||
return (this.groupKeys || []).includes(key);
|
return (this.groupKeys || []).includes(key);
|
||||||
},
|
},
|
||||||
@@ -140,11 +91,6 @@ export default {
|
|||||||
const n = Number(value || 0);
|
const n = Number(value || 0);
|
||||||
return Number(n.toFixed(2));
|
return Number(n.toFixed(2));
|
||||||
},
|
},
|
||||||
formatCell(row, key) {
|
|
||||||
if (key === 'roll') return this.formatRoll(row.roll);
|
|
||||||
if (key === 'weight') return this.formatWeight(row.weight);
|
|
||||||
return row[key] || '';
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
<template>
|
||||||
|
<view class="fabric-out-summary">
|
||||||
|
<scroll-view scroll-x class="fabric-out-summaryScroll">
|
||||||
|
<view class="fabric-out-summaryInner" :style="{ width: tableWidth }">
|
||||||
|
<t-table border="1" border-color="#e1e1e1">
|
||||||
|
<t-tr font-size="18" color="#3e3e3e" align="center">
|
||||||
|
<t-th
|
||||||
|
v-for="col in headers"
|
||||||
|
:key="col.key"
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
<view class="fabric-out-th" :style="cellStyle(col)">{{ col.label }}</view>
|
||||||
|
</t-th>
|
||||||
|
</t-tr>
|
||||||
|
<t-tr
|
||||||
|
v-for="(row, rowIndex) in contents"
|
||||||
|
:key="row.group_key || rowIndex"
|
||||||
|
font-size="18"
|
||||||
|
color="#333"
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
<t-td
|
||||||
|
v-for="col in headers"
|
||||||
|
:key="col.key"
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="fabric-out-td"
|
||||||
|
:style="cellStyle(col)"
|
||||||
|
@click="onCellClick(col.key, row)"
|
||||||
|
>{{ formatCell(row, col.key) }}</view>
|
||||||
|
</t-td>
|
||||||
|
</t-tr>
|
||||||
|
</t-table>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<view v-if="!contents.length" class="fabric-out-summaryEmpty">暂无数据~~</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import tTable from '@/components/t-table/t-table.vue';
|
||||||
|
import tTr from '@/components/t-table/t-tr.vue';
|
||||||
|
import tTh from '@/components/t-table/t-th.vue';
|
||||||
|
import tTd from '@/components/t-table/t-td.vue';
|
||||||
|
import { SUMMARY_TABLE_COLUMNS } from '@/common/storeFabricBusinessOut';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { tTable, tTr, tTh, tTd },
|
||||||
|
props: {
|
||||||
|
rows: { type: Array, default: () => [] },
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
headers() {
|
||||||
|
return SUMMARY_TABLE_COLUMNS;
|
||||||
|
},
|
||||||
|
tableWidth() {
|
||||||
|
const total = this.headers.reduce((sum, col) => sum + (col.width || 160), 0);
|
||||||
|
return `${total}rpx`;
|
||||||
|
},
|
||||||
|
contents() {
|
||||||
|
return (this.rows || []).map((row) => ({
|
||||||
|
...row,
|
||||||
|
grey_fabric_code: row.grey_fabric_code || '',
|
||||||
|
grey_fabric_name: row.grey_fabric_name || '',
|
||||||
|
yarn_batch: row.yarn_batch || '',
|
||||||
|
machine_number: row.machine_number || '',
|
||||||
|
roll: row.roll != null && row.roll !== '' ? String(row.roll) : '0',
|
||||||
|
weight: row.weight != null && row.weight !== '' ? String(row.weight) : '0',
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
cellStyle(col) {
|
||||||
|
const width = `${col.width || 160}rpx`;
|
||||||
|
return {
|
||||||
|
width,
|
||||||
|
minWidth: width,
|
||||||
|
maxWidth: width,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
formatCell(row, key) {
|
||||||
|
const val = row[key];
|
||||||
|
if (val === 0) return '0';
|
||||||
|
return val != null && val !== '' ? val : '-';
|
||||||
|
},
|
||||||
|
onCellClick(key, row) {
|
||||||
|
this.$emit('cell-click', { key, lineData: row });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import '@/common/pda-typography.scss';
|
||||||
|
|
||||||
|
.fabric-out-summary {
|
||||||
|
background: #fff;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
}
|
||||||
|
.fabric-out-summaryScroll {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.fabric-out-summaryInner {
|
||||||
|
min-width: 100%;
|
||||||
|
}
|
||||||
|
.fabric-out-summary ::v-deep .t-table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.fabric-out-summary ::v-deep .t-th,
|
||||||
|
.fabric-out-summary ::v-deep .t-td {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: auto;
|
||||||
|
padding: 0;
|
||||||
|
min-height: $pda-row-min-height;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.fabric-out-th,
|
||||||
|
.fabric-out-td {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: $pda-row-min-height;
|
||||||
|
padding: 16rpx 12rpx;
|
||||||
|
font-size: $pda-font-body;
|
||||||
|
word-break: break-all;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.fabric-out-th {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.fabric-out-summaryEmpty {
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
font-size: $pda-font-body;
|
||||||
|
line-height: $pda-row-min-height;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -21,11 +21,17 @@
|
|||||||
:class="{ actionCell: col.key === 'action' && !readonly }"
|
:class="{ actionCell: col.key === 'action' && !readonly }"
|
||||||
:style="cellStyle(col)"
|
:style="cellStyle(col)"
|
||||||
@click="onCellTap(col.key, rowIndex)"
|
@click="onCellTap(col.key, rowIndex)"
|
||||||
>{{ row[col.key] }}</view>
|
>
|
||||||
|
<text
|
||||||
|
v-if="col.key === 'action' && !readonly"
|
||||||
|
class="deleteBtn"
|
||||||
|
>{{ row[col.key] }}</text>
|
||||||
|
<template v-else>{{ row[col.key] }}</template>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<view v-if="!readonly && list.length" class="tableTip">点击「操作」列删除,将调用扫码删除接口</view>
|
<view v-if="!readonly && list.length" class="tableTip">点击「删除」将调用扫码删除接口</view>
|
||||||
</view>
|
</view>
|
||||||
</u-popup>
|
</u-popup>
|
||||||
</template>
|
</template>
|
||||||
@@ -81,9 +87,11 @@ export default {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
|
@import '@/common/pda-typography.scss';
|
||||||
|
|
||||||
.popupWrap {
|
.popupWrap {
|
||||||
padding: 24rpx 16rpx 30rpx;
|
padding: 28rpx 16rpx 32rpx;
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -91,18 +99,18 @@ export default {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.popupTitle {
|
.popupTitle {
|
||||||
font-size: 32rpx;
|
font-size: $pda-font-popup-title;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 20rpx;
|
margin-bottom: 24rpx;
|
||||||
color: #333;
|
color: #333;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
.emptyTip {
|
.emptyTip {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #999;
|
color: #999;
|
||||||
padding: 40rpx 0;
|
padding: 48rpx 0;
|
||||||
font-size: 28rpx;
|
font-size: $pda-font-popup-sub;
|
||||||
}
|
}
|
||||||
.tableScroll {
|
.tableScroll {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -118,6 +126,7 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
|
align-items: stretch;
|
||||||
border-bottom: 1rpx solid #e1e1e1;
|
border-bottom: 1rpx solid #e1e1e1;
|
||||||
}
|
}
|
||||||
.tableRow:last-child {
|
.tableRow:last-child {
|
||||||
@@ -131,8 +140,12 @@ export default {
|
|||||||
}
|
}
|
||||||
.tableCell {
|
.tableCell {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
padding: 12rpx 8rpx;
|
display: flex;
|
||||||
font-size: 22rpx;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: $pda-row-min-height;
|
||||||
|
padding: 16rpx 10rpx;
|
||||||
|
font-size: $pda-font-popup-item;
|
||||||
color: #333;
|
color: #333;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-right: 1rpx solid #e1e1e1;
|
border-right: 1rpx solid #e1e1e1;
|
||||||
@@ -146,13 +159,28 @@ export default {
|
|||||||
.headCell {
|
.headCell {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #3e3e3e;
|
color: #3e3e3e;
|
||||||
|
min-height: 80rpx;
|
||||||
}
|
}
|
||||||
.actionCell {
|
.actionCell {
|
||||||
|
padding: 12rpx 8rpx;
|
||||||
|
}
|
||||||
|
.deleteBtn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 120rpx;
|
||||||
|
min-height: 72rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
background: #fff1f0;
|
||||||
|
border: 1rpx solid #ffa39e;
|
||||||
color: #f5222d;
|
color: #f5222d;
|
||||||
|
font-size: $pda-font-action;
|
||||||
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
.tableTip {
|
.tableTip {
|
||||||
margin-top: 16rpx;
|
margin-top: 20rpx;
|
||||||
font-size: 22rpx;
|
font-size: $pda-font-popup-sub;
|
||||||
color: #999;
|
color: #999;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|||||||
@@ -32,11 +32,11 @@ export default {
|
|||||||
border-bottom: 1rpx solid #f5f5f5;
|
border-bottom: 1rpx solid #f5f5f5;
|
||||||
}
|
}
|
||||||
.statusLabel {
|
.statusLabel {
|
||||||
font-size: 28rpx;
|
font-size: 40rpx;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
.statusTag {
|
.statusTag {
|
||||||
font-size: 24rpx;
|
font-size: 34rpx;
|
||||||
padding: 4rpx 12rpx;
|
padding: 4rpx 12rpx;
|
||||||
border-radius: 6rpx;
|
border-radius: 6rpx;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
|||||||
@@ -0,0 +1,199 @@
|
|||||||
|
<template>
|
||||||
|
<u-popup v-model="visible" mode="bottom" :safe-area-inset-bottom="true" border-radius="16">
|
||||||
|
<view class="search-select" :style="{ maxHeight: panelMaxHeight + 'px' }">
|
||||||
|
<view class="search-select__bar">
|
||||||
|
<text class="search-select__title">{{ title }}</text>
|
||||||
|
<text class="search-select__cancel" @click="visible = false">取消</text>
|
||||||
|
</view>
|
||||||
|
<view class="search-select__search">
|
||||||
|
<u-search v-model="keyword" :placeholder="placeholder" :show-action="false" />
|
||||||
|
</view>
|
||||||
|
<scroll-view
|
||||||
|
scroll-y
|
||||||
|
class="search-select__list"
|
||||||
|
:style="{ height: listHeight + 'px' }"
|
||||||
|
:enable-back-to-top="false"
|
||||||
|
>
|
||||||
|
<view v-if="!filteredList.length" class="search-select__empty">暂无匹配数据</view>
|
||||||
|
<view
|
||||||
|
v-for="item in filteredList"
|
||||||
|
:key="String(item.value)"
|
||||||
|
class="search-select__item"
|
||||||
|
:class="{ 'is-selected': multiple && isPicked(item) }"
|
||||||
|
@click="onItemClick(item)"
|
||||||
|
>
|
||||||
|
<text class="search-select__item-label">{{ item.label }}</text>
|
||||||
|
<text v-if="multiple && isPicked(item)" class="search-select__check">已选</text>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<view v-if="multiple" class="search-select__footer">
|
||||||
|
<view class="search-select__ok" @click="confirmMultiple">确定</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</u-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
show: { type: Boolean, default: false },
|
||||||
|
title: { type: String, default: '请选择' },
|
||||||
|
placeholder: { type: String, default: '请输入名称搜索' },
|
||||||
|
list: { type: Array, default: () => [] },
|
||||||
|
multiple: { type: Boolean, default: false },
|
||||||
|
selected: { type: Array, default: () => [] },
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
keyword: '',
|
||||||
|
panelMaxHeight: 520,
|
||||||
|
listHeight: 360,
|
||||||
|
picked: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
visible: {
|
||||||
|
get() { return this.show; },
|
||||||
|
set(val) { this.$emit('update:show', val); },
|
||||||
|
},
|
||||||
|
filteredList() {
|
||||||
|
const keyword = (this.keyword || '').trim().toLowerCase();
|
||||||
|
if (!keyword) return this.list;
|
||||||
|
return this.list.filter((item) => String(item.label || '').toLowerCase().includes(keyword));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
show(val) {
|
||||||
|
if (val) {
|
||||||
|
this.keyword = '';
|
||||||
|
this.picked = (this.selected || []).map((item) => String(item));
|
||||||
|
this.calcHeight();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.calcHeight();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
calcHeight() {
|
||||||
|
try {
|
||||||
|
const sys = uni.getSystemInfoSync();
|
||||||
|
const winH = sys.windowHeight || 600;
|
||||||
|
// 弹层约占屏高 65%,列表为弹层去掉标题+搜索后的剩余高度
|
||||||
|
this.panelMaxHeight = Math.floor(winH * 0.65);
|
||||||
|
const chrome = this.multiple ? 230 : 140;
|
||||||
|
this.listHeight = Math.max(220, this.panelMaxHeight - chrome);
|
||||||
|
} catch (e) {
|
||||||
|
this.panelMaxHeight = 520;
|
||||||
|
this.listHeight = this.multiple ? 280 : 360;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isPicked(item) {
|
||||||
|
return this.picked.includes(String(item.value));
|
||||||
|
},
|
||||||
|
onItemClick(item) {
|
||||||
|
if (!this.multiple) {
|
||||||
|
this.confirm(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const key = String(item.value);
|
||||||
|
if (this.picked.includes(key)) {
|
||||||
|
this.picked = this.picked.filter((value) => value !== key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.picked = this.picked.concat(key);
|
||||||
|
},
|
||||||
|
confirm(item) {
|
||||||
|
this.visible = false;
|
||||||
|
this.$emit('confirm', item);
|
||||||
|
},
|
||||||
|
confirmMultiple() {
|
||||||
|
const selected = (this.list || []).filter((item) => this.isPicked(item));
|
||||||
|
this.visible = false;
|
||||||
|
this.$emit('confirm', selected);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import '@/common/pda-typography.scss';
|
||||||
|
|
||||||
|
.search-select {
|
||||||
|
background: #fff;
|
||||||
|
padding-bottom: 20rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.search-select__bar {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 24rpx 30rpx 12rpx;
|
||||||
|
}
|
||||||
|
.search-select__title {
|
||||||
|
font-size: $pda-font-popup-title;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #202328;
|
||||||
|
}
|
||||||
|
.search-select__cancel {
|
||||||
|
font-size: $pda-font-popup-sub;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
.search-select__search {
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: 0 24rpx 12rpx;
|
||||||
|
}
|
||||||
|
.search-select__list {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.search-select__empty {
|
||||||
|
padding: 80rpx 0;
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
font-size: $pda-font-popup-sub;
|
||||||
|
}
|
||||||
|
.search-select__item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
min-height: $pda-row-min-height;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: $pda-font-popup-item;
|
||||||
|
color: #202328;
|
||||||
|
border-bottom: 1px solid #f2f2f2;
|
||||||
|
}
|
||||||
|
.search-select__item-label {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
font-size: $pda-font-popup-item;
|
||||||
|
color: #202328;
|
||||||
|
}
|
||||||
|
.search-select__item.is-selected .search-select__item-label {
|
||||||
|
color: #2f78e6;
|
||||||
|
}
|
||||||
|
.search-select__check {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
font-size: $pda-font-action;
|
||||||
|
color: #2f78e6;
|
||||||
|
}
|
||||||
|
.search-select__footer {
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: 16rpx 30rpx 8rpx;
|
||||||
|
}
|
||||||
|
.search-select__ok {
|
||||||
|
height: $pda-button-height;
|
||||||
|
line-height: $pda-button-height;
|
||||||
|
text-align: center;
|
||||||
|
font-size: $pda-font-button;
|
||||||
|
color: #fff;
|
||||||
|
background: #2979ff;
|
||||||
|
border-radius: 46rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="warehouse-table-wrap">
|
<view class="warehouse-table-wrap" :class="{ 'is-auto-height': isAutoHeight }">
|
||||||
<scroll-view scroll-x class="tableScrollX">
|
|
||||||
<wyb-table
|
<wyb-table
|
||||||
ref="table"
|
ref="table"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
@@ -10,7 +9,6 @@
|
|||||||
:first-line-fixed="firstLineFixed"
|
:first-line-fixed="firstLineFixed"
|
||||||
@onCellClick="onCellClick"
|
@onCellClick="onCellClick"
|
||||||
/>
|
/>
|
||||||
</scroll-view>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -22,10 +20,14 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
headers: { type: Array, default: () => [] },
|
headers: { type: Array, default: () => [] },
|
||||||
contents: { type: Array, default: () => [] },
|
contents: { type: Array, default: () => [] },
|
||||||
|
// auto:高度随内容撑开,纵向滚动交给外层 scroll-view,避免与下拉刷新抢手势
|
||||||
height: { type: String, default: 'auto' },
|
height: { type: String, default: 'auto' },
|
||||||
firstLineFixed: { type: Boolean, default: true },
|
firstLineFixed: { type: Boolean, default: false },
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
isAutoHeight() {
|
||||||
|
return !this.height || this.height === 'auto';
|
||||||
|
},
|
||||||
tableWidth() {
|
tableWidth() {
|
||||||
const total = (this.headers || []).reduce((sum, col) => sum + (col.width || 160), 0);
|
const total = (this.headers || []).reduce((sum, col) => sum + (col.width || 160), 0);
|
||||||
return `${total}rpx`;
|
return `${total}rpx`;
|
||||||
@@ -46,7 +48,10 @@ export default {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
.tableScrollX {
|
/* 取消表格内部纵向滚动,只保留横向;纵向由页面 scroll-view 处理 */
|
||||||
width: 100%;
|
.is-auto-height ::v-deep .wyb-table-scroll-view {
|
||||||
|
height: auto !important;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: visible;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<view class="t-table" :style="{ 'border-width': border + 'px', 'border-color': borderColor }">
|
||||||
|
<slot />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
border: {
|
||||||
|
type: String,
|
||||||
|
default: '1'
|
||||||
|
},
|
||||||
|
borderColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#d0dee5'
|
||||||
|
},
|
||||||
|
isCheck: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
provide() {
|
||||||
|
return {
|
||||||
|
table: this
|
||||||
|
};
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.childrens = [];
|
||||||
|
this.index = 0;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fire(e, index, len) {
|
||||||
|
let childrens = this.childrens;
|
||||||
|
console.log(childrens);
|
||||||
|
// 全选
|
||||||
|
if (index === 0) {
|
||||||
|
childrens.map((vm, index) => {
|
||||||
|
vm.checkboxData.checked = e;
|
||||||
|
return vm;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let isAll = childrens.find((n, ids) => ids !== 0 && !n.checkboxData.checked);
|
||||||
|
childrens[0].checkboxData.checked = isAll ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let fireArr = [];
|
||||||
|
for (let i = 0; i < childrens.length; i++) {
|
||||||
|
if (childrens[i].checkboxData.checked && i !== 0) {
|
||||||
|
fireArr.push(childrens[i].checkboxData.value - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$emit('change', {
|
||||||
|
detail: fireArr
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.t-table {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px #d0dee5 solid;
|
||||||
|
border-left: none;
|
||||||
|
border-top: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-table>>>t-tr {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-table>>>t-tr:nth-child(2n) {
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifdef H5 */
|
||||||
|
.t-table>>>.t-tr:nth-child(2n) {
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<view class="t-td" :style="{ 'border-width': thBorder + 'px','border-color':borderColor ,'font-size':fontSize+'px' ,'color':color,'justify-content':tdAlignCpd}">
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
align: String
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
thBorder: '1',
|
||||||
|
borderColor: '#d0dee5',
|
||||||
|
fontSize: '14',
|
||||||
|
color: '#555c60',
|
||||||
|
tdAlign: 'center'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
inject: ['table', 'tr'],
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.thBorder = this.table.border;
|
||||||
|
this.borderColor = this.table.borderColor;
|
||||||
|
this.fontSize = this.tr.fontSize;
|
||||||
|
this.color = this.tr.color;
|
||||||
|
if (this.align) {
|
||||||
|
this.tdAlign = this.align;
|
||||||
|
} else {
|
||||||
|
this.tdAlign = this.tr.align
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
tdAlignCpd() {
|
||||||
|
let nameAlign = '';
|
||||||
|
switch (this.tdAlign) {
|
||||||
|
case 'left':
|
||||||
|
nameAlign = 'flex-start'
|
||||||
|
break;
|
||||||
|
case 'center':
|
||||||
|
nameAlign = 'center'
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
nameAlign = 'flex-end'
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nameAlign = 'center'
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return nameAlign
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.t-td {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding: 14upx;
|
||||||
|
border-top: 1px #d0dee5 solid;
|
||||||
|
border-left: 1px #d0dee5 solid;
|
||||||
|
text-align: center;
|
||||||
|
color: #555c60;
|
||||||
|
font-size: 28upx;
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<view class="t-th" :style="{ 'border-width': thBorder + 'px' ,'border-color':borderColor,'font-size':fontSize+'px' ,'color':color,'justify-content':thAlignCpd}">
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
align: String,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
thBorder: '1',
|
||||||
|
borderColor: '#d0dee5',
|
||||||
|
fontSize: '15',
|
||||||
|
color: '#3b4246',
|
||||||
|
thAlign: 'center'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
inject: ['table', 'tr'],
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.thBorder = this.table.border;
|
||||||
|
this.borderColor = this.table.borderColor;
|
||||||
|
this.fontSize = this.tr.fontSize;
|
||||||
|
this.color = this.tr.color;
|
||||||
|
if (this.align) {
|
||||||
|
this.thAlign = this.align;
|
||||||
|
} else {
|
||||||
|
this.thAlign = this.tr.align
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
thAlignCpd() {
|
||||||
|
let nameAlign = '';
|
||||||
|
switch (this.thAlign) {
|
||||||
|
case 'left':
|
||||||
|
nameAlign = 'flex-start'
|
||||||
|
break;
|
||||||
|
case 'center':
|
||||||
|
nameAlign = 'center'
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
nameAlign = 'flex-end'
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nameAlign = 'center'
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return nameAlign
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.t-th {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 30upx;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
color: #3b4246;
|
||||||
|
border-left: 1px #d0dee5 solid;
|
||||||
|
border-top: 1px #d0dee5 solid;
|
||||||
|
padding: 15upx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
<template>
|
||||||
|
<view class="t-tr">
|
||||||
|
<view v-if="isCheck" class="t-check-box" :style="{ 'border-width': thBorder + 'px' ,'border-color':borderColor}">
|
||||||
|
<checkbox-group @change="checkboxChange">
|
||||||
|
<checkbox :value="checkboxData.value + ''" :checked="checkboxData.checked" />
|
||||||
|
</checkbox-group>
|
||||||
|
</view>
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
fontSize: String,
|
||||||
|
color: String,
|
||||||
|
align: String
|
||||||
|
},
|
||||||
|
inject: ['table'],
|
||||||
|
provide() {
|
||||||
|
return {
|
||||||
|
tr: this
|
||||||
|
};
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isCheck: false,
|
||||||
|
checkboxData: {
|
||||||
|
value: 0,
|
||||||
|
checked: false
|
||||||
|
},
|
||||||
|
checked: false,
|
||||||
|
thBorder: '1',
|
||||||
|
borderColor: '#d0dee5'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.thBorder = this.table.border;
|
||||||
|
this.borderColor = this.table.borderColor;
|
||||||
|
this.table.childrens.push(this);
|
||||||
|
this.checkboxData.value = this.table.index++;
|
||||||
|
this.isCheck = this.table.isCheck;
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
checkboxChange(e) {
|
||||||
|
this.checkboxData.checked = !this.checkboxData.checked;
|
||||||
|
this.table.childrens[this.checkboxData.value] = this;
|
||||||
|
this.table.fire(e.detail.value[0] ? true : false, this.checkboxData.value, this.table.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.t-tr {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-tr t-th,
|
||||||
|
.t-tr t-td {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-tr .t-check-box {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 80upx;
|
||||||
|
color: #3b4246;
|
||||||
|
border-left: 1px #d0dee5 solid;
|
||||||
|
border-top: 1px #d0dee5 solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-tr .t-check-box checkbox {
|
||||||
|
transform: scale(0.8);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,589 @@
|
|||||||
|
<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" :style="hasCustomItemHeight ? bodyStyle : null">
|
||||||
|
<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"
|
||||||
|
:style="pickerViewStyle"
|
||||||
|
:indicator-style="indicatorStyle"
|
||||||
|
: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"
|
||||||
|
:style="hasCustomItemHeight ? itemStyle : null"
|
||||||
|
v-for="(item1, index1) in item"
|
||||||
|
:key="item1[valueName] != null ? item1[valueName] : index1"
|
||||||
|
>
|
||||||
|
<view class="u-line-1" :style="hasCustomItemHeight ? itemStyle : null">{{ 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
|
||||||
|
},
|
||||||
|
/** 选项行高(rpx)。App 端需与 indicator 同步,避免选中框错位 */
|
||||||
|
itemHeight: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
/** 可见行数,用于计算滚轮高度;需为奇数,选中行才能居中 */
|
||||||
|
visibleItemCount: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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;
|
||||||
|
},
|
||||||
|
hasCustomItemHeight() {
|
||||||
|
return Number(this.itemHeight) > 0;
|
||||||
|
},
|
||||||
|
itemHeightRpx() {
|
||||||
|
return Number(this.itemHeight) || 70;
|
||||||
|
},
|
||||||
|
itemHeightPx() {
|
||||||
|
return uni.upx2px(this.itemHeightRpx);
|
||||||
|
},
|
||||||
|
visibleCount() {
|
||||||
|
const n = Number(this.visibleItemCount) || 5;
|
||||||
|
return n % 2 === 0 ? n + 1 : n;
|
||||||
|
},
|
||||||
|
indicatorStyle() {
|
||||||
|
if (!this.hasCustomItemHeight) return '';
|
||||||
|
return `height: ${this.itemHeightPx}px;`;
|
||||||
|
},
|
||||||
|
itemStyle() {
|
||||||
|
return {
|
||||||
|
height: `${this.itemHeightPx}px`,
|
||||||
|
lineHeight: `${this.itemHeightPx}px`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
pickerViewStyle() {
|
||||||
|
if (!this.hasCustomItemHeight) return null;
|
||||||
|
return { height: `${this.itemHeightPx * this.visibleCount}px` };
|
||||||
|
},
|
||||||
|
bodyStyle() {
|
||||||
|
return this.pickerViewStyle;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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() {
|
||||||
|
const columnNum = this.columnNum || 1;
|
||||||
|
const defaultValue = Array.isArray(this.defaultValue) ? this.defaultValue.slice() : [];
|
||||||
|
this.defaultSelector = defaultValue.length === columnNum
|
||||||
|
? defaultValue
|
||||||
|
: Array(columnNum).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>
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
borderRight: index === headers.length - 1 || (!showVertBorder && index !== 0) ? 'none' : '1px solid' + borderColor,
|
borderRight: index === headers.length - 1 || (!showVertBorder && index !== 0) ? 'none' : '1px solid' + borderColor,
|
||||||
zIndex: index === 0 ? 20 : 0,
|
zIndex: index === 0 ? 20 : 0,
|
||||||
left: index === 0 && firstLineFixed ? (enableCheck ? checkColWidth + 'rpx' : 0) : 'auto',
|
left: index === 0 && firstLineFixed ? (enableCheck ? checkColWidth + 'rpx' : 0) : 'auto',
|
||||||
position: index === 0 ? 'sticky' : 'static'}">
|
position: index === 0 && firstLineFixed ? 'sticky' : 'static'}">
|
||||||
<text :style="{marginLeft: autoSortShow(index) && textAlign !== 'left' ? fontSize[0] * 0.65 + 'rpx' : 0}">
|
<text :style="{marginLeft: autoSortShow(index) && textAlign !== 'left' ? fontSize[0] * 0.65 + 'rpx' : 0}">
|
||||||
{{item.label || emptyString}}
|
{{item.label || emptyString}}
|
||||||
</text>
|
</text>
|
||||||
|
|||||||
+19
@@ -17,6 +17,25 @@ import VueI18n from '@/common/vue-i18n.min.js';
|
|||||||
import lang_zh_CN from '@/common/locales/zh_CN.js';
|
import lang_zh_CN from '@/common/locales/zh_CN.js';
|
||||||
import lang_en from '@/common/locales/en.js';
|
import lang_en from '@/common/locales/en.js';
|
||||||
|
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
// Android 5.x 等老 PDA 不信任 Let's Encrypt 新证书链,全局关闭 HTTPS 证书校验
|
||||||
|
(() => {
|
||||||
|
const patchSslVerify = (methodName) => {
|
||||||
|
const original = uni[methodName];
|
||||||
|
if (typeof original !== 'function') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uni[methodName] = (options = {}) => original({
|
||||||
|
...options,
|
||||||
|
sslVerify: false
|
||||||
|
});
|
||||||
|
};
|
||||||
|
patchSslVerify('request');
|
||||||
|
patchSslVerify('downloadFile');
|
||||||
|
patchSslVerify('uploadFile');
|
||||||
|
})();
|
||||||
|
// #endif
|
||||||
|
|
||||||
Vue.config.productionTip = false;
|
Vue.config.productionTip = false;
|
||||||
|
|
||||||
App.mpType = 'app';
|
App.mpType = 'app';
|
||||||
|
|||||||
+4
-4
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name" : "浩拓技术",
|
"name" : "浩拓织厂",
|
||||||
"appid" : "__UNI__F79F300",
|
"appid" : "__UNI__F79F300",
|
||||||
"description" : "浩拓纺织平台",
|
"description" : "周尚-浩拓织厂",
|
||||||
"versionName" : "1.1.4",
|
"versionName" : "1.1.26",
|
||||||
"versionCode" : 104,
|
"versionCode" : 126,
|
||||||
"transformPx" : false,
|
"transformPx" : false,
|
||||||
"app-plus" : {
|
"app-plus" : {
|
||||||
"optimization" : {
|
"optimization" : {
|
||||||
|
|||||||
+8
-18
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"easycom": {
|
"easycom": {
|
||||||
|
"^u-select$": "@/components/u-select/u-select.vue",
|
||||||
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
|
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
|
||||||
},
|
},
|
||||||
"pages": [
|
"pages": [
|
||||||
@@ -576,6 +577,13 @@
|
|||||||
"navigationBarTitleText": "坯布出库列表",
|
"navigationBarTitleText": "坯布出库列表",
|
||||||
"enablePullDownRefresh": false
|
"enablePullDownRefresh": false
|
||||||
}
|
}
|
||||||
|
},{
|
||||||
|
"path": "pages/storefabric/storeFabricManualIn",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "手动进仓",
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
},{
|
},{
|
||||||
"path" : "pages/storefabric/storeFabricBusinessOutAdd",
|
"path" : "pages/storefabric/storeFabricBusinessOutAdd",
|
||||||
"style" :
|
"style" :
|
||||||
@@ -800,30 +808,12 @@
|
|||||||
"backgroundColor": "#ffffff",
|
"backgroundColor": "#ffffff",
|
||||||
"borderStyle": "white",
|
"borderStyle": "white",
|
||||||
"list": [
|
"list": [
|
||||||
{
|
|
||||||
"pagePath": "pages/sys/msg/index",
|
|
||||||
"iconPath": "static/aidex/tabbar/msg_1.png",
|
|
||||||
"selectedIconPath": "static/aidex/tabbar/msg_2.png",
|
|
||||||
"text": "消息"
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// "pagePath": "pages/sys/home/index",
|
|
||||||
// "iconPath": "static/aidex/tabbar/home_1.png",
|
|
||||||
// "selectedIconPath": "static/aidex/tabbar/home_2.png",
|
|
||||||
// "text": "首页"
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
"pagePath": "pages/sys/workbench/index",
|
"pagePath": "pages/sys/workbench/index",
|
||||||
"iconPath": "static/aidex/tabbar/apply_1.png",
|
"iconPath": "static/aidex/tabbar/apply_1.png",
|
||||||
"selectedIconPath": "static/aidex/tabbar/apply_2.png",
|
"selectedIconPath": "static/aidex/tabbar/apply_2.png",
|
||||||
"text": "工作台"
|
"text": "工作台"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"pagePath": "pages/sys/book/index",
|
|
||||||
"iconPath": "static/aidex/tabbar/book_1.png",
|
|
||||||
"selectedIconPath": "static/aidex/tabbar/book_2.png",
|
|
||||||
"text": "通讯录"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"pagePath": "pages/sys/user/index",
|
"pagePath": "pages/sys/user/index",
|
||||||
"iconPath": "static/aidex/tabbar/my_1.png",
|
"iconPath": "static/aidex/tabbar/my_1.png",
|
||||||
|
|||||||
@@ -17,6 +17,14 @@
|
|||||||
</u-form-item>
|
</u-form-item>
|
||||||
<u-form-item label-width="130" label="条码资料:">
|
<u-form-item label-width="130" label="条码资料:">
|
||||||
<input type="text" v-model="QRBarCode" maxlength="-1" style="width: 170px" @confirm="SalePickBillDetailScan" />
|
<input type="text" v-model="QRBarCode" maxlength="-1" style="width: 170px" @confirm="SalePickBillDetailScan" />
|
||||||
|
<u-icon
|
||||||
|
v-if="usePhoneScanFallback"
|
||||||
|
name="scan"
|
||||||
|
size="44"
|
||||||
|
color="#2979ff"
|
||||||
|
style="margin-left: 8px;"
|
||||||
|
@click="handlePhoneScan"
|
||||||
|
/>
|
||||||
<checkbox-group @change="handleAllCrockNoChange">
|
<checkbox-group @change="handleAllCrockNoChange">
|
||||||
<checkbox :checked="AllCrockNoScanStatus">整缸</checkbox>
|
<checkbox :checked="AllCrockNoScanStatus">整缸</checkbox>
|
||||||
</checkbox-group>
|
</checkbox-group>
|
||||||
@@ -182,21 +190,16 @@ export default {
|
|||||||
|
|
||||||
onUnload() {
|
onUnload() {
|
||||||
this.isPageActive = false;
|
this.isPageActive = false;
|
||||||
// #ifdef APP-PLUS
|
|
||||||
this.unregisterScanBroadcast();
|
this.unregisterScanBroadcast();
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onHide() {
|
onHide() {
|
||||||
this.isPageActive = false;
|
this.isPageActive = false;
|
||||||
// #ifdef APP-PLUS
|
|
||||||
this.unregisterScanBroadcast();
|
this.unregisterScanBroadcast();
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onShow() {
|
onShow() {
|
||||||
this.isPageActive = true;
|
this.isPageActive = true;
|
||||||
// #ifdef APP-PLUS
|
|
||||||
this.registerScanBroadcast((scanResult) => {
|
this.registerScanBroadcast((scanResult) => {
|
||||||
console.log("配布单详情-扫码结果:", scanResult);
|
console.log("配布单详情-扫码结果:", scanResult);
|
||||||
this.QRBarCode = scanResult;
|
this.QRBarCode = scanResult;
|
||||||
@@ -204,10 +207,13 @@ export default {
|
|||||||
this.handleScans();
|
this.handleScans();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
handlePhoneScan() {
|
||||||
|
this.openPhoneScan();
|
||||||
|
},
|
||||||
|
|
||||||
playSuccess() {
|
playSuccess() {
|
||||||
util.playSuccessAudio();
|
util.playSuccessAudio();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,214 +1,138 @@
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
<view class="fabric-out-page">
|
<view class="fabric-out-page">
|
||||||
|
<view v-if="showHeaderToggle" class="fabric-out-headerBar" @click="toggleHeader">
|
||||||
|
<view class="fabric-out-headerBarMain">
|
||||||
|
<text class="fabric-out-headerBarTitle">单据信息</text>
|
||||||
|
<text v-if="form.order_no" class="fabric-out-headerBarSub">{{ form.order_no }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="fabric-out-headerBarAction">
|
||||||
|
<text>{{ headerExpanded ? '收起' : '展开' }}</text>
|
||||||
|
<u-icon class="fabric-out-headerBarIcon" :name="headerExpanded ? 'arrow-up' : 'arrow-down'" size="32" color="#2979ff"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-show="headerExpanded">
|
||||||
<OrderStatusBar class="fabric-out-mt32" :status="displayAuditStatus" :name="displayAuditStatusName" />
|
<OrderStatusBar class="fabric-out-mt32" :status="displayAuditStatus" :name="displayAuditStatusName" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<view class="flex-white-plr26 ptb10 bdb_f5">
|
<view class="flex-white-plr26 ptb10 bdb_f5">
|
||||||
|
|
||||||
<text class="mr26">出仓单号</text>
|
<text class="mr26">出仓单号</text>
|
||||||
|
|
||||||
<u-input disabled placeholder="保存后自动生成" v-model="form.order_no" />
|
<u-input disabled placeholder="保存后自动生成" v-model="form.order_no" />
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="flex-white-plr26 ptb20 bdb_f5">
|
<view class="flex-white-plr26 ptb20 bdb_f5">
|
||||||
|
|
||||||
<text class="mr26">出仓类型</text>
|
<text class="mr26">出仓类型</text>
|
||||||
|
|
||||||
<view>{{ getBillTypeName() }}</view>
|
<view>{{ getBillTypeName() }}</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view @click="pickerSelectFun('接收单位')" class="flex-white-plr26 ptb20 bdb_f5">
|
<view @click="pickerSelectFun('接收单位')" class="flex-white-plr26 ptb20 bdb_f5">
|
||||||
|
|
||||||
<text class="mr26">接收单位<text class="redXingh">*</text></text>
|
<text class="mr26">接收单位<text class="redXingh">*</text></text>
|
||||||
|
|
||||||
<view :class="form.business_unit_name ? '' : 'cBlack'">
|
<view :class="form.business_unit_name ? '' : 'cBlack'">
|
||||||
|
|
||||||
{{ form.business_unit_name || '请选择' }}
|
{{ form.business_unit_name || '请选择' }}
|
||||||
|
|
||||||
<u-icon v-if="headerEditable" class="ml26" name="arrow-right" size="40" color="#888888"></u-icon>
|
<u-icon v-if="headerEditable" class="ml26" name="arrow-right" size="40" color="#888888"></u-icon>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<view class="flex-white-plr26 ptb20 bdb_f5">
|
<view class="flex-white-plr26 ptb20 bdb_f5">
|
||||||
|
|
||||||
<text class="mr26">{{ dateLabel }}<text class="redXingh">*</text></text>
|
<text class="mr26">{{ dateLabel }}<text class="redXingh">*</text></text>
|
||||||
|
|
||||||
<picker mode="date" :value="form.delivery_time" :disabled="!headerEditable" @change="bindDateChange">
|
<picker mode="date" :value="form.delivery_time" :disabled="!headerEditable" @change="bindDateChange">
|
||||||
|
|
||||||
<view>{{ form.delivery_time }}</view>
|
<view>{{ form.delivery_time }}</view>
|
||||||
|
|
||||||
</picker>
|
</picker>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<view class="flex-white-plr26-column ptb20 mt32">
|
<view class="flex-white-plr26-column ptb20 mt32">
|
||||||
|
|
||||||
<view style="margin-bottom: 8rpx;"><text>单据备注</text></view>
|
<view style="margin-bottom: 8rpx;"><text>单据备注</text></view>
|
||||||
|
|
||||||
<u-input v-model="form.remark" :disabled="!headerEditable" type="textarea" :border="true" :height="100" :auto-height="true" />
|
<u-input v-model="form.remark" :disabled="!headerEditable" type="textarea" :border="true" :height="100" :auto-height="true" />
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<view v-if="showScanSection">
|
||||||
|
<PlusBarcodePanel
|
||||||
<FabricOutDetailList
|
ref="plusBarcodePanel"
|
||||||
|
:visible.sync="phoneScanPanelOpen"
|
||||||
:list="form.item_data"
|
hint-text="连续扫码出仓,扫完可继续下一条"
|
||||||
|
:scan-time-space="1200"
|
||||||
@fabric-info="openFabricInfo"
|
@success="onPlusBarcodeSuccess"
|
||||||
|
/>
|
||||||
@fine-code="openFineCode"
|
|
||||||
|
|
||||||
>
|
|
||||||
|
|
||||||
<FabricOutScanBar
|
<FabricOutScanBar
|
||||||
|
|
||||||
slot="before-list"
|
|
||||||
|
|
||||||
:can-scan="canScan"
|
:can-scan="canScan"
|
||||||
|
|
||||||
:value="QRBarCode"
|
:value="QRBarCode"
|
||||||
|
|
||||||
:delete-mode="BarCodeDelStatus"
|
:delete-mode="BarCodeDelStatus"
|
||||||
|
|
||||||
:message="BillDataMessage"
|
:message="BillDataMessage"
|
||||||
|
|
||||||
disabled-tip="请先提交保存后再扫码"
|
disabled-tip="请先提交保存后再扫码"
|
||||||
|
:scanning="phoneScanPanelOpen"
|
||||||
@input="QRBarCode = $event"
|
@input="QRBarCode = $event"
|
||||||
|
|
||||||
@scan="handleScan"
|
@scan="handleScan"
|
||||||
|
@phone-scan="handlePhoneScan"
|
||||||
@delete-mode-change="BarCodeDelChange"
|
@delete-mode-change="BarCodeDelChange"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FabricOutScanDetail
|
<FabricOutScanDetail
|
||||||
slot="before-list"
|
|
||||||
:detail="scanDetail"
|
:detail="scanDetail"
|
||||||
:item-data="form.item_data"
|
|
||||||
:group-keys="scanGroupKeys"
|
:group-keys="scanGroupKeys"
|
||||||
@group-change="scanGroupKeys = $event"
|
@group-change="scanGroupKeys = $event"
|
||||||
/>
|
/>
|
||||||
|
<FabricOutSummaryTable
|
||||||
</FabricOutDetailList>
|
:rows="form.summary_rows"
|
||||||
|
@cell-click="onSummaryCellClick"
|
||||||
|
|
||||||
|
|
||||||
<FabricOutFooter
|
|
||||||
|
|
||||||
v-if="!headerSaved"
|
|
||||||
|
|
||||||
:buttons="[{ label: '提交保存', action: 'save' }]"
|
|
||||||
|
|
||||||
single
|
|
||||||
|
|
||||||
@action="submitSave"
|
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FabricOutFooter
|
|
||||||
|
|
||||||
v-else
|
|
||||||
|
|
||||||
:buttons="statusActionButtons"
|
|
||||||
|
|
||||||
@action="handleStatusAction"
|
|
||||||
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<u-select v-model="selectShow" :list="selectList" @confirm="selectConfirmFun"></u-select>
|
|
||||||
|
|
||||||
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
|
||||||
|
|
||||||
<FineCodePopup :show.sync="fineCodeShow" :list="currentFineCodes" :readonly="false" @delete="onDeleteFineCode" />
|
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<FabricOutFooter
|
||||||
|
v-if="!headerSaved"
|
||||||
|
:buttons="[{ label: '提交保存', action: 'save' }]"
|
||||||
|
single
|
||||||
|
@action="submitSave"
|
||||||
|
/>
|
||||||
|
<FabricOutFooter
|
||||||
|
v-else
|
||||||
|
:buttons="statusActionButtons"
|
||||||
|
@action="handleStatusAction"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<search-select-popup
|
||||||
|
:show.sync="selectShow"
|
||||||
|
title="选择接收单位"
|
||||||
|
placeholder="请输入染厂名称"
|
||||||
|
:list="selectList"
|
||||||
|
@confirm="selectConfirmFun"
|
||||||
|
/>
|
||||||
|
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
||||||
|
<FineCodePopup :show.sync="fineCodeShow" :list="currentFineCodes" :readonly="false" @delete="onDeleteFineCode" />
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import formMixin from './storeFabricBusinessOutMixin.js';
|
import formMixin from './storeFabricBusinessOutMixin.js';
|
||||||
|
|
||||||
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
||||||
|
|
||||||
import FineCodePopup from '@/components/storefabric/FineCodePopup.vue';
|
import FineCodePopup from '@/components/storefabric/FineCodePopup.vue';
|
||||||
|
|
||||||
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
||||||
|
|
||||||
import FabricOutDetailList from '@/components/storefabric/FabricOutDetailList.vue';
|
|
||||||
|
|
||||||
import FabricOutScanBar from '@/components/storefabric/FabricOutScanBar.vue';
|
import FabricOutScanBar from '@/components/storefabric/FabricOutScanBar.vue';
|
||||||
|
|
||||||
import FabricOutScanDetail from '@/components/storefabric/FabricOutScanDetail.vue';
|
import FabricOutScanDetail from '@/components/storefabric/FabricOutScanDetail.vue';
|
||||||
|
import FabricOutSummaryTable from '@/components/storefabric/FabricOutSummaryTable.vue';
|
||||||
import FabricOutFooter from '@/components/storefabric/FabricOutFooter.vue';
|
import FabricOutFooter from '@/components/storefabric/FabricOutFooter.vue';
|
||||||
|
import SearchSelectPopup from '@/components/storefabric/SearchSelectPopup.vue';
|
||||||
|
import PlusBarcodePanel from '@/components/common/PlusBarcodePanel.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
|
|
||||||
FabricInfoPopup,
|
FabricInfoPopup,
|
||||||
|
|
||||||
FineCodePopup,
|
FineCodePopup,
|
||||||
|
|
||||||
OrderStatusBar,
|
OrderStatusBar,
|
||||||
|
|
||||||
FabricOutDetailList,
|
|
||||||
|
|
||||||
FabricOutScanBar,
|
FabricOutScanBar,
|
||||||
|
|
||||||
FabricOutScanDetail,
|
FabricOutScanDetail,
|
||||||
|
FabricOutSummaryTable,
|
||||||
FabricOutFooter,
|
FabricOutFooter,
|
||||||
|
SearchSelectPopup,
|
||||||
|
PlusBarcodePanel,
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [formMixin],
|
mixins: [formMixin],
|
||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
|
|
||||||
uni.setNavigationBarTitle({ title: '新增坯布出仓单' });
|
uni.setNavigationBarTitle({ title: '新增坯布出仓单' });
|
||||||
|
|
||||||
this.pageMode = 'add';
|
this.pageMode = 'add';
|
||||||
|
|
||||||
this.loadBaseDropdowns();
|
this.loadBaseDropdowns();
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
||||||
@import '@/pages/storefabric/storeFabricBusinessOutPage.scss';
|
@import '@/pages/storefabric/storeFabricBusinessOutPage.scss';
|
||||||
|
|
||||||
page {
|
page {
|
||||||
background-color: #F8F8F8;
|
background-color: #F8F8F8;
|
||||||
padding-bottom: 260rpx;
|
padding-bottom: 260rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="fabric-out-page">
|
<view class="fabric-out-page">
|
||||||
<OrderStatusBar class="fabric-out-mt32" :status="displayAuditStatus" :name="displayAuditStatusName" />
|
<view v-if="showHeaderToggle" class="fabric-out-headerBar" @click="toggleHeader">
|
||||||
|
<view class="fabric-out-headerBarMain">
|
||||||
|
<text class="fabric-out-headerBarTitle">单据信息</text>
|
||||||
|
<text v-if="form.order_no" class="fabric-out-headerBarSub">{{ form.order_no }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="fabric-out-headerBarAction">
|
||||||
|
<text>{{ headerExpanded ? '收起' : '展开' }}</text>
|
||||||
|
<u-icon class="fabric-out-headerBarIcon" :name="headerExpanded ? 'arrow-up' : 'arrow-down'" size="32" color="#2979ff"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-show="headerExpanded">
|
||||||
|
<OrderStatusBar class="fabric-out-mt32" :status="displayAuditStatus" :name="displayAuditStatusName" />
|
||||||
<view class="flex-white-plr26 ptb10 bdb_f5">
|
<view class="flex-white-plr26 ptb10 bdb_f5">
|
||||||
<text class="mr26">出仓单号</text>
|
<text class="mr26">出仓单号</text>
|
||||||
<text>{{ form.order_no }}</text>
|
<text>{{ form.order_no }}</text>
|
||||||
@@ -22,34 +33,47 @@
|
|||||||
<text class="mr26">单据备注</text>
|
<text class="mr26">单据备注</text>
|
||||||
<text>{{ form.remark || '-' }}</text>
|
<text>{{ form.remark || '-' }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<FabricOutDetailList
|
<view v-if="showScanSection">
|
||||||
:list="form.item_data"
|
<PlusBarcodePanel
|
||||||
@fabric-info="openFabricInfo"
|
ref="plusBarcodePanel"
|
||||||
@fine-code="openFineCode"
|
:visible.sync="phoneScanPanelOpen"
|
||||||
>
|
hint-text="连续扫码出仓,扫完可继续下一条"
|
||||||
|
:scan-time-space="1200"
|
||||||
|
@success="onPlusBarcodeSuccess"
|
||||||
|
/>
|
||||||
<FabricOutScanBar
|
<FabricOutScanBar
|
||||||
slot="before-list"
|
|
||||||
:can-scan="canScan"
|
:can-scan="canScan"
|
||||||
:value="QRBarCode"
|
:value="QRBarCode"
|
||||||
:delete-mode="BarCodeDelStatus"
|
:delete-mode="BarCodeDelStatus"
|
||||||
:message="BillDataMessage"
|
:message="BillDataMessage"
|
||||||
|
:scanning="phoneScanPanelOpen"
|
||||||
@input="QRBarCode = $event"
|
@input="QRBarCode = $event"
|
||||||
@scan="handleScan"
|
@scan="handleScan"
|
||||||
|
@phone-scan="handlePhoneScan"
|
||||||
@delete-mode-change="BarCodeDelChange"
|
@delete-mode-change="BarCodeDelChange"
|
||||||
/>
|
/>
|
||||||
<FabricOutScanDetail
|
<FabricOutScanDetail
|
||||||
slot="before-list"
|
|
||||||
:detail="scanDetail"
|
:detail="scanDetail"
|
||||||
:item-data="form.item_data"
|
|
||||||
:group-keys="scanGroupKeys"
|
:group-keys="scanGroupKeys"
|
||||||
@group-change="scanGroupKeys = $event"
|
@group-change="scanGroupKeys = $event"
|
||||||
/>
|
/>
|
||||||
</FabricOutDetailList>
|
<FabricOutSummaryTable
|
||||||
|
:rows="form.summary_rows"
|
||||||
|
@cell-click="onSummaryCellClick"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
<FabricOutFooter :buttons="statusActionButtons" @action="handleStatusAction" />
|
<FabricOutFooter :buttons="statusActionButtons" @action="handleStatusAction" />
|
||||||
|
|
||||||
<u-select v-model="selectShow" :list="selectList" @confirm="selectConfirmFun"></u-select>
|
<search-select-popup
|
||||||
|
:show.sync="selectShow"
|
||||||
|
title="选择接收单位"
|
||||||
|
placeholder="请输入染厂名称"
|
||||||
|
:list="selectList"
|
||||||
|
@confirm="selectConfirmFun"
|
||||||
|
/>
|
||||||
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
<FabricInfoPopup :show.sync="fabricInfoShow" :data="currentFabricInfo" />
|
||||||
<FineCodePopup :show.sync="fineCodeShow" :list="currentFineCodes" :readonly="false" @delete="onDeleteFineCode" />
|
<FineCodePopup :show.sync="fineCodeShow" :list="currentFineCodes" :readonly="false" @delete="onDeleteFineCode" />
|
||||||
</view>
|
</view>
|
||||||
@@ -60,25 +84,36 @@ import formMixin from './storeFabricBusinessOutMixin.js';
|
|||||||
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
import FabricInfoPopup from '@/components/storefabric/FabricInfoPopup.vue';
|
||||||
import FineCodePopup from '@/components/storefabric/FineCodePopup.vue';
|
import FineCodePopup from '@/components/storefabric/FineCodePopup.vue';
|
||||||
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
import OrderStatusBar from '@/components/storefabric/OrderStatusBar.vue';
|
||||||
import FabricOutDetailList from '@/components/storefabric/FabricOutDetailList.vue';
|
|
||||||
import FabricOutScanBar from '@/components/storefabric/FabricOutScanBar.vue';
|
import FabricOutScanBar from '@/components/storefabric/FabricOutScanBar.vue';
|
||||||
import FabricOutScanDetail from '@/components/storefabric/FabricOutScanDetail.vue';
|
import FabricOutScanDetail from '@/components/storefabric/FabricOutScanDetail.vue';
|
||||||
|
import FabricOutSummaryTable from '@/components/storefabric/FabricOutSummaryTable.vue';
|
||||||
import FabricOutFooter from '@/components/storefabric/FabricOutFooter.vue';
|
import FabricOutFooter from '@/components/storefabric/FabricOutFooter.vue';
|
||||||
|
import SearchSelectPopup from '@/components/storefabric/SearchSelectPopup.vue';
|
||||||
|
import PlusBarcodePanel from '@/components/common/PlusBarcodePanel.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
FabricInfoPopup,
|
FabricInfoPopup,
|
||||||
FineCodePopup,
|
FineCodePopup,
|
||||||
OrderStatusBar,
|
OrderStatusBar,
|
||||||
FabricOutDetailList,
|
|
||||||
FabricOutScanBar,
|
FabricOutScanBar,
|
||||||
FabricOutScanDetail,
|
FabricOutScanDetail,
|
||||||
|
FabricOutSummaryTable,
|
||||||
FabricOutFooter,
|
FabricOutFooter,
|
||||||
|
SearchSelectPopup,
|
||||||
|
PlusBarcodePanel,
|
||||||
},
|
},
|
||||||
mixins: [formMixin],
|
mixins: [formMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageMode: 'edit',
|
||||||
|
headerExpanded: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
onLoad(e) {
|
onLoad(e) {
|
||||||
uni.setNavigationBarTitle({ title: '编辑坯布出仓单' });
|
uni.setNavigationBarTitle({ title: '编辑坯布出仓单' });
|
||||||
this.pageMode = 'edit';
|
this.pageMode = 'edit';
|
||||||
|
this.headerExpanded = false;
|
||||||
if (e.id) {
|
if (e.id) {
|
||||||
this.loadOrder(Number(e.id), { rejectIfLocked: true });
|
this.loadOrder(Number(e.id), { rejectIfLocked: true });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<view class="filterBar">
|
<view class="filterBar">
|
||||||
<u-search v-model="filters.order_no" placeholder="出仓单号" :show-action="false" @search="loadList" @custom="loadList" />
|
<u-search
|
||||||
<view class="filterBtn" @click="filterShow = true">
|
v-model="filters.order_no"
|
||||||
<u-icon name="list" size="40" color="#666"></u-icon>
|
placeholder="出仓单号"
|
||||||
|
:show-action="false"
|
||||||
|
@search="applySearch"
|
||||||
|
@custom="applySearch"
|
||||||
|
@clear="applySearch"
|
||||||
|
/>
|
||||||
|
<view class="filterBtn" :class="{ 'filterBtn--active': hasActiveFilter }" @click="filterShow = true">
|
||||||
|
<view class="filterBtn__icon">
|
||||||
|
<u-icon name="list" size="44" :color="hasActiveFilter ? '#2979ff' : '#666'"></u-icon>
|
||||||
|
<view v-if="hasActiveFilter" class="filterBtn__badge"></view>
|
||||||
|
</view>
|
||||||
<text>筛选</text>
|
<text>筛选</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -20,36 +30,48 @@
|
|||||||
|
|
||||||
<addBtn url="./storeFabricBusinessOutAdd"></addBtn>
|
<addBtn url="./storeFabricBusinessOutAdd"></addBtn>
|
||||||
|
|
||||||
<u-popup v-model="filterShow" mode="right" width="580rpx" :safe-area-inset-bottom="true">
|
<u-popup v-model="filterShow" mode="right" width="580rpx" :safe-area-inset-bottom="true" @close="cancelFilterEdit">
|
||||||
<view class="filterPanel">
|
<view class="filterPanel">
|
||||||
<view class="filterTitle">筛选条件</view>
|
<view class="filterTitle">筛选条件</view>
|
||||||
<view class="filterItem">
|
<view class="filterItem">
|
||||||
<text class="filterLabel">出仓单号</text>
|
<text class="filterLabel">出仓单号</text>
|
||||||
<u-input v-model="filters.order_no" placeholder="请输入出仓单号" />
|
<view class="filterInput">
|
||||||
|
<u-input
|
||||||
|
v-model="filters.order_no"
|
||||||
|
placeholder="请输入出仓单号"
|
||||||
|
:height="100"
|
||||||
|
:custom-style="{ fontSize: '36rpx', color: '#202328' }"
|
||||||
|
placeholder-style="color: #aeb4bf; font-size: 34rpx;"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="filterItem">
|
<view class="filterItem">
|
||||||
<text class="filterLabel">出仓日期</text>
|
<text class="filterLabel">出仓日期</text>
|
||||||
<view class="dateRow">
|
<view class="dateRow">
|
||||||
<picker mode="date" :value="filters.start_date" @change="e => filters.start_date = e.detail.value">
|
<picker class="datePicker" mode="date" :value="filters.start_date" @change="e => filters.start_date = e.detail.value">
|
||||||
<view class="dateInput">{{ filters.start_date || '开始日期' }}</view>
|
<view class="dateInput" :class="{ 'dateInput--placeholder': !filters.start_date }">
|
||||||
|
{{ filters.start_date || '开始日期' }}
|
||||||
|
</view>
|
||||||
</picker>
|
</picker>
|
||||||
<text>~</text>
|
<text class="dateSeparator">~</text>
|
||||||
<picker mode="date" :value="filters.end_date" @change="e => filters.end_date = e.detail.value">
|
<picker class="datePicker" mode="date" :value="filters.end_date" @change="e => filters.end_date = e.detail.value">
|
||||||
<view class="dateInput">{{ filters.end_date || '结束日期' }}</view>
|
<view class="dateInput" :class="{ 'dateInput--placeholder': !filters.end_date }">
|
||||||
|
{{ filters.end_date || '结束日期' }}
|
||||||
|
</view>
|
||||||
</picker>
|
</picker>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="filterItem" @click="openDeliveryUnitSelect">
|
<view class="filterItem" @click="openDeliveryUnitSelect">
|
||||||
<text class="filterLabel">出仓单位</text>
|
<text class="filterLabel">出仓单位</text>
|
||||||
<view class="filterValue">{{ deliveryUnitLabel || '全部' }} <u-icon name="arrow-right" size="28"></u-icon></view>
|
<view class="filterValue">{{ deliveryUnitLabel || '全部' }} <u-icon name="arrow-right" size="36"></u-icon></view>
|
||||||
</view>
|
</view>
|
||||||
<view class="filterItem" @click="openBusinessUnitSelect">
|
<view class="filterItem" @click="openBusinessUnitSelect">
|
||||||
<text class="filterLabel">接收单位</text>
|
<text class="filterLabel">接收单位</text>
|
||||||
<view class="filterValue">{{ businessUnitLabel || '全部' }} <u-icon name="arrow-right" size="28"></u-icon></view>
|
<view class="filterValue">{{ businessUnitLabel || '全部' }} <u-icon name="arrow-right" size="36"></u-icon></view>
|
||||||
</view>
|
</view>
|
||||||
<view class="filterItem" @click="openStatusSelect">
|
<view class="filterItem" @click="openStatusSelect">
|
||||||
<text class="filterLabel">订单状态</text>
|
<text class="filterLabel">订单状态</text>
|
||||||
<view class="filterValue">{{ statusLabel || '全部' }} <u-icon name="arrow-right" size="28"></u-icon></view>
|
<view class="filterValue">{{ statusLabel || '全部' }} <u-icon name="arrow-right" size="36"></u-icon></view>
|
||||||
</view>
|
</view>
|
||||||
<view class="filterActions">
|
<view class="filterActions">
|
||||||
<u-button type="warning" size="medium" @click="resetFilter">重置</u-button>
|
<u-button type="warning" size="medium" @click="resetFilter">重置</u-button>
|
||||||
@@ -58,25 +80,76 @@
|
|||||||
</view>
|
</view>
|
||||||
</u-popup>
|
</u-popup>
|
||||||
|
|
||||||
<u-select v-model="statusSelectShow" :list="statusSelectList" @confirm="onStatusConfirm"></u-select>
|
<u-select
|
||||||
<u-select v-model="unitSelectShow" :list="unitSelectList" @confirm="onUnitConfirm"></u-select>
|
class="pdaSelect"
|
||||||
|
v-model="statusSelectShow"
|
||||||
|
title="选择订单状态"
|
||||||
|
:list="statusSelectList"
|
||||||
|
:default-value="statusSelectDefault"
|
||||||
|
@confirm="onStatusConfirm"
|
||||||
|
></u-select>
|
||||||
|
<u-select
|
||||||
|
class="pdaSelect"
|
||||||
|
v-model="unitSelectShow"
|
||||||
|
title="选择出仓单位"
|
||||||
|
:list="unitSelectList"
|
||||||
|
:default-value="unitSelectDefault"
|
||||||
|
@confirm="onUnitConfirm"
|
||||||
|
></u-select>
|
||||||
|
<search-select-popup
|
||||||
|
:show.sync="businessUnitSelectShow"
|
||||||
|
title="选择接收单位"
|
||||||
|
placeholder="请输入染厂名称"
|
||||||
|
:list="businessUnitSelectList"
|
||||||
|
@confirm="onBusinessUnitConfirm"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import addBtn from '@/components/addBtn/addBtn.vue';
|
import addBtn from '@/components/addBtn/addBtn.vue';
|
||||||
import FabricOutItem from '@/components/card/storeFabricBusinessOutItem.vue';
|
import FabricOutItem from '@/components/card/storeFabricBusinessOutItem.vue';
|
||||||
|
import SearchSelectPopup from '@/components/storefabric/SearchSelectPopup.vue';
|
||||||
import {
|
import {
|
||||||
getStatusOptions,
|
getStatusOptions,
|
||||||
|
AUDIT_STATUS,
|
||||||
AUDIT_STATUS_MAP,
|
AUDIT_STATUS_MAP,
|
||||||
BILL_TYPES,
|
BILL_TYPES,
|
||||||
|
BUSINESS_UNIT_TYPE_DYEING_FACTORY,
|
||||||
formatRoll,
|
formatRoll,
|
||||||
mapToSelectOptions,
|
mapToSelectOptions,
|
||||||
fetchAllOrderList,
|
fetchAllOrderList,
|
||||||
} from '@/common/storeFabricBusinessOut';
|
} from '@/common/storeFabricBusinessOut';
|
||||||
|
|
||||||
|
const FILTER_STORAGE_KEY = 'storeFabricBusinessOutListFilters';
|
||||||
|
|
||||||
|
const createDefaultFilters = () => ({
|
||||||
|
order_no: '',
|
||||||
|
start_date: '',
|
||||||
|
end_date: '',
|
||||||
|
delivery_unit_id: '',
|
||||||
|
delivery_unit_name: '',
|
||||||
|
business_unit_id: '',
|
||||||
|
business_unit_name: '',
|
||||||
|
audit_status: AUDIT_STATUS.PENDING,
|
||||||
|
});
|
||||||
|
|
||||||
|
const normalizeFilters = (value) => {
|
||||||
|
const filters = createDefaultFilters();
|
||||||
|
if (!value || typeof value !== 'object' || Array.isArray(value)) return filters;
|
||||||
|
|
||||||
|
Object.keys(filters).forEach((key) => {
|
||||||
|
if (typeof value[key] === 'string' || typeof value[key] === 'number') {
|
||||||
|
filters[key] = value[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!filters.delivery_unit_id) filters.delivery_unit_name = '';
|
||||||
|
if (!filters.business_unit_id) filters.business_unit_name = '';
|
||||||
|
return filters;
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { addBtn, FabricOutItem },
|
components: { addBtn, FabricOutItem, SearchSelectPopup },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
list: [],
|
list: [],
|
||||||
@@ -85,20 +158,14 @@ export default {
|
|||||||
filterShow: false,
|
filterShow: false,
|
||||||
statusSelectShow: false,
|
statusSelectShow: false,
|
||||||
unitSelectShow: false,
|
unitSelectShow: false,
|
||||||
|
businessUnitSelectShow: false,
|
||||||
unitSelectType: '',
|
unitSelectType: '',
|
||||||
unitOptions: [],
|
deliveryUnitOptions: [],
|
||||||
|
businessUnitOptions: [],
|
||||||
unitOptionsLoading: false,
|
unitOptionsLoading: false,
|
||||||
billTypeName: (BILL_TYPES[0] || {}).label || '坯布其他出货单',
|
billTypeName: (BILL_TYPES[0] || {}).label || '坯布其他出货单',
|
||||||
filters: {
|
filters: createDefaultFilters(),
|
||||||
order_no: '',
|
appliedFilters: createDefaultFilters(),
|
||||||
start_date: '',
|
|
||||||
end_date: '',
|
|
||||||
delivery_unit_id: '',
|
|
||||||
delivery_unit_name: '',
|
|
||||||
business_unit_id: '',
|
|
||||||
business_unit_name: '',
|
|
||||||
audit_status: '',
|
|
||||||
},
|
|
||||||
statusSelectList: [
|
statusSelectList: [
|
||||||
{ value: '', label: '全部' },
|
{ value: '', label: '全部' },
|
||||||
...getStatusOptions(),
|
...getStatusOptions(),
|
||||||
@@ -117,54 +184,140 @@ export default {
|
|||||||
return this.filters.business_unit_name || '';
|
return this.filters.business_unit_name || '';
|
||||||
},
|
},
|
||||||
unitSelectList() {
|
unitSelectList() {
|
||||||
return [{ value: '', label: '全部' }, ...this.unitOptions];
|
return [{ value: '', label: '全部' }, ...this.deliveryUnitOptions];
|
||||||
|
},
|
||||||
|
businessUnitSelectList() {
|
||||||
|
return [{ value: '', label: '全部' }, ...this.businessUnitOptions];
|
||||||
|
},
|
||||||
|
statusSelectDefault() {
|
||||||
|
const index = this.statusSelectList.findIndex(
|
||||||
|
(item) => String(item.value) === String(this.filters.audit_status)
|
||||||
|
);
|
||||||
|
return [index >= 0 ? index : 0];
|
||||||
|
},
|
||||||
|
unitSelectDefault() {
|
||||||
|
const index = this.unitSelectList.findIndex(
|
||||||
|
(item) => String(item.value) === String(this.filters.delivery_unit_id)
|
||||||
|
);
|
||||||
|
return [index >= 0 ? index : 0];
|
||||||
|
},
|
||||||
|
hasActiveFilter() {
|
||||||
|
const filters = this.appliedFilters;
|
||||||
|
return Boolean(
|
||||||
|
String(filters.order_no || '').trim()
|
||||||
|
|| filters.start_date
|
||||||
|
|| filters.end_date
|
||||||
|
|| filters.delivery_unit_id
|
||||||
|
|| filters.business_unit_id
|
||||||
|
|| (filters.audit_status !== '' && filters.audit_status !== null)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
uni.setNavigationBarTitle({ title: '坯布出库列表' });
|
uni.setNavigationBarTitle({ title: '坯布出库列表' });
|
||||||
|
this.restoreFilterCache();
|
||||||
uni.getSystemInfo({
|
uni.getSystemInfo({
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
this.scrollHeight = `${res.windowHeight - 50}px`;
|
this.scrollHeight = `${res.windowHeight - 50}px`;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.loadUnitOptions();
|
|
||||||
this.loadList();
|
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
this.loadList();
|
this.loadList();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loadUnitOptions() {
|
restoreFilterCache() {
|
||||||
if (this.unitOptions.length || this.unitOptionsLoading) return Promise.resolve(this.unitOptions);
|
try {
|
||||||
this.unitOptionsLoading = true;
|
const filters = normalizeFilters(uni.getStorageSync(FILTER_STORAGE_KEY));
|
||||||
|
this.filters = { ...filters };
|
||||||
|
this.appliedFilters = { ...filters };
|
||||||
|
} catch (e) {
|
||||||
|
this.filters = createDefaultFilters();
|
||||||
|
this.appliedFilters = createDefaultFilters();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
saveFilterCache() {
|
||||||
|
try {
|
||||||
|
uni.setStorageSync(FILTER_STORAGE_KEY, { ...this.appliedFilters });
|
||||||
|
} catch (e) {
|
||||||
|
// 缓存失败不影响列表筛选
|
||||||
|
}
|
||||||
|
},
|
||||||
|
commitFilters() {
|
||||||
|
const filters = normalizeFilters(this.filters);
|
||||||
|
this.filters = { ...filters };
|
||||||
|
this.appliedFilters = { ...filters };
|
||||||
|
this.saveFilterCache();
|
||||||
|
this.loadList();
|
||||||
|
},
|
||||||
|
applySearch() {
|
||||||
|
this.commitFilters();
|
||||||
|
},
|
||||||
|
cancelFilterEdit() {
|
||||||
|
this.filters = { ...this.appliedFilters };
|
||||||
|
},
|
||||||
|
loadDeliveryUnitOptions() {
|
||||||
|
if (this.deliveryUnitOptions.length) return Promise.resolve(this.deliveryUnitOptions);
|
||||||
return this.$u.api.businessUnit.list({})
|
return this.$u.api.businessUnit.list({})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.unitOptions = mapToSelectOptions(res);
|
this.deliveryUnitOptions = mapToSelectOptions(res);
|
||||||
return this.unitOptions;
|
return this.deliveryUnitOptions;
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.unitOptions = [];
|
this.deliveryUnitOptions = [];
|
||||||
return this.unitOptions;
|
return this.deliveryUnitOptions;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
loadBusinessUnitOptions() {
|
||||||
|
if (this.businessUnitOptions.length) return Promise.resolve(this.businessUnitOptions);
|
||||||
|
return this.$u.api.businessUnit.list({ unit_type_id: BUSINESS_UNIT_TYPE_DYEING_FACTORY })
|
||||||
|
.then((res) => {
|
||||||
|
this.businessUnitOptions = mapToSelectOptions(res);
|
||||||
|
return this.businessUnitOptions;
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.catch(() => {
|
||||||
this.unitOptionsLoading = false;
|
this.businessUnitOptions = [];
|
||||||
|
return this.businessUnitOptions;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
openUnitSelect(type) {
|
openUnitSelect(type) {
|
||||||
this.loadUnitOptions().then((list) => {
|
if (this.unitOptionsLoading) return;
|
||||||
|
this.unitOptionsLoading = true;
|
||||||
|
const loadFn = type === 'delivery' ? this.loadDeliveryUnitOptions : this.loadBusinessUnitOptions;
|
||||||
|
loadFn.call(this)
|
||||||
|
.then((list) => {
|
||||||
if (!list.length) {
|
if (!list.length) {
|
||||||
uni.showToast({ title: '暂无可选单位', icon: 'none' });
|
uni.showToast({ title: '暂无可选单位', icon: 'none' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.unitSelectType = type;
|
this.unitSelectType = type;
|
||||||
this.unitSelectShow = true;
|
this.unitSelectShow = true;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.unitOptionsLoading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
openDeliveryUnitSelect() {
|
openDeliveryUnitSelect() {
|
||||||
this.openUnitSelect('delivery');
|
this.openUnitSelect('delivery');
|
||||||
},
|
},
|
||||||
openBusinessUnitSelect() {
|
openBusinessUnitSelect() {
|
||||||
this.openUnitSelect('business');
|
if (this.unitOptionsLoading) return;
|
||||||
|
this.unitOptionsLoading = true;
|
||||||
|
this.loadBusinessUnitOptions()
|
||||||
|
.then((list) => {
|
||||||
|
if (!list.length) {
|
||||||
|
uni.showToast({ title: '暂无可选单位', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.businessUnitSelectShow = true;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.unitOptionsLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onBusinessUnitConfirm(item) {
|
||||||
|
this.filters.business_unit_id = item.value;
|
||||||
|
this.filters.business_unit_name = item.value ? item.label : '';
|
||||||
},
|
},
|
||||||
onUnitConfirm(e) {
|
onUnitConfirm(e) {
|
||||||
const item = e[0] || {};
|
const item = e[0] || {};
|
||||||
@@ -177,10 +330,11 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
loadList() {
|
loadList() {
|
||||||
|
const filters = this.appliedFilters;
|
||||||
const params = {};
|
const params = {};
|
||||||
if (this.filters.order_no) params.order_no = this.filters.order_no;
|
if (filters.order_no) params.order_no = filters.order_no;
|
||||||
if (this.filters.audit_status !== '' && this.filters.audit_status !== null) {
|
if (filters.audit_status !== '' && filters.audit_status !== null) {
|
||||||
params.audit_status = this.filters.audit_status;
|
params.audit_status = filters.audit_status;
|
||||||
}
|
}
|
||||||
fetchAllOrderList((p) => this.$u.api.gfmOtherDeliveryOrder.list(p), params)
|
fetchAllOrderList((p) => this.$u.api.gfmOtherDeliveryOrder.list(p), params)
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
@@ -214,12 +368,13 @@ export default {
|
|||||||
},
|
},
|
||||||
// 后端列表仅支持 单号/状态 过滤,出仓日期与单位在前端做本地过滤
|
// 后端列表仅支持 单号/状态 过滤,出仓日期与单位在前端做本地过滤
|
||||||
matchClientFilter(item) {
|
matchClientFilter(item) {
|
||||||
if (this.filters.start_date && item.out_date < this.filters.start_date) return false;
|
const filters = this.appliedFilters;
|
||||||
if (this.filters.end_date && item.out_date > this.filters.end_date) return false;
|
if (filters.start_date && item.out_date < filters.start_date) return false;
|
||||||
if (this.filters.delivery_unit_id && String(item.delivery_unit_id) !== String(this.filters.delivery_unit_id)) {
|
if (filters.end_date && item.out_date > filters.end_date) return false;
|
||||||
|
if (filters.delivery_unit_id && String(item.delivery_unit_id) !== String(filters.delivery_unit_id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this.filters.business_unit_id && String(item.business_unit_id) !== String(this.filters.business_unit_id)) {
|
if (filters.business_unit_id && String(item.business_unit_id) !== String(filters.business_unit_id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -229,40 +384,165 @@ export default {
|
|||||||
this.loadList();
|
this.loadList();
|
||||||
},
|
},
|
||||||
goView(item) {
|
goView(item) {
|
||||||
uni.navigateTo({ url: `./storeFabricBusinessOutView?id=${item.id}` });
|
const page = Number(item.audit_status) === AUDIT_STATUS.PENDING
|
||||||
|
? 'storeFabricBusinessOutEdit'
|
||||||
|
: 'storeFabricBusinessOutView';
|
||||||
|
uni.navigateTo({ url: `./${page}?id=${item.id}` });
|
||||||
},
|
},
|
||||||
openStatusSelect() { this.statusSelectShow = true; },
|
openStatusSelect() { this.statusSelectShow = true; },
|
||||||
onStatusConfirm(e) { this.filters.audit_status = e[0].value; },
|
onStatusConfirm(e) { this.filters.audit_status = e[0].value; },
|
||||||
resetFilter() {
|
resetFilter() {
|
||||||
this.filters = {
|
this.filters = createDefaultFilters();
|
||||||
order_no: '',
|
|
||||||
start_date: '',
|
|
||||||
end_date: '',
|
|
||||||
delivery_unit_id: '',
|
|
||||||
delivery_unit_name: '',
|
|
||||||
business_unit_id: '',
|
|
||||||
business_unit_name: '',
|
|
||||||
audit_status: '',
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
applyFilter() {
|
applyFilter() {
|
||||||
|
this.commitFilters();
|
||||||
this.filterShow = false;
|
this.filterShow = false;
|
||||||
this.loadList();
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style lang="scss">
|
||||||
|
@import '@/common/pda-typography.scss';
|
||||||
|
|
||||||
page { background-color: #F8F8F8; }
|
page { background-color: #F8F8F8; }
|
||||||
.filterBar { display: flex; align-items: center; padding: 16rpx 20rpx; background: #fff; gap: 16rpx; }
|
.filterBar { display: flex; align-items: center; padding: 16rpx 20rpx; background: #fff; gap: 16rpx; }
|
||||||
.filterBtn { display: flex; flex-direction: column; align-items: center; font-size: 22rpx; color: #666; min-width: 80rpx; }
|
.filterBtn {
|
||||||
.filterPanel { padding: 30rpx; }
|
display: flex;
|
||||||
.filterTitle { font-size: 32rpx; font-weight: bold; margin-bottom: 30rpx; }
|
flex-direction: column;
|
||||||
.filterItem { margin-bottom: 24rpx; }
|
align-items: center;
|
||||||
.filterLabel { display: block; font-size: 28rpx; color: #666; margin-bottom: 12rpx; }
|
justify-content: center;
|
||||||
.filterValue { display: flex; align-items: center; justify-content: space-between; padding: 16rpx; background: #f5f5f5; border-radius: 8rpx; font-size: 28rpx; }
|
min-width: 88rpx;
|
||||||
.dateRow { display: flex; align-items: center; gap: 12rpx; }
|
min-height: 76rpx;
|
||||||
.dateInput { padding: 16rpx; background: #f5f5f5; border-radius: 8rpx; font-size: 26rpx; min-width: 200rpx; text-align: center; }
|
padding: 6rpx 8rpx;
|
||||||
.filterActions { display: flex; gap: 20rpx; margin-top: 40rpx; }
|
border: 2rpx solid transparent;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: $pda-font-nav-sub;
|
||||||
|
line-height: 1.2;
|
||||||
|
color: #666;
|
||||||
|
transition: color 0.2s, background-color 0.2s, border-color 0.2s;
|
||||||
|
}
|
||||||
|
.filterBtn--active {
|
||||||
|
color: #2979ff;
|
||||||
|
background: #eef5ff;
|
||||||
|
border-color: #9fc5ff;
|
||||||
|
}
|
||||||
|
.filterBtn__icon {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.filterBtn__badge {
|
||||||
|
position: absolute;
|
||||||
|
top: -3rpx;
|
||||||
|
right: -7rpx;
|
||||||
|
width: 13rpx;
|
||||||
|
height: 13rpx;
|
||||||
|
border: 3rpx solid #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #ff4d4f;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
.filterPanel {
|
||||||
|
min-height: 100%;
|
||||||
|
padding: 32rpx 28rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.filterTitle {
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
font-size: $pda-font-popup-title;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #202328;
|
||||||
|
}
|
||||||
|
.filterItem { margin-bottom: 28rpx; }
|
||||||
|
.filterLabel {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 14rpx;
|
||||||
|
font-size: $pda-font-body;
|
||||||
|
line-height: 1.35;
|
||||||
|
color: #555b66;
|
||||||
|
}
|
||||||
|
.filterInput {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
min-height: $pda-row-min-height;
|
||||||
|
padding: 0 18rpx;
|
||||||
|
background: #f5f6f8;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
::v-deep .filterInput .u-input__input {
|
||||||
|
font-size: $pda-font-body !important;
|
||||||
|
color: #202328;
|
||||||
|
}
|
||||||
|
::v-deep .filterInput .u-input__input::placeholder {
|
||||||
|
font-size: $pda-font-placeholder;
|
||||||
|
color: #aeb4bf;
|
||||||
|
}
|
||||||
|
.filterValue {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
min-height: $pda-row-min-height;
|
||||||
|
padding: 0 18rpx;
|
||||||
|
background: #f5f6f8;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: $pda-font-body;
|
||||||
|
color: #202328;
|
||||||
|
}
|
||||||
|
.dateRow {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
}
|
||||||
|
.datePicker {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.dateInput {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: $pda-row-min-height;
|
||||||
|
padding: 0 8rpx;
|
||||||
|
background: #f5f6f8;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: $pda-font-body;
|
||||||
|
color: #202328;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.dateInput--placeholder {
|
||||||
|
font-size: $pda-font-placeholder;
|
||||||
|
color: #7d8490;
|
||||||
|
}
|
||||||
|
.dateSeparator {
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-size: $pda-font-body;
|
||||||
|
color: #555b66;
|
||||||
|
}
|
||||||
|
.filterActions {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
.filterActions .u-btn {
|
||||||
|
flex: 1;
|
||||||
|
height: $pda-button-height !important;
|
||||||
|
line-height: $pda-button-height !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
font-size: $pda-font-button !important;
|
||||||
|
}
|
||||||
|
::v-deep .pdaSelect .u-select__header {
|
||||||
|
height: $pda-row-min-height;
|
||||||
|
}
|
||||||
|
::v-deep .pdaSelect .u-select__header__btn,
|
||||||
|
::v-deep .pdaSelect .u-select__header__title,
|
||||||
|
::v-deep .pdaSelect .u-select__body__picker-view__item {
|
||||||
|
font-size: $pda-font-popup-item !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,15 +4,16 @@
|
|||||||
* 业务说明:
|
* 业务说明:
|
||||||
* 1. 后端当前仅提供「坯布其他出货单」一种类型的接口,故出仓类型固定为 other,
|
* 1. 后端当前仅提供「坯布其他出货单」一种类型的接口,故出仓类型固定为 other,
|
||||||
* 表头保留接收单位(business_unit) / 出货日期 / 备注 等字段。
|
* 表头保留接收单位(business_unit) / 出货日期 / 备注 等字段。
|
||||||
* 2. 用户先填写表头并「提交保存」(addGfmOtherDeliveryOrder),拿到出仓单 id 后即可扫码;
|
* 2. 用户先填写表头并「提交保存」(addGfmOtherDeliveryOrder),拿到出仓单 id 后才显示扫码区和汇总表;
|
||||||
* 扫码新增/删除细码走 updateGfmOtherDeliveryOrder;勾选锁定维度时附带 *_lock 字段,操作后用返回的最新详情刷新。
|
* 扫码新增/删除细码走 updateGfmOtherDeliveryOrder;勾选锁定维度时附带 *_lock 字段,操作后用返回的最新详情刷新。
|
||||||
* 3. 后端没有「修改表头」接口,保存成功或编辑进入后表头变为只读,仅可扫码维护细码。
|
* 3. 后端没有「修改表头」接口,保存成功或编辑进入后表头变为只读,并默认收起,仅可扫码维护细码。
|
||||||
*/
|
*/
|
||||||
import util from '@/common/util';
|
import util from '@/common/util';
|
||||||
import scanMixin from '@/common/scanMixin.js';
|
import scanMixin from '@/common/scanMixin.js';
|
||||||
import {
|
import {
|
||||||
AUDIT_STATUS_MAP,
|
AUDIT_STATUS_MAP,
|
||||||
BILL_TYPES,
|
BILL_TYPES,
|
||||||
|
BUSINESS_UNIT_TYPE_DYEING_FACTORY,
|
||||||
normalizeOrder,
|
normalizeOrder,
|
||||||
mapToSelectOptions,
|
mapToSelectOptions,
|
||||||
getFineCodeScanCode,
|
getFineCodeScanCode,
|
||||||
@@ -21,6 +22,7 @@ import {
|
|||||||
getFormStatusActionButtons,
|
getFormStatusActionButtons,
|
||||||
orderToFormFields,
|
orderToFormFields,
|
||||||
confirmOrderStatusAction,
|
confirmOrderStatusAction,
|
||||||
|
STATUS_ACTION_VOICE,
|
||||||
DRAFT_AUDIT_STATUS,
|
DRAFT_AUDIT_STATUS,
|
||||||
DRAFT_AUDIT_STATUS_NAME,
|
DRAFT_AUDIT_STATUS_NAME,
|
||||||
getEmptyScanDetail,
|
getEmptyScanDetail,
|
||||||
@@ -40,6 +42,8 @@ export default {
|
|||||||
orderId: 0,
|
orderId: 0,
|
||||||
form: this.getEmptyForm(),
|
form: this.getEmptyForm(),
|
||||||
headerSaved: false,
|
headerSaved: false,
|
||||||
|
// 新增未保存时展开表头;保存后及编辑进入时收起
|
||||||
|
headerExpanded: true,
|
||||||
selectShow: false,
|
selectShow: false,
|
||||||
selectList: [],
|
selectList: [],
|
||||||
selectType: '',
|
selectType: '',
|
||||||
@@ -60,6 +64,7 @@ export default {
|
|||||||
auditStatus: 0,
|
auditStatus: 0,
|
||||||
businessUnitOptions: [],
|
businessUnitOptions: [],
|
||||||
dropdownLoading: false,
|
dropdownLoading: false,
|
||||||
|
phoneScanPanelOpen: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -73,6 +78,14 @@ export default {
|
|||||||
headerEditable() {
|
headerEditable() {
|
||||||
return this.pageMode === 'add' && !this.headerSaved;
|
return this.pageMode === 'add' && !this.headerSaved;
|
||||||
},
|
},
|
||||||
|
/** 已保存或编辑页才提供收起/展开 */
|
||||||
|
showHeaderToggle() {
|
||||||
|
return this.pageMode === 'edit' || this.headerSaved;
|
||||||
|
},
|
||||||
|
/** 未保存只填表头;保存后才出现扫码区与汇总表 */
|
||||||
|
showScanSection() {
|
||||||
|
return this.headerSaved;
|
||||||
|
},
|
||||||
dateLabel() {
|
dateLabel() {
|
||||||
return '出货日期';
|
return '出货日期';
|
||||||
},
|
},
|
||||||
@@ -91,42 +104,49 @@ export default {
|
|||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
this.isPageActive = true;
|
this.isPageActive = true;
|
||||||
// #ifdef APP-PLUS
|
|
||||||
if (this.canScan && this.isEditable) {
|
if (this.canScan && this.isEditable) {
|
||||||
this.registerScanBroadcast((scanResult) => {
|
this.registerScanBroadcast((scanResult) => {
|
||||||
this.QRBarCode = scanResult.trim().replace(/[\r\n]/g, '');
|
this.QRBarCode = scanResult.trim().replace(/[\r\n]/g, '');
|
||||||
this.$nextTick(() => this.handleScan());
|
this.$nextTick(() => this.handleScan());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
onHide() {
|
onHide() {
|
||||||
this.isPageActive = false;
|
this.isPageActive = false;
|
||||||
// #ifdef APP-PLUS
|
this.closePhoneScanPanel();
|
||||||
this.unregisterScanBroadcast();
|
this.unregisterScanBroadcast();
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
onUnload() {
|
onUnload() {
|
||||||
this.isPageActive = false;
|
this.isPageActive = false;
|
||||||
// #ifdef APP-PLUS
|
this.closePhoneScanPanel();
|
||||||
this.unregisterScanBroadcast();
|
this.unregisterScanBroadcast();
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
handlePhoneScan() {
|
||||||
|
if (!this.canScan) {
|
||||||
|
this.showError('请先提交保存后再扫码');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.phoneScanPanelOpen = !this.phoneScanPanelOpen;
|
||||||
|
},
|
||||||
|
closePhoneScanPanel() {
|
||||||
|
this.phoneScanPanelOpen = false;
|
||||||
|
},
|
||||||
|
onPlusBarcodeSuccess(scanResult) {
|
||||||
|
this.QRBarCode = String(scanResult || '').trim().replace(/[\r\n]/g, '');
|
||||||
|
return this.handleScan();
|
||||||
|
},
|
||||||
registerOrderScanBroadcast() {
|
registerOrderScanBroadcast() {
|
||||||
// #ifdef APP-PLUS
|
|
||||||
this.registerScanBroadcast((scanResult) => {
|
this.registerScanBroadcast((scanResult) => {
|
||||||
this.QRBarCode = scanResult.trim().replace(/[\r\n]/g, '');
|
this.QRBarCode = scanResult.trim().replace(/[\r\n]/g, '');
|
||||||
this.$nextTick(() => this.handleScan());
|
this.$nextTick(() => this.handleScan());
|
||||||
});
|
});
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
syncCanScanFromStatus(status) {
|
syncCanScanFromStatus(status) {
|
||||||
const nextCanScan = this.isEditable && canScanAtStatus(status);
|
const nextCanScan = this.isEditable && canScanAtStatus(status);
|
||||||
if (this.canScan && !nextCanScan) {
|
if (this.canScan && !nextCanScan) {
|
||||||
// #ifdef APP-PLUS
|
|
||||||
this.unregisterScanBroadcast();
|
this.unregisterScanBroadcast();
|
||||||
// #endif
|
this.closePhoneScanPanel();
|
||||||
}
|
}
|
||||||
this.canScan = nextCanScan;
|
this.canScan = nextCanScan;
|
||||||
},
|
},
|
||||||
@@ -142,7 +162,7 @@ export default {
|
|||||||
},
|
},
|
||||||
ensureBusinessUnitOptions() {
|
ensureBusinessUnitOptions() {
|
||||||
if (this.businessUnitOptions.length) return Promise.resolve(this.businessUnitOptions);
|
if (this.businessUnitOptions.length) return Promise.resolve(this.businessUnitOptions);
|
||||||
return this.$u.api.businessUnit.list({})
|
return this.$u.api.businessUnit.list({ unit_type_id: BUSINESS_UNIT_TYPE_DYEING_FACTORY })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.businessUnitOptions = mapToSelectOptions(res);
|
this.businessUnitOptions = mapToSelectOptions(res);
|
||||||
return this.businessUnitOptions;
|
return this.businessUnitOptions;
|
||||||
@@ -156,8 +176,13 @@ export default {
|
|||||||
delivery_time: this.$u.timeFormat(new Date(), 'yyyy-mm-dd'),
|
delivery_time: this.$u.timeFormat(new Date(), 'yyyy-mm-dd'),
|
||||||
remark: '',
|
remark: '',
|
||||||
item_data: [],
|
item_data: [],
|
||||||
|
summary_rows: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
toggleHeader() {
|
||||||
|
if (!this.showHeaderToggle) return;
|
||||||
|
this.headerExpanded = !this.headerExpanded;
|
||||||
|
},
|
||||||
loadOrder(id, options = {}) {
|
loadOrder(id, options = {}) {
|
||||||
const { rejectIfLocked = false } = options;
|
const { rejectIfLocked = false } = options;
|
||||||
return this.$u.api.gfmOtherDeliveryOrder.detail({ id })
|
return this.$u.api.gfmOtherDeliveryOrder.detail({ id })
|
||||||
@@ -203,12 +228,10 @@ export default {
|
|||||||
.catch((e) => this.showError(e.message || '加载单位列表失败'));
|
.catch((e) => this.showError(e.message || '加载单位列表失败'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
selectConfirmFun(e) {
|
selectConfirmFun(item) {
|
||||||
const item = e[0];
|
if (!item || this.selectType !== '接收单位') return;
|
||||||
if (this.selectType === '接收单位') {
|
|
||||||
this.form.business_unit_id = item.value;
|
this.form.business_unit_id = item.value;
|
||||||
this.form.business_unit_name = item.label;
|
this.form.business_unit_name = item.label;
|
||||||
}
|
|
||||||
},
|
},
|
||||||
bindDateChange(e) {
|
bindDateChange(e) {
|
||||||
this.form.delivery_time = e.detail.value;
|
this.form.delivery_time = e.detail.value;
|
||||||
@@ -249,8 +272,9 @@ export default {
|
|||||||
const order = normalizeOrder(detail);
|
const order = normalizeOrder(detail);
|
||||||
this.applyOrder(order);
|
this.applyOrder(order);
|
||||||
this.headerSaved = true;
|
this.headerSaved = true;
|
||||||
|
this.headerExpanded = false;
|
||||||
this.syncCanScanFromStatus(order.audit_status);
|
this.syncCanScanFromStatus(order.audit_status);
|
||||||
this.showSuccess('保存成功,可以扫码');
|
this.showSuccess('保存成功,可以扫码', '提交成功');
|
||||||
this.registerOrderScanBroadcast();
|
this.registerOrderScanBroadcast();
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
@@ -305,14 +329,14 @@ export default {
|
|||||||
if (!this.canScan || !this.orderId) {
|
if (!this.canScan || !this.orderId) {
|
||||||
this.showError('请先提交保存后再扫码');
|
this.showError('请先提交保存后再扫码');
|
||||||
this.QRBarCode = '';
|
this.QRBarCode = '';
|
||||||
return;
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
if (!code) {
|
if (!code) {
|
||||||
this.QRBarCode = '';
|
this.QRBarCode = '';
|
||||||
return;
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
const scanType = this.BarCodeDelStatus ? 2 : 1;
|
const scanType = this.BarCodeDelStatus ? 2 : 1;
|
||||||
this.doScanUpdate(code, scanType);
|
return this.doScanUpdate(code, scanType);
|
||||||
},
|
},
|
||||||
BarCodeDelChange(e) {
|
BarCodeDelChange(e) {
|
||||||
this.BarCodeDelStatus = (e.detail.value || []).length > 0;
|
this.BarCodeDelStatus = (e.detail.value || []).length > 0;
|
||||||
@@ -332,16 +356,18 @@ export default {
|
|||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
const order = normalizeOrder(detail);
|
const order = normalizeOrder(detail);
|
||||||
this.form.item_data = order.item_data;
|
this.form.item_data = order.item_data;
|
||||||
|
this.form.summary_rows = order.summary_rows || [];
|
||||||
this.auditStatus = order.audit_status;
|
this.auditStatus = order.audit_status;
|
||||||
this.applyScanDetail(scanCode, order, scanType);
|
this.applyScanDetail(scanCode, order, scanType);
|
||||||
if (refreshFineCodes) {
|
if (refreshFineCodes) {
|
||||||
const row = order.item_data.find((i) => (i.group_key || String(i.id)) === this.currentGroupKey);
|
const rows = order.summary_rows || [];
|
||||||
this.currentFineCodes = row ? [...row.fine_codes] : [];
|
const row = rows.find((i) => i.group_key === this.currentGroupKey);
|
||||||
|
this.currentFineCodes = row ? [...(row.fine_codes || [])] : [];
|
||||||
}
|
}
|
||||||
this.BillDataMessage = scanType === 2 ? '删除成功' : '扫描成功';
|
this.BillDataMessage = scanType === 2 ? '删除成功' : '扫码出仓成功';
|
||||||
this.QRBarCode = '';
|
this.QRBarCode = '';
|
||||||
if (scanType === 2) this.showSuccess('删除成功');
|
if (scanType === 2) this.showSuccess('删除成功', '删除成功');
|
||||||
else util.playSuccessAudio();
|
else util.playSpeak('扫码出仓成功');
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
@@ -358,6 +384,15 @@ export default {
|
|||||||
this.currentFineCodes = [...(row.fine_codes || [])];
|
this.currentFineCodes = [...(row.fine_codes || [])];
|
||||||
this.fineCodeShow = true;
|
this.fineCodeShow = true;
|
||||||
},
|
},
|
||||||
|
onSummaryCellClick(event) {
|
||||||
|
const row = event && event.lineData;
|
||||||
|
if (!row) return;
|
||||||
|
if (event.key === 'grey_fabric_code' || event.key === 'grey_fabric_name') {
|
||||||
|
this.openFabricInfo(row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.openFineCode(row);
|
||||||
|
},
|
||||||
onDeleteFineCode(fineCode) {
|
onDeleteFineCode(fineCode) {
|
||||||
if (this.isReadonly || !this.canScan) return;
|
if (this.isReadonly || !this.canScan) return;
|
||||||
const scanCode = getFineCodeScanCode(fineCode);
|
const scanCode = getFineCodeScanCode(fineCode);
|
||||||
@@ -385,7 +420,8 @@ export default {
|
|||||||
if (!order) return;
|
if (!order) return;
|
||||||
this.applyOrder(order);
|
this.applyOrder(order);
|
||||||
this.syncCanScanFromStatus(order.audit_status);
|
this.syncCanScanFromStatus(order.audit_status);
|
||||||
this.showSuccess('操作成功');
|
const voice = STATUS_ACTION_VOICE[action] || '';
|
||||||
|
this.showSuccess(voice || '操作成功', voice);
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -393,8 +429,9 @@ export default {
|
|||||||
util.playErrorAudio();
|
util.playErrorAudio();
|
||||||
uni.showModal({ title: '提示', content: message, showCancel: false });
|
uni.showModal({ title: '提示', content: message, showCancel: false });
|
||||||
},
|
},
|
||||||
showSuccess(message) {
|
showSuccess(message, speakText) {
|
||||||
util.playSuccessAudio();
|
if (speakText) util.playSpeak(speakText);
|
||||||
|
else util.playSuccessAudio();
|
||||||
uni.showToast({ title: message, icon: 'success' });
|
uni.showToast({ title: message, icon: 'success' });
|
||||||
},
|
},
|
||||||
getBillTypeName() {
|
getBillTypeName() {
|
||||||
|
|||||||
@@ -6,8 +6,66 @@
|
|||||||
.fabric-out-mt32 {
|
.fabric-out-mt32 {
|
||||||
margin-top: 32rpx;
|
margin-top: 32rpx;
|
||||||
}
|
}
|
||||||
|
.fabric-out-headerBar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
min-height: 100rpx;
|
||||||
|
padding: 16rpx 26rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-bottom: 1rpx solid #f5f5f5;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.fabric-out-headerBarMain {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.fabric-out-headerBarTitle {
|
||||||
|
font-size: 40rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.fabric-out-headerBarSub {
|
||||||
|
margin-left: 16rpx;
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #666;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.fabric-out-headerBarAction {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #2979ff;
|
||||||
|
}
|
||||||
|
.fabric-out-headerBarIcon {
|
||||||
|
margin-left: 8rpx;
|
||||||
|
}
|
||||||
|
.fabric-out-page .flex-white-plr26,
|
||||||
|
.fabric-out-page .flex-white-plr26-column,
|
||||||
|
.fabric-out-page .flex-white-plr26 text,
|
||||||
|
.fabric-out-page .flex-white-plr26 view,
|
||||||
|
.fabric-out-page .u-input__input,
|
||||||
|
.fabric-out-page .uni-input-input,
|
||||||
|
.fabric-out-page .uni-textarea-textarea {
|
||||||
|
font-size: 40rpx;
|
||||||
|
}
|
||||||
|
.fabric-out-page .redXingh {
|
||||||
|
font-size: 40rpx;
|
||||||
|
}
|
||||||
|
.fabric-out-page .u-btn {
|
||||||
|
font-size: 36rpx !important;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
}
|
||||||
.fabric-out-sectionTitle {
|
.fabric-out-sectionTitle {
|
||||||
font-size: 30rpx;
|
font-size: 42rpx;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding: 24rpx 26rpx 12rpx;
|
padding: 24rpx 26rpx 12rpx;
|
||||||
border-left: 6rpx solid #007AFF;
|
border-left: 6rpx solid #007AFF;
|
||||||
@@ -16,7 +74,7 @@
|
|||||||
.fabric-out-scanTip {
|
.fabric-out-scanTip {
|
||||||
padding: 20rpx 26rpx;
|
padding: 20rpx 26rpx;
|
||||||
color: #fa8c16;
|
color: #fa8c16;
|
||||||
font-size: 26rpx;
|
font-size: 36rpx;
|
||||||
background: #fff7e6;
|
background: #fff7e6;
|
||||||
margin: 16rpx 26rpx;
|
margin: 16rpx 26rpx;
|
||||||
border-radius: 8rpx;
|
border-radius: 8rpx;
|
||||||
@@ -24,7 +82,7 @@
|
|||||||
.fabric-out-msgTip {
|
.fabric-out-msgTip {
|
||||||
padding: 12rpx 26rpx;
|
padding: 12rpx 26rpx;
|
||||||
color: #52c41a;
|
color: #52c41a;
|
||||||
font-size: 26rpx;
|
font-size: 36rpx;
|
||||||
}
|
}
|
||||||
.fabric-out-detailList {
|
.fabric-out-detailList {
|
||||||
padding: 0 26rpx;
|
padding: 0 26rpx;
|
||||||
@@ -39,7 +97,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 28rpx;
|
font-size: 38rpx;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-bottom: 12rpx;
|
padding-bottom: 12rpx;
|
||||||
border-bottom: 1rpx solid #f0f0f0;
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
@@ -49,7 +107,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 20rpx;
|
gap: 20rpx;
|
||||||
padding-top: 12rpx;
|
padding-top: 12rpx;
|
||||||
font-size: 26rpx;
|
font-size: 36rpx;
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
.fabric-out-scanRow {
|
.fabric-out-scanRow {
|
||||||
@@ -66,7 +124,7 @@
|
|||||||
.fabric-out-delCheck {
|
.fabric-out-delCheck {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 26rpx;
|
font-size: 36rpx;
|
||||||
color: #666;
|
color: #666;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
@@ -82,7 +140,7 @@
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
padding: 16rpx 20rpx;
|
padding: 16rpx 20rpx;
|
||||||
border-bottom: 1rpx solid #f0f0f0;
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
font-size: 26rpx;
|
font-size: 36rpx;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
.fabric-out-scanDetailRow--2col {
|
.fabric-out-scanDetailRow--2col {
|
||||||
@@ -108,34 +166,6 @@
|
|||||||
color: #333;
|
color: #333;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
.fabric-out-scanDetailTableScroll {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.fabric-out-scanDetailTable {
|
|
||||||
min-width: 100%;
|
|
||||||
}
|
|
||||||
.fabric-out-scanDetailTableRow {
|
|
||||||
display: flex;
|
|
||||||
border-bottom: 1rpx solid #f0f0f0;
|
|
||||||
}
|
|
||||||
.fabric-out-scanDetailTableHead {
|
|
||||||
background: #f5f5f5;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.fabric-out-scanDetailTableCell {
|
|
||||||
padding: 14rpx 8rpx;
|
|
||||||
font-size: 24rpx;
|
|
||||||
color: #333;
|
|
||||||
text-align: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
.fabric-out-scanDetailEmpty {
|
|
||||||
padding: 24rpx;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 26rpx;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
.fabric-out-submitView {
|
.fabric-out-submitView {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 16rpx 26rpx 26rpx;
|
padding: 16rpx 26rpx 26rpx;
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ import {
|
|||||||
getViewStatusActionButtons,
|
getViewStatusActionButtons,
|
||||||
confirmOrderStatusAction,
|
confirmOrderStatusAction,
|
||||||
formatDisplayTime,
|
formatDisplayTime,
|
||||||
|
STATUS_ACTION_VOICE,
|
||||||
} from '@/common/storeFabricBusinessOut';
|
} from '@/common/storeFabricBusinessOut';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -123,8 +124,10 @@ export default {
|
|||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
const order = normalizeOrder(res);
|
const order = normalizeOrder(res);
|
||||||
if (order) this.order = order;
|
if (order) this.order = order;
|
||||||
util.playSuccessAudio();
|
const voice = STATUS_ACTION_VOICE[action] || '';
|
||||||
uni.showToast({ title: '操作成功', icon: 'success' });
|
if (voice) util.playSpeak(voice);
|
||||||
|
else util.playSuccessAudio();
|
||||||
|
uni.showToast({ title: voice || '操作成功', icon: 'success' });
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,691 @@
|
|||||||
|
<template>
|
||||||
|
<view class="manual-in">
|
||||||
|
<common-navbar title="手动进仓">
|
||||||
|
<template #right>
|
||||||
|
<view class="manual-in__setting" @click="navToSetting">
|
||||||
|
<u-icon name="setting" color="#333333" size="34"></u-icon>
|
||||||
|
<text>设置</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</common-navbar>
|
||||||
|
|
||||||
|
<PlusBarcodePanel
|
||||||
|
ref="plusBarcodePanel"
|
||||||
|
:visible.sync="phoneScanPanelOpen"
|
||||||
|
hint-text="先扫描布票,再填写信息后确认进仓"
|
||||||
|
:scan-time-space="1200"
|
||||||
|
@success="onPlusBarcodeSuccess"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<view class="manual-in__scan">
|
||||||
|
<input
|
||||||
|
class="manual-in__scan-input"
|
||||||
|
type="text"
|
||||||
|
confirm-type="done"
|
||||||
|
:confirm-hold="true"
|
||||||
|
:focus="scanFocus"
|
||||||
|
v-model="scanCode"
|
||||||
|
placeholder="请先扫描布票编码"
|
||||||
|
placeholder-class="manual-in__placeholder"
|
||||||
|
@confirm="onScanConfirm"
|
||||||
|
/>
|
||||||
|
<view
|
||||||
|
v-if="scanCode"
|
||||||
|
class="manual-in__scan-icon"
|
||||||
|
@click.stop="clearScanCode"
|
||||||
|
>
|
||||||
|
<u-icon name="close-circle-fill" size="44" color="#bfbfbf" />
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
v-if="phoneScanPanelOpen"
|
||||||
|
class="manual-in__scan-close"
|
||||||
|
@click.stop="handlePhoneScan"
|
||||||
|
>
|
||||||
|
关闭扫码
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
v-else
|
||||||
|
class="manual-in__scan-icon"
|
||||||
|
@click.stop="handlePhoneScan"
|
||||||
|
>
|
||||||
|
<u-icon name="scan" size="44" color="#595959" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="manual-in__panel">
|
||||||
|
<view class="manual-in__row">
|
||||||
|
<text class="manual-in__label">布票编码</text>
|
||||||
|
<text class="manual-in__value">{{ detail.fabric_piece_code || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="manual-in__row">
|
||||||
|
<text class="manual-in__label">生产单号</text>
|
||||||
|
<text class="manual-in__value">{{ detail.production_order_no || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="manual-in__row">
|
||||||
|
<text class="manual-in__label">机台</text>
|
||||||
|
<text class="manual-in__value">{{ detail.machine_number || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="manual-in__row">
|
||||||
|
<text class="manual-in__label">布种名称</text>
|
||||||
|
<text class="manual-in__value">{{ detail.grey_fabric_name || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="manual-in__row">
|
||||||
|
<text class="manual-in__label">坯布编号</text>
|
||||||
|
<text class="manual-in__value">{{ detail.grey_fabric_code || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="manual-in__row">
|
||||||
|
<text class="manual-in__label">卷号</text>
|
||||||
|
<text class="manual-in__value">{{ detail.volume_number != null && detail.volume_number !== '' ? detail.volume_number : '-' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="manual-in__panel manual-in__panel--form">
|
||||||
|
<view class="manual-in__row manual-in__row--input" @click="openInspectorPicker">
|
||||||
|
<text class="manual-in__label">查布工</text>
|
||||||
|
<view class="manual-in__right">
|
||||||
|
<text :class="detail.inspector_name ? 'manual-in__field-text' : 'manual-in__placeholder'">
|
||||||
|
{{ detail.inspector_name || '请选择查布工' }}
|
||||||
|
</text>
|
||||||
|
<text class="manual-in__action" @click.stop="clearInspector">取消</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="manual-in__row manual-in__row--input">
|
||||||
|
<text class="manual-in__label">重量</text>
|
||||||
|
<view class="manual-in__right">
|
||||||
|
<input
|
||||||
|
class="manual-in__field"
|
||||||
|
type="digit"
|
||||||
|
v-model="weightKg"
|
||||||
|
placeholder="请输入"
|
||||||
|
placeholder-class="manual-in__placeholder"
|
||||||
|
/>
|
||||||
|
<text class="manual-in__unit">KG</text>
|
||||||
|
<text class="manual-in__action" @click="clearWeight">取消</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="manual-in__row manual-in__row--input" @click="openLevelPicker">
|
||||||
|
<text class="manual-in__label">等级</text>
|
||||||
|
<view class="manual-in__right">
|
||||||
|
<text :class="levelDisplayName ? 'manual-in__field-text' : 'manual-in__placeholder'">
|
||||||
|
{{ levelDisplayName || '请选择等级' }}
|
||||||
|
</text>
|
||||||
|
<text class="manual-in__action" @click.stop="clearLevel">取消</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="manual-in__row manual-in__row--input">
|
||||||
|
<text class="manual-in__label">存放仓位</text>
|
||||||
|
<view class="manual-in__right">
|
||||||
|
<input
|
||||||
|
class="manual-in__field"
|
||||||
|
type="text"
|
||||||
|
v-model="warehouseBinName"
|
||||||
|
placeholder="/"
|
||||||
|
placeholder-class="manual-in__placeholder"
|
||||||
|
/>
|
||||||
|
<text class="manual-in__action" @click="editWarehouseBin">修改</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="manual-in__footer">
|
||||||
|
<u-button
|
||||||
|
type="primary"
|
||||||
|
:loading="submitting"
|
||||||
|
:disabled="submitting || loadingDetail"
|
||||||
|
@click="submitInWarehouse"
|
||||||
|
>
|
||||||
|
确认进仓
|
||||||
|
</u-button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<SearchSelectPopup
|
||||||
|
:show.sync="levelPickerShow"
|
||||||
|
title="选择等级"
|
||||||
|
placeholder="请输入等级名称"
|
||||||
|
:list="levelOptions"
|
||||||
|
multiple
|
||||||
|
:selected="detail.grey_fabric_level_id"
|
||||||
|
@confirm="onLevelConfirm"
|
||||||
|
/>
|
||||||
|
<SearchSelectPopup
|
||||||
|
:show.sync="inspectorPickerShow"
|
||||||
|
title="选择查布工"
|
||||||
|
placeholder="请输入查布工姓名"
|
||||||
|
:list="inspectorOptions"
|
||||||
|
@confirm="onInspectorConfirm"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CommonNavbar from '@/components/common-navbar/index';
|
||||||
|
import SearchSelectPopup from '@/components/storefabric/SearchSelectPopup.vue';
|
||||||
|
import PlusBarcodePanel from '@/components/common/PlusBarcodePanel.vue';
|
||||||
|
import scanMixin from '@/common/scanMixin.js';
|
||||||
|
import util from '@/common/util.js';
|
||||||
|
import { formatWeightKg } from '@/common/storeFabricBusinessOut.js';
|
||||||
|
|
||||||
|
// 坯布等级字典 id(与后台字典配置一致)
|
||||||
|
const DICTIONARY_TYPE_GREY_FABRIC_LEVEL = 10025;
|
||||||
|
// 查布工岗位 duty(验布/查布相关)
|
||||||
|
const INSPECTOR_DUTY = '20004,20011';
|
||||||
|
const WEIGHT_SCALE = 10000;
|
||||||
|
|
||||||
|
function emptyDetail() {
|
||||||
|
return {
|
||||||
|
fabric_piece_code: '',
|
||||||
|
production_order_no: '',
|
||||||
|
machine_number: '',
|
||||||
|
grey_fabric_name: '',
|
||||||
|
grey_fabric_code: '',
|
||||||
|
inspection_weight: null,
|
||||||
|
grey_fabric_level_id: [],
|
||||||
|
grey_fabric_level_name: '',
|
||||||
|
inspector_id: null,
|
||||||
|
inspector_name: '',
|
||||||
|
volume_number: '',
|
||||||
|
grey_fabric_id: '',
|
||||||
|
id: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function toWeightInt(kg) {
|
||||||
|
const raw = String(kg == null ? '' : kg).trim();
|
||||||
|
if (!raw) return null;
|
||||||
|
const n = Number(raw);
|
||||||
|
if (!Number.isFinite(n) || n <= 0) return null;
|
||||||
|
return Math.round(n * WEIGHT_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDisplayWeightKg(value) {
|
||||||
|
if (value == null || value === '') return '';
|
||||||
|
const n = Number(value);
|
||||||
|
if (!Number.isFinite(n) || n <= 0) return '';
|
||||||
|
return String(formatWeightKg(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeLevelIds(value) {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map((item) => Number(item)).filter((item) => Number.isFinite(item));
|
||||||
|
}
|
||||||
|
if (value == null || value === '') return [];
|
||||||
|
const n = Number(value);
|
||||||
|
return Number.isFinite(n) ? [n] : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { CommonNavbar, SearchSelectPopup, PlusBarcodePanel },
|
||||||
|
mixins: [scanMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
scanCode: '',
|
||||||
|
scanFocus: true,
|
||||||
|
submitting: false,
|
||||||
|
loadingDetail: false,
|
||||||
|
warehouseBinId: null,
|
||||||
|
warehouseBinName: '',
|
||||||
|
weightKg: '',
|
||||||
|
detail: emptyDetail(),
|
||||||
|
levelPickerShow: false,
|
||||||
|
levelOptions: [],
|
||||||
|
levelOptionsLoaded: false,
|
||||||
|
inspectorPickerShow: false,
|
||||||
|
inspectorOptions: [],
|
||||||
|
inspectorOptionsLoaded: false,
|
||||||
|
phoneScanPanelOpen: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
levelDisplayName() {
|
||||||
|
if (this.detail.grey_fabric_level_name) return this.detail.grey_fabric_level_name;
|
||||||
|
const ids = normalizeLevelIds(this.detail.grey_fabric_level_id);
|
||||||
|
if (!ids.length) return '';
|
||||||
|
const nameMap = {};
|
||||||
|
this.levelOptions.forEach((item) => {
|
||||||
|
nameMap[String(item.value)] = item.label;
|
||||||
|
});
|
||||||
|
return ids.map((id) => nameMap[String(id)]).filter(Boolean).join('、');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.registerScanBroadcast(this.handleScanCode);
|
||||||
|
this.loadLevelOptions();
|
||||||
|
this.loadInspectorOptions();
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
this.isPageActive = true;
|
||||||
|
this.refocusScanInput(50);
|
||||||
|
},
|
||||||
|
onHide() {
|
||||||
|
this.isPageActive = false;
|
||||||
|
this.closePhoneScanPanel();
|
||||||
|
},
|
||||||
|
onUnload() {
|
||||||
|
this.isPageActive = false;
|
||||||
|
this.closePhoneScanPanel();
|
||||||
|
clearTimeout(this._scanFocusTimer);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
refocusScanInput(delay = 120) {
|
||||||
|
clearTimeout(this._scanFocusTimer);
|
||||||
|
this.scanFocus = false;
|
||||||
|
this._scanFocusTimer = setTimeout(() => {
|
||||||
|
this.scanFocus = true;
|
||||||
|
}, delay);
|
||||||
|
},
|
||||||
|
closePhoneScanPanel() {
|
||||||
|
this.phoneScanPanelOpen = false;
|
||||||
|
},
|
||||||
|
onPlusBarcodeSuccess(scanResult) {
|
||||||
|
return this.handleScanCode(scanResult);
|
||||||
|
},
|
||||||
|
navToSetting() {
|
||||||
|
uni.navigateTo({ url: '/pages/sys/user/scan-settings' });
|
||||||
|
},
|
||||||
|
clearWeight() {
|
||||||
|
this.weightKg = '';
|
||||||
|
this.detail.inspection_weight = null;
|
||||||
|
},
|
||||||
|
clearLevel() {
|
||||||
|
this.detail.grey_fabric_level_id = [];
|
||||||
|
this.detail.grey_fabric_level_name = '';
|
||||||
|
},
|
||||||
|
clearInspector() {
|
||||||
|
this.detail.inspector_id = null;
|
||||||
|
this.detail.inspector_name = '';
|
||||||
|
},
|
||||||
|
editWarehouseBin() {
|
||||||
|
uni.showModal({
|
||||||
|
title: '存放仓位',
|
||||||
|
editable: true,
|
||||||
|
placeholderText: '请输入仓位名称',
|
||||||
|
content: this.warehouseBinName || '',
|
||||||
|
success: (res) => {
|
||||||
|
if (!res.confirm) return;
|
||||||
|
this.warehouseBinName = (res.content || '').trim();
|
||||||
|
this.warehouseBinId = null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async loadLevelOptions() {
|
||||||
|
try {
|
||||||
|
const res = await this.$u.api.dictionary.getDetailEnumList({
|
||||||
|
dictionary_id: DICTIONARY_TYPE_GREY_FABRIC_LEVEL,
|
||||||
|
status: 1,
|
||||||
|
size: 200,
|
||||||
|
});
|
||||||
|
const list = Array.isArray(res) ? res : (Array.isArray(res && res.list) ? res.list : []);
|
||||||
|
this.levelOptions = list
|
||||||
|
.map((item) => ({
|
||||||
|
value: item.id,
|
||||||
|
label: item.name || item.code || String(item.id),
|
||||||
|
}))
|
||||||
|
.filter((item) => item.value != null);
|
||||||
|
this.levelOptionsLoaded = true;
|
||||||
|
} catch (error) {
|
||||||
|
console.log('加载坯布等级枚举失败', error);
|
||||||
|
this.levelOptions = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async openLevelPicker() {
|
||||||
|
if (!this.levelOptionsLoaded || !this.levelOptions.length) {
|
||||||
|
await this.loadLevelOptions();
|
||||||
|
}
|
||||||
|
if (!this.levelOptions.length) {
|
||||||
|
this.$u.toast('暂无等级可选,请检查等级字典配置');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.levelPickerShow = true;
|
||||||
|
},
|
||||||
|
onLevelConfirm(items) {
|
||||||
|
const list = Array.isArray(items) ? items : (items ? [items] : []);
|
||||||
|
this.detail.grey_fabric_level_id = list
|
||||||
|
.map((item) => Number(item.value))
|
||||||
|
.filter((item) => Number.isFinite(item));
|
||||||
|
this.detail.grey_fabric_level_name = list
|
||||||
|
.map((item) => item.label)
|
||||||
|
.filter(Boolean)
|
||||||
|
.join('、');
|
||||||
|
},
|
||||||
|
async loadInspectorOptions() {
|
||||||
|
try {
|
||||||
|
const res = await this.$u.api.employee.listEnum({
|
||||||
|
size: 50,
|
||||||
|
duty: INSPECTOR_DUTY,
|
||||||
|
});
|
||||||
|
const list = Array.isArray(res) ? res : (Array.isArray(res && res.list) ? res.list : []);
|
||||||
|
this.inspectorOptions = list
|
||||||
|
.map((item) => ({
|
||||||
|
value: item.id,
|
||||||
|
label: item.name || item.employee_name || item.real_name || item.code || String(item.id),
|
||||||
|
}))
|
||||||
|
.filter((item) => item.value != null);
|
||||||
|
this.inspectorOptionsLoaded = true;
|
||||||
|
} catch (error) {
|
||||||
|
console.log('加载查布工枚举失败', error);
|
||||||
|
this.inspectorOptions = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async openInspectorPicker() {
|
||||||
|
if (!this.inspectorOptionsLoaded || !this.inspectorOptions.length) {
|
||||||
|
await this.loadInspectorOptions();
|
||||||
|
}
|
||||||
|
if (!this.inspectorOptions.length) {
|
||||||
|
this.$u.toast('暂无查布工可选');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.inspectorPickerShow = true;
|
||||||
|
},
|
||||||
|
onInspectorConfirm(item) {
|
||||||
|
if (!item) return;
|
||||||
|
this.detail.inspector_id = Number(item.value);
|
||||||
|
this.detail.inspector_name = item.label || '';
|
||||||
|
},
|
||||||
|
handleScanCode(scanResult) {
|
||||||
|
const code = String(scanResult || '').trim().replace(/[\r\n]/g, '');
|
||||||
|
if (!code) return;
|
||||||
|
this.fetchScanDetail(code);
|
||||||
|
},
|
||||||
|
clearScanCode() {
|
||||||
|
this.scanCode = '';
|
||||||
|
this.refocusScanInput();
|
||||||
|
},
|
||||||
|
handlePhoneScan() {
|
||||||
|
this.phoneScanPanelOpen = !this.phoneScanPanelOpen;
|
||||||
|
},
|
||||||
|
onScanConfirm() {
|
||||||
|
const code = String(this.scanCode || '').trim();
|
||||||
|
if (!code) {
|
||||||
|
this.$u.toast('请扫描或输入布票编码');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.fetchScanDetail(code);
|
||||||
|
},
|
||||||
|
validateBeforeSubmit() {
|
||||||
|
const fabricPieceCode = String(this.detail.fabric_piece_code || this.scanCode || '').trim();
|
||||||
|
if (!fabricPieceCode) {
|
||||||
|
return '请先扫描或输入布票编码';
|
||||||
|
}
|
||||||
|
const inspectorName = String(this.detail.inspector_name || '').trim();
|
||||||
|
if (!inspectorName && (this.detail.inspector_id == null || this.detail.inspector_id === '')) {
|
||||||
|
return '请选择查布工';
|
||||||
|
}
|
||||||
|
if (toWeightInt(this.weightKg) == null) {
|
||||||
|
return '请输入有效重量';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
async fetchScanDetail(code) {
|
||||||
|
if (this.loadingDetail || this.submitting) return;
|
||||||
|
this.loadingDetail = true;
|
||||||
|
this.scanCode = code;
|
||||||
|
try {
|
||||||
|
const res = await this.$u.api.productionScheduleOrder.getScanFineCodeDetail({
|
||||||
|
fabric_piece_code: code,
|
||||||
|
});
|
||||||
|
this.applyScanDetail(res, code);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('扫码获取细码失败', error);
|
||||||
|
const kept = this.keepFormFields();
|
||||||
|
this.detail = {
|
||||||
|
...emptyDetail(),
|
||||||
|
fabric_piece_code: code,
|
||||||
|
...kept,
|
||||||
|
};
|
||||||
|
this.scanCode = '';
|
||||||
|
this.refocusScanInput(200);
|
||||||
|
} finally {
|
||||||
|
this.loadingDetail = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
keepFormFields() {
|
||||||
|
return {
|
||||||
|
grey_fabric_level_id: normalizeLevelIds(this.detail.grey_fabric_level_id),
|
||||||
|
grey_fabric_level_name: this.detail.grey_fabric_level_name || '',
|
||||||
|
inspector_id: this.detail.inspector_id,
|
||||||
|
inspector_name: this.detail.inspector_name || '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
applyScanDetail(res, fallbackCode) {
|
||||||
|
const data = res || {};
|
||||||
|
const kept = this.keepFormFields();
|
||||||
|
this.detail = {
|
||||||
|
...emptyDetail(),
|
||||||
|
fabric_piece_code: data.fabric_piece_code || fallbackCode || '',
|
||||||
|
production_order_no: data.production_order_no || '',
|
||||||
|
machine_number: data.machine_number || '',
|
||||||
|
grey_fabric_name: data.grey_fabric_name || '',
|
||||||
|
grey_fabric_code: data.grey_fabric_code || '',
|
||||||
|
inspection_weight: toWeightInt(this.weightKg),
|
||||||
|
volume_number: data.volume_number != null && data.volume_number !== '' ? data.volume_number : null,
|
||||||
|
...kept,
|
||||||
|
};
|
||||||
|
this.scanCode = this.detail.fabric_piece_code;
|
||||||
|
},
|
||||||
|
async submitInWarehouse() {
|
||||||
|
const err = this.validateBeforeSubmit();
|
||||||
|
if (err) {
|
||||||
|
this.$u.toast(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const fabricPieceCode = String(this.detail.fabric_piece_code || this.scanCode || '').trim();
|
||||||
|
const actualWeight = toWeightInt(this.weightKg);
|
||||||
|
const levelIds = normalizeLevelIds(this.detail.grey_fabric_level_id);
|
||||||
|
if (this.submitting) return;
|
||||||
|
this.submitting = true;
|
||||||
|
try {
|
||||||
|
const payload = {
|
||||||
|
fabric_piece_code: fabricPieceCode,
|
||||||
|
actual_weight: actualWeight,
|
||||||
|
electronic_scale_weight: actualWeight,
|
||||||
|
};
|
||||||
|
if (levelIds.length) {
|
||||||
|
payload.grey_fabric_level_id = levelIds;
|
||||||
|
}
|
||||||
|
const inspectorName = String(this.detail.inspector_name || '').trim();
|
||||||
|
if (inspectorName) {
|
||||||
|
payload.inspector_name = inspectorName;
|
||||||
|
}
|
||||||
|
if (this.detail.inspector_id != null && this.detail.inspector_id !== '') {
|
||||||
|
payload.inspector_id = Number(this.detail.inspector_id);
|
||||||
|
}
|
||||||
|
const binName = String(this.warehouseBinName || '').trim();
|
||||||
|
if (binName && binName !== '/') {
|
||||||
|
payload.warehouse_bin_name = binName;
|
||||||
|
}
|
||||||
|
if (this.warehouseBinId != null && this.warehouseBinId !== '') {
|
||||||
|
payload.warehouse_bin_id = Number(this.warehouseBinId);
|
||||||
|
}
|
||||||
|
const res = await this.$u.api.productionScheduleOrder.scanInWarehouseFineCode(payload);
|
||||||
|
if (res) {
|
||||||
|
this.detail.volume_number = res.volume_number != null ? res.volume_number : this.detail.volume_number;
|
||||||
|
this.detail.grey_fabric_id = res.grey_fabric_id != null ? res.grey_fabric_id : this.detail.grey_fabric_id;
|
||||||
|
this.detail.id = res.id != null ? res.id : this.detail.id;
|
||||||
|
if (res.fabric_piece_code) {
|
||||||
|
this.detail.fabric_piece_code = res.fabric_piece_code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const volumeText = res && res.volume_number != null ? `,卷号 ${res.volume_number}` : '';
|
||||||
|
util.playSpeak('进仓成功');
|
||||||
|
this.$u.toast(`进仓成功${volumeText}`);
|
||||||
|
this.resetForNextScan();
|
||||||
|
} catch (error) {
|
||||||
|
console.log('手动进仓失败', error);
|
||||||
|
this.scanCode = '';
|
||||||
|
this.refocusScanInput(200);
|
||||||
|
} finally {
|
||||||
|
this.submitting = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resetForNextScan() {
|
||||||
|
const kept = this.keepFormFields();
|
||||||
|
this.scanCode = '';
|
||||||
|
this.detail = {
|
||||||
|
...emptyDetail(),
|
||||||
|
...kept,
|
||||||
|
};
|
||||||
|
// toast 会抢焦点,稍后再聚焦,方便连续扫码
|
||||||
|
this.refocusScanInput(600);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '@/common/pda-typography.scss';
|
||||||
|
|
||||||
|
.manual-in {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f5f6f8;
|
||||||
|
padding-bottom: calc(160rpx + env(safe-area-inset-bottom));
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__setting {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8rpx;
|
||||||
|
font-size: $pda-font-nav-sub;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__scan {
|
||||||
|
margin: 16rpx 0;
|
||||||
|
padding: 0 28rpx;
|
||||||
|
background: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__scan-input {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
height: $pda-scan-input-height;
|
||||||
|
font-size: $pda-font-body;
|
||||||
|
color: #202328;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__scan-icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
border: 1rpx solid #d9d9d9;
|
||||||
|
background: #f7f7f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__scan-close {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 72rpx;
|
||||||
|
padding: 0 16rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
border: 1rpx solid #2979ff;
|
||||||
|
background: #eaf2ff;
|
||||||
|
color: #2979ff;
|
||||||
|
font-size: $pda-font-action;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__placeholder {
|
||||||
|
color: #b0b4bb;
|
||||||
|
font-size: $pda-font-placeholder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__panel {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__panel--form {
|
||||||
|
margin-top: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__footer {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
padding: 20rpx 28rpx calc(20rpx + env(safe-area-inset-bottom));
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
|
box-sizing: border-box;
|
||||||
|
z-index: 20;
|
||||||
|
|
||||||
|
::v-deep .u-btn {
|
||||||
|
height: $pda-button-height !important;
|
||||||
|
font-size: $pda-font-button !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
min-height: $pda-row-min-height;
|
||||||
|
padding: 12rpx 28rpx;
|
||||||
|
border-bottom: 1rpx solid #eceff3;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__row--input {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__label {
|
||||||
|
width: $pda-label-width;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-size: $pda-font-body;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__value {
|
||||||
|
flex: 1;
|
||||||
|
font-size: $pda-font-body;
|
||||||
|
color: #202328;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__right {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__field {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
text-align: right;
|
||||||
|
font-size: $pda-font-body;
|
||||||
|
color: #202328;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__field-text {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
text-align: right;
|
||||||
|
font-size: $pda-font-body;
|
||||||
|
color: #202328;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__unit {
|
||||||
|
font-size: $pda-font-unit;
|
||||||
|
color: #666;
|
||||||
|
padding: 6rpx 14rpx;
|
||||||
|
border: 1rpx solid #d7dbe3;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manual-in__action {
|
||||||
|
font-size: $pda-font-action;
|
||||||
|
color: #2f78e6;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<WarehouseDataTable
|
<WarehouseDataTable
|
||||||
:headers="tableHeaders"
|
:headers="tableHeaders"
|
||||||
:contents="tableContents"
|
:contents="tableContents"
|
||||||
:height="tableHeight"
|
height="auto"
|
||||||
@row-click="goStockList"
|
@row-click="goStockList"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
@@ -56,7 +56,6 @@ import {
|
|||||||
GROUP_TABLE_COLUMNS,
|
GROUP_TABLE_COLUMNS,
|
||||||
buildGroupListQuery,
|
buildGroupListQuery,
|
||||||
buildStockListNavigateQuery,
|
buildStockListNavigateQuery,
|
||||||
calcTableHeight,
|
|
||||||
fetchAllWarehouseList,
|
fetchAllWarehouseList,
|
||||||
mapGroupTableRow,
|
mapGroupTableRow,
|
||||||
sumStockTotals,
|
sumStockTotals,
|
||||||
@@ -85,9 +84,6 @@ export default {
|
|||||||
totals() {
|
totals() {
|
||||||
return sumStockTotals(this.list);
|
return sumStockTotals(this.list);
|
||||||
},
|
},
|
||||||
tableHeight() {
|
|
||||||
return calcTableHeight(this.tableContents.length);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
uni.setNavigationBarTitle({ title: '坯布库存' });
|
uni.setNavigationBarTitle({ title: '坯布库存' });
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
<WarehouseDataTable
|
<WarehouseDataTable
|
||||||
:headers="tableHeaders"
|
:headers="tableHeaders"
|
||||||
:contents="tableContents"
|
:contents="tableContents"
|
||||||
:height="tableHeight"
|
height="auto"
|
||||||
@row-click="goDetail"
|
@row-click="goDetail"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
@@ -50,7 +50,6 @@ import {
|
|||||||
STOCK_TABLE_COLUMNS,
|
STOCK_TABLE_COLUMNS,
|
||||||
buildDetailNavigateQuery,
|
buildDetailNavigateQuery,
|
||||||
buildStockListQuery,
|
buildStockListQuery,
|
||||||
calcTableHeight,
|
|
||||||
fetchAllWarehouseList,
|
fetchAllWarehouseList,
|
||||||
mapStockTableRow,
|
mapStockTableRow,
|
||||||
parsePageQuery,
|
parsePageQuery,
|
||||||
@@ -84,9 +83,6 @@ export default {
|
|||||||
totals() {
|
totals() {
|
||||||
return sumStockTotals(this.list);
|
return sumStockTotals(this.list);
|
||||||
},
|
},
|
||||||
tableHeight() {
|
|
||||||
return calcTableHeight(this.tableContents.length, { maxPx: 9999 });
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
onLoad(options) {
|
onLoad(options) {
|
||||||
const parsed = parsePageQuery(options || {});
|
const parsed = parsePageQuery(options || {});
|
||||||
|
|||||||
@@ -31,6 +31,14 @@
|
|||||||
</view>
|
</view>
|
||||||
<u-form-item label-width="150" label="条码资料:">
|
<u-form-item label-width="150" label="条码资料:">
|
||||||
<input type="text" maxlength="-1" v-model="QRBarCode" style="width:200px;" @confirm="GoodsCheckBillDetailScan" />
|
<input type="text" maxlength="-1" v-model="QRBarCode" style="width:200px;" @confirm="GoodsCheckBillDetailScan" />
|
||||||
|
<u-icon
|
||||||
|
v-if="usePhoneScanFallback"
|
||||||
|
name="scan"
|
||||||
|
size="44"
|
||||||
|
color="#2979ff"
|
||||||
|
style="margin-left: 8px;"
|
||||||
|
@click="handlePhoneScan"
|
||||||
|
/>
|
||||||
<checkbox-group @change="BarCodeDelChange">
|
<checkbox-group @change="BarCodeDelChange">
|
||||||
<checkbox ref="checkBoxRef" :checked="BarCodeDelStatus">删除</checkbox>
|
<checkbox ref="checkBoxRef" :checked="BarCodeDelStatus">删除</checkbox>
|
||||||
</checkbox-group>
|
</checkbox-group>
|
||||||
@@ -193,28 +201,20 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
onUnload() {
|
onUnload() {
|
||||||
// #ifdef APP-PLUS
|
|
||||||
this.isPageActive = false;
|
this.isPageActive = false;
|
||||||
this.unregisterScanBroadcast();
|
this.unregisterScanBroadcast();
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onHide() {
|
onHide() {
|
||||||
// 页面隐藏时
|
|
||||||
this.isPageActive = false;
|
this.isPageActive = false;
|
||||||
// #ifdef APP-PLUS
|
|
||||||
this.unregisterScanBroadcast();
|
this.unregisterScanBroadcast();
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onShow() {
|
onShow() {
|
||||||
// 页面显示时
|
|
||||||
this.isPageActive = true;
|
this.isPageActive = true;
|
||||||
// #ifdef APP-PLUS
|
|
||||||
this.registerScanBroadcast((scanResult) => {
|
this.registerScanBroadcast((scanResult) => {
|
||||||
console.log("扫码结果:", scanResult);
|
console.log("扫码结果:", scanResult);
|
||||||
|
|
||||||
// 处理扫描结果,按照原有逻辑
|
|
||||||
if(!this.StoreName){
|
if(!this.StoreName){
|
||||||
this.showError('请先选择仓库');
|
this.showError('请先选择仓库');
|
||||||
return;
|
return;
|
||||||
@@ -240,9 +240,11 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
handlePhoneScan() {
|
||||||
|
this.openPhoneScan();
|
||||||
|
},
|
||||||
|
|
||||||
// 添加通用错误提示方法
|
// 添加通用错误提示方法
|
||||||
showError(message) {
|
showError(message) {
|
||||||
|
|||||||
@@ -12,6 +12,14 @@
|
|||||||
<u-form-item label-width="150" label="条码资料:">
|
<u-form-item label-width="150" label="条码资料:">
|
||||||
<input type="text" v-model="QRBarCode" maxlength="-1" style="width:200px;"
|
<input type="text" v-model="QRBarCode" maxlength="-1" style="width:200px;"
|
||||||
@confirm="GoodsCheckBillDetailScan" />
|
@confirm="GoodsCheckBillDetailScan" />
|
||||||
|
<u-icon
|
||||||
|
v-if="usePhoneScanFallback"
|
||||||
|
name="scan"
|
||||||
|
size="44"
|
||||||
|
color="#2979ff"
|
||||||
|
style="margin-left: 8px;"
|
||||||
|
@click="handlePhoneScan"
|
||||||
|
/>
|
||||||
<checkbox-group @change="BarCodeDelChange">
|
<checkbox-group @change="BarCodeDelChange">
|
||||||
<checkbox ref="checkBoxRef" :checked="BarCodeDelStatus">删除</checkbox>
|
<checkbox ref="checkBoxRef" :checked="BarCodeDelStatus">删除</checkbox>
|
||||||
</checkbox-group>
|
</checkbox-group>
|
||||||
@@ -147,36 +155,30 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onShow() {
|
onShow() {
|
||||||
// 设置页面激活状态
|
|
||||||
this.isPageActive = true;
|
this.isPageActive = true;
|
||||||
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
this.registerScanBroadcast((scanResult) => {
|
this.registerScanBroadcast((scanResult) => {
|
||||||
console.log("扫码结果:", scanResult);
|
console.log("扫码结果:", scanResult);
|
||||||
|
|
||||||
// 处理扫描结果
|
|
||||||
this.QRBarCode = scanResult;
|
this.QRBarCode = scanResult;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.GoodsCheckBillDetailScan();
|
this.GoodsCheckBillDetailScan();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onHide() {
|
onHide() {
|
||||||
this.isPageActive = false;
|
this.isPageActive = false;
|
||||||
// #ifdef APP-PLUS
|
|
||||||
this.unregisterScanBroadcast();
|
this.unregisterScanBroadcast();
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onUnload() {
|
onUnload() {
|
||||||
this.isPageActive = false;
|
this.isPageActive = false;
|
||||||
// #ifdef APP-PLUS
|
|
||||||
this.unregisterScanBroadcast();
|
this.unregisterScanBroadcast();
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
handlePhoneScan() {
|
||||||
|
this.openPhoneScan();
|
||||||
|
},
|
||||||
|
|
||||||
// 添加通用错误提示方法
|
// 添加通用错误提示方法
|
||||||
showError(message) {
|
showError(message) {
|
||||||
this.playError();
|
this.playError();
|
||||||
|
|||||||
@@ -26,6 +26,14 @@
|
|||||||
<u-form-item label-width="150" label="条码资料:" :class="{ 'input-highlight': shouldHighlightQR }">
|
<u-form-item label-width="150" label="条码资料:" :class="{ 'input-highlight': shouldHighlightQR }">
|
||||||
<input type="text" v-model="QRBarCode" maxlength="-1" style="width:150px;"
|
<input type="text" v-model="QRBarCode" maxlength="-1" style="width:150px;"
|
||||||
@confirm="GoodsStoreStationMoveScan" />
|
@confirm="GoodsStoreStationMoveScan" />
|
||||||
|
<u-icon
|
||||||
|
v-if="usePhoneScanFallback"
|
||||||
|
name="scan"
|
||||||
|
size="44"
|
||||||
|
color="#2979ff"
|
||||||
|
style="margin-left: 8px;"
|
||||||
|
@click="handlePhoneScan"
|
||||||
|
/>
|
||||||
</u-form-item>
|
</u-form-item>
|
||||||
<u-form-item>
|
<u-form-item>
|
||||||
<text class="title">{{ BillDataMessage }}</text>
|
<text class="title">{{ BillDataMessage }}</text>
|
||||||
@@ -150,10 +158,8 @@ export default {
|
|||||||
this.StoreNameID = getApp().globalData.StoreNameID;
|
this.StoreNameID = getApp().globalData.StoreNameID;
|
||||||
this.StoreName = getApp().globalData.StoreName;
|
this.StoreName = getApp().globalData.StoreName;
|
||||||
};
|
};
|
||||||
// #ifdef APP-PLUS
|
|
||||||
// 使用 scanMixin 的方法注册扫码广播,传入自定义回调
|
// 使用 scanMixin 的方法注册扫码广播,传入自定义回调
|
||||||
this.registerScanBroadcast(this.handleScanCode);
|
this.registerScanBroadcast(this.handleScanCode);
|
||||||
// #endif
|
|
||||||
},
|
},
|
||||||
// onUnload, onHide, onShow 已由 scanMixin 自动处理
|
// onUnload, onHide, onShow 已由 scanMixin 自动处理
|
||||||
/* onBackPress() {
|
/* onBackPress() {
|
||||||
@@ -174,6 +180,10 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
handlePhoneScan() {
|
||||||
|
this.openPhoneScan();
|
||||||
|
},
|
||||||
|
|
||||||
playSuccess() {
|
playSuccess() {
|
||||||
util.playSuccessAudio();
|
util.playSuccessAudio();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,17 +4,17 @@
|
|||||||
<view class="haotoplogo">
|
<view class="haotoplogo">
|
||||||
<image src="/static/haotop/image/logo/Start.jpg" mode="aspectFit" class="logoimg"></image>
|
<image src="/static/haotop/image/logo/Start.jpg" mode="aspectFit" class="logoimg"></image>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="app-name">{{ appName }}</view>
|
||||||
<!-- <div v-if="loginType === 'currentPhone'">-->
|
<!-- <div v-if="loginType === 'currentPhone'">-->
|
||||||
<!-- <u-tabs :list="list" :is-scroll="false" :current="current" @change="onClickItem"></u-tabs> -->
|
<!-- <u-tabs :list="list" :is-scroll="false" :current="current" @change="onClickItem"></u-tabs> -->
|
||||||
<!-- <view v-if="current === 0"> -->
|
<!-- <view v-if="current === 0"> -->
|
||||||
<view class="list">
|
<view class="list">
|
||||||
<template v-if="isDevelopment">
|
<view class="list-call env-call">
|
||||||
<view class="list-call">
|
<view class="iconfont icon-link" style="font-size: 28px;color:#5473e8;"></view>
|
||||||
<view class="iconfont icon-link" style="font-size: 22px;color:#5473e8;"></view>
|
|
||||||
<view style="width: 100%;">
|
<view style="width: 100%;">
|
||||||
<view class="server-selector" @click="showServerPicker">
|
<view class="server-selector" @click="showServerPicker">
|
||||||
<text>{{ getApiUrlLabel() }}</text>
|
<text>{{ getApiUrlLabel() }}</text>
|
||||||
<view class="iconfont icon-arrow-down" style="font-size: 16px;"></view>
|
<view class="iconfont icon-arrow-down"></view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
<input class="u-input" type="text" v-model="customApiUrl" maxlength="100" placeholder="请输入服务器地址"
|
<input class="u-input" type="text" v-model="customApiUrl" maxlength="100" placeholder="请输入服务器地址"
|
||||||
@blur="handleBlurInputUrl" />
|
@blur="handleBlurInputUrl" />
|
||||||
</view>
|
</view>
|
||||||
</template>
|
|
||||||
<view class="list-call">
|
<view class="list-call">
|
||||||
<view class="iconfont icon-avatar" style="font-size: 22px;color:#5473e8;"></view>
|
<view class="iconfont icon-avatar" style="font-size: 22px;color:#5473e8;"></view>
|
||||||
<input class="u-input" type="text" v-model="login.username" maxlength="32"
|
<input class="u-input" type="text" v-model="login.username" maxlength="32"
|
||||||
@@ -105,8 +104,9 @@
|
|||||||
<!-- </view>-->
|
<!-- </view>-->
|
||||||
<!-- </view>-->
|
<!-- </view>-->
|
||||||
<!-- </div>-->
|
<!-- </div>-->
|
||||||
<u-picker v-model="showApiUrlPicker" mode="selector" :range="apiUrlList" range-key="label"
|
<u-select class="login-env-picker" v-model="showApiUrlPicker" :list="apiUrlList" :default-value="apiUrlDefaultIndex"
|
||||||
@confirm="onApiUrlConfirm" @cancel="showApiUrlPicker = false"></u-picker>
|
title="选择服务器" :show-search="false" :item-height="88" :visible-item-count="5"
|
||||||
|
@confirm="onApiUrlConfirm" @cancel="showApiUrlPicker = false"></u-select>
|
||||||
<!-- 版本信息显示 -->
|
<!-- 版本信息显示 -->
|
||||||
<view class="version-info">
|
<view class="version-info">
|
||||||
<text class="version-text">版本: {{ appVersion }}</text>
|
<text class="version-text">版本: {{ appVersion }}</text>
|
||||||
@@ -118,13 +118,23 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
||||||
*/
|
*/
|
||||||
import config from '@/common/config.js';
|
import config, { getDefaultApiUrl, resolveUpgradeDownloadUrl } from '@/common/config.js';
|
||||||
import base64 from '@/common/base64.js';
|
import base64 from '@/common/base64.js';
|
||||||
import util from '@/common/util.js';
|
import util from '@/common/util.js';
|
||||||
import md5 from '@/common/md5.js';
|
import md5 from '@/common/md5.js';
|
||||||
import manifest from '@/manifest.json';
|
import manifest from '@/manifest.json';
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import app_upgrade from '@/uni_modules/app-upgrade/js_sdk/index.js'
|
import app_upgrade from '@/uni_modules/app-upgrade/js_sdk/index.js'
|
||||||
|
import { ensureScanConfigAfterLogin } from '@/common/scanAutoConfig.js'
|
||||||
|
|
||||||
|
function isDefaultPassword(data) {
|
||||||
|
if (!data || typeof data !== 'object') return false;
|
||||||
|
const value = data.is_default_password != null
|
||||||
|
? data.is_default_password
|
||||||
|
: (data.user && data.user.is_default_password);
|
||||||
|
return value === true || value === 1 || value === '1' || value === 'true';
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -136,10 +146,9 @@ export default {
|
|||||||
password: ""
|
password: ""
|
||||||
},
|
},
|
||||||
showApiUrlPicker: false,
|
showApiUrlPicker: false,
|
||||||
// 根据环境设置默认URL和选项
|
selectedApiUrl: getDefaultApiUrl(),
|
||||||
selectedApiUrl: config.isDevelopment ? config.devApiUrlOptions[0].value : config.productionApiUrl,
|
|
||||||
customApiUrl: 'http://192.168.1.66:50002/hcscm_weave/pda/v1',
|
customApiUrl: 'http://192.168.1.66:50002/hcscm_weave/pda/v1',
|
||||||
apiUrlList: config.isDevelopment ? config.devApiUrlOptions : [],
|
apiUrlList: config.devApiUrlOptions,
|
||||||
phoneNo: '',
|
phoneNo: '',
|
||||||
//username: '',
|
//username: '',
|
||||||
//password: '',
|
//password: '',
|
||||||
@@ -159,25 +168,27 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
appName() {
|
||||||
|
return manifest.name || '';
|
||||||
|
},
|
||||||
appVersion() {
|
appVersion() {
|
||||||
return manifest.versionName;
|
return manifest.versionName;
|
||||||
},
|
},
|
||||||
envName() {
|
envName() {
|
||||||
return process.env.VUE_APP_ENV_NAME || '';
|
return process.env.VUE_APP_ENV_NAME || '';
|
||||||
|
},
|
||||||
|
apiUrlDefaultIndex() {
|
||||||
|
const list = this.apiUrlList || [];
|
||||||
|
let index = list.findIndex(item => item.value === this.selectedApiUrl);
|
||||||
|
if (index < 0) index = list.findIndex(item => item.label === '正式环境');
|
||||||
|
return [index >= 0 ? index : 0];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onShow() {
|
onShow() {
|
||||||
// 只在开发环境读取存储的URL
|
const defaultUrl = getDefaultApiUrl();
|
||||||
if (config.isDevelopment) {
|
util.updateApiUrl(defaultUrl);
|
||||||
uni.getStorage({
|
this.selectedApiUrl = defaultUrl;
|
||||||
key: 'ApiUrl',
|
|
||||||
success: (e) => {
|
|
||||||
util.updateApiUrl(e.data);
|
|
||||||
this.selectedApiUrl = e.data;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
uni.getStorage({
|
uni.getStorage({
|
||||||
key: 'UserInfo',
|
key: 'UserInfo',
|
||||||
@@ -218,9 +229,8 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onApiUrlConfirm(e) {
|
onApiUrlConfirm(e) {
|
||||||
console.log('e', JSON.stringify(e));
|
const selectedValue = e && e[0] && e[0].value;
|
||||||
const selectedValue = this.apiUrlList[e[0]].value;
|
if (selectedValue == null) return;
|
||||||
console.log('selectedValue', selectedValue)
|
|
||||||
this.selectedApiUrl = selectedValue;
|
this.selectedApiUrl = selectedValue;
|
||||||
this.showApiUrlPicker = false;
|
this.showApiUrlPicker = false;
|
||||||
|
|
||||||
@@ -300,21 +310,12 @@ export default {
|
|||||||
title: '登录中...'
|
title: '登录中...'
|
||||||
});
|
});
|
||||||
|
|
||||||
let currentApiUrl;
|
const currentApiUrl = this.selectedApiUrl === 'custom' ? this.customApiUrl : this.selectedApiUrl;
|
||||||
|
|
||||||
if (config.isDevelopment) {
|
|
||||||
// 开发环境:使用选择的URL
|
|
||||||
currentApiUrl = this.selectedApiUrl === 'custom' ? this.customApiUrl : this.selectedApiUrl;
|
|
||||||
if (!currentApiUrl || currentApiUrl.length === 0) {
|
if (!currentApiUrl || currentApiUrl.length === 0) {
|
||||||
this.$u.toast('请输入服务器地址');
|
this.$u.toast('请输入服务器地址');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 更新store中的URL
|
|
||||||
this.$store.dispatch('updateApiUrl', currentApiUrl);
|
this.$store.dispatch('updateApiUrl', currentApiUrl);
|
||||||
} else {
|
|
||||||
// 生产环境:使用固定的生产URL
|
|
||||||
currentApiUrl = config.productionApiUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.login.username.length == 0) {
|
if (this.login.username.length == 0) {
|
||||||
this.$u.toast('请输入账号');
|
this.$u.toast('请输入账号');
|
||||||
@@ -334,19 +335,16 @@ export default {
|
|||||||
this.$u.api.pdaLogin({
|
this.$u.api.pdaLogin({
|
||||||
'phone': this.login.username,
|
'phone': this.login.username,
|
||||||
'password': this.login.password,
|
'password': this.login.password,
|
||||||
}).then((res) => {
|
}).then(async (res) => {
|
||||||
console.log('login res', res)
|
console.log('login res', res)
|
||||||
var aLoginUserData = res;
|
var aLoginUserData = res;
|
||||||
|
|
||||||
//console.log('--aLoginUserData->>' + JSON.stringify(aLoginUserData));
|
//console.log('--aLoginUserData->>' + JSON.stringify(aLoginUserData));
|
||||||
// 只在开发环境保存 apiurl 到本地存储
|
|
||||||
if (config.isDevelopment) {
|
|
||||||
uni.setStorage({
|
uni.setStorage({
|
||||||
key: 'ApiUrl',
|
key: 'ApiUrl',
|
||||||
data: currentApiUrl
|
data: currentApiUrl
|
||||||
});
|
});
|
||||||
util.updateApiUrl(currentApiUrl);
|
util.updateApiUrl(currentApiUrl);
|
||||||
}
|
|
||||||
// 保存 token 到本地存储
|
// 保存 token 到本地存储
|
||||||
uni.setStorageSync('RemoteTokenData', aLoginUserData);
|
uni.setStorageSync('RemoteTokenData', aLoginUserData);
|
||||||
|
|
||||||
@@ -368,9 +366,17 @@ export default {
|
|||||||
getApp().globalData.StoreNameID = aLoginUserData.default_physical_warehouse_id;
|
getApp().globalData.StoreNameID = aLoginUserData.default_physical_warehouse_id;
|
||||||
getApp().globalData.StoreName = aLoginUserData.default_physical_warehouse_name;
|
getApp().globalData.StoreName = aLoginUserData.default_physical_warehouse_name;
|
||||||
getApp().globalData.StoreTypeNo = '';
|
getApp().globalData.StoreTypeNo = '';
|
||||||
|
try {
|
||||||
|
await ensureScanConfigAfterLogin(this.$u.api);
|
||||||
|
} catch (scanError) {
|
||||||
|
console.log('自动匹配扫码设置失败', scanError);
|
||||||
|
}
|
||||||
|
const workbenchUrl = isDefaultPassword(aLoginUserData)
|
||||||
|
? '/pages/sys/workbench/index?defaultPassword=1'
|
||||||
|
: '/pages/sys/workbench/index';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
url: '/pages/sys/workbench/index'
|
url: workbenchUrl
|
||||||
});
|
});
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
@@ -443,10 +449,18 @@ export default {
|
|||||||
return { status: 0 };
|
return { status: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 用户已取消过该版本:登录页自动检查不再弹框
|
||||||
|
const dismissedVersion = uni.getStorageSync('appUpdateDismissedVersion');
|
||||||
|
if (dismissedVersion && String(dismissedVersion) === String(res.latest_version)) {
|
||||||
|
console.log('用户已取消该版本更新,跳过自动弹框:', dismissedVersion);
|
||||||
|
return { status: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
changelog: res.message + ',最新版本:' + res.latest_version,
|
changelog: res.message + ',最新版本:' + res.latest_version,
|
||||||
status: res.need_update ? 1 : 0, // 0 无新版本 | 1 有新版本
|
status: res.need_update ? 1 : 0, // 0 无新版本 | 1 有新版本
|
||||||
path: res.download_url // 新apk地址
|
path: resolveUpgradeDownloadUrl(res.download_url), // 新apk地址
|
||||||
|
latest_version: res.latest_version
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('检查版本更新失败:', error);
|
console.log('检查版本更新失败:', error);
|
||||||
@@ -456,19 +470,15 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleBlurInputUrl(e) {
|
handleBlurInputUrl(e) {
|
||||||
// 只在开发环境处理自定义URL
|
|
||||||
if (config.isDevelopment) {
|
|
||||||
const url = e.detail.value.trim();
|
const url = e.detail.value.trim();
|
||||||
if (url) {
|
if (url) {
|
||||||
this.customApiUrl = url;
|
this.customApiUrl = url;
|
||||||
// 保存到本地存储
|
|
||||||
uni.setStorage({
|
uni.setStorage({
|
||||||
key: 'ApiUrl',
|
key: 'ApiUrl',
|
||||||
data: url
|
data: url
|
||||||
});
|
});
|
||||||
util.updateApiUrl(url);
|
util.updateApiUrl(url);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -476,14 +486,25 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import 'index.scss';
|
@import 'index.scss';
|
||||||
|
|
||||||
|
.env-call {
|
||||||
|
height: auto;
|
||||||
|
min-height: 140rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.server-selector {
|
.server-selector {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 10rpx 0;
|
min-height: 80rpx;
|
||||||
|
padding: 16rpx 0;
|
||||||
|
font-size: 40rpx;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.server-selector .icon-arrow-down {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
.list-call {
|
.list-call {
|
||||||
.u-select {
|
.u-select {
|
||||||
margin-bottom: 10rpx;
|
margin-bottom: 10rpx;
|
||||||
@@ -499,7 +520,16 @@ export default {
|
|||||||
height: 150rpx;
|
height: 150rpx;
|
||||||
// max-width: 5%;
|
// max-width: 5%;
|
||||||
// max-height: 5%;
|
// max-height: 5%;
|
||||||
margin: 10rpx auto 10rpx auto;
|
margin: 10rpx auto 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-name {
|
||||||
|
margin: 8rpx 0 24rpx;
|
||||||
|
color: #242820;
|
||||||
|
font-size: 40rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.3;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logoimg {
|
.logoimg {
|
||||||
@@ -598,3 +628,21 @@ export default {
|
|||||||
margin-left: 10rpx;
|
margin-left: 10rpx;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.login-env-picker {
|
||||||
|
::v-deep .u-select__header,
|
||||||
|
::v-deep .u-select__header__btn {
|
||||||
|
height: 100rpx;
|
||||||
|
font-size: 36rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .u-select__header__title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .u-select__body__picker-view__item,
|
||||||
|
::v-deep .u-line-1 {
|
||||||
|
font-size: 40rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -41,20 +41,28 @@
|
|||||||
<u-gap height="20" bg-color="#f5f5f5"></u-gap>
|
<u-gap height="20" bg-color="#f5f5f5"></u-gap>
|
||||||
<u-cell-item icon="question-circle" :iconStyle="{ color: '#ff8d06' }" title="常见问题" @click="navTo('problem')"></u-cell-item>
|
<u-cell-item icon="question-circle" :iconStyle="{ color: '#ff8d06' }" title="常见问题" @click="navTo('problem')"></u-cell-item>
|
||||||
<u-cell-item icon="kefu-ermai" :iconStyle="{ color: '#5f8dff' }" title="意见反馈" @click="navTo('comment')"></u-cell-item>
|
<u-cell-item icon="kefu-ermai" :iconStyle="{ color: '#5f8dff' }" title="意见反馈" @click="navTo('comment')"></u-cell-item>
|
||||||
<u-cell-item icon="map" :iconStyle="{ color: '#316ede' }" title="账号安全" @click="navTo('pwd')"></u-cell-item>
|
<u-cell-item icon="map" :iconStyle="{ color: '#316ede' }" title="修改密码" @click="navTo('pwd')"></u-cell-item>
|
||||||
<u-cell-item icon="scan" :iconStyle="{ color: '#36cfc9' }" title="扫描设置" @click="navTo('scan-settings')"></u-cell-item>
|
<u-cell-item icon="scan" :iconStyle="{ color: '#36cfc9' }" title="扫描设置" @click="navTo('scan-settings')"></u-cell-item>
|
||||||
<u-cell-item icon="order" :iconStyle="{ color: '#59bdf9' }" title="清除缓存" @click="navTo('clear-cache')"></u-cell-item>
|
<u-cell-item icon="order" :iconStyle="{ color: '#59bdf9' }" title="清除缓存" @click="navTo('clear-cache')"></u-cell-item>
|
||||||
<!--<u-cell-item icon="account" :iconStyle="{ color: '#27c0dc' }" title="关于我们" @click="navTo('about')"></u-cell-item>
|
<!--<u-cell-item icon="account" :iconStyle="{ color: '#27c0dc' }" title="关于我们" @click="navTo('about')"></u-cell-item>
|
||||||
<u-cell-item icon="kefu-ermai" :iconStyle="{ color: '#ff8a00' }" title="联系客服" @click="navTo('service')"></u-cell-item>!-->
|
<u-cell-item icon="kefu-ermai" :iconStyle="{ color: '#ff8a00' }" title="联系客服" @click="navTo('service')"></u-cell-item>!-->
|
||||||
<u-gap height="20" bg-color="#f5f5f5"></u-gap>
|
<u-gap height="20" bg-color="#f5f5f5"></u-gap>
|
||||||
|
<u-cell-item icon="reload" :iconStyle="{ color: '#19be6b' }" title="版本更新" @click="upgrade"></u-cell-item>
|
||||||
<u-cell-item icon="setting" :iconStyle="{ color: '#2767dc' }" title="系统设置" @click="navTo('setting')"></u-cell-item>
|
<u-cell-item icon="setting" :iconStyle="{ color: '#2767dc' }" title="系统设置" @click="navTo('setting')"></u-cell-item>
|
||||||
</u-cell-group>
|
</u-cell-group>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="app-meta">
|
||||||
|
<text class="app-name">{{ appName }}</text>
|
||||||
|
<text class="app-version">版本 {{ appVersion }}</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import CommonNavbar from "@/components/common-navbar/index";
|
import CommonNavbar from "@/components/common-navbar/index";
|
||||||
|
import app_upgrade from '@/uni_modules/app-upgrade/js_sdk/index.js';
|
||||||
|
import config, { resolveUpgradeDownloadUrl } from '@/common/config.js';
|
||||||
|
import manifest from '@/manifest.json';
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
||||||
*/
|
*/
|
||||||
@@ -73,6 +81,12 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
appName() {
|
||||||
|
return manifest.name || '';
|
||||||
|
},
|
||||||
|
appVersion() {
|
||||||
|
return manifest.versionName || '';
|
||||||
|
},
|
||||||
avatarUrl() {
|
avatarUrl() {
|
||||||
// let url = this.vuex_user.avatarUrl || '/ctxPath/static/images/user1.jpg';
|
// let url = this.vuex_user.avatarUrl || '/ctxPath/static/images/user1.jpg';
|
||||||
// url = url.replace('/ctxPath/', this.vuex_config.baseUrl + '/');
|
// url = url.replace('/ctxPath/', this.vuex_config.baseUrl + '/');
|
||||||
@@ -102,25 +116,30 @@ export default {
|
|||||||
},
|
},
|
||||||
upgrade(){
|
upgrade(){
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
this.$u.api.upgradeCheck().then(res => {
|
app_upgrade(async () => {
|
||||||
if (res.result == 'true'){
|
const appInfo = await new Promise((resolve) => {
|
||||||
uni.showModal({
|
plus.runtime.getProperty(plus.runtime.appid, (inf) => {
|
||||||
title: '提示',
|
resolve(inf);
|
||||||
content: res.message + '是否下载更新?',
|
|
||||||
showCancel: true,
|
|
||||||
success: function (res2) {
|
|
||||||
if (res2.confirm) {
|
|
||||||
plus.runtime.openURL(res.data.apkUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}else{
|
|
||||||
this.$u.toast(res.message);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
const res = await this.$u.api.upgradeCheck({
|
||||||
|
app_name: config.upgradeName,
|
||||||
|
current_version: appInfo.version
|
||||||
|
});
|
||||||
|
if (!res.download_url) {
|
||||||
|
this.$u.toast('当前版本已是最新版');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
changelog: res.message + ',最新版本:' + res.latest_version,
|
||||||
|
status: res.need_update ? 1 : 0,
|
||||||
|
path: resolveUpgradeDownloadUrl(res.download_url),
|
||||||
|
latest_version: res.latest_version
|
||||||
|
};
|
||||||
|
}, 1);
|
||||||
// #endif
|
// #endif
|
||||||
// #ifndef APP-PLUS
|
// #ifndef APP-PLUS
|
||||||
this.$u.toast('小程序端或H5端无需检查更新')
|
this.$u.toast('小程序端或H5端已是最新版,无需检查更新!');
|
||||||
// #endif
|
// #endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,4 +164,22 @@ page {
|
|||||||
height:50rpx;
|
height:50rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.app-meta {
|
||||||
|
padding: 48rpx 30rpx 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.app-name {
|
||||||
|
display: block;
|
||||||
|
color: #242820;
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
.app-version {
|
||||||
|
display: block;
|
||||||
|
margin-top: 8rpx;
|
||||||
|
color: #8a8f86;
|
||||||
|
font-size: 32rpx;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -68,31 +68,30 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
submit() {
|
submit() {
|
||||||
this.$refs.uForm.validate(valid => {
|
this.$refs.uForm.validate(valid => {
|
||||||
if (valid) {
|
if (!valid) {
|
||||||
|
this.$u.toast('您填写的信息有误,请根据提示修正。');
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.$u.api.user.infoSavePwd({
|
this.$u.api.user.infoSavePwd({
|
||||||
oldPassword: this.model.oldPassword,
|
oldPassword: this.model.oldPassword,
|
||||||
newPassword: this.model.newPassword
|
newPassword: this.model.newPassword
|
||||||
}).then(res => {
|
}).then(() => {
|
||||||
if(res.code == '200'){
|
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
content: res.msg,
|
content: '密码修改成功',
|
||||||
showCancel: false,
|
showCancel: false,
|
||||||
success: function () {
|
success: () => {
|
||||||
uni.navigateBack();
|
uni.navigateBack();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}else{
|
}).catch((err) => {
|
||||||
|
const message = (err && (err.message || err.msg)) || '修改密码失败';
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
content: res.msg,
|
content: message,
|
||||||
showCancel: false
|
showCancel: false
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
this.$u.toast('您填写的信息有误,请根据提示修正。');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
cancel() {
|
cancel() {
|
||||||
|
|||||||
+11
-12
@@ -33,7 +33,7 @@ export default {
|
|||||||
model: {
|
model: {
|
||||||
oldPassword: '',
|
oldPassword: '',
|
||||||
newPassword: '',
|
newPassword: '',
|
||||||
confirmNewPassword: ''
|
confirmPassword: ''
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
oldPassword: [
|
oldPassword: [
|
||||||
@@ -78,31 +78,30 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
submit() {
|
submit() {
|
||||||
this.$refs.uForm.validate(valid => {
|
this.$refs.uForm.validate(valid => {
|
||||||
if (valid) {
|
if (!valid) {
|
||||||
|
this.$u.toast('您填写的信息有误,请根据提示修正。');
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.$u.api.user.infoSavePwd({
|
this.$u.api.user.infoSavePwd({
|
||||||
oldPassword: this.model.oldPassword,
|
oldPassword: this.model.oldPassword,
|
||||||
newPassword: this.model.newPassword
|
newPassword: this.model.newPassword
|
||||||
}).then(res => {
|
}).then(() => {
|
||||||
if(res.code == '200'){
|
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
content: res.msg,
|
content: '密码修改成功',
|
||||||
showCancel: false,
|
showCancel: false,
|
||||||
success: function () {
|
success: () => {
|
||||||
uni.navigateBack();
|
uni.navigateBack();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}else{
|
}).catch((err) => {
|
||||||
|
const message = (err && (err.message || err.msg)) || '修改密码失败';
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
content: res.msg,
|
content: message,
|
||||||
showCancel: false
|
showCancel: false
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
this.$u.toast('您填写的信息有误,请根据提示修正。');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
cancel() {
|
cancel() {
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
<common-navbar title="扫描设置"></common-navbar>
|
<common-navbar title="扫描设置"></common-navbar>
|
||||||
<u-gap height="20" bg-color="#f5f5f5"></u-gap>
|
<u-gap height="20" bg-color="#f5f5f5"></u-gap>
|
||||||
<u-cell-group :border="false">
|
<u-cell-group :border="false">
|
||||||
<u-cell-item title="PDA品牌" :value="form.name || '请选择'" @click="brandSelectShow = true"></u-cell-item>
|
<u-cell-item title="扫码方式" :value="form.name || '请选择'" @click="brandSelectShow = true"></u-cell-item>
|
||||||
|
<template v-if="!form.isPhoneScan">
|
||||||
<u-cell-item title="广播动作" :arrow="false">
|
<u-cell-item title="广播动作" :arrow="false">
|
||||||
<u-input
|
<u-input
|
||||||
slot="right-icon"
|
slot="right-icon"
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
:clearable="false"
|
:clearable="false"
|
||||||
></u-input>
|
></u-input>
|
||||||
</u-cell-item>
|
</u-cell-item>
|
||||||
|
</template>
|
||||||
</u-cell-group>
|
</u-cell-group>
|
||||||
<view class="form-footer">
|
<view class="form-footer">
|
||||||
<u-button type="primary" :loading="submitting" @click="submit">确定</u-button>
|
<u-button type="primary" :loading="submitting" @click="submit">确定</u-button>
|
||||||
@@ -33,7 +35,15 @@
|
|||||||
<script>
|
<script>
|
||||||
import CommonNavbar from '@/components/common-navbar/index';
|
import CommonNavbar from '@/components/common-navbar/index';
|
||||||
import scanMixin from '@/common/scanMixin.js';
|
import scanMixin from '@/common/scanMixin.js';
|
||||||
import { getScanConfig, DICTIONARY_TYPE_SCANNER, mapDictionaryToScannerConfig, saveScanConfig } from '@/common/scanConfig.js';
|
import {
|
||||||
|
getScanConfig,
|
||||||
|
DICTIONARY_TYPE_SCANNER,
|
||||||
|
isPhoneScanConfig,
|
||||||
|
mapDictionaryToScannerConfig,
|
||||||
|
PHONE_SCAN_BRAND,
|
||||||
|
saveScanConfig,
|
||||||
|
autoConfigureScanSettings,
|
||||||
|
} from '@/common/scanConfig.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -50,6 +60,7 @@ export default {
|
|||||||
name: '',
|
name: '',
|
||||||
action: '',
|
action: '',
|
||||||
dataKey: '',
|
dataKey: '',
|
||||||
|
isPhoneScan: false,
|
||||||
needSetup: false,
|
needSetup: false,
|
||||||
setupAction: '',
|
setupAction: '',
|
||||||
setupParams: null,
|
setupParams: null,
|
||||||
@@ -73,13 +84,13 @@ export default {
|
|||||||
const res = await this.$u.api.dictionary.getDetailEnumList({
|
const res = await this.$u.api.dictionary.getDetailEnumList({
|
||||||
dictionary_id: DICTIONARY_TYPE_SCANNER,
|
dictionary_id: DICTIONARY_TYPE_SCANNER,
|
||||||
});
|
});
|
||||||
const list = Array.isArray(res) ? res : [];
|
const list = Array.isArray(res) ? res : (Array.isArray(res && res.list) ? res.list : []);
|
||||||
const builtinConfigs = this.getScannerConfigs();
|
const builtinConfigs = this.getScannerConfigs();
|
||||||
if (list.length) {
|
if (list.length) {
|
||||||
this.configList = list
|
this.configList = list
|
||||||
.map((item) => mapDictionaryToScannerConfig(item, builtinConfigs))
|
.map((item) => mapDictionaryToScannerConfig(item, builtinConfigs))
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
this.remoteScannerConfigs = this.configList;
|
this.remoteScannerConfigs = this.configList.filter((item) => !isPhoneScanConfig(item));
|
||||||
} else {
|
} else {
|
||||||
this.useFallbackConfigList();
|
this.useFallbackConfigList();
|
||||||
}
|
}
|
||||||
@@ -87,28 +98,76 @@ export default {
|
|||||||
console.log('获取扫码枪字典配置失败,使用内置配置', error);
|
console.log('获取扫码枪字典配置失败,使用内置配置', error);
|
||||||
this.useFallbackConfigList();
|
this.useFallbackConfigList();
|
||||||
}
|
}
|
||||||
|
this.ensurePhoneScanOption();
|
||||||
|
this.ensureSeuicOption();
|
||||||
|
this.ensureNlscanOption();
|
||||||
|
this.ensureNlscanCompatOption();
|
||||||
this.initFormFromSaved();
|
this.initFormFromSaved();
|
||||||
},
|
},
|
||||||
useFallbackConfigList() {
|
useFallbackConfigList() {
|
||||||
this.configList = this.getScannerConfigs();
|
this.configList = this.getScannerConfigs();
|
||||||
this.remoteScannerConfigs = [];
|
this.remoteScannerConfigs = [];
|
||||||
},
|
},
|
||||||
|
ensurePhoneScanOption() {
|
||||||
|
const phoneConfig = this.getPhoneScanConfig();
|
||||||
|
if (!this.configList.find((item) => item.brand === PHONE_SCAN_BRAND)) {
|
||||||
|
this.configList.push(phoneConfig);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ensureBuiltinScannerOption(brand) {
|
||||||
|
const builtinConfig = this.getScannerConfigs().find((item) => item.brand === brand);
|
||||||
|
if (!builtinConfig) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const exists = this.configList.some((item) => {
|
||||||
|
return item.brand === builtinConfig.brand || item.action === builtinConfig.action;
|
||||||
|
});
|
||||||
|
if (exists) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const phoneIndex = this.configList.findIndex((item) => item.brand === PHONE_SCAN_BRAND);
|
||||||
|
if (phoneIndex >= 0) {
|
||||||
|
this.configList.splice(phoneIndex, 0, builtinConfig);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.configList.push(builtinConfig);
|
||||||
|
},
|
||||||
|
ensureSeuicOption() {
|
||||||
|
this.ensureBuiltinScannerOption('seuic');
|
||||||
|
},
|
||||||
|
ensureNlscanOption() {
|
||||||
|
this.ensureBuiltinScannerOption('nlscan');
|
||||||
|
},
|
||||||
|
ensureNlscanCompatOption() {
|
||||||
|
this.ensureBuiltinScannerOption('nlscan_compat');
|
||||||
|
},
|
||||||
initFormFromSaved() {
|
initFormFromSaved() {
|
||||||
const savedConfig = getScanConfig();
|
// N5S 曾被误识别为东集时,进入设置页会纠正并写回
|
||||||
|
const rematch = autoConfigureScanSettings({
|
||||||
|
remoteConfigs: this.remoteScannerConfigs || [],
|
||||||
|
});
|
||||||
|
const savedConfig = (rematch && rematch.config) || getScanConfig(this.getScannerConfigs());
|
||||||
if (savedConfig) {
|
if (savedConfig) {
|
||||||
this.applyConfig(savedConfig);
|
this.applyConfig(savedConfig);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.configList.length) {
|
if (!this.isPdaDevice()) {
|
||||||
this.applyConfig(this.configList[0]);
|
this.applyConfig(this.getPhoneScanConfig());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pdaConfigs = this.configList.filter((item) => !isPhoneScanConfig(item));
|
||||||
|
if (pdaConfigs.length) {
|
||||||
|
this.applyConfig(pdaConfigs[0]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
applyConfig(config) {
|
applyConfig(config) {
|
||||||
|
const isPhoneScan = isPhoneScanConfig(config);
|
||||||
this.form = {
|
this.form = {
|
||||||
brand: config.brand || '',
|
brand: config.brand || '',
|
||||||
name: config.name || '',
|
name: config.name || '',
|
||||||
action: config.action || '',
|
action: config.action || '',
|
||||||
dataKey: config.dataKey || '',
|
dataKey: config.dataKey || '',
|
||||||
|
isPhoneScan,
|
||||||
needSetup: !!config.needSetup,
|
needSetup: !!config.needSetup,
|
||||||
setupAction: config.setupAction || '',
|
setupAction: config.setupAction || '',
|
||||||
setupParams: config.setupParams || null,
|
setupParams: config.setupParams || null,
|
||||||
@@ -122,13 +181,17 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
submit() {
|
submit() {
|
||||||
const action = (this.form.action || '').trim();
|
|
||||||
const dataKey = (this.form.dataKey || '').trim();
|
|
||||||
|
|
||||||
if (!this.form.brand) {
|
if (!this.form.brand) {
|
||||||
this.$u.toast('请选择PDA品牌');
|
this.$u.toast('请选择扫码方式');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let payload;
|
||||||
|
if (this.form.isPhoneScan) {
|
||||||
|
payload = this.getPhoneScanConfig();
|
||||||
|
} else {
|
||||||
|
const action = (this.form.action || '').trim();
|
||||||
|
const dataKey = (this.form.dataKey || '').trim();
|
||||||
if (!action) {
|
if (!action) {
|
||||||
this.$u.toast('请输入广播动作');
|
this.$u.toast('请输入广播动作');
|
||||||
return;
|
return;
|
||||||
@@ -137,12 +200,12 @@ export default {
|
|||||||
this.$u.toast('请输入数据标签');
|
this.$u.toast('请输入数据标签');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
payload = {
|
||||||
const payload = {
|
|
||||||
...this.form,
|
...this.form,
|
||||||
action,
|
action,
|
||||||
dataKey,
|
dataKey,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
this.submitting = true;
|
this.submitting = true;
|
||||||
if (!saveScanConfig(payload)) {
|
if (!saveScanConfig(payload)) {
|
||||||
@@ -153,7 +216,7 @@ export default {
|
|||||||
|
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
this.unregisterScanBroadcast();
|
this.unregisterScanBroadcast();
|
||||||
const registered = this.registerScanBroadcastByConfig(payload);
|
const registered = this.registerScanBroadcastByConfig(payload, null);
|
||||||
if (!registered) {
|
if (!registered) {
|
||||||
this.submitting = false;
|
this.submitting = false;
|
||||||
this.$u.toast('保存成功,但广播注册失败');
|
this.$u.toast('保存成功,但广播注册失败');
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
<u-cell-group :border="false">
|
<u-cell-group :border="false">
|
||||||
<u-cell-item title="通用" @click="navTo('/pages/sys/user/currency')" :arrow="true"></u-cell-item>
|
<u-cell-item title="通用" @click="navTo('/pages/sys/user/currency')" :arrow="true"></u-cell-item>
|
||||||
<u-gap height="20" bg-color="#f5f5f5"></u-gap>
|
<u-gap height="20" bg-color="#f5f5f5"></u-gap>
|
||||||
<u-cell-item title="版本更新" @click="upgrade()" :arrow="true"></u-cell-item>
|
|
||||||
<u-cell-item title="隐私政策" @click="navTo('')" :arrow="true"></u-cell-item>
|
<u-cell-item title="隐私政策" @click="navTo('')" :arrow="true"></u-cell-item>
|
||||||
<u-cell-item title="用户协议" @click="navTo('')" :arrow="true"></u-cell-item>
|
<u-cell-item title="用户协议" @click="navTo('')" :arrow="true"></u-cell-item>
|
||||||
</u-cell-group>
|
</u-cell-group>
|
||||||
@@ -18,10 +17,6 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
||||||
*/
|
*/
|
||||||
import app_upgrade from '@/uni_modules/app-upgrade/js_sdk/index.js'
|
|
||||||
import util from '@/common/util.js';
|
|
||||||
import config from '../../../common/config';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -34,36 +29,6 @@ export default {
|
|||||||
url: url
|
url: url
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
upgrade(){
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
app_upgrade(async ()=>{
|
|
||||||
// 获取应用信息
|
|
||||||
const appInfo = await new Promise((resolve) => {
|
|
||||||
plus.runtime.getProperty(plus.runtime.appid, (inf) => {
|
|
||||||
resolve(inf);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const res = await this.$u.api.upgradeCheck({
|
|
||||||
app_name: config.upgradeName,
|
|
||||||
current_version: appInfo.version
|
|
||||||
})
|
|
||||||
console.log('res',res)
|
|
||||||
if(!res.download_url){
|
|
||||||
this.$u.toast('当前版本已是最新版');
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
changelog: res.message + ',最新版本:' + res.latest_version,
|
|
||||||
|
|
||||||
status: res.need_update ? 1 : 0, // 0 无新版本 | 1 有新版本
|
|
||||||
path: res.download_url // 新apk地址
|
|
||||||
}
|
|
||||||
}, 1)
|
|
||||||
// #endif
|
|
||||||
// #ifndef APP-PLUS
|
|
||||||
this.$u.toast('小程序端或H5端已是最新版,无需检查更新!');
|
|
||||||
// #endif
|
|
||||||
},
|
|
||||||
openSettings() {
|
openSettings() {
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
uni.getSystemInfo({
|
uni.getSystemInfo({
|
||||||
|
|||||||
+270
-250
@@ -1,301 +1,321 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="wrap">
|
<view class="app-center">
|
||||||
<common-navbar title="工作台" :showBack="false">
|
<view class="app-center__status" :style="{ height: statusBarHeight + 'px' }"></view>
|
||||||
<template #right>
|
<view class="app-center__header">
|
||||||
<view class="scan_box">
|
<text class="app-center__version">v{{ appVersion }}</text>
|
||||||
<u-icon name="scan" color="#333333" size="46" @click="handleScan"></u-icon>
|
<text class="app-center__title">工作台</text>
|
||||||
|
<view class="app-center__setting" @click="navTo('/pages/sys/user/setting')">
|
||||||
|
<u-icon name="setting" color="#333333" size="34"></u-icon>
|
||||||
|
<text>设置</text>
|
||||||
</view>
|
</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="0" @click="navTo('/pages/storegoods/dyeworksDyeback')">-->
|
|
||||||
<!-- <view class="home-icon icon-color04">-->
|
|
||||||
<!-- <i class="iconfont icon-finance"></i>-->
|
|
||||||
<!-- </view>-->
|
|
||||||
<!-- <view class="grid-text">染整进仓</view>-->
|
|
||||||
<!-- </u-grid-item>-->
|
|
||||||
<!-- <u-grid-item :index="1" @click="navTo('/pages/storegoods/storeGoodsBusinessIn')">-->
|
|
||||||
<!-- <view class="home-icon icon-color03">-->
|
|
||||||
<!-- <i class="iconfont icon-mall-bag"></i>-->
|
|
||||||
<!-- </view>-->
|
|
||||||
<!-- <view class="grid-text">成品进仓</view>-->
|
|
||||||
<!-- </u-grid-item>-->
|
|
||||||
<!-- <u-grid-item :index="2" @click="navTo('/pages/storegoods/storeGoodsBusinessOut')">-->
|
|
||||||
<!-- <view class="home-icon icon-color12">-->
|
|
||||||
<!-- <i class="iconfont icon-baoxiaodan"></i>-->
|
|
||||||
<!-- </view>-->
|
|
||||||
<!-- <view class="grid-text">成品出仓</view>-->
|
|
||||||
<!-- </u-grid-item>-->
|
|
||||||
<!-- <u-grid-item @click="navTo('/pages/storegoods/storeGoodsBusinessCheck')">-->
|
|
||||||
<!-- <view class="home-icon icon-color04">-->
|
|
||||||
<!-- <i class="iconfont icon-shenpi"></i>-->
|
|
||||||
<!-- </view>-->
|
|
||||||
<!-- <view class="grid-text">成品盘点</view>-->
|
|
||||||
<!-- </u-grid-item>-->
|
|
||||||
<!-- <u-grid-item @click="navTo('/pages/storegoods/storeGoodsBusinessStationMoveOnly')">-->
|
|
||||||
<!-- <view class="home-icon icon-color04">-->
|
|
||||||
<!-- <i class="iconfont icon-shenpi"></i>-->
|
|
||||||
<!-- </view>-->
|
|
||||||
<!-- <view class="grid-text">成品移架</view>-->
|
|
||||||
<!-- </u-grid-item>-->
|
|
||||||
<!-- <u-grid-item @click="navTo('/pages/storegoods/storegoodsstoresearch')">-->
|
|
||||||
<!-- <view class="home-icon icon-color04">-->
|
|
||||||
<!-- <i class="iconfont icon-shenpi"></i>-->
|
|
||||||
<!-- </view>-->
|
|
||||||
<!-- <view class="grid-text">成品库存</view>-->
|
|
||||||
<!-- </u-grid-item>-->
|
|
||||||
<!-- <u-grid-item @click="navTo('/pages/storegoods/storegoodsstoreallin')">-->
|
|
||||||
<!-- <view class="home-icon icon-color04">-->
|
|
||||||
<!-- <i class="iconfont icon-shenpi"></i>-->
|
|
||||||
<!-- </view>-->
|
|
||||||
<!-- <view class="grid-text">进仓查询</view>-->
|
|
||||||
<!-- </u-grid-item>-->
|
|
||||||
<!-- <u-grid-item @click="navTo('/pages/storegoods/storegoodsstoreallout')">-->
|
|
||||||
<!-- <view class="home-icon icon-color04">-->
|
|
||||||
<!-- <i class="iconfont icon-shenpi"></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 @click="navTo('/pages/storefabric/storefabricInStore')">-->
|
|
||||||
<!-- <view class="home-icon icon-color04">-->
|
|
||||||
<!-- <i class="iconfont icon-hetongguanli"></i>-->
|
|
||||||
<!-- </view>-->
|
|
||||||
<!-- <view class="grid-text">坯布进仓</view>-->
|
|
||||||
<!-- </u-grid-item>-->
|
|
||||||
<u-grid-item @click="navTo('/pages/storefabric/storeFabricBusinessOutList')">
|
|
||||||
<view class="home-icon icon-color03">
|
|
||||||
<i class="iconfont icon-chucha"></i>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="grid-text">坯布出库</view>
|
|
||||||
</u-grid-item>
|
<view class="app-center__grid">
|
||||||
<u-grid-item @click="navTo('/pages/storefabric/storeFabricWarehouseGroupList')">
|
<view
|
||||||
<view class="home-icon icon-color05">
|
v-for="item in menuList"
|
||||||
<i class="iconfont icon-huiyishi"></i>
|
:key="item.path"
|
||||||
|
class="menu-card"
|
||||||
|
:class="item.tone"
|
||||||
|
hover-class="menu-card--pressed"
|
||||||
|
@click="navTo(item.path)"
|
||||||
|
>
|
||||||
|
<image class="menu-card__bg" :src="item.bg" mode="aspectFill"></image>
|
||||||
|
<view class="menu-card__mask"></view>
|
||||||
|
<text class="menu-card__quote">“</text>
|
||||||
|
<view v-if="item.tag" class="menu-card__tag">
|
||||||
|
<text>{{ item.tag }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="menu-card__body">
|
||||||
|
<text class="menu-card__name">{{ item.name }}</text>
|
||||||
|
<text class="menu-card__en">{{ item.en }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="menu-card__arrow">
|
||||||
|
<text>›</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="grid-text">坯布库存</view>
|
|
||||||
</u-grid-item>
|
|
||||||
<!-- <u-grid-item @click="navTo('/pages/storefabric/storefabricstoreallin')">-->
|
|
||||||
<!-- <view class="home-icon icon-color05">-->
|
|
||||||
<!-- <i class="iconfont icon-huiyishi"></i>-->
|
|
||||||
<!-- </view>-->
|
|
||||||
<!-- <view class="grid-text">进仓查询</view>-->
|
|
||||||
<!-- </u-grid-item>-->
|
|
||||||
<!-- <u-grid-item @click="navTo('/pages/storefabric/storefabricstoreallout')">-->
|
|
||||||
<!-- <view class="home-icon icon-color05">-->
|
|
||||||
<!-- <i class="iconfont icon-huiyishi"></i>-->
|
|
||||||
<!-- </view>-->
|
|
||||||
<!-- <view class="grid-text">出仓查询</view>-->
|
|
||||||
<!-- </u-grid-item>-->
|
|
||||||
</u-grid>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import CommonNavbar from "@/components/common-navbar/index";
|
|
||||||
import scanMixin from '@/common/scanMixin.js';
|
import scanMixin from '@/common/scanMixin.js';
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
||||||
*/
|
*/
|
||||||
export default {
|
export default {
|
||||||
components: {
|
|
||||||
CommonNavbar,
|
|
||||||
},
|
|
||||||
mixins: [scanMixin],
|
mixins: [scanMixin],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show: false,
|
statusBarHeight: 20,
|
||||||
head: "/static/aidex/images/head.png",
|
appVersion: '1.1.10',
|
||||||
imgList: [
|
menuList: [
|
||||||
{ image: "/static/aidex/banner/banner01.png" },
|
{
|
||||||
//{image: '/static/aidex/banner/banner02.png'},
|
name: '坯布出库',
|
||||||
//{image: '/static/aidex/banner/banner03.png'}
|
en: 'FABRIC OUT',
|
||||||
],
|
tag: '出库',
|
||||||
todoCount: 3,
|
path: '/pages/storefabric/storeFabricBusinessOutList',
|
||||||
// scanReceiver 和 isPageActive 已由 scanMixin 提供
|
tone: 'tone-out',
|
||||||
|
bg: '/static/img/workbench/fabric-out.jpg'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '坯布库存',
|
||||||
|
en: 'FABRIC STOCK',
|
||||||
|
tag: '库存',
|
||||||
|
path: '/pages/storefabric/storeFabricWarehouseGroupList',
|
||||||
|
tone: 'tone-stock',
|
||||||
|
bg: '/static/img/workbench/fabric-stock.jpg'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '手动进仓',
|
||||||
|
en: 'MANUAL ENTRY',
|
||||||
|
tag: '进仓',
|
||||||
|
path: '/pages/storefabric/storeFabricManualIn',
|
||||||
|
tone: 'tone-in',
|
||||||
|
bg: '/static/img/workbench/fabric-stock.jpg'
|
||||||
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
onLoad() {
|
onLoad(options) {
|
||||||
|
const sys = uni.getSystemInfoSync();
|
||||||
|
this.statusBarHeight = sys.statusBarHeight || 20;
|
||||||
|
if (options && String(options.defaultPassword) === '1') {
|
||||||
|
this.promptChangePassword();
|
||||||
|
}
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
// 使用 scanMixin 的方法注册扫码广播,传入自定义回调
|
plus.runtime.getProperty(plus.runtime.appid, (inf) => {
|
||||||
this.registerScanBroadcast(this.handleScanCode);
|
if (inf && inf.version) {
|
||||||
|
this.appVersion = inf.version;
|
||||||
|
}
|
||||||
|
});
|
||||||
// #endif
|
// #endif
|
||||||
|
this.registerScanBroadcast(this.handleScanCode);
|
||||||
},
|
},
|
||||||
// onUnload, onHide, onShow 已由 scanMixin 自动处理
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
contentStyle() {
|
|
||||||
const navHeight = getStatusBarHeight() + 44;
|
|
||||||
return {
|
|
||||||
height: `${navHeight}px`,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
// 自定义扫码处理回调 - 处理本页面特有的扫码逻辑
|
promptChangePassword() {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '当前使用的是默认密码,请修改密码',
|
||||||
|
confirmText: '去修改',
|
||||||
|
cancelText: '稍后',
|
||||||
|
success: (res) => {
|
||||||
|
if (!res.confirm) return;
|
||||||
|
uni.navigateTo({ url: '/pages/sys/user/pwd' });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, 400);
|
||||||
|
},
|
||||||
handleScanCode(scanResult) {
|
handleScanCode(scanResult) {
|
||||||
console.log('工作台-扫码结果:', scanResult);
|
|
||||||
const cleanResult = scanResult.trim().replace(/[\r\n]/g, '');
|
const cleanResult = scanResult.trim().replace(/[\r\n]/g, '');
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages/saleship/salepickscandetail?order_no=' + cleanResult
|
url: '/pages/saleship/salepickscandetail?order_no=' + cleanResult
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
navTo(url) {
|
navTo(url) {
|
||||||
uni.navigateTo({
|
uni.navigateTo({ url });
|
||||||
url: url,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
imgListClick(index) {
|
|
||||||
console.log(`点击了第${index + 1}页图片`);
|
|
||||||
},
|
|
||||||
itemClick(index) {
|
|
||||||
console.log(index);
|
|
||||||
},
|
|
||||||
// 处理扫码(手动点击扫码按钮)
|
|
||||||
handleScan() {
|
|
||||||
// uni.navigateTo({
|
|
||||||
// url: '/pages/saleship/salepickscandetail?order_no=FPD-PB-202412270196'
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// #ifdef APP-PLUS || MP-WEIXIN
|
|
||||||
uni.scanCode({
|
|
||||||
scanType: ['qrCode', 'barCode'], // 同时支持二维码和条形码
|
|
||||||
success: (res) => {
|
|
||||||
console.log('扫码成功:', res);
|
|
||||||
const cleanResult = res.result.trim().replace(/[\r\n]/g, '');
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages/saleship/salepickscandetail?order_no=' + cleanResult
|
|
||||||
})
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
console.error('扫码失败:', err);
|
|
||||||
uni.showToast({
|
|
||||||
title: '扫码失败',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
uni.showToast({
|
|
||||||
title: "H5环境不支持扫码功能",
|
|
||||||
icon: "error",
|
|
||||||
});
|
|
||||||
// #endif
|
|
||||||
},
|
|
||||||
// 处理扫码成功
|
|
||||||
handleScanSuccess(result) {
|
|
||||||
try {
|
|
||||||
// 这里可以根据实际需求处理扫码结果
|
|
||||||
// 例如:验证扫码结果的格式或内容
|
|
||||||
if (this.validateScanResult(result)) {
|
|
||||||
// 扫码验证通过,执行其他逻辑
|
|
||||||
uni.showToast({
|
|
||||||
title: "执行成功",
|
|
||||||
icon: "success",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: "无效的二维码",
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error("处理扫码结果失败:", error);
|
|
||||||
uni.showToast({
|
|
||||||
title: "处理失败",
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// registerScanBroadcast 和 unregisterScanBroadcast 已由 scanMixin 提供
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import "index.scss";
|
page {
|
||||||
|
background: #eef1f4;
|
||||||
|
}
|
||||||
|
|
||||||
.scan_box {
|
.app-center {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #eef1f4;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-center__header {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
height: 88rpx;
|
||||||
.scan_text {
|
padding: 0 24rpx;
|
||||||
font-size: 12px;
|
background: #ffffff;
|
||||||
color: #2979ff;
|
border-bottom: 1rpx solid #e5e8ec;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.banner-box {
|
.app-center__version {
|
||||||
padding: 0 2%;
|
position: absolute;
|
||||||
width: 96%;
|
left: 24rpx;
|
||||||
height: 170rpx;
|
font-size: 24rpx;
|
||||||
margin: 30rpx 0 30rpx;
|
color: #9aa3ad;
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.u-swiper-wrap {
|
.app-center__title {
|
||||||
padding: 0 10px;
|
font-size: 36rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1f2430;
|
||||||
|
letter-spacing: 2rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.banner-pic {
|
.app-center__setting {
|
||||||
width: 47%;
|
position: absolute;
|
||||||
float: left;
|
right: 24rpx;
|
||||||
display: inline-block;
|
display: flex;
|
||||||
margin: 0 1.5%;
|
align-items: center;
|
||||||
}
|
gap: 6rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
.banner-pic image {
|
|
||||||
width: 100%;
|
|
||||||
height: 170rpx;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.u-mode-light-info {
|
|
||||||
background-color: #ffffff;
|
|
||||||
color: #666666;
|
|
||||||
border: 1px solid #e9ecf6;
|
|
||||||
font-size: 12px;
|
|
||||||
padding: 2px 8px;
|
|
||||||
position: relative;
|
|
||||||
top: -3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.workbench-title {
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #333333;
|
color: #333333;
|
||||||
padding: 15px 30rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-icon i.icon-tongzhi {
|
.app-center__grid {
|
||||||
font-size: 22px;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 28rpx 48rpx 40rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card {
|
||||||
|
position: relative;
|
||||||
|
width: 310rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
margin-bottom: 22rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
box-shadow: 0 6rpx 14rpx rgba(20, 40, 70, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card--pressed {
|
||||||
|
opacity: 0.88;
|
||||||
|
transform: scale(0.985);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card__bg {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 0;
|
||||||
|
opacity: 0.38;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card__mask {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card__quote {
|
||||||
|
position: absolute;
|
||||||
|
left: 14rpx;
|
||||||
|
top: 2rpx;
|
||||||
|
font-size: 48rpx;
|
||||||
|
line-height: 1;
|
||||||
|
color: rgba(255, 255, 255, 0.55);
|
||||||
|
font-weight: 700;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card__tag {
|
||||||
|
position: absolute;
|
||||||
|
top: 14rpx;
|
||||||
|
right: 48rpx;
|
||||||
|
padding: 2rpx 12rpx;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
background: #ffffff;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card__tag text {
|
||||||
|
font-size: 20rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card__body {
|
||||||
|
position: absolute;
|
||||||
|
left: 22rpx;
|
||||||
|
right: 22rpx;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-42%);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card__name {
|
||||||
|
display: block;
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card__en {
|
||||||
|
display: block;
|
||||||
|
margin-top: 8rpx;
|
||||||
|
font-size: 18rpx;
|
||||||
|
letter-spacing: 1rpx;
|
||||||
|
color: rgba(255, 255, 255, 0.88);
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card__arrow {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 48rpx;
|
||||||
|
height: 42rpx;
|
||||||
|
background: #eef1f4;
|
||||||
|
border-top-left-radius: 16rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-card__arrow text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #8a93a0;
|
||||||
|
line-height: 1;
|
||||||
|
margin-top: -4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-out {
|
||||||
|
background: #e14b3b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-out .menu-card__mask {
|
||||||
|
background: rgba(225, 75, 59, 0.72);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-out .menu-card__tag text {
|
||||||
|
color: #e14b3b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-stock {
|
||||||
|
background: #2f78e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-stock .menu-card__mask {
|
||||||
|
background: rgba(47, 120, 230, 0.72);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-stock .menu-card__tag text {
|
||||||
|
color: #2f78e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-in {
|
||||||
|
background: #3f51b5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-in .menu-card__mask {
|
||||||
|
background: rgba(63, 81, 181, 0.72);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tone-in .menu-card__tag text {
|
||||||
|
color: #3f51b5;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 204 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 137 KiB |
+9
-22
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
* Copyright (c) 2013-Now http://aidex.vip All rights reserved.
|
||||||
*/
|
*/
|
||||||
import config from '@/common/config.js';
|
import config, { getDefaultApiUrl } from '@/common/config.js';
|
||||||
import util from '@/common/util.js';
|
import util from '@/common/util.js';
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
@@ -19,21 +19,15 @@ try{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化API URL
|
// 初始化API URL(默认正式环境)
|
||||||
function initApiUrl() {
|
function initApiUrl() {
|
||||||
if (config.isDevelopment) {
|
const defaultUrl = getDefaultApiUrl();
|
||||||
// 开发环境:从存储读取,如果没有则使用测试环境
|
|
||||||
try {
|
try {
|
||||||
const savedApiUrl = uni.getStorageSync('ApiUrl');
|
uni.setStorageSync('ApiUrl', defaultUrl);
|
||||||
return savedApiUrl || config.devApiUrlOptions[0].value;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('读取存储的 apiurl 失败', e);
|
console.log('写入正式环境地址失败', e);
|
||||||
return config.devApiUrlOptions[0].value;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 生产环境:使用固定的生产URL
|
|
||||||
return config.productionApiUrl;
|
|
||||||
}
|
}
|
||||||
|
return defaultUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 需要永久存储,且下次APP启动需要取出的,在state中的变量名
|
// 需要永久存储,且下次APP启动需要取出的,在state中的变量名
|
||||||
@@ -105,13 +99,7 @@ const store = new Vuex.Store({
|
|||||||
state.vuex_notificationAudio = audio;
|
state.vuex_notificationAudio = audio;
|
||||||
},
|
},
|
||||||
SET_API_URL(state, url) {
|
SET_API_URL(state, url) {
|
||||||
// 生产环境不允许修改URL
|
|
||||||
if (!config.isDevelopment) {
|
|
||||||
console.warn('生产环境不允许修改API URL');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
state.apiurl = url
|
state.apiurl = url
|
||||||
// 同时保存到本地存储
|
|
||||||
uni.setStorageSync('ApiUrl', url)
|
uni.setStorageSync('ApiUrl', url)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -173,6 +161,9 @@ const store = new Vuex.Store({
|
|||||||
uni.request({
|
uni.request({
|
||||||
url: util.apiurl + "/product/fpmArrangeOrder/getFpmArrangeOrderList",
|
url: util.apiurl + "/product/fpmArrangeOrder/getFpmArrangeOrderList",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
sslVerify: false,
|
||||||
|
// #endif
|
||||||
header: {
|
header: {
|
||||||
platform: "2",
|
platform: "2",
|
||||||
Authorization: uni.getStorageSync("RemoteTokenData").token,
|
Authorization: uni.getStorageSync("RemoteTokenData").token,
|
||||||
@@ -221,10 +212,6 @@ const store = new Vuex.Store({
|
|||||||
name: 'vuex_messageList',
|
name: 'vuex_messageList',
|
||||||
value: newList
|
value: newList
|
||||||
});
|
});
|
||||||
uni.setTabBarBadge({
|
|
||||||
index: 0,
|
|
||||||
text: `${newList.length}`
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// 使用 $uStore 方式更新状态
|
// 使用 $uStore 方式更新状态
|
||||||
commit('$uStore', {
|
commit('$uStore', {
|
||||||
|
|||||||
@@ -37,11 +37,12 @@ class AppDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 显示
|
// 显示
|
||||||
show(apkUrl, changelog) {
|
show(apkUrl, changelog, latestVersion = '') {
|
||||||
this.drawView(changelog)
|
this.drawView(changelog)
|
||||||
this.maskEl.show()
|
this.maskEl.show()
|
||||||
this.popupEl.show()
|
this.popupEl.show()
|
||||||
this.apkUrl = apkUrl;
|
this.apkUrl = apkUrl;
|
||||||
|
this.latestVersion = latestVersion || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 隐藏
|
// 隐藏
|
||||||
@@ -309,8 +310,12 @@ class AppDialog {
|
|||||||
const buttonWidth = (this.viewWidth - this.viewPadding) / 2;
|
const buttonWidth = (this.viewWidth - this.viewPadding) / 2;
|
||||||
if (e.clientY > maxTop - 40 && e.clientY < maxTop) {
|
if (e.clientY > maxTop - 40 && e.clientY < maxTop) {
|
||||||
if (showCancel) {
|
if (showCancel) {
|
||||||
// 取消
|
// 取消:记住已跳过的版本,登录页自动检查不再弹出
|
||||||
// if(e.clientX>this.viewPadding && e.clientX<maxLeft-buttonWidth-this.viewPadding){}
|
if (e.clientX > this.viewPadding && e.clientX < this.viewPadding + buttonWidth) {
|
||||||
|
if (this.latestVersion) {
|
||||||
|
uni.setStorageSync('appUpdateDismissedVersion', String(this.latestVersion));
|
||||||
|
}
|
||||||
|
}
|
||||||
// 确定
|
// 确定
|
||||||
if (e.clientX > maxLeft - buttonWidth && e.clientX < maxLeft) {
|
if (e.clientX > maxLeft - buttonWidth && e.clientX < maxLeft) {
|
||||||
upgrade.checkOs(this.apkUrl)
|
upgrade.checkOs(this.apkUrl)
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ class CheckUpate{
|
|||||||
if(res.status===1){
|
if(res.status===1){
|
||||||
const path=res.path || '';
|
const path=res.path || '';
|
||||||
const changeLog=res.changelog || '';
|
const changeLog=res.changelog || '';
|
||||||
appDialog.show(path,changeLog);
|
const latestVersion=res.latest_version || '';
|
||||||
|
appDialog.show(path,changeLog,latestVersion);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.storageTimeStamp()
|
this.storageTimeStamp()
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ module.exports = {
|
|||||||
'process.env': {
|
'process.env': {
|
||||||
...definitions[0]['process.env'],
|
...definitions[0]['process.env'],
|
||||||
VUE_APP_UPGRADE_NAME: JSON.stringify(process.env.VUE_APP_UPGRADE_NAME),
|
VUE_APP_UPGRADE_NAME: JSON.stringify(process.env.VUE_APP_UPGRADE_NAME),
|
||||||
|
VUE_APP_UPGRADE_CDN_PREFIX: JSON.stringify(process.env.VUE_APP_UPGRADE_CDN_PREFIX),
|
||||||
VUE_APP_PRODUCTION_API_URL: JSON.stringify(process.env.VUE_APP_PRODUCTION_API_URL),
|
VUE_APP_PRODUCTION_API_URL: JSON.stringify(process.env.VUE_APP_PRODUCTION_API_URL),
|
||||||
VUE_APP_DEV_API_URL: JSON.stringify(process.env.VUE_APP_DEV_API_URL),
|
VUE_APP_DEV_API_URL: JSON.stringify(process.env.VUE_APP_DEV_API_URL),
|
||||||
VUE_APP_ENV_NAME: JSON.stringify(process.env.VUE_APP_ENV_NAME),
|
VUE_APP_ENV_NAME: JSON.stringify(process.env.VUE_APP_ENV_NAME),
|
||||||
|
|||||||
@@ -1,593 +0,0 @@
|
|||||||
{
|
|
||||||
"openapi": "3.0.1",
|
|
||||||
"info": {
|
|
||||||
"title": "默认模块",
|
|
||||||
"description": "erp管理系统",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"contact": {}
|
|
||||||
},
|
|
||||||
"tags": [
|
|
||||||
{
|
|
||||||
"name": "【PDA-坯布出仓单】"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"paths": {
|
|
||||||
"/hcscm_weave/pda/v1/grey_fabric_manage/gfmOtherDeliveryOrder/updateGfmOtherDeliveryOrder": {
|
|
||||||
"put": {
|
|
||||||
"summary": "PDA扫码新增/删除坯布出仓单细码",
|
|
||||||
"deprecated": false,
|
|
||||||
"description": "扫描坯布条码进行新增或删除;操作完成后返回最新出仓单详情(含表头、详情及细码),供前端刷新展示",
|
|
||||||
"tags": [
|
|
||||||
"【PDA-坯布出仓单】"
|
|
||||||
],
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "Platform",
|
|
||||||
"in": "header",
|
|
||||||
"description": "终端ID",
|
|
||||||
"required": true,
|
|
||||||
"example": "",
|
|
||||||
"schema": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Authorization",
|
|
||||||
"in": "header",
|
|
||||||
"description": "token",
|
|
||||||
"required": true,
|
|
||||||
"example": "",
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/grey_fabric_manage.PDAScanGfmOtherDeliveryOrderParam"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/grey_fabric_manage.GetGfmOtherDeliveryOrderData"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"headers": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"ApiKeyAuth": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"components": {
|
|
||||||
"schemas": {
|
|
||||||
"common.BusinessClose": {
|
|
||||||
"type": "integer",
|
|
||||||
"enum": [
|
|
||||||
1,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
"x-enum-comments": {
|
|
||||||
"BusinessCloseNo": "开启",
|
|
||||||
"BusinessCloseYes": "关闭"
|
|
||||||
},
|
|
||||||
"x-enum-varnames": [
|
|
||||||
"BusinessCloseNo",
|
|
||||||
"BusinessCloseYes"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"common.OrderStatus": {
|
|
||||||
"type": "integer",
|
|
||||||
"enum": [
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
4
|
|
||||||
],
|
|
||||||
"x-enum-comments": {
|
|
||||||
"OrderStatusAudited": "已审核",
|
|
||||||
"OrderStatusPendingAudit": "待审核",
|
|
||||||
"OrderStatusRejected": "已驳回",
|
|
||||||
"OrderStatusVoided": "已作废"
|
|
||||||
},
|
|
||||||
"x-enum-varnames": [
|
|
||||||
"OrderStatusPendingAudit",
|
|
||||||
"OrderStatusAudited",
|
|
||||||
"OrderStatusRejected",
|
|
||||||
"OrderStatusVoided"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"grey_fabric_manage.GetGfmOtherDeliveryOrderData": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"audit_status": {
|
|
||||||
"description": "审核状态",
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/common.OrderStatus"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"audit_status_name": {
|
|
||||||
"description": "审核状态name",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"audit_time": {
|
|
||||||
"description": "审核时间",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"auditer_id": {
|
|
||||||
"description": "审核人ID (关联user.id)",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"auditer_name": {
|
|
||||||
"description": "审核人名称",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"business_close": {
|
|
||||||
"description": "业务关闭",
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/common.BusinessClose"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"business_close_name": {
|
|
||||||
"description": "业务关闭状态name",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"business_close_time": {
|
|
||||||
"description": "业务关闭时间",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"business_close_user_id": {
|
|
||||||
"description": "业务关闭操作人",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"business_close_user_name": {
|
|
||||||
"description": "业务关闭操作人名",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"business_unit_id": {
|
|
||||||
"description": "往来单位id,必填",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"business_unit_name": {
|
|
||||||
"description": "往来单位name",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"create_time": {
|
|
||||||
"description": "创建时间",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"creator_id": {
|
|
||||||
"description": "创建人",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"creator_name": {
|
|
||||||
"description": "创建人",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"customer_id": {
|
|
||||||
"description": "该条码所属客户id",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"customer_name": {
|
|
||||||
"description": "该条码所属客户",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"delivery_time": {
|
|
||||||
"description": "出货日期,必",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"delivery_unit_id": {
|
|
||||||
"description": "出货单位id,必填",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"delivery_unit_name": {
|
|
||||||
"description": "出货单位name",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"department_id": {
|
|
||||||
"description": "下单用户所属部门",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"grey_fabric_code": {
|
|
||||||
"description": "坯布编号",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_level_id": {
|
|
||||||
"description": "坯布等级id",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"grey_fabric_level_name": {
|
|
||||||
"description": "坯布等级",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_name": {
|
|
||||||
"description": "坯布名称",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"id": {
|
|
||||||
"description": "记录ID",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"item_data": {
|
|
||||||
"description": "坯布信息",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/grey_fabric_manage.GetGfmOtherDeliveryOrderItemData"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"machine_number": {
|
|
||||||
"description": "机台号",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"number": {
|
|
||||||
"description": "编号流水:每日重新更新",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"order_no": {
|
|
||||||
"description": "单据编号",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"produce_order_no": {
|
|
||||||
"description": "生产通知单号",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"remark": {
|
|
||||||
"description": "备注",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"sale_system_id": {
|
|
||||||
"description": "营销体系id,必填",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"sale_system_name": {
|
|
||||||
"description": "营销体系name",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"scanned_total_roll": {
|
|
||||||
"description": "PDA扫码操作后补充返回的统计及当前条码信息",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"summary_stock_roll": {
|
|
||||||
"description": "该条码汇总库存条数",
|
|
||||||
"type": "number"
|
|
||||||
},
|
|
||||||
"total_roll": {
|
|
||||||
"description": "总匹数,0.01匹",
|
|
||||||
"type": "number"
|
|
||||||
},
|
|
||||||
"total_weight": {
|
|
||||||
"description": "总数量,xxx/g",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"update_time": {
|
|
||||||
"description": "修改时间",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"update_user_name": {
|
|
||||||
"description": "修改人",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"updater_id": {
|
|
||||||
"description": "修改人",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"volume_number": {
|
|
||||||
"description": "卷号",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"yarn_batch": {
|
|
||||||
"description": "纱批",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"grey_fabric_manage.GetGfmOtherDeliveryOrderItemData": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"create_time": {
|
|
||||||
"description": "创建时间",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"creator_id": {
|
|
||||||
"description": "创建人",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"creator_name": {
|
|
||||||
"description": "创建人",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"customer_id": {
|
|
||||||
"description": "客户id,必填",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"customer_name": {
|
|
||||||
"description": "客户名",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"gray_fabric_color_id": {
|
|
||||||
"description": "坯布颜色id",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"gray_fabric_color_name": {
|
|
||||||
"description": "颜色名",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_code": {
|
|
||||||
"description": "坯布编号,必",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_gram_weight": {
|
|
||||||
"description": "坯布克重",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_gram_weight_and_unit_name": {
|
|
||||||
"description": "坯布克重及单位名称",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_gram_weight_unit_id": {
|
|
||||||
"description": "坯布克重单位id(字典)",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"grey_fabric_gram_weight_unit_name": {
|
|
||||||
"description": "坯布克重单位名称",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_id": {
|
|
||||||
"description": "坯布id",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"grey_fabric_level_id": {
|
|
||||||
"description": "坯布等级id",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"grey_fabric_level_name": {
|
|
||||||
"description": "等级名",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_name": {
|
|
||||||
"description": "坯布名,必",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_other_delivery_id": {
|
|
||||||
"description": "坯布出货单id",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"grey_fabric_remark": {
|
|
||||||
"description": "坯布备注",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_width": {
|
|
||||||
"description": "坯布幅宽",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_width_and_unit_name": {
|
|
||||||
"description": "坯布幅宽及单位名称",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_width_unit_id": {
|
|
||||||
"description": "坯布幅宽单位id(字典)",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"grey_fabric_width_unit_name": {
|
|
||||||
"description": "坯布幅宽单位名称",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"id": {
|
|
||||||
"description": "记录ID",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"item_fc_data": {
|
|
||||||
"description": "细码",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/grey_fabric_manage.GetGfmOtherDeliveryOrderItemFineCodeData"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"machine_number": {
|
|
||||||
"description": "机台号",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"needle_size": {
|
|
||||||
"description": "针寸数",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"order_no": {
|
|
||||||
"description": "单据编号",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"raw_material_batch_brand": {
|
|
||||||
"description": "原料品牌",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"raw_material_batch_num": {
|
|
||||||
"description": "原料批号",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"raw_material_yarn_name": {
|
|
||||||
"description": "原料纱名",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"remark": {
|
|
||||||
"description": "备注",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"roll": {
|
|
||||||
"description": "出货匹数,必,乘100xx/0.01匹",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"total_weight": {
|
|
||||||
"description": "总数量,xxx/g;细码中所有数量字段总和",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"update_time": {
|
|
||||||
"description": "修改时间",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"update_user_name": {
|
|
||||||
"description": "修改人",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"updater_id": {
|
|
||||||
"description": "修改人",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"warehouse_sum_id": {
|
|
||||||
"description": "汇总库存id",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"weaving_process": {
|
|
||||||
"description": "织造工艺",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"yarn_batch": {
|
|
||||||
"description": "纱批",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"grey_fabric_manage.GetGfmOtherDeliveryOrderItemFineCodeData": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"bar_code": {
|
|
||||||
"description": "条码",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"create_time": {
|
|
||||||
"description": "创建时间",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"creator_id": {
|
|
||||||
"description": "创建人",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"creator_name": {
|
|
||||||
"description": "创建人",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"fabric_piece_code": {
|
|
||||||
"description": "条码",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"gfm_other_delivery_item_id": {
|
|
||||||
"description": "坯布出货信息id",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"grey_fabric_stock_id": {
|
|
||||||
"description": "坯布仓库-坯布库存id",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"id": {
|
|
||||||
"description": "记录ID",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"description": "仓位",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"roll": {
|
|
||||||
"description": "匹数,必;乘100xx/0.01匹",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"update_time": {
|
|
||||||
"description": "修改时间",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"update_user_name": {
|
|
||||||
"description": "修改人",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"updater_id": {
|
|
||||||
"description": "修改人",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"volume_number": {
|
|
||||||
"description": "卷号",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"warehouse_bin_id": {
|
|
||||||
"description": "仓位id",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"weight": {
|
|
||||||
"description": "数量,xxx/g",
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"grey_fabric_manage.PDAScanGfmOtherDeliveryOrderParam": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"grey_fabric_code_lock": {
|
|
||||||
"description": "坯布编号锁定",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"grey_fabric_level_id_lock": {
|
|
||||||
"description": "坯布等级锁定",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"id": {
|
|
||||||
"description": "坯布出仓单id,必填",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"machine_number_lock": {
|
|
||||||
"description": "机台锁定",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"produce_order_no_lock": {
|
|
||||||
"description": "生产通知单锁定",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"scan_code": {
|
|
||||||
"description": "扫描的坯布条码(细码条码fabric_piece_code 或 卷号volume_number),必填",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"scan_type": {
|
|
||||||
"description": "操作类型:1扫码新增 2扫码删除,必填",
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"yarn_batch_lock": {
|
|
||||||
"description": "纱批锁定",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {},
|
|
||||||
"securitySchemes": {
|
|
||||||
"ApiKeyAuth": {
|
|
||||||
"type": "apiKey",
|
|
||||||
"name": "Authorization",
|
|
||||||
"in": "header"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"servers": [],
|
|
||||||
"security": []
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user