Compare commits
456 Commits
master
...
hella_vue3
Author | SHA1 | Date |
---|---|---|
|
e17df7b0d8 | 7 months ago |
|
25daf96696 | 7 months ago |
|
37058e5c01 | 8 months ago |
|
30e0ca53c5 | 8 months ago |
|
0ec30d4e53 | 8 months ago |
|
2c810f50ec | 8 months ago |
|
40b32f5456 | 8 months ago |
|
cd6cf24520 | 8 months ago |
|
d072b12309 | 8 months ago |
|
a57256000c | 8 months ago |
|
a263602deb | 8 months ago |
|
a1faee9aac | 8 months ago |
|
31b19c23e4 | 8 months ago |
|
ce11ed696e | 8 months ago |
|
864430cdc4 | 8 months ago |
|
f0d3f18ddd | 8 months ago |
|
f1bdb1cfa8 | 8 months ago |
|
ffa29b802b | 8 months ago |
|
1952d7b7e8 | 8 months ago |
|
0b268ed2e2 | 8 months ago |
|
9190adbdd7 | 8 months ago |
|
e3618f70a9 | 8 months ago |
|
a574a49984 | 8 months ago |
|
53c44b1aa5 | 8 months ago |
|
cee85c60ff | 8 months ago |
|
eba5273896 | 8 months ago |
|
be04eb258d | 8 months ago |
|
0be5334006 | 8 months ago |
|
bbc67e3d70 | 8 months ago |
|
96f6b6ecaa | 8 months ago |
|
fc15060dc3 | 8 months ago |
|
2ec44be25d | 8 months ago |
|
042ebdecde | 8 months ago |
|
ea6f46aafe | 8 months ago |
|
694688ab65 | 8 months ago |
|
c1e7fcd245 | 8 months ago |
|
3a75b774ab | 8 months ago |
|
55af9befa2 | 8 months ago |
|
51b53d3e60 | 8 months ago |
|
8f66e72844 | 8 months ago |
|
316099aa54 | 8 months ago |
|
f1738c952f | 8 months ago |
|
38e1fc2f36 | 8 months ago |
|
da792b67bd | 8 months ago |
|
9ac369b992 | 8 months ago |
|
b8bdbac627 | 8 months ago |
|
91140e285a | 8 months ago |
|
11304e965d | 8 months ago |
|
834c19b9fb | 8 months ago |
|
1ad14f5a3e | 8 months ago |
|
e15df659f0 | 8 months ago |
|
302b6fca1c | 8 months ago |
|
445dff443a | 8 months ago |
|
827799f186 | 8 months ago |
|
3db82d1364 | 8 months ago |
|
5df309e342 | 8 months ago |
|
b0f22c3b28 | 8 months ago |
|
21a6f3a18a | 8 months ago |
|
5ef62fb37b | 8 months ago |
|
cb439eddf6 | 8 months ago |
|
410d81dc87 | 8 months ago |
|
03dc9caab4 | 8 months ago |
|
04890c1922 | 8 months ago |
|
4ae564d47e | 8 months ago |
|
96d26ac908 | 8 months ago |
|
254b563563 | 8 months ago |
|
7c12adc9f1 | 8 months ago |
|
ee8d706cb0 | 8 months ago |
|
b7647bb2f8 | 8 months ago |
|
8be7a296ac | 8 months ago |
|
4a10ab1e6e | 8 months ago |
|
54ddb6bef0 | 8 months ago |
|
212472f628 | 8 months ago |
|
1b4c4f21d5 | 8 months ago |
|
cb34c0e8a0 | 8 months ago |
|
cd3690cf4d | 8 months ago |
|
5d17be69be | 8 months ago |
|
8fdb2017d3 | 8 months ago |
|
7beaec532f | 8 months ago |
|
164f9595d6 | 8 months ago |
|
f2e6ce3838 | 8 months ago |
|
47c6716e47 | 8 months ago |
|
3cb5df117e | 8 months ago |
|
6ceb4108a8 | 8 months ago |
|
0589b23409 | 8 months ago |
|
5d9c296c5a | 8 months ago |
|
7adcef4d12 | 8 months ago |
|
b3d5a0aae1 | 8 months ago |
|
a916ae924b | 8 months ago |
|
49f63a9d8c | 8 months ago |
|
7eece6e49d | 8 months ago |
|
004f472040 | 8 months ago |
|
021a678e4d | 8 months ago |
|
74555ce7ad | 8 months ago |
|
668899df83 | 8 months ago |
|
f02b5a87a6 | 8 months ago |
|
c2ced0d734 | 8 months ago |
|
ab9058e744 | 8 months ago |
|
05c24a6a4c | 8 months ago |
|
4e55a8dcf6 | 8 months ago |
|
a6c14baa6c | 8 months ago |
|
e65e75151a | 8 months ago |
|
4920e82c6d | 8 months ago |
|
ac0efd189d | 8 months ago |
|
d2aa7e2f89 | 8 months ago |
|
5f53730dec | 8 months ago |
|
cc3a2d8878 | 8 months ago |
|
6106c5630b | 8 months ago |
|
82f202f5a3 | 8 months ago |
|
97c69365d7 | 8 months ago |
|
61ecba7dc9 | 8 months ago |
|
e08be65e79 | 8 months ago |
|
9e3e4b8fe4 | 8 months ago |
|
dbac1e67da | 8 months ago |
|
1f88f83fe1 | 8 months ago |
|
559cf97eef | 8 months ago |
|
ce51bd898a | 8 months ago |
|
eb9685ff6a | 8 months ago |
|
cfc15c1f53 | 8 months ago |
|
3f7a11fbf2 | 8 months ago |
|
d83f7fd700 | 8 months ago |
|
df2c6f785c | 8 months ago |
|
2c3c3c4079 | 8 months ago |
|
fe40054d40 | 8 months ago |
|
6edd503bcd | 8 months ago |
|
97fded5ac0 | 8 months ago |
|
2572452cb1 | 8 months ago |
|
3ba05343e1 | 8 months ago |
|
0c8ffb7dd1 | 8 months ago |
|
ac3e5f0b15 | 8 months ago |
|
686d24393e | 8 months ago |
|
9d97501d95 | 8 months ago |
|
b82074dcd1 | 8 months ago |
|
ac5f44c92c | 8 months ago |
|
f002e441d9 | 8 months ago |
|
d3517108ba | 8 months ago |
|
8f6548874b | 8 months ago |
|
0c1650388e | 8 months ago |
|
43a8310ed5 | 8 months ago |
|
9e78826694 | 8 months ago |
|
fa45e596da | 8 months ago |
|
e7d8e04fb9 | 8 months ago |
|
10d14adeaa | 8 months ago |
|
d8bcc17a31 | 8 months ago |
|
438d3861b9 | 8 months ago |
|
461c4a2c48 | 8 months ago |
|
bae3f57070 | 8 months ago |
|
265f698119 | 8 months ago |
|
87440a1b8c | 8 months ago |
|
505f232192 | 8 months ago |
|
dc45abe72e | 8 months ago |
|
f1bf3e34de | 8 months ago |
|
9fd445780a | 8 months ago |
|
944073e0aa | 8 months ago |
|
c1a8c7a336 | 8 months ago |
|
f3a7deb83e | 8 months ago |
|
c83b393163 | 8 months ago |
|
fa9dcc68bb | 8 months ago |
|
bfc14865fa | 8 months ago |
|
af8d109dee | 8 months ago |
|
0d4d745829 | 8 months ago |
|
62f956ab1c | 8 months ago |
|
f50a44b1d9 | 8 months ago |
|
ab8028619b | 8 months ago |
|
376a5d1276 | 8 months ago |
|
4f503a5380 | 8 months ago |
|
d5d225702d | 8 months ago |
|
024d5920e7 | 8 months ago |
|
177277872b | 8 months ago |
|
c695154058 | 8 months ago |
|
5d0d83aa2d | 8 months ago |
|
8137a35465 | 8 months ago |
|
11051c9dc0 | 8 months ago |
|
4b558ba646 | 8 months ago |
|
fd6c6b4c10 | 8 months ago |
|
3fabf36d7c | 8 months ago |
|
213bc7d37b | 8 months ago |
|
094cf0bfee | 8 months ago |
|
550638a5d0 | 8 months ago |
|
dfceaf0fa1 | 8 months ago |
|
43c8627cae | 8 months ago |
|
b847d241e5 | 8 months ago |
|
64b42e0e71 | 8 months ago |
|
868b356a37 | 8 months ago |
|
63202ac8eb | 8 months ago |
|
7263bc3161 | 8 months ago |
|
ad6b121a96 | 8 months ago |
|
30c6f6c4be | 8 months ago |
|
03bb07e415 | 8 months ago |
|
3c7760b8a7 | 8 months ago |
|
4a68d7201a | 8 months ago |
|
84cc39bcc9 | 8 months ago |
|
ff9a9f009e | 8 months ago |
|
8f429b6630 | 8 months ago |
|
3b54cba6d7 | 8 months ago |
|
ad777dca57 | 8 months ago |
|
d63b25e478 | 8 months ago |
|
b4a7995882 | 8 months ago |
|
c54583182d | 8 months ago |
|
d181863e03 | 8 months ago |
|
1c5e3ad92c | 8 months ago |
|
6f0995ad7a | 8 months ago |
|
5b5637ce20 | 8 months ago |
|
2b6bd254f7 | 8 months ago |
|
248212a279 | 8 months ago |
|
31a4cc5bf4 | 8 months ago |
|
24f67a1282 | 8 months ago |
|
7d7505a21e | 8 months ago |
|
054900db97 | 8 months ago |
|
24e9ab2fff | 8 months ago |
|
5ba9676fcc | 8 months ago |
|
9e6c5635e7 | 8 months ago |
|
9614bd465e | 8 months ago |
|
129b933893 | 8 months ago |
|
a26e5dd64b | 8 months ago |
|
3ed1a278b7 | 8 months ago |
|
b0e7fe5312 | 8 months ago |
|
31db3d40ab | 8 months ago |
|
6553b2d0ee | 8 months ago |
|
5bdeabd63d | 8 months ago |
|
c0ee72332a | 8 months ago |
|
64b3fe6db4 | 8 months ago |
|
8f22527b8f | 8 months ago |
|
5d104109b1 | 8 months ago |
|
c832238124 | 8 months ago |
|
d01008daef | 8 months ago |
|
2f3e13c12f | 8 months ago |
|
0ca8be2cc4 | 8 months ago |
|
d275bbf7f4 | 10 months ago |
|
5328d2119f | 10 months ago |
|
9fb38ff589 | 10 months ago |
|
38fe15dd4a | 10 months ago |
|
22760b8409 | 10 months ago |
|
ccaad1ca3c | 10 months ago |
|
1b5df5fded | 10 months ago |
|
0eb9eee7d8 | 10 months ago |
|
d0cd063493 | 10 months ago |
|
d716fe237e | 10 months ago |
|
64ea8ebeca | 10 months ago |
|
323b67c8ad | 10 months ago |
|
ebdcfa896c | 10 months ago |
|
becd817108 | 10 months ago |
|
d02c823304 | 10 months ago |
|
7453288b2e | 10 months ago |
|
a5e1e583a6 | 10 months ago |
|
f328e61e08 | 10 months ago |
|
63ee947b31 | 10 months ago |
|
bf7b78223c | 10 months ago |
|
4ec6b3e2cd | 10 months ago |
|
f4097fede8 | 10 months ago |
|
5a00aaf5c8 | 10 months ago |
|
ec66fc3df6 | 10 months ago |
|
feb4d0d534 | 10 months ago |
|
c578b157ef | 10 months ago |
|
116a5598ce | 10 months ago |
|
305a135735 | 10 months ago |
|
88613d0eb2 | 10 months ago |
|
1335f3861c | 10 months ago |
|
d7b9b77c7e | 10 months ago |
|
edf39d9f04 | 10 months ago |
|
c56c4bc515 | 10 months ago |
|
973f959f3b | 10 months ago |
|
a3b06a49b1 | 10 months ago |
|
accc0e1eb0 | 10 months ago |
|
541253d6c5 | 10 months ago |
|
cc68fcbff0 | 10 months ago |
|
e859de7dd4 | 10 months ago |
|
42fb46c61e | 10 months ago |
|
0d9f96fbe6 | 10 months ago |
|
5e3a333c90 | 10 months ago |
|
a148be3127 | 10 months ago |
|
48e2bd6cbc | 10 months ago |
|
ad4adbc25a | 10 months ago |
|
e634cd5cdd | 10 months ago |
|
9dbe73d0b5 | 10 months ago |
|
7ec6a5ffb2 | 10 months ago |
|
adff8617c9 | 10 months ago |
|
1cdec1142b | 10 months ago |
|
6ec83002d5 | 10 months ago |
|
4a414161a8 | 10 months ago |
|
6659954fbe | 10 months ago |
|
584377da42 | 10 months ago |
|
a99f65dfeb | 10 months ago |
|
82eaf91bbb | 10 months ago |
|
0e0e0323e4 | 10 months ago |
|
eff81553fe | 10 months ago |
|
1cfb4b8579 | 10 months ago |
|
a9d0069afe | 10 months ago |
|
cf7d600add | 10 months ago |
|
937c7574be | 10 months ago |
|
f609957e14 | 10 months ago |
|
804cde655f | 10 months ago |
|
bc919bf89e | 10 months ago |
|
cb5964dbc2 | 10 months ago |
|
9458c72085 | 10 months ago |
|
394d381373 | 10 months ago |
|
33a59d5e26 | 10 months ago |
|
3aa0d74ab5 | 10 months ago |
|
e497412681 | 10 months ago |
|
c7d93b865c | 10 months ago |
|
b5c618d7d6 | 10 months ago |
|
59a863a9e6 | 10 months ago |
|
922a6ca3ea | 10 months ago |
|
a129f7420c | 10 months ago |
|
4c26aa814c | 10 months ago |
|
72f8f62986 | 10 months ago |
|
ff0649af5e | 10 months ago |
|
2e62d67844 | 10 months ago |
|
1c12bb1a47 | 10 months ago |
|
ac0f8cb931 | 1 year ago |
|
f017805d76 | 1 year ago |
|
3e278ce6e2 | 1 year ago |
|
18a518be06 | 1 year ago |
|
61084b90ca | 1 year ago |
|
2f61b30b4b | 1 year ago |
|
6cb5b7840a | 1 year ago |
|
143e95c540 | 1 year ago |
|
fbe96a097b | 1 year ago |
|
95de5ee2b3 | 1 year ago |
|
11a0986d6b | 1 year ago |
|
965f7e81cc | 1 year ago |
|
b023fad1f0 | 1 year ago |
|
dfd3742667 | 1 year ago |
|
f6f44c02bb | 1 year ago |
|
e19c63b2d3 | 1 year ago |
|
2fcc173aad | 1 year ago |
|
25eb91a677 | 1 year ago |
|
813738ef39 | 1 year ago |
|
191a9ca271 | 1 year ago |
|
0dbb038e57 | 1 year ago |
|
11609288fb | 1 year ago |
|
9b0818564b | 1 year ago |
|
c7ef460c8a | 1 year ago |
|
aac9333bc9 | 1 year ago |
|
becd39f135 | 1 year ago |
|
9725bd4a7a | 1 year ago |
|
ab46faec0a | 1 year ago |
|
0ba1a3439d | 1 year ago |
|
e092299817 | 1 year ago |
|
4109a37d70 | 1 year ago |
|
3945e8c62c | 1 year ago |
|
0459a9b101 | 1 year ago |
|
501062b03b | 1 year ago |
|
06c418c66c | 1 year ago |
|
96978e396a | 1 year ago |
|
832778a318 | 1 year ago |
|
77d6dc77d6 | 1 year ago |
|
ddb00b8e8c | 1 year ago |
|
3100ee0625 | 1 year ago |
|
f3ad067992 | 1 year ago |
|
00e5d71199 | 1 year ago |
|
2d2b0928a2 | 1 year ago |
|
0ad4051cbc | 1 year ago |
|
2a61a76747 | 1 year ago |
|
b2996bc205 | 1 year ago |
|
a16bdb3639 | 1 year ago |
|
1f35ccc894 | 1 year ago |
|
6f09def9de | 1 year ago |
|
11598d0fe9 | 1 year ago |
|
4f628eef9f | 1 year ago |
|
7eb925f20d | 1 year ago |
|
de241ef8f6 | 1 year ago |
|
26981d77e1 | 1 year ago |
|
64831c1f73 | 1 year ago |
|
19a677fcc1 | 1 year ago |
|
4da7dcc15f | 1 year ago |
|
e209873949 | 1 year ago |
|
2981c09a62 | 1 year ago |
|
97fb039d25 | 1 year ago |
|
ebe3e03872 | 1 year ago |
|
77d44406e0 | 1 year ago |
|
033dbb39d0 | 1 year ago |
|
29284fb824 | 1 year ago |
|
13039715d5 | 1 year ago |
|
a197bf484f | 1 year ago |
|
725adb6a5c | 1 year ago |
|
558b3b400e | 1 year ago |
|
a8d2d7e890 | 1 year ago |
|
fff686d287 | 1 year ago |
|
9525533074 | 1 year ago |
|
1ec30743b1 | 1 year ago |
|
dfb9194b13 | 1 year ago |
|
5c9165bc75 | 1 year ago |
|
49959e3862 | 1 year ago |
|
9bda5815a0 | 1 year ago |
|
b2bb54b6c7 | 1 year ago |
|
0ba5894242 | 1 year ago |
|
e07512faf6 | 1 year ago |
|
2a2509e2d4 | 1 year ago |
|
0a1235c223 | 1 year ago |
|
677a9f7d10 | 1 year ago |
|
d9fb5fecc5 | 1 year ago |
|
837339efb0 | 1 year ago |
|
44a8f369d5 | 1 year ago |
|
e2f9b05134 | 1 year ago |
|
9582c1d183 | 1 year ago |
|
95c6594fa3 | 1 year ago |
|
4fc1029961 | 1 year ago |
|
e50e73f3e0 | 1 year ago |
|
6241e913ae | 1 year ago |
|
8d354069eb | 1 year ago |
|
244c2042c9 | 1 year ago |
|
07082655da | 1 year ago |
|
351ae12524 | 1 year ago |
|
9a7677546f | 1 year ago |
|
f5d1e37384 | 1 year ago |
|
3462f73287 | 1 year ago |
|
ab69394079 | 1 year ago |
|
7cd4df004d | 1 year ago |
|
cf3e1311fd | 1 year ago |
|
c0c637388a | 1 year ago |
|
4f173f179d | 1 year ago |
|
e83e6a4512 | 1 year ago |
|
d27bcf2313 | 1 year ago |
|
e31d10e346 | 1 year ago |
|
f796ccac69 | 1 year ago |
|
b8ff5958ad | 1 year ago |
|
c4450633fb | 1 year ago |
|
8c54221efa | 1 year ago |
|
eb44fa07b8 | 1 year ago |
|
04997d2d1e | 1 year ago |
|
ac9d1b0458 | 1 year ago |
|
086fc126d9 | 1 year ago |
|
061f57a2f5 | 1 year ago |
|
3b1fcc747d | 1 year ago |
|
db2b76947e | 1 year ago |
|
3cffde3b2f | 1 year ago |
|
98f6a409bd | 1 year ago |
|
8e4ce6de11 | 1 year ago |
|
f6b5639e6d | 1 year ago |
|
f5d2e2ace1 | 1 year ago |
|
fe91a3f283 | 1 year ago |
|
5ca1cc49e7 | 1 year ago |
|
3167e9e482 | 1 year ago |
|
32c46f219c | 1 year ago |
|
3c19692f8e | 1 year ago |
|
c8519dfc3d | 1 year ago |
|
2fd174658e | 1 year ago |
|
1fa968c4ae | 1 year ago |
|
a8353597d4 | 1 year ago |
|
cae517392c | 1 year ago |
|
4467f0a6b1 | 1 year ago |
|
67a30941d2 | 1 year ago |
|
927b162255 | 1 year ago |
|
3851d362da | 1 year ago |
|
c342722ca9 | 1 year ago |
|
c1bb7601b0 | 1 year ago |
|
29c71637f5 | 1 year ago |
|
6b63aaf4d4 | 1 year ago |
|
9610965086 | 1 year ago |
|
6d3fdb8c57 | 1 year ago |
|
1df31bb8bc | 1 year ago |
|
bd9e6a0afb | 1 year ago |
|
068bd7c003 | 1 year ago |
|
da4c5c11e2 | 1 year ago |
|
be9985d925 | 1 year ago |
1109 changed files with 139908 additions and 113792 deletions
@ -0,0 +1,71 @@ |
|||
// @ts-check
|
|||
/** @type {import('cz-git').UserConfig} */ |
|||
module.exports = { |
|||
extends: ['@commitlint/config-conventional'], |
|||
rules: { |
|||
'body-leading-blank': [2, 'always'], |
|||
'footer-leading-blank': [1, 'always'], |
|||
'header-max-length': [2, 'always', 108], |
|||
'subject-empty': [2, 'never'], |
|||
'type-empty': [2, 'never'], |
|||
'subject-case': [0], |
|||
'type-enum': [ |
|||
2, |
|||
'always', |
|||
[ |
|||
'feat', |
|||
'fix', |
|||
'perf', |
|||
'style', |
|||
'docs', |
|||
'test', |
|||
'refactor', |
|||
'build', |
|||
'ci', |
|||
'chore', |
|||
'revert', |
|||
'wip', |
|||
'workflow', |
|||
'types', |
|||
'release' |
|||
] |
|||
] |
|||
}, |
|||
prompt: { |
|||
// 中英文对照版
|
|||
// messages: {
|
|||
// type: '选择你要提交的类型 :',
|
|||
// scope: '选择一个提交范围 (可选):',
|
|||
// customScope: '请输入自定义的提交范围 :',
|
|||
// subject: '填写简短精炼的变更描述 :\n',
|
|||
// body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n',
|
|||
// breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n',
|
|||
// footerPrefixsSelect: '选择关联issue前缀 (可选):',
|
|||
// customFooterPrefixs: '输入自定义issue前缀 :',
|
|||
// footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
|
|||
// confirmCommit: '是否提交或修改commit ?'
|
|||
// },
|
|||
// types: [
|
|||
// { value: 'feat', name: 'feat: 新增功能' },
|
|||
// { value: 'fix', name: 'fix: 修复缺陷' },
|
|||
// { value: 'docs', name: 'docs: 文档变更' },
|
|||
// { value: 'style', name: 'style: 代码格式' },
|
|||
// { value: 'refactor', name: 'refactor: 代码重构' },
|
|||
// { value: 'perf', name: 'perf: 性能优化' },
|
|||
// { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' },
|
|||
// {
|
|||
// value: 'build',
|
|||
// name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)'
|
|||
// },
|
|||
// { value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
|
|||
// { value: 'revert', name: 'revert: 回滚 commit' },
|
|||
// {
|
|||
// value: 'chore',
|
|||
// name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)'
|
|||
// },
|
|||
// { value: 'wip', name: 'wip: 正在开发中' },
|
|||
// { value: 'workflow', name: 'workflow: 工作流程改进' },
|
|||
// { value: 'types', name: 'types: 类型定义文件修改' }
|
|||
// ]
|
|||
} |
|||
} |
@ -0,0 +1,15 @@ |
|||
VITE_BASE_URL=http://localhost:12080/admin-api |
|||
#VITE_BASE_URL=http://dev.ccwin-in.com:28051/api/admin-api |
|||
# VITE_BASE_URL_IMAGE=http://172.22.32.9:81/admin-api |
|||
|
|||
# 租户配置 |
|||
VITE_TENANT='[{"text":"英泰","value":1}]' |
|||
|
|||
# 是否是测试环境 |
|||
VITE_isDevelopment=true |
|||
|
|||
# 积木报表请求路径 |
|||
VITE_JMREPORT_BASE_URL='http://172.22.32.9:90' |
|||
|
|||
# 项目管理模式 批次货/包装 |
|||
VITE_MANAGE_MODEL="BY_BATCH" |
@ -0,0 +1,11 @@ |
|||
VITE_BASE_URL=http://172.21.32.13:81/api/admin-api |
|||
VITE_BASE_URL_IMAGE=http://172.21.32.13:81/admin-api |
|||
|
|||
# 租户配置 |
|||
VITE_TENANT='[{"text":"长春","value":1}]' |
|||
|
|||
# 是否是测试环境 |
|||
VITE_isDevelopment=false |
|||
|
|||
# 积木报表请求路径 |
|||
VITE_JMREPORT_BASE_URL='http://172.21.32.13:90' |
@ -0,0 +1,11 @@ |
|||
VITE_BASE_URL=http://172.21.32.14:81/api/admin-api |
|||
VITE_BASE_URL_IMAGE=http://172.21.32.14:81/admin-api |
|||
|
|||
# 租户配置 |
|||
VITE_TENANT='[{"text":"长春","value":1}]' |
|||
|
|||
# 是否是测试环境 |
|||
VITE_isDevelopment=false |
|||
|
|||
# 积木报表请求路径 |
|||
VITE_JMREPORT_BASE_URL='http://172.21.32.14:90' |
@ -0,0 +1,11 @@ |
|||
VITE_BASE_URL=https://scp.faway-hella.com:81/api/admin-api |
|||
VITE_BASE_URL_IMAGE=https://scp.faway-hella.com:81/admin-api |
|||
|
|||
# 租户配置 |
|||
VITE_TENANT='[{"text":"长春","value":1}]' |
|||
|
|||
# 是否是测试环境 |
|||
VITE_isDevelopment=false |
|||
|
|||
# 积木报表请求路径 |
|||
VITE_JMREPORT_BASE_URL='https://scp.faway-hella.com' |
@ -0,0 +1,11 @@ |
|||
VITE_BASE_URL=https://scptest.faway-hella.com:81/api/admin-api |
|||
VITE_BASE_URL_IMAGE=https://scptest.faway-hella.com:81/admin-api |
|||
|
|||
# 租户配置 |
|||
VITE_TENANT='[{"text":"长春","value":1},{"text":"成都","value":2}]' |
|||
|
|||
# 是否是测试环境 |
|||
VITE_isDevelopment=false |
|||
|
|||
# 积木报表请求路径 |
|||
VITE_JMREPORT_BASE_URL='https://scptest.faway-hella.com' |
@ -0,0 +1,12 @@ |
|||
VITE_BASE_URL=http://172.22.32.8:81/api/admin-api |
|||
VITE_BASE_URL_IMAGE=http://172.22.32.8:81/admin-api |
|||
|
|||
# 租户配置 |
|||
VITE_TENANT='[{"text":"成都","value":2}]' |
|||
|
|||
# 是否是测试环境 |
|||
VITE_isDevelopment=false |
|||
|
|||
|
|||
# 积木报表请求路径 |
|||
VITE_JMREPORT_BASE_URL='http://172.22.32.8:90' |
@ -0,0 +1,11 @@ |
|||
VITE_BASE_URL=http://172.22.32.9:81/api/admin-api |
|||
VITE_BASE_URL_IMAGE=http://172.22.32.9:81/admin-api |
|||
|
|||
# 租户配置 |
|||
VITE_TENANT='[{"text":"成都","value":2}]' |
|||
|
|||
# 是否是测试环境 |
|||
VITE_isDevelopment=false |
|||
|
|||
# 积木报表请求路径 |
|||
VITE_JMREPORT_BASE_URL='http://172.22.32.9:90' |
@ -0,0 +1,7 @@ |
|||
VITE_BASE_URL=http://172.21.32.14:81/api/admin-api
VITE_BASE_URL_IMAGE=http://172.21.32.14:81/admin-api
# 租户配置
VITE_TENANT='[{"text":"长春","value":1},{"text":"成都","value":2}]' |
|||
|
|||
# 是否是测试环境 |
|||
VITE_isDevelopment=false |
|||
|
|||
# 积木报表请求路径 |
|||
VITE_JMREPORT_BASE_URL='http://172.21.32.14:90' |
@ -0,0 +1,12 @@ |
|||
|
|||
VITE_BASE_URL=http://dev.ccwin-in.com:25300/api/admin-api |
|||
VITE_BASE_URL_IMAGE=http://dev.ccwin-in.com:25300/admin-api |
|||
|
|||
# 租户配置 |
|||
VITE_TENANT='[{"text":"长春","value":1},{"text":"成都","value":2}]' |
|||
|
|||
# 是否是测试环境 |
|||
VITE_isDevelopment=false |
|||
|
|||
# 积木报表请求路径 |
|||
VITE_JMREPORT_BASE_URL='http://dev.ccwin-in.com:25310' |
@ -0,0 +1,2 @@ |
|||
dist |
|||
*.nvue |
@ -0,0 +1,49 @@ |
|||
{ |
|||
"parser": "vue-eslint-parser", |
|||
"env": { |
|||
"browser": true, |
|||
"commonjs": true, |
|||
"es2021": true |
|||
}, |
|||
"parserOptions": { |
|||
"ecmaVersion": 2021, |
|||
"parser": "@typescript-eslint/parser", |
|||
"sourceType": "module", |
|||
"ecmaFeatures": { |
|||
"jsx": true |
|||
} |
|||
}, |
|||
"extends": [ |
|||
"airbnb-base", |
|||
"eslint:recommended", |
|||
"plugin:prettier/recommended", |
|||
"plugin:vue/vue3-essential", |
|||
"plugin:@typescript-eslint/recommended" |
|||
], |
|||
"plugins": ["vue", "@typescript-eslint", "todo-ddl"], |
|||
"rules": { |
|||
"@typescript-eslint/ban-types": "off", |
|||
"@typescript-eslint/no-explicit-any": "off", |
|||
"@typescript-eslint/explicit-module-boundary-types": "off", |
|||
"import/extensions": "off", |
|||
"quotes": ["warn", "single"], |
|||
"semi": ["warn", "never"], |
|||
"import/no-unresolved": "off", |
|||
"todo-ddl/diy": "warn", |
|||
"import/prefer-default-export": "off", |
|||
"no-param-reassign": "warn", |
|||
"import/no-extraneous-dependencies": "off", |
|||
"max-len": "warn", |
|||
"no-restricted-syntax": "off", |
|||
"no-bitwise": "off", |
|||
"camelcase": "off", |
|||
"no-case-declarations": "off", |
|||
"@typescript-eslint/no-namespace": "off", |
|||
"no-undef": "off", |
|||
"no-promise-executor-return": "off", |
|||
"vue/multi-word-component-names": "off", |
|||
"@typescript-eslint/no-non-null-assertion": "off", |
|||
"@typescript-eslint/ban-ts-comment": "off", |
|||
"linebreak-style": "off" |
|||
} |
|||
} |
@ -1,21 +1,31 @@ |
|||
# Logs |
|||
logs |
|||
*.log |
|||
.DS_Store |
|||
node_modules/ |
|||
unpackage/ |
|||
dist/ |
|||
wxcomponents |
|||
|
|||
# local env files |
|||
.env.local |
|||
.env.*.local |
|||
|
|||
# Log files |
|||
npm-debug.log* |
|||
yarn-debug.log* |
|||
yarn-error.log* |
|||
pnpm-debug.log* |
|||
lerna-debug.log* |
|||
|
|||
node_modules |
|||
.DS_Store |
|||
dist |
|||
*.local |
|||
|
|||
# Editor directories and files |
|||
.project |
|||
.idea |
|||
.vscode |
|||
*.suo |
|||
*.ntvs* |
|||
*.njsproj |
|||
*.sln |
|||
*.sw? |
|||
*.sw* |
|||
.hbuilderx |
|||
|
|||
.gitee |
|||
.github |
|||
|
|||
package-lock.json |
|||
yarn.lock |
@ -1,4 +0,0 @@ |
|||
{ |
|||
"rootPathIndex": 1, |
|||
"webRoot": "${projectDir}" |
|||
} |
@ -1,20 +0,0 @@ |
|||
{ |
|||
// launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/ |
|||
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数 |
|||
"version" : "0.0", |
|||
"configurations" : [ |
|||
{ |
|||
"app-plus" : { |
|||
"launchtype" : "local" |
|||
}, |
|||
"default" : { |
|||
"launchtype" : "local" |
|||
}, |
|||
"type" : "uniCloud" |
|||
}, |
|||
{ |
|||
"openVueDevtools" : true, |
|||
"type" : "uni-app:h5" |
|||
} |
|||
] |
|||
} |
@ -0,0 +1,9 @@ |
|||
module.exports = { |
|||
printWidth: 700, // 一行的字符数,如果超过会进行换行,默认为80
|
|||
tabWidth: 2, // 一个 tab 代表几个空格数,默认为 2 个
|
|||
useTabs: false, //是否使用 tab 进行缩进,默认为false,表示用空格进行缩减
|
|||
singleQuote: true, // 字符串是否使用单引号,默认为 false,使用双引号
|
|||
semi: false, // 行尾是否使用分号,默认为true
|
|||
trailingComma: 'none', // 是否使用尾逗号
|
|||
bracketSpacing: true // 对象大括号直接是否有空格,默认为 true,效果:{ a: 1 }
|
|||
} |
@ -0,0 +1,7 @@ |
|||
# 设置基础镜像 |
|||
FROM win-nginx |
|||
|
|||
WORKDIR /opt/eam-pda |
|||
COPY nginx.conf /usr/local/nginx/conf/nginx.conf |
|||
# 将dist/build/h5/文件中的内容复制到 /opt/eam-pda 这个目录下面 |
|||
COPY dist/build/h5/ /opt/eam-pda |
@ -0,0 +1,21 @@ |
|||
MIT License |
|||
|
|||
Copyright (c) 2021 sugar |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in all |
|||
copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|||
SOFTWARE. |
@ -0,0 +1,260 @@ |
|||
# uni-vue3-ts-template |
|||
uni-app Vue3 + TypeScript + Vite + Pinia + Unocss 模板项目 |
|||
|
|||
支持小程序,H5,App |
|||
|
|||
 |
|||
|
|||
 |
|||
|
|||
| H5 | 微信小程序 | App(iOS) | App(Android) | |
|||
| :-------------------------------------------------------------------------: | :-------------------------------------------------------------------------: | :-------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------: | |
|||
|  |  |  | <img src="https://img.cdn.sugarat.top/mdImg/MTY1MzIxMzkyOTQxNg==653213929416" width="360"/> | |
|||
|
|||
其它模板 |
|||
* Vue3的uni-app 纯js模板:[uni-app-template](https://github.com/ATQQ/uni-app-template) |
|||
* Vue3的Web应用模板:[vite-vue3-template](https://github.com/ATQQ/vite-vue3-template) |
|||
|
|||
## Env Suggest |
|||
**Node >= 14.19** |
|||
|
|||
**pnpm 7** |
|||
|
|||
**Registry taobao - https://registry.npmmirror.com/** |
|||
|
|||
## Use This Template |
|||
```sh |
|||
npx degit atqq/uni-vue3-ts-template#main my-uni-vue3-ts-vite-project |
|||
``` |
|||
## Feature |
|||
### Prod |
|||
* [x] [Vue3](https://vuejs.org/) |
|||
* [x] [Pinia](https://pinia.vuejs.org/) - replace vuex |
|||
* [x] [Axios](https://github.com/axios/axios) |
|||
* UI/组件库 |
|||
* [x] [uView](https://vkuviewdoc.fsq.pub/) - vk-uview-ui |
|||
* [ ] [uni-ui](https://github.com/dcloudio/uni-ui) - 待接入 |
|||
### Dev |
|||
* [x] [Vite](https://github.com/vitejs/vite) |
|||
* [x] [TypeScript](https://github.com/microsoft/TypeScript/#readme) |
|||
* [x] [Sass](https://github.com/sass/sass) |
|||
* [x] [Less](https://github.com/less/less.js) |
|||
* [x] [Eslint](https://eslint.org/) |
|||
* [x] [Prettier](https://prettier.io/) |
|||
* [x] [Vitest](https://vitest.dev/) - replace jest |
|||
* [x] [unocss](https://github.com/unocss/unocss) - 即时按需原子 css 引擎 |
|||
* [x] GitHooks [simple-git-hooks](https://github.com/toplenboren/simple-git-hooks#readme) |
|||
* ~~LintStaged~~ |
|||
* ~~StyleLint~~ |
|||
|
|||
## 使用 |
|||
### 安装依赖 |
|||
**建议使用pnpm,依赖安装速度更快** |
|||
```sh |
|||
npm i -g pnpm |
|||
``` |
|||
|
|||
```sh |
|||
pnpm install |
|||
``` |
|||
|
|||
**MAC M1(ARM芯片),其它操作系统无需关注**,正常运行需要手动安装 `esbuild-darwin-64`即可 |
|||
```sh |
|||
pnpm add esbuild-darwin-64@0.15.13 -D |
|||
``` |
|||
|
|||
## 本地启动 |
|||
### 微信小程序 |
|||
```sh |
|||
# 构建出产物 |
|||
pnpm dev:mp-weixin |
|||
``` |
|||
|
|||
> **Q1:** 如果dev的时候发现报错,可以尝试删除`node_modules`之后再在命令行中运行`pnpm install --shamefully-hoist`重新安装依赖再`pnpm dev:mp-weixin` |
|||
> |
|||
> [详细参考文档](https://pnpm.io/zh/faq#%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%883) |
|||
|
|||
> **Q2:** 如果运行白屏,有报错信息 “app.js错误ReferenceError: regeneratorRuntime is not defined” |
|||
> |
|||
> 参考[解决方案](https://blog.csdn.net/FUFCY/article/details/125160828) 给微信小程序IDE开启**增强编译选项** |
|||
|
|||
然后将编译结果`dist/dev/mp-weixin`导入微信开发者工具即可运行 |
|||
|
|||
<details> |
|||
<summary>点击查看 导入详细步骤</summary> |
|||
|
|||
 |
|||
|
|||
 |
|||
|
|||
 |
|||
|
|||
</details> |
|||
|
|||
### H5 |
|||
```sh |
|||
# CSR |
|||
pnpm dev:h5 |
|||
# SSR |
|||
pnpm dev:h5:ssr |
|||
``` |
|||
|
|||
根据提示,打开对应地址即可访问 |
|||
|
|||
 |
|||
|
|||
### App |
|||
>**Q1:** 如启动到App侧有报错? |
|||
>请更新至最新的HBuilderX-Alpha客户端 |
|||
#### 安装一些必要工具 |
|||
需要使用 `uni-app` 官方提供的 [HBuilderX](https://www.dcloud.io/hbuilderx.html) 启动项目 |
|||
|
|||
**Android模拟器在MacOSX、Windows上都可以安装;iOS模拟器只能在MacOSX上安装。** |
|||
|
|||
先安装相关模拟器,[详细参考文档](https://hx.dcloud.net.cn/Tutorial/App/installSimulator) |
|||
* 安卓:[夜神模拟器](https://www.yeshen.com/blog/) |
|||
* iOS:Mac上安装Xcode |
|||
|
|||
准备就绪后,使用 HBuilderX 打开项目 |
|||
#### iOS模拟器运行 |
|||
通过顶部菜单栏,找到运行入口 |
|||
|
|||
 |
|||
|
|||
选择一个目标设备,点击启动即可 |
|||
|
|||
 |
|||
|
|||
#### Android模拟器运行 |
|||
这里以[夜神模拟器](https://www.yeshen.com/blog/)为例 |
|||
|
|||
<details> |
|||
<summary>点击查看 详细步骤</summary> |
|||
|
|||
先通过 HBuilderX 修改模拟器端口为 `62001` |
|||
|
|||
 |
|||
|
|||
打开夜神模拟器 |
|||
|
|||
 |
|||
|
|||
选择运行到 Android 基座 |
|||
|
|||
 |
|||
|
|||
选择已经打开的模拟器,点击运行即可 |
|||
 |
|||
|
|||
 |
|||
|
|||
</details> |
|||
|
|||
|
|||
## 打包构建 |
|||
### 微信小程序 |
|||
``` |
|||
pnpm build:mp-weixin |
|||
``` |
|||
### H5 |
|||
```sh |
|||
# CSR |
|||
pnpm build:h5 |
|||
# SSR |
|||
pnpm build:h5:ssr |
|||
``` |
|||
|
|||
### App |
|||
基于 `HBuilderX` 参考[官方文档](https://hx.dcloud.net.cn/Tutorial/App/SafePack)进行进一步的操作 |
|||
|
|||
其它更多运行脚本 查看 [package.json](./package.json)中的scripts |
|||
|
|||
## css预处理 |
|||
|
|||
### 已配置`scss`和`less`全局变量 |
|||
```typescript |
|||
// vite.config.ts |
|||
export default defineConfig({ |
|||
// ...... |
|||
css: { |
|||
preprocessorOptions: { |
|||
scss: { |
|||
additionalData: '@import "@/static/styles/variables.scss";' |
|||
}, |
|||
less: { |
|||
additionalData: '@import "@/static/styles/variables.less";' |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
``` |
|||
|
|||
|
|||
|
|||
`additionalData`的值是文件的路径,可以按照自己业务需求去修改,**如果项目样式变量分的比较细,可以使用一个样式文件引入多个变量样式文件,然后在这里引入入口文件** |
|||
|
|||
|
|||
|
|||
## 别名配置 |
|||
|
|||
如果我们想要在`import`的时候 src 的路径简写成`@`,下面的就是配置 vite 的别名,[属性类型请查看vite文档](https://vitejs.cn/config/#resolve-alias) |
|||
|
|||
- `@` 代替 `./src` |
|||
- `@components`代替`./src/components` |
|||
|
|||
```typescript |
|||
// vite.config.ts |
|||
export default defineConfig({ |
|||
// ...... |
|||
resolve: { |
|||
alias: { |
|||
'@': path.resolve(__dirname, './src'), |
|||
'@components': path.resolve(__dirname, './src/components') |
|||
} |
|||
} |
|||
}) |
|||
``` |
|||
|
|||
例子: |
|||
|
|||
```diff |
|||
// pages/index/index.vue |
|||
- import Hello from '../../components/hello/index.vue' |
|||
+ import Hello from '@/components/hello/index.vue' |
|||
// 或者 |
|||
+ import Hello from '@components/hello/index.vue' |
|||
``` |
|||
|
|||
|
|||
|
|||
### ts |
|||
|
|||
如果是使用ts开发,这样还不够,ts不会识别路径的别名,显示找不到模块的报错,这个时候需要修改 `tsconfig.json` 文件,纠正下路径才可以。 |
|||
|
|||
|
|||
|
|||
```diff |
|||
// tsconfig.json |
|||
{ |
|||
// ...... |
|||
"compilerOptions": { |
|||
// ...... |
|||
+ "baseUrl": "./", |
|||
+ "paths": { |
|||
+ "@/*": ["src/*"], |
|||
+ "@components/*": ["src/components/*"] |
|||
} |
|||
}, |
|||
} |
|||
|
|||
``` |
|||
|
|||
添加 `baseUrl` 和 `paths` 参数,就可以完美解决编辑器的报错提示了! |
|||
|
|||
## 原子化css |
|||
* [unocss](https://github.com/unocss/unocss) - 即时按需原子 css 引擎 |
|||
* [unocss-preset-weapp](https://github.com/MellowCo/unocss-preset-weapp) - 兼容小程序 unocss 预设 |
|||
|
|||
> 支持小程序,h5,app |
|||
|
|||
 |
@ -1,22 +1,25 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<script> |
|||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || |
|||
CSS.supports('top: constant(a)')) |
|||
document.write( |
|||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + |
|||
(coverSupport ? ', viewport-fit=cover' : '') + '" />') |
|||
</script> |
|||
<title></title> |
|||
<!--preload-links--> |
|||
<!--app-context--> |
|||
<!-- 配置H5的 web图标static/logo.png --> |
|||
<link rel="icon" href="../../static/logo.png" /> |
|||
</head> |
|||
<body> |
|||
<div id="app"><!--app-html--></div> |
|||
<script type="module" src="/src/main.js"></script> |
|||
</body> |
|||
</html> |
|||
|
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<script> |
|||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || |
|||
CSS.supports('top: constant(a)')) |
|||
document.write( |
|||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + |
|||
(coverSupport ? ', viewport-fit=cover' : '') + '" />') |
|||
</script> |
|||
<title></title> |
|||
<!--preload-links--> |
|||
<!--app-context--> |
|||
</head> |
|||
|
|||
<body> |
|||
<div id="app"> |
|||
<!--app-html--> |
|||
</div> |
|||
<script type="module" src="/src/main.ts"></script> |
|||
</body> |
|||
|
|||
</html> |
@ -0,0 +1,53 @@ |
|||
user root; |
|||
worker_processes 2; |
|||
|
|||
events { |
|||
worker_connections 1024; |
|||
} |
|||
|
|||
http { |
|||
include mime.types; |
|||
charset utf-8,gbk; |
|||
default_type application/octet-stream; |
|||
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' |
|||
'$status $body_bytes_sent "$http_referer" ' |
|||
'"$http_user_agent" "$http_x_forwarded_for" "$request_time $upstream_response_time"'; |
|||
|
|||
proxy_cache_path /opt/nginx_cache/ levels=1:2 keys_zone=my_zone:10m inactive=300s max_size=5g; |
|||
access_log logs/access.log main; |
|||
sendfile on; |
|||
#tcp_nopush on; |
|||
keepalive_timeout 600s; |
|||
client_max_body_size 200m; |
|||
gzip on; |
|||
gzip_min_length 10k; |
|||
gzip_comp_level 9; |
|||
gzip_buffers 4 16k; |
|||
gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/gif image/png; |
|||
gzip_vary on; |
|||
gzip_disable "MSIE [1-6]\."; |
|||
upstream eam { |
|||
server localhost:25210 weight=10 max_fails=3 fail_timeout=10s; |
|||
} |
|||
server { |
|||
listen 25203; |
|||
server_name_in_redirect off; |
|||
server_name dev.ccwin-in.com; |
|||
location /api/ { |
|||
proxy_pass http://eam/; |
|||
proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header; |
|||
proxy_set_header X-Forwared-For $proxy_add_x_forwarded_for; |
|||
proxy_set_header Host $http_host; |
|||
proxy_set_header X-Real-IP $remote_addr; |
|||
proxy_set_header X-Forwarded-For $http_x_forwarded_for; |
|||
} |
|||
location / { |
|||
proxy_cache my_zone; |
|||
proxy_cache_valid 200 304 12h; |
|||
proxy_cache_key $host$uri$is_args$args; |
|||
try_files $uri $uri/ /index.html; |
|||
root /opt/eam-pda; |
|||
index index.html index.htm; |
|||
} |
|||
} |
|||
} |
File diff suppressed because it is too large
@ -1,46 +1,86 @@ |
|||
{ |
|||
"name": "uni-preset-vue", |
|||
"version": "0.0.0", |
|||
"name": "闻荫APP", |
|||
"version": "1.0.0", |
|||
"private": true, |
|||
"scripts": { |
|||
"dev": "uni", |
|||
"dev:mp-weixin": "uni -p mp-weixin", |
|||
"dev:app": "uni -p app", |
|||
"dev:app-android": "uni -p app-android", |
|||
"dev:app-ios": "uni -p app-ios", |
|||
"dev:custom": "uni -p", |
|||
"dev:h5": "uni", |
|||
"dev:h5:ssr": "uni --ssr", |
|||
"dev:mp-weixin": "uni -p mp-weixin", |
|||
"build:app": "uni build -p app", |
|||
"build:app-android": "uni build -p app-android", |
|||
"build:app-ios": "uni build -p app-ios", |
|||
"build:custom": "uni build -p", |
|||
"build:h5": "uni build", |
|||
"build:h5:ssr": "uni build --ssr", |
|||
"build:mp-weixin": "uni build -p mp-weixin" |
|||
"test": "uni build --mode test", |
|||
"test:mp-weixin": "uni build -p mp-weixin", |
|||
"test:app": "uni build -p app", |
|||
"test:custom": "uni build -p", |
|||
"prod:mp-weixin": "uni build -p mp-weixin --mode production", |
|||
"prod:app": "uni build -p app --mode production", |
|||
"prod:custom": "uni build -p --mode production", |
|||
"prod": "uni build --mode production", |
|||
"hella8": "uni build --mode hella8", |
|||
"hella9": "uni build --mode hella9", |
|||
"hella13": "uni build --mode hella13", |
|||
"hella14": "uni build --mode hella14", |
|||
"hella15": "uni build --mode hella15", |
|||
"hella16": "uni build --mode hella16" |
|||
}, |
|||
"dependencies": { |
|||
"@dcloudio/uni-app": "3.0.0-3090920231225001", |
|||
"@dcloudio/uni-app-plus": "3.0.0-3090920231225001", |
|||
"@dcloudio/uni-components": "3.0.0-3090920231225001", |
|||
"@dcloudio/uni-h5": "3.0.0-3090920231225001", |
|||
"@dcloudio/uni-mp-weixin": "3.0.0-3090920231225001", |
|||
"less": "^4.2.0", |
|||
"vue": "^3.2.45", |
|||
"@dcloudio/uni-app": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-app-plus": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-components": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-h5": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-mp-alipay": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-mp-baidu": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-mp-kuaishou": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-mp-lark": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-mp-qq": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-mp-toutiao": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-mp-weixin": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-quickapp-webview": "3.0.0-alpha-3060920221114001", |
|||
"axios": "^0.27.2", |
|||
"cz-git": "^1.4.1", |
|||
"decimal.js": "^10.4.3", |
|||
"or": "^0.2.0", |
|||
"pinia": "^2.0.35", |
|||
"vk-uview-ui": "^1.3.7", |
|||
"vue": "^3.2.41", |
|||
"vue-demi": "latest", |
|||
"vue-i18n": "^9.1.9", |
|||
"vuex": "^4.1.0" |
|||
"vuex": "^4.0.2" |
|||
}, |
|||
"devDependencies": { |
|||
"@dcloudio/types": "^3.3.2", |
|||
"@dcloudio/uni-automator": "3.0.0-3090920231225001", |
|||
"@dcloudio/uni-cli-shared": "3.0.0-3090920231225001", |
|||
"@dcloudio/uni-stacktracey": "3.0.0-3090920231225001", |
|||
"@dcloudio/vite-plugin-uni": "3.0.0-3090920231225001", |
|||
"@vue/runtime-core": "^3.2.45", |
|||
"axios": "^1.3.4", |
|||
"decimal.js": "^10.4.3", |
|||
"jwt-decode": "^3.1.2", |
|||
"sass": "^1.70.0", |
|||
"sass-loader": "^14.1.0", |
|||
"vite": "4.0.3", |
|||
"vue-clipboard2": "^0.3.3" |
|||
"@commitlint/cli": "^17.4.2", |
|||
"@commitlint/config-conventional": "^17.4.2", |
|||
"@dcloudio/types": "^3.0.16", |
|||
"@dcloudio/uni-automator": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-cli-shared": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/uni-stacktracey": "3.0.0-alpha-3060920221114001", |
|||
"@dcloudio/vite-plugin-uni": "3.0.0-alpha-3060920221114001", |
|||
"@types/node": "^17.0.45", |
|||
"@typescript-eslint/eslint-plugin": "^5.30.3", |
|||
"@typescript-eslint/parser": "^5.30.3", |
|||
"@vitejs/plugin-vue": "^2.3.3", |
|||
"@vitest/ui": "^0.10.5", |
|||
"c8": "^7.11.3", |
|||
"czg": "^1.4.1", |
|||
"eslint": "^8.19.0", |
|||
"eslint-config-airbnb-base": "^15.0.0", |
|||
"eslint-config-prettier": "^8.5.0", |
|||
"eslint-plugin-import": "^2.26.0", |
|||
"eslint-plugin-prettier": "^4.2.1", |
|||
"eslint-plugin-todo-ddl": "^1.1.1", |
|||
"eslint-plugin-vue": "^9.1.1", |
|||
"jsdom": "^24.0.0", |
|||
"less": "^4.1.3", |
|||
"prettier": "^2.7.1", |
|||
"sass": "^1.53.0", |
|||
"simple-git-hooks": "^2.8.1", |
|||
"typescript": "^4.7.4", |
|||
"unocss": "^0.46.4", |
|||
"unocss-preset-weapp": "^0.2.1", |
|||
"vite": "^3.1.8", |
|||
"vite-plugin-eslint": "^1.6.1", |
|||
"vitest": "^0.16.0" |
|||
}, |
|||
"simple-git-hooks": { |
|||
"commit-msg": "npx --no-install commitlint --edit \"$1\"" |
|||
} |
|||
} |
|||
|
@ -1,2 +0,0 @@ |
|||
别名:testalias |
|||
密码: wms3.0 |
File diff suppressed because it is too large
@ -1,10 +0,0 @@ |
|||
/// <reference types='@dcloudio/types' />
|
|||
import 'vue' |
|||
|
|||
declare module '@vue/runtime-core' { |
|||
type Hooks = App.AppInstance & Page.PageInstance; |
|||
|
|||
interface ComponentCustomOptions extends Hooks { |
|||
|
|||
} |
|||
} |
@ -0,0 +1,132 @@ |
|||
import axios from 'axios' |
|||
|
|||
import { getFullURL } from '@/utils/http' |
|||
import { getAccessToken, removeToken } from '@/utils/auth' |
|||
|
|||
const instance = axios.create({ |
|||
baseURL: import.meta.env.VITE_BASE_URL, |
|||
adapter(config) { |
|||
const { url, method, data, params, headers, baseURL, paramsSerializer } = |
|||
config |
|||
config.timeout = 300000 |
|||
return new Promise((resolve, reject) => { |
|||
uni.request({ |
|||
method: method!.toUpperCase() as any, |
|||
url: getFullURL(baseURL || '', url!, params, paramsSerializer), |
|||
header: headers, |
|||
data, |
|||
dataType: 'json', |
|||
responseType: config.responseType, |
|||
success: (res : any) => { |
|||
resolve(res) |
|||
}, |
|||
fail: (error : any) => { |
|||
// var message = error.errMsg
|
|||
// if (message === 'Network Error') {
|
|||
// message = '接口连接异常'
|
|||
// } else if (message.includes('timeout')) {
|
|||
// message = '接口请求超时'
|
|||
// } else if (message.includes('Request failed with status code')) {
|
|||
// message = '接口' + message.substr(message.length - 3) + '异常'
|
|||
// }
|
|||
// reject("系统异常:"+message);
|
|||
// console.log("系统异常",message)
|
|||
} |
|||
}) |
|||
}) |
|||
} |
|||
}) |
|||
|
|||
|
|||
/** |
|||
* 请求拦截 |
|||
*/ |
|||
instance.interceptors.request.use((config) => { |
|||
const { method, params, url } = config |
|||
// 附带鉴权的token
|
|||
// const tenantId = 1
|
|||
var tenantId = uni.getStorageSync('tenantId') |
|||
const headers : any = { |
|||
token: getAccessToken(), |
|||
"tenant-id": tenantId, |
|||
"dataSource":"PDA", |
|||
'Authorization': 'Bearer ' + getAccessToken() |
|||
} |
|||
if (uni.getStorageSync('openId')) { |
|||
headers['openId'] = uni.getStorageSync('openId') |
|||
} |
|||
// 不缓存get请求
|
|||
if (method === 'get') { |
|||
headers['Cache-Control'] = 'no-cache' |
|||
} |
|||
// delete请求参数放入body中
|
|||
if (method === 'delete') { |
|||
headers['Content-type'] = 'application/json;' |
|||
Object.assign(config, { |
|||
data: params, |
|||
params: {} |
|||
}) |
|||
} |
|||
|
|||
return { |
|||
...config, |
|||
headers |
|||
} |
|||
}) |
|||
|
|||
/** |
|||
* 响应拦截 |
|||
*/ |
|||
instance.interceptors.response.use((v) => { |
|||
if (v) { |
|||
if (v.statusCode == 200) { |
|||
if (v.data.code == 0) { |
|||
// return v.data
|
|||
return Promise.resolve(v.data) |
|||
}else if(v.data.code == 404){ |
|||
uni.showModal({ |
|||
title: '系统提示', |
|||
content: '登录状态已过期,您可以继续留在该页面,或者重新登录', |
|||
cancelText: '关闭', |
|||
confirmText: '重新登录', |
|||
success: function (res) { |
|||
if (res.confirm) { |
|||
uni.reLaunch({ url: '/pages/login/index' }) |
|||
} |
|||
} |
|||
}) |
|||
} else if(v.data.code == 401){ |
|||
uni.clearStorageSync() |
|||
uni.removeStorageSync('overPackageRecord') |
|||
uni.showModal({ |
|||
title: '系统提示', |
|||
content: '账号未登录,请重新登录', |
|||
cancelText: '关闭', |
|||
confirmText: '重新登录', |
|||
success: function (res) { |
|||
if (res.confirm) { |
|||
uni.reLaunch({ url: '/pages/login/index' }) |
|||
} |
|||
} |
|||
}) |
|||
} else { |
|||
// return v.data
|
|||
return Promise.reject("系统异常:" + v.data.msg) |
|||
} |
|||
|
|||
} else { |
|||
return Promise.reject("系统异常:" + v.data.msg) |
|||
} |
|||
|
|||
} else { |
|||
return Promise.reject("系统异常:" + v.data.msg) |
|||
} |
|||
|
|||
}, error => { |
|||
console.log(error) |
|||
uni.showToast({ |
|||
title: '网络错误', |
|||
icon: 'none' |
|||
}) |
|||
}) |
|||
export default instance |
@ -1,67 +0,0 @@ |
|||
|
|||
import storage from '../common/utils/storage' |
|||
import config from '../static/config.js' |
|||
|
|||
function service(options = {}) { |
|||
var token = storage.getStorage(storage.constant.token) |
|||
var tenantId = 1 |
|||
// if(getApp()!=undefined){
|
|||
// tenantId = getApp().globalData.tenantId
|
|||
// }
|
|||
|
|||
// if(getApp()!=undefined){
|
|||
// requestUrl = getApp().globalData.request_url
|
|||
// }
|
|||
var requestUrl = "" |
|||
requestUrl =config.request_url |
|||
|
|||
options.header = { |
|||
"content-type": "application/json", |
|||
"Authorization": "Bearer "+token, |
|||
"dataType":"json", |
|||
"tenant-id":tenantId |
|||
}; |
|||
options.timeout = 10000 |
|||
|
|||
options.url = requestUrl+options.url |
|||
|
|||
return new Promise((resolve, reject) => { |
|||
options.success = (res) => { |
|||
if (res ) { |
|||
if(res.statusCode == 200){ |
|||
if(res.data.code==0){ |
|||
resolve(res.data); |
|||
}else { |
|||
reject("系统异常:"+res.data.msg) |
|||
console.log("系统异常",res.data.msg) |
|||
} |
|||
|
|||
}else { |
|||
reject("系统异常:"+ res.data.msg) |
|||
console.log("系统异常",res.data.msg) |
|||
} |
|||
|
|||
} else { |
|||
reject("系统异常:"+res.data.msg) |
|||
console.log("系统异常",res.data.msg) |
|||
} |
|||
}; |
|||
options.fail = (error) => { |
|||
var message = error.errMsg |
|||
if (message === 'Network Error') { |
|||
message = '接口连接异常' |
|||
} else if (message.includes('timeout')) { |
|||
message = '接口请求超时' |
|||
} else if (message.includes('Request failed with status code')) { |
|||
message = '接口' + message.substr(message.length - 3) + '异常' |
|||
} |
|||
reject("系统异常:"+message); |
|||
console.log("系统异常",message) |
|||
}; |
|||
uni.request(options); |
|||
}); |
|||
} |
|||
|
|||
|
|||
|
|||
export default service; |
@ -0,0 +1,41 @@ |
|||
import http from './http' |
|||
|
|||
// 登录方法
|
|||
export function login(username, password, captchaVerification, tenantName, rememberMe, code, uuid) { |
|||
const data = { |
|||
username, |
|||
password, |
|||
captchaVerification, |
|||
tenantName, |
|||
rememberMe, |
|||
code, |
|||
uuid, |
|||
} |
|||
return http.post('/system/auth/loginNoCode', data) |
|||
} |
|||
|
|||
// 获取用户详细信息
|
|||
export function getInfo() { |
|||
return http.get('/system/user/profile/get') |
|||
} |
|||
// 获取权限
|
|||
export function getPermissionInfo() { |
|||
return http.get('/system/auth/get-permission-info') |
|||
} |
|||
// 退出方法
|
|||
export function logout() { |
|||
return http.post('/system/auth/logout') |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
File diff suppressed because it is too large
@ -1,16 +1,24 @@ |
|||
/* 解决js计算精度问题 */ |
|||
import { Decimal } from 'decimal.js';//引入
|
|||
import Decimal from 'decimal.js' |
|||
class Calc { |
|||
add(num1,num2) { |
|||
num1 = num1 || 0 |
|||
num2 = num2 || 0 |
|||
return new Decimal(num1).add(new Decimal(num2)).toNumber() |
|||
} |
|||
sub(num1,num2) { |
|||
num1 = num1 || 0 |
|||
num2 = num2 || 0 |
|||
return new Decimal(num1).sub(new Decimal(num2)).toNumber() |
|||
} |
|||
mul(num1,num2) { |
|||
num1 = num1 || 0 |
|||
num2 = num2 || 0 |
|||
return new Decimal(num1).mul(new Decimal(num2)).toNumber() |
|||
} |
|||
div(num1,num2) { |
|||
num1 = num1 || 0 |
|||
num2 = num2 || 0 |
|||
return new Decimal(num1).div(new Decimal(num2)).toNumber() |
|||
} |
|||
} |
|||
|
@ -0,0 +1,9 @@ |
|||
export const overPagePrint="overPage_print" |
|||
export const overPageTemplate="overPage_Template" |
|||
//3分钟刷新
|
|||
export const planRefreshTime=3*60*1000 |
|||
|
|||
export const issueJobFilter="issue_job_filter" |
|||
export const repleinshJobFilter="repleinsh_job_filter" |
|||
export const overPackageJobFilter="over_package_job_filter" |
|||
export const productionReceiptJobFilter="production_receipt_job_filter" |
@ -1,83 +1,232 @@ |
|||
import { |
|||
calc |
|||
} from '@/common/calc' |
|||
|
|||
import { Decimal } from 'decimal.js';//引入
|
|||
export function getDataSource(subList) { |
|||
let items = []; |
|||
subList.forEach(detail => { |
|||
var item = items.find(r => |
|||
r.itemCode == detail.itemCode) |
|||
if (item == undefined) { |
|||
item = createItemInfo(detail); |
|||
let newDetail = createDetailInfo(detail); //
|
|||
item.subList.push(newDetail); |
|||
items.push(item) |
|||
} else { |
|||
item.qty = calc.add(item.qty, detail.qty) |
|||
let newDetail = createDetailInfo(detail); //
|
|||
item.subList.push(newDetail); |
|||
} |
|||
}) |
|||
return items; |
|||
} |
|||
calc |
|||
} from '@/common/calc' |
|||
|
|||
import { |
|||
Decimal |
|||
} from 'decimal.js'; //引入
|
|||
|
|||
|
|||
|
|||
export function getTreeDataSource(dataList) { |
|||
let items = []; |
|||
|
|||
let parentList = dataList.filter(r => r.parentPackingNumber == null || r |
|||
.parentPackingNumber == ''); |
|||
let childList = dataList.filter(r => r.parentPackingNumber != '' && r.parentPackingNumber != null); |
|||
|
|||
export function createItemInfo(detail) { |
|||
let item = { |
|||
itemCode: detail.itemCode, |
|||
itemName: detail.itemName, |
|||
stdPackQty: Number(detail.stdPackQty) || undefined, |
|||
stdPackUnit: detail.stdPackUnit, |
|||
qty: Number(detail.qty), |
|||
handleQty: 0, |
|||
uom: detail.uom, |
|||
subList: [] |
|||
parentList.forEach(detail => { |
|||
var item = items.find(r => |
|||
r.itemCode == detail.itemCode) |
|||
if (item == undefined) { |
|||
item = createItemInfo(detail); |
|||
let newDetail = createDetailInfo(detail); //
|
|||
item.subList.push(newDetail); |
|||
items.push(item) |
|||
} else { |
|||
item.qty = calc.add(item.qty, detail.qty) |
|||
let newDetail = createDetailInfo(detail); //
|
|||
item.subList.push(newDetail); |
|||
} |
|||
return item; |
|||
}) |
|||
|
|||
if (childList.length > 0) { |
|||
items.forEach(r => |
|||
r.subList.forEach(s => { |
|||
s.packList = childList.filter(c => c.parentPackingNumber == s.packingNumber) |
|||
s.packList.forEach(pac => { |
|||
pac.scaned = false; |
|||
pac.scanDate = new Date(); |
|||
}) |
|||
}) |
|||
) |
|||
} |
|||
|
|||
export function createDetailInfo(data) { |
|||
data.scaned = false; |
|||
// data.record = {};
|
|||
let detail = data; |
|||
return detail; |
|||
return items; |
|||
} |
|||
export function getThreeDataSource(data) { |
|||
let items = [] |
|||
let obj ={ |
|||
...data.subList[0] |
|||
} |
|||
console.log(12) |
|||
data.subList.forEach((item)=>{ |
|||
item.threeList = [{ |
|||
fromLocationCode:item.fromLocationCode, |
|||
batch:item.batch, |
|||
handleQty:0, |
|||
qty:item.qty, |
|||
inventoryStatus:item.inventoryStatus, |
|||
toLocationCode:item.toLocationCode, |
|||
}] |
|||
item.packList=[{ |
|||
scaned : false, |
|||
scanDate: new Date() |
|||
}] |
|||
}) |
|||
obj.subList = data.subList |
|||
items.push(obj) |
|||
return items; |
|||
} |
|||
export function getDataSourceBatch(subList) { |
|||
let items = []; |
|||
subList.forEach(detail => { |
|||
var item = items.find(r => |
|||
r.itemCode == detail.itemCode ) |
|||
if (item == undefined) { |
|||
item = createItemInfo(detail); |
|||
let newDetail = createDetailInfo(detail); //
|
|||
item.subList.push(newDetail); |
|||
items.push(item) |
|||
} else { |
|||
item.qty = calc.add(item.qty, detail.qty) |
|||
let newDetail = createDetailInfo(detail); //
|
|||
item.subList.push(newDetail); |
|||
} |
|||
}) |
|||
return items; |
|||
} |
|||
export function getDataSource(subList) { |
|||
let items = []; |
|||
subList.forEach(detail => { |
|||
var item = items.find(r => |
|||
r.itemCode == detail.itemCode) |
|||
if (item == undefined) { |
|||
item = createItemInfo(detail); |
|||
let newDetail = createDetailInfo(detail); //
|
|||
item.subList.push(newDetail); |
|||
items.push(item) |
|||
} else { |
|||
item.qty = calc.add(item.qty, detail.qty) |
|||
let newDetail = createDetailInfo(detail); //
|
|||
item.subList.push(newDetail); |
|||
} |
|||
}) |
|||
return items; |
|||
} |
|||
|
|||
//根据明细创建记录
|
|||
export function createRecordInfo(detail, balance) { |
|||
var record = {} |
|||
// let record = JSON.parse(JSON.stringify(detail));
|
|||
//克隆对象,深度克隆,防止双向绑定同一个变量
|
|||
Object.assign(record, detail) |
|||
detail.scaned = true; |
|||
detail.balance = balance; |
|||
detail.recommendInventoryStatus = detail.inventoryStatus; |
|||
detail.inventoryStatus = balance.inventoryStatus; |
|||
record.qty = Number(balance.qty); |
|||
return record; |
|||
export function createItemInfo(detail) { |
|||
let item = { |
|||
itemCode: detail.itemCode, |
|||
itemName: detail.itemName, |
|||
packQty: Number(detail.packQty) || undefined, |
|||
packUnit: detail.packUnit, |
|||
qty: Number(detail.qty), |
|||
handleQty: 0, |
|||
uom: detail.uom, |
|||
subList: [] |
|||
} |
|||
return item; |
|||
} |
|||
|
|||
export function createDetailInfo(data) { |
|||
data.scaned = false; |
|||
data.scanDate = new Date(); |
|||
let detail = data; |
|||
detail.packList = []; |
|||
return detail; |
|||
} |
|||
|
|||
//计算实际数量
|
|||
export function calcHandleQty(detailSource) { |
|||
for (let item of detailSource) { |
|||
item.handleQty = new Decimal(0).toNumber(); |
|||
item.qty = new Decimal(0).toNumber(); |
|||
for (let detail of item.subList) { |
|||
if (detail != undefined && detail.scaned) { |
|||
item.handleQty = calc.add(item.handleQty,detail.handleQty); |
|||
item.qty = calc.add(item.qty,detail.qty); |
|||
//根据明细创建记录
|
|||
export function createRecordInfo(detail, balance) { |
|||
var record = {} |
|||
// let record = JSON.parse(JSON.stringify(detail));
|
|||
//克隆对象,深度克隆,防止双向绑定同一个变量
|
|||
Object.assign(record, detail) |
|||
detail.scaned = true; |
|||
detail.balance = balance; |
|||
detail.recommendInventoryStatus = detail.inventoryStatus; |
|||
detail.inventoryStatus = balance.inventoryStatus; |
|||
record.qty = Number(balance.qty); |
|||
return record; |
|||
} |
|||
|
|||
//计算实际数量
|
|||
export function calcHandleQty(detailSource) { |
|||
for (let item of detailSource) { |
|||
item.handleQty = new Decimal(0).toNumber(); |
|||
item.qty = new Decimal(0).toNumber(); |
|||
for (let detail of item.subList) { |
|||
if (detail != undefined) { |
|||
if (detail.scaned) { |
|||
item.handleQty = calc.add(item.handleQty, detail.handleQty); |
|||
} |
|||
item.qty = calc.add(item.qty, detail.qty); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
//计算计划外入库实际数量和任务数量
|
|||
export function calcHandleQtyPlanOut(detailSource) { |
|||
for (let item of detailSource) { |
|||
item.handleQty = new Decimal(0).toNumber(); |
|||
item.qty = new Decimal(0).toNumber(); |
|||
for (let detail of item.subList) { |
|||
if (detail != undefined) { |
|||
if (detail.scaned) { |
|||
item.handleQty = calc.add(item.handleQty, detail.handleQty); |
|||
} |
|||
console.log(detail.isRecommend) |
|||
if(detail.isRecommend){ |
|||
item.qty = calc.add(item.qty, detail.qty); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
//计算推荐和扫描的不是用一个的数量
|
|||
export function calcHandleNewQty(detailSource) { |
|||
for (let item of detailSource) { |
|||
item.handleQty = new Decimal(0).toNumber(); |
|||
// item.qty = new Decimal(0).toNumber();
|
|||
for (let detail of item.subList) { |
|||
if (detail ) { |
|||
if (!detail.isRecommend && detail.scaned) { |
|||
item.handleQty = calc.add(item.handleQty, detail.handleQty); |
|||
} |
|||
// if (!detail.isRecommend ) {
|
|||
// item.qty = calc.add(item.qty, detail.qty);
|
|||
// }
|
|||
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
export function calcTreeHandleQty(detailSource) { |
|||
for (let item of detailSource) { |
|||
item.handleQty = new Decimal(0).toNumber(); |
|||
|
|||
export function getScanCount(subList) { |
|||
let items = subList.filter(r => { |
|||
if (r.scaned) { |
|||
return r; |
|||
for (let detail of item.subList) { |
|||
if (detail) { |
|||
if (detail.packList && detail.packList.length > 0) { |
|||
detail.handleQty = new Decimal(0).toNumber(); |
|||
for (let pack of detail.packList) { |
|||
if (pack && pack.scaned) { |
|||
detail.handleQty = calc.add(detail.handleQty, pack.handleQty); |
|||
} |
|||
} |
|||
}else{ |
|||
detail.handleQty = new Decimal(0).toNumber(); |
|||
} |
|||
if(detail.handleQty){ |
|||
item.handleQty = calc.add(item.handleQty, detail.handleQty); |
|||
} |
|||
} |
|||
}) |
|||
let scanCount = items != null ? items.length : 0; |
|||
return scanCount; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
export function getScanCount(subList) { |
|||
let items = subList.filter(r => { |
|||
if (r.scaned) { |
|||
return r; |
|||
} |
|||
}) |
|||
let scanCount = items != null ? items.length : 0; |
|||
return scanCount; |
|||
} |
@ -0,0 +1,44 @@ |
|||
// 防止处理多次点击
|
|||
function noMultipleClicks(methods, info) { |
|||
// methods是需要点击后需要执行的函数, info是点击需要传的参数
|
|||
let that = this; |
|||
if (that.noClick) { |
|||
// 第一次点击
|
|||
that.noClick= false; |
|||
if(info && info !== '') { |
|||
// info是执行函数需要传的参数
|
|||
methods(info); |
|||
} else { |
|||
methods(); |
|||
} |
|||
let timer = setTimeout(()=> { |
|||
that.noClick= true; |
|||
clearTimeout(timer) |
|||
}, 2000) |
|||
} else { |
|||
// 这里是重复点击的判断
|
|||
} |
|||
} |
|||
|
|||
|
|||
// 节流函数
|
|||
const throttle = (fn, t,_this) => { |
|||
console.log('throttle') |
|||
return ()=> { |
|||
if (!_this.timer) { |
|||
_this.timer = setTimeout(()=>{ |
|||
console.log('fn') |
|||
//·清空定时器
|
|||
_this.timer = null |
|||
}, t) |
|||
fn() |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
//导出
|
|||
export default { |
|||
noMultipleClicks,//禁止多次点击
|
|||
throttle |
|||
} |
After Width: | Height: | Size: 42 KiB |
@ -0,0 +1,416 @@ |
|||
<template> |
|||
<view class="kk-printer"> |
|||
<view class="kk-printer-btn" @tap="handlePrintTap"> |
|||
{{isPrinting?printingText:defaultText}} |
|||
</view> |
|||
<view class="kk-shadow" :class="isShowSearch?'show':''" @tap="handleSearchClose"> |
|||
<view class="kk-modal" @tap.stop="doNothing"> |
|||
<view class="kk-search-device"> |
|||
<view class="kk-filter-wrap"> |
|||
<view class="filter-title">根据SRRI过滤设备</view> |
|||
<slider @change="handleSRRIChange" max='-20' min='-100' value="-95" show-value/> |
|||
</view> |
|||
<view class="kk-filter-wrap"> |
|||
<view class="filter-title">根据蓝牙名过滤</view> |
|||
<input type="text" placeholder-class="kk-placeholder-class" placeholder="请输入蓝牙名字或设备ID搜索" v-model="filterName" /> |
|||
</view> |
|||
<view class="kk-btn-wrap"> |
|||
<view class="kk-btn-item confirm-btn" @tap="searchBtnTap" v-if="!isSearching"> |
|||
搜索设备 |
|||
</view> |
|||
<view class="kk-btn-item confirm-btn" v-else> |
|||
搜索中... |
|||
</view> |
|||
<view class="kk-btn-item" @tap="stopSearchBtnTap"> |
|||
停止搜索 |
|||
</view> |
|||
</view> |
|||
<view class="kk-devices-wrap"> |
|||
<view class="empty-wrap" v-if="filterDeviceList.length <= 0"> |
|||
<view class="empty-icon"></view> |
|||
<view class="empty-text">~ 无可搜索到的设备 ~</view> |
|||
</view> |
|||
<view class="" v-else> |
|||
<view class="kk-devices-item" v-for="(item,index) in filterDeviceList" :key="index" @tap="handleConnectDevice(item)"> |
|||
<view class="name"> |
|||
<text>设备名称:</text> |
|||
<text>{{item.name?item.name:'未命名'}}</text> |
|||
</view> |
|||
<view class="rssi"> |
|||
<text>信号强度:</text> |
|||
<text>({{Math.max(0, item.RSSI + 100)}}%)</text> |
|||
</view> |
|||
<view class="deviceid"> |
|||
<text>设备ID:</text> |
|||
<text>{{item.deviceId}}</text> |
|||
</view> |
|||
<view class="advmac" v-if="item.advMac"> |
|||
<text>advMac:</text> |
|||
<text>{{item.advMac}}</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import * as gbk from '@/components/kk-printer/utils/printUtil-GBK.js'; |
|||
import * as blesdk from './utils/bluetoolth'; |
|||
import * as util from './utils/util.js'; |
|||
export default { |
|||
data(){ |
|||
return{ |
|||
//是否正在打印 |
|||
isPrinting:false, |
|||
//是否正在搜索设备 |
|||
isSearching:false, |
|||
//是否显示蓝牙列表 |
|||
isShowSearch:false, |
|||
//按蓝牙名过滤 |
|||
filterName:'', |
|||
//按信号过滤 |
|||
filterRSSI:-95, |
|||
//设备列表 |
|||
devicesList:[], |
|||
//连接的设备ID |
|||
deviceId:'', |
|||
//根据设备ID获取的服务 |
|||
services:'', |
|||
//获取特征值时返回的三要素 |
|||
serviceId: '', |
|||
writeId: '', |
|||
readId: '' |
|||
} |
|||
}, |
|||
props:{ |
|||
//按钮默认文字 |
|||
defaultText:{ |
|||
type:String, |
|||
default:'打印' |
|||
}, |
|||
//按钮打印中的文字 |
|||
printingText:{ |
|||
type:String, |
|||
default:'打印中...' |
|||
}, |
|||
bufferData:{ |
|||
type:String, |
|||
require:true |
|||
} |
|||
}, |
|||
computed:{ |
|||
mapFilterRSSI(){ |
|||
return (0 - this.filterRSSI) |
|||
}, |
|||
filterDeviceList(){ |
|||
let devices = this.devicesList; |
|||
let name = this.filterName; |
|||
let rssi = this.filterRSSI; |
|||
console.log(devices,name,rssi) |
|||
//按RSSI过滤 |
|||
let filterDevices1 = devices.filter((item)=>{ |
|||
return item.RSSI > rssi |
|||
}) |
|||
console.log(filterDevices1) |
|||
// 按名字过滤 |
|||
let filterDevices2 |
|||
if(name!=''){ |
|||
filterDevices2 = filterDevices1.filter((item)=>{ |
|||
return (item.name.indexOf(name) >= 0 || item.deviceId.indexOf(name) >= 0) |
|||
}) |
|||
}else{ |
|||
filterDevices2 = filterDevices1 |
|||
} |
|||
// 根据广播数据提取MAC地址 |
|||
for (let i = 0; i < filterDevices2.length;i++) { |
|||
if (filterDevices2[i].hasOwnProperty('advertisData')){ |
|||
if (filterDevices2[i].advertisData.byteLength == 8) { |
|||
filterDevices2[i].advMac = util.buf2hex(filterDevices2[i].advertisData.slice(2, 7)); |
|||
} |
|||
} |
|||
} |
|||
return filterDevices2 |
|||
} |
|||
}, |
|||
mounted() { |
|||
|
|||
}, |
|||
beforeDestroy(){ |
|||
this.stopSearchBtnTap(); |
|||
}, |
|||
methods:{ |
|||
doNothing(){ |
|||
return; |
|||
}, |
|||
//点击打印按钮 |
|||
handlePrintTap(){ |
|||
console.log(11) |
|||
//打开蓝牙适配器 |
|||
blesdk.openBlue().then((res)=>{ |
|||
console.log(99,res) |
|||
//获取已连接设备 |
|||
blesdk.getConnectedBluetoothDevices().then((res)=>{ |
|||
//若没有已连接设备,弹框搜索设备 |
|||
console.log(66,res,this.deviceId,this.serviceId,this.writeId,this.bufferData,this.onPrintSuccess) |
|||
if(res.devices.length == 0){ |
|||
this.isShowSearch = true |
|||
}else{ |
|||
let datalen=20; |
|||
if (plus.os.name != 'Android') |
|||
{ |
|||
datalen=180; |
|||
} |
|||
this.isPrinting = true; |
|||
this.$emit('onPrint'); |
|||
this.$nextTick(()=>{ |
|||
console.log(1,this.bufferData) |
|||
if(this.bufferData!=''){ |
|||
let buffer = gbk.strToGBKByte(this.bufferData) |
|||
console.log(2,buffer) |
|||
let opt = { |
|||
deviceId: this.deviceId, |
|||
serviceId: this.serviceId, |
|||
characteristicId: this.writeId, |
|||
value:buffer, |
|||
lasterSuccess: this.onPrintSuccess, |
|||
onceLength:datalen |
|||
} |
|||
console.log(3,opt) |
|||
blesdk.sendDataToDevice(opt); |
|||
this.isPrinting = false; |
|||
} |
|||
}) |
|||
} |
|||
}).catch((err)=>{ |
|||
console.log(88,err) |
|||
blesdk.catchToast(err); |
|||
}) |
|||
}).catch((err)=>{ |
|||
console.log(77,err) |
|||
blesdk.catchToast(err); |
|||
}) |
|||
}, |
|||
onGetDevice(res){ |
|||
this.devicesList = res; |
|||
}, |
|||
handleSearchClose(){ |
|||
this.isShowSearch = false |
|||
}, |
|||
handleSRRIChange(e){ |
|||
this.filterRSSI = e.detail.value |
|||
}, |
|||
//开始搜索设备 |
|||
searchBtnTap(){ |
|||
blesdk.startBluetoothDevicesDiscovery(); |
|||
this.isSearching = true; |
|||
blesdk.onfindBlueDevices(this.onGetDevice) |
|||
}, |
|||
//停止搜索设备 |
|||
stopSearchBtnTap(){ |
|||
blesdk.stopBlueDevicesDiscovery(); |
|||
this.isSearching = false; |
|||
}, |
|||
//点击连接设备 |
|||
handleConnectDevice(device){ |
|||
|
|||
let deviceId = device.deviceId; |
|||
let name = device.name; |
|||
this.deviceId = deviceId; |
|||
console.log('deviceId',this.deviceId) |
|||
// uni.setStorageSync('k_curDeviceID',deviceId); |
|||
// uni.setStorageSync('k_curDeviceName',name); |
|||
uni.onBLEConnectionStateChange((res)=>{ |
|||
console.log('连接',res) |
|||
if(res.connected){ |
|||
plus.nativeUI.toast('设备'+ res.deviceId + '已连接',{ |
|||
verticalAlign:'center' |
|||
}) |
|||
}else{ |
|||
plus.nativeUI.toast('设备'+ res.deviceId + '已断开连接',{ |
|||
verticalAlign:'center' |
|||
}) |
|||
} |
|||
}) |
|||
blesdk.createBLEConnection(deviceId, this.onConnectSuccess, this.onConnectFail); |
|||
}, |
|||
onConnectSuccess(res){ |
|||
this.stopSearchBtnTap() |
|||
blesdk.getBLEDeviceServices(this.deviceId, this.onGetServicesSuccess, this.onGetServicesFail); |
|||
}, |
|||
onConnectFail(err){ |
|||
console.log('链接失败',err) |
|||
}, |
|||
onGetServicesSuccess(res){ |
|||
console.log('获取服务',res) |
|||
this.services = res.serviceId; |
|||
blesdk.getDeviceCharacteristics(this.deviceId, this.services, this.onGetCharacterSuccess, this.onGetCharacterFail); |
|||
}, |
|||
onGetServicesFail(err){ |
|||
console.log('获取服务失败') |
|||
}, |
|||
onGetCharacterSuccess(res){ |
|||
console.log('获取特征值成功',res) |
|||
this.serviceId = res.serviceId; |
|||
this.writeId = res.writeId; |
|||
this.readId = res.readId; |
|||
this.isShowSearch = false; |
|||
}, |
|||
onGetCharacterFail(err){ |
|||
console.log('特征值获取失败') |
|||
}, |
|||
onPrintSuccess(){ |
|||
this.isPrinting = false; |
|||
console.log('打印成功') |
|||
this.$emit('onPrintSuccess') |
|||
}, |
|||
onPrintFail(){ |
|||
console.log('打印失败') |
|||
this.isPrinting = false; |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.kk-printer{ |
|||
width:100%; |
|||
height:100%; |
|||
&-btn{ |
|||
width:100%; |
|||
height:100%; |
|||
text-align: center; |
|||
line-height: 50px; |
|||
} |
|||
.kk-shadow{ |
|||
display: none; |
|||
&.show{ |
|||
display: block; |
|||
width:100vw; |
|||
height:100vh; |
|||
background: rgba(0,0,0,0.4); |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
.kk-modal{ |
|||
width:680upx; |
|||
height: 80%; |
|||
padding:24upx; |
|||
box-sizing: border-box; |
|||
overflow-y: auto; |
|||
border-radius: 20upx; |
|||
background: #ffffff; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
.kk-search-device{ |
|||
width:100%; |
|||
height: 100%; |
|||
.kk-filter-wrap{ |
|||
width:100%; |
|||
height: 160upx; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: flex-start; |
|||
align-items: flex-start; |
|||
.filter-title{ |
|||
line-height: 70upx; |
|||
font-size: 30upx; |
|||
color: #999999; |
|||
} |
|||
&>slider{ |
|||
width:90%; |
|||
height: 90upx; |
|||
} |
|||
&>input{ |
|||
padding:0 20upx; |
|||
box-sizing: border-box; |
|||
border-radius: 10upx; |
|||
height: 90upx; |
|||
width:100%; |
|||
border: 1upx solid #ebebeb; |
|||
} |
|||
} |
|||
.kk-btn-wrap{ |
|||
width:100%; |
|||
height: 140upx; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
&>view{ |
|||
flex:1 1 auto; |
|||
height: 100upx; |
|||
line-height: 100upx; |
|||
border-radius: 16upx; |
|||
text-align: center; |
|||
color:#ffffff; |
|||
&.confirm-btn{ |
|||
background: #007AFF; |
|||
margin-right:30upx; |
|||
} |
|||
&:nth-last-child(1){ |
|||
background: #DD524D; |
|||
} |
|||
} |
|||
} |
|||
.kk-devices-wrap{ |
|||
height: calc(100% - 460upx); |
|||
overflow-y:auto; |
|||
padding:10upx 20upx; |
|||
box-sizing: border-box; |
|||
border: 1upx solid #ebebeb; |
|||
box-sizing: border-box; |
|||
border-radius: 20upx; |
|||
.empty-wrap{ |
|||
width:100%; |
|||
height: 100%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
align-items: center; |
|||
.empty-icon{ |
|||
width:268upx; |
|||
height: 240upx; |
|||
background: url('./empty-icon.png') no-repeat; |
|||
background-size:100% 100%; |
|||
margin-bottom: 26upx; |
|||
} |
|||
.empty-text{ |
|||
width: 100%; |
|||
line-height: 50upx; |
|||
font-size: 30upx; |
|||
text-align: center; |
|||
color: #999999; |
|||
} |
|||
} |
|||
.kk-devices-item{ |
|||
width:100%; |
|||
border-bottom: 1upx solid #ebebeb; |
|||
padding:10upx 0; |
|||
box-sizing: border-box; |
|||
&:nth-last-child(1){ |
|||
border-bottom: none; |
|||
} |
|||
&>view{ |
|||
width:100%; |
|||
font-size: 30upx; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
} |
|||
.kk-placeholder-class{ |
|||
font-size: 30upx; |
|||
color:#999999; |
|||
} |
|||
</style> |
@ -0,0 +1,402 @@ |
|||
var CHAR_TILDE = 126; |
|||
var CODE_FNC1 = 102; |
|||
|
|||
var SET_STARTA = 103; |
|||
var SET_STARTB = 104; |
|||
var SET_STARTC = 105; |
|||
var SET_SHIFT = 98; |
|||
var SET_CODEA = 101; |
|||
var SET_CODEB = 100; |
|||
var SET_STOP = 106; |
|||
|
|||
|
|||
var REPLACE_CODES = { |
|||
CHAR_TILDE: CODE_FNC1 //~ corresponds to FNC1 in GS1-128 standard
|
|||
} |
|||
|
|||
var CODESET = { |
|||
ANY: 1, |
|||
AB: 2, |
|||
A: 3, |
|||
B: 4, |
|||
C: 5 |
|||
}; |
|||
|
|||
function getBytes(str) { |
|||
var bytes = []; |
|||
for (var i = 0; i < str.length; i++) { |
|||
bytes.push(str.charCodeAt(i)); |
|||
} |
|||
return bytes; |
|||
} |
|||
|
|||
exports.code128 = function (ctx, text, width, height) { |
|||
|
|||
width = parseInt(width); |
|||
|
|||
height = parseInt(height); |
|||
|
|||
var codes = stringToCode128(text); |
|||
|
|||
var g = new Graphics(ctx, width, height); |
|||
|
|||
var barWeight = g.area.width / ((codes.length - 3) * 11 + 35); |
|||
|
|||
var x = g.area.left; |
|||
var y = g.area.top; |
|||
for (var i = 0; i < codes.length; i++) { |
|||
var c = codes[i]; |
|||
//two bars at a time: 1 black and 1 white
|
|||
for (var bar = 0; bar < 8; bar += 2) { |
|||
var barW = PATTERNS[c][bar] * barWeight; |
|||
// var barH = height - y - this.border;
|
|||
var barH = height - y; |
|||
var spcW = PATTERNS[c][bar + 1] * barWeight; |
|||
|
|||
//no need to draw if 0 width
|
|||
if (barW > 0) { |
|||
g.fillFgRect(x, y, barW, barH); |
|||
} |
|||
|
|||
x += barW + spcW; |
|||
} |
|||
} |
|||
|
|||
ctx.draw(); |
|||
} |
|||
|
|||
|
|||
function stringToCode128(text) { |
|||
|
|||
var barc = { |
|||
currcs: CODESET.C |
|||
}; |
|||
|
|||
var bytes = getBytes(text); |
|||
//decide starting codeset
|
|||
var index = bytes[0] == CHAR_TILDE ? 1 : 0; |
|||
|
|||
var csa1 = bytes.length > 0 ? codeSetAllowedFor(bytes[index++]) : CODESET.AB; |
|||
var csa2 = bytes.length > 0 ? codeSetAllowedFor(bytes[index++]) : CODESET.AB; |
|||
barc.currcs = getBestStartSet(csa1, csa2); |
|||
barc.currcs = perhapsCodeC(bytes, barc.currcs); |
|||
|
|||
//if no codeset changes this will end up with bytes.length+3
|
|||
//start, checksum and stop
|
|||
var codes = new Array(); |
|||
|
|||
switch (barc.currcs) { |
|||
case CODESET.A: |
|||
codes.push(SET_STARTA); |
|||
break; |
|||
case CODESET.B: |
|||
codes.push(SET_STARTB); |
|||
break; |
|||
default: |
|||
codes.push(SET_STARTC); |
|||
break; |
|||
} |
|||
|
|||
|
|||
for (var i = 0; i < bytes.length; i++) { |
|||
var b1 = bytes[i]; //get the first of a pair
|
|||
//should we translate/replace
|
|||
if (b1 in REPLACE_CODES) { |
|||
codes.push(REPLACE_CODES[b1]); |
|||
i++ //jump to next
|
|||
b1 = bytes[i]; |
|||
} |
|||
|
|||
//get the next in the pair if possible
|
|||
var b2 = bytes.length > (i + 1) ? bytes[i + 1] : -1; |
|||
|
|||
codes = codes.concat(codesForChar(b1, b2, barc.currcs)); |
|||
//code C takes 2 chars each time
|
|||
if (barc.currcs == CODESET.C) i++; |
|||
} |
|||
|
|||
//calculate checksum according to Code 128 standards
|
|||
var checksum = codes[0]; |
|||
for (var weight = 1; weight < codes.length; weight++) { |
|||
checksum += (weight * codes[weight]); |
|||
} |
|||
codes.push(checksum % 103); |
|||
|
|||
codes.push(SET_STOP); |
|||
|
|||
//encoding should now be complete
|
|||
return codes; |
|||
|
|||
function getBestStartSet(csa1, csa2) { |
|||
//tries to figure out the best codeset
|
|||
//to start with to get the most compact code
|
|||
var vote = 0; |
|||
vote += csa1 == CODESET.A ? 1 : 0; |
|||
vote += csa1 == CODESET.B ? -1 : 0; |
|||
vote += csa2 == CODESET.A ? 1 : 0; |
|||
vote += csa2 == CODESET.B ? -1 : 0; |
|||
//tie goes to B due to my own predudices
|
|||
return vote > 0 ? CODESET.A : CODESET.B; |
|||
} |
|||
|
|||
function perhapsCodeC(bytes, codeset) { |
|||
for (var i = 0; i < bytes.length; i++) { |
|||
var b = bytes[i] |
|||
if ((b < 48 || b > 57) && b != CHAR_TILDE) |
|||
return codeset; |
|||
} |
|||
return CODESET.C; |
|||
} |
|||
|
|||
//chr1 is current byte
|
|||
//chr2 is the next byte to process. looks ahead.
|
|||
function codesForChar(chr1, chr2, currcs) { |
|||
var result = []; |
|||
var shifter = -1; |
|||
|
|||
if (charCompatible(chr1, currcs)) { |
|||
if (currcs == CODESET.C) { |
|||
if (chr2 == -1) { |
|||
shifter = SET_CODEB; |
|||
currcs = CODESET.B; |
|||
} |
|||
else if ((chr2 != -1) && !charCompatible(chr2, currcs)) { |
|||
//need to check ahead as well
|
|||
if (charCompatible(chr2, CODESET.A)) { |
|||
shifter = SET_CODEA; |
|||
currcs = CODESET.A; |
|||
} |
|||
else { |
|||
shifter = SET_CODEB; |
|||
currcs = CODESET.B; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
else { |
|||
//if there is a next char AND that next char is also not compatible
|
|||
if ((chr2 != -1) && !charCompatible(chr2, currcs)) { |
|||
//need to switch code sets
|
|||
switch (currcs) { |
|||
case CODESET.A: |
|||
shifter = SET_CODEB; |
|||
currcs = CODESET.B; |
|||
break; |
|||
case CODESET.B: |
|||
shifter = SET_CODEA; |
|||
currcs = CODESET.A; |
|||
break; |
|||
} |
|||
} |
|||
else { |
|||
//no need to shift code sets, a temporary SHIFT will suffice
|
|||
shifter = SET_SHIFT; |
|||
} |
|||
} |
|||
|
|||
//ok some type of shift is nessecary
|
|||
if (shifter != -1) { |
|||
result.push(shifter); |
|||
result.push(codeValue(chr2)); |
|||
} |
|||
else { |
|||
if (currcs == CODESET.C) { |
|||
//include next as well
|
|||
result.push(codeValue(chr1, chr2)); |
|||
} |
|||
else { |
|||
result.push(codeValue(chr1)); |
|||
} |
|||
} |
|||
barc.currcs = currcs; |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
|
|||
//reduce the ascii code to fit into the Code128 char table
|
|||
function codeValue(chr1, chr2) { |
|||
if (typeof chr2 == "undefined") { |
|||
return chr1 >= 32 ? chr1 - 32 : chr1 + 64; |
|||
} |
|||
else { |
|||
return parseInt(String.fromCharCode(chr1) + String.fromCharCode(chr2)); |
|||
} |
|||
} |
|||
|
|||
function charCompatible(chr, codeset) { |
|||
var csa = codeSetAllowedFor(chr); |
|||
if (csa == CODESET.ANY) return true; |
|||
//if we need to change from current
|
|||
if (csa == CODESET.AB) return true; |
|||
if (csa == CODESET.A && codeset == CODESET.A) return true; |
|||
if (csa == CODESET.B && codeset == CODESET.B) return true; |
|||
return false; |
|||
} |
|||
|
|||
function codeSetAllowedFor(chr) { |
|||
if (chr >= 48 && chr <= 57) { |
|||
//0-9
|
|||
return CODESET.ANY; |
|||
} |
|||
else if (chr >= 32 && chr <= 95) { |
|||
//0-9 A-Z
|
|||
return CODESET.AB; |
|||
} |
|||
else { |
|||
//if non printable
|
|||
return chr < 32 ? CODESET.A : CODESET.B; |
|||
} |
|||
} |
|||
|
|||
var Graphics = function(ctx, width, height) { |
|||
|
|||
this.width = width; |
|||
this.height = height; |
|||
this.quiet = Math.round(this.width / 40); |
|||
|
|||
this.border_size = 0; |
|||
this.padding_width = 0; |
|||
|
|||
this.area = { |
|||
width : width - this.padding_width * 2 - this.quiet * 2, |
|||
height: height - this.border_size * 2, |
|||
top : this.border_size - 4, |
|||
left : this.padding_width + this.quiet |
|||
}; |
|||
|
|||
this.ctx = ctx; |
|||
this.fg = "#000000"; |
|||
this.bg = "#ffffff"; |
|||
|
|||
// fill background
|
|||
this.fillBgRect(0,0, width, height); |
|||
|
|||
// fill center to create border
|
|||
this.fillBgRect(0, this.border_size, width, height - this.border_size * 2); |
|||
} |
|||
|
|||
//use native color
|
|||
Graphics.prototype._fillRect = function(x, y, width, height, color) { |
|||
this.ctx.setFillStyle(color) |
|||
this.ctx.fillRect(x, y, width, height) |
|||
} |
|||
|
|||
Graphics.prototype.fillFgRect = function(x,y, width, height) { |
|||
this._fillRect(x, y, width, height, this.fg); |
|||
} |
|||
|
|||
Graphics.prototype.fillBgRect = function(x,y, width, height) { |
|||
this._fillRect(x, y, width, height, this.bg); |
|||
} |
|||
|
|||
var PATTERNS = [ |
|||
[2, 1, 2, 2, 2, 2, 0, 0], // 0
|
|||
[2, 2, 2, 1, 2, 2, 0, 0], // 1
|
|||
[2, 2, 2, 2, 2, 1, 0, 0], // 2
|
|||
[1, 2, 1, 2, 2, 3, 0, 0], // 3
|
|||
[1, 2, 1, 3, 2, 2, 0, 0], // 4
|
|||
[1, 3, 1, 2, 2, 2, 0, 0], // 5
|
|||
[1, 2, 2, 2, 1, 3, 0, 0], // 6
|
|||
[1, 2, 2, 3, 1, 2, 0, 0], // 7
|
|||
[1, 3, 2, 2, 1, 2, 0, 0], // 8
|
|||
[2, 2, 1, 2, 1, 3, 0, 0], // 9
|
|||
[2, 2, 1, 3, 1, 2, 0, 0], // 10
|
|||
[2, 3, 1, 2, 1, 2, 0, 0], // 11
|
|||
[1, 1, 2, 2, 3, 2, 0, 0], // 12
|
|||
[1, 2, 2, 1, 3, 2, 0, 0], // 13
|
|||
[1, 2, 2, 2, 3, 1, 0, 0], // 14
|
|||
[1, 1, 3, 2, 2, 2, 0, 0], // 15
|
|||
[1, 2, 3, 1, 2, 2, 0, 0], // 16
|
|||
[1, 2, 3, 2, 2, 1, 0, 0], // 17
|
|||
[2, 2, 3, 2, 1, 1, 0, 0], // 18
|
|||
[2, 2, 1, 1, 3, 2, 0, 0], // 19
|
|||
[2, 2, 1, 2, 3, 1, 0, 0], // 20
|
|||
[2, 1, 3, 2, 1, 2, 0, 0], // 21
|
|||
[2, 2, 3, 1, 1, 2, 0, 0], // 22
|
|||
[3, 1, 2, 1, 3, 1, 0, 0], // 23
|
|||
[3, 1, 1, 2, 2, 2, 0, 0], // 24
|
|||
[3, 2, 1, 1, 2, 2, 0, 0], // 25
|
|||
[3, 2, 1, 2, 2, 1, 0, 0], // 26
|
|||
[3, 1, 2, 2, 1, 2, 0, 0], // 27
|
|||
[3, 2, 2, 1, 1, 2, 0, 0], // 28
|
|||
[3, 2, 2, 2, 1, 1, 0, 0], // 29
|
|||
[2, 1, 2, 1, 2, 3, 0, 0], // 30
|
|||
[2, 1, 2, 3, 2, 1, 0, 0], // 31
|
|||
[2, 3, 2, 1, 2, 1, 0, 0], // 32
|
|||
[1, 1, 1, 3, 2, 3, 0, 0], // 33
|
|||
[1, 3, 1, 1, 2, 3, 0, 0], // 34
|
|||
[1, 3, 1, 3, 2, 1, 0, 0], // 35
|
|||
[1, 1, 2, 3, 1, 3, 0, 0], // 36
|
|||
[1, 3, 2, 1, 1, 3, 0, 0], // 37
|
|||
[1, 3, 2, 3, 1, 1, 0, 0], // 38
|
|||
[2, 1, 1, 3, 1, 3, 0, 0], // 39
|
|||
[2, 3, 1, 1, 1, 3, 0, 0], // 40
|
|||
[2, 3, 1, 3, 1, 1, 0, 0], // 41
|
|||
[1, 1, 2, 1, 3, 3, 0, 0], // 42
|
|||
[1, 1, 2, 3, 3, 1, 0, 0], // 43
|
|||
[1, 3, 2, 1, 3, 1, 0, 0], // 44
|
|||
[1, 1, 3, 1, 2, 3, 0, 0], // 45
|
|||
[1, 1, 3, 3, 2, 1, 0, 0], // 46
|
|||
[1, 3, 3, 1, 2, 1, 0, 0], // 47
|
|||
[3, 1, 3, 1, 2, 1, 0, 0], // 48
|
|||
[2, 1, 1, 3, 3, 1, 0, 0], // 49
|
|||
[2, 3, 1, 1, 3, 1, 0, 0], // 50
|
|||
[2, 1, 3, 1, 1, 3, 0, 0], // 51
|
|||
[2, 1, 3, 3, 1, 1, 0, 0], // 52
|
|||
[2, 1, 3, 1, 3, 1, 0, 0], // 53
|
|||
[3, 1, 1, 1, 2, 3, 0, 0], // 54
|
|||
[3, 1, 1, 3, 2, 1, 0, 0], // 55
|
|||
[3, 3, 1, 1, 2, 1, 0, 0], // 56
|
|||
[3, 1, 2, 1, 1, 3, 0, 0], // 57
|
|||
[3, 1, 2, 3, 1, 1, 0, 0], // 58
|
|||
[3, 3, 2, 1, 1, 1, 0, 0], // 59
|
|||
[3, 1, 4, 1, 1, 1, 0, 0], // 60
|
|||
[2, 2, 1, 4, 1, 1, 0, 0], // 61
|
|||
[4, 3, 1, 1, 1, 1, 0, 0], // 62
|
|||
[1, 1, 1, 2, 2, 4, 0, 0], // 63
|
|||
[1, 1, 1, 4, 2, 2, 0, 0], // 64
|
|||
[1, 2, 1, 1, 2, 4, 0, 0], // 65
|
|||
[1, 2, 1, 4, 2, 1, 0, 0], // 66
|
|||
[1, 4, 1, 1, 2, 2, 0, 0], // 67
|
|||
[1, 4, 1, 2, 2, 1, 0, 0], // 68
|
|||
[1, 1, 2, 2, 1, 4, 0, 0], // 69
|
|||
[1, 1, 2, 4, 1, 2, 0, 0], // 70
|
|||
[1, 2, 2, 1, 1, 4, 0, 0], // 71
|
|||
[1, 2, 2, 4, 1, 1, 0, 0], // 72
|
|||
[1, 4, 2, 1, 1, 2, 0, 0], // 73
|
|||
[1, 4, 2, 2, 1, 1, 0, 0], // 74
|
|||
[2, 4, 1, 2, 1, 1, 0, 0], // 75
|
|||
[2, 2, 1, 1, 1, 4, 0, 0], // 76
|
|||
[4, 1, 3, 1, 1, 1, 0, 0], // 77
|
|||
[2, 4, 1, 1, 1, 2, 0, 0], // 78
|
|||
[1, 3, 4, 1, 1, 1, 0, 0], // 79
|
|||
[1, 1, 1, 2, 4, 2, 0, 0], // 80
|
|||
[1, 2, 1, 1, 4, 2, 0, 0], // 81
|
|||
[1, 2, 1, 2, 4, 1, 0, 0], // 82
|
|||
[1, 1, 4, 2, 1, 2, 0, 0], // 83
|
|||
[1, 2, 4, 1, 1, 2, 0, 0], // 84
|
|||
[1, 2, 4, 2, 1, 1, 0, 0], // 85
|
|||
[4, 1, 1, 2, 1, 2, 0, 0], // 86
|
|||
[4, 2, 1, 1, 1, 2, 0, 0], // 87
|
|||
[4, 2, 1, 2, 1, 1, 0, 0], // 88
|
|||
[2, 1, 2, 1, 4, 1, 0, 0], // 89
|
|||
[2, 1, 4, 1, 2, 1, 0, 0], // 90
|
|||
[4, 1, 2, 1, 2, 1, 0, 0], // 91
|
|||
[1, 1, 1, 1, 4, 3, 0, 0], // 92
|
|||
[1, 1, 1, 3, 4, 1, 0, 0], // 93
|
|||
[1, 3, 1, 1, 4, 1, 0, 0], // 94
|
|||
[1, 1, 4, 1, 1, 3, 0, 0], // 95
|
|||
[1, 1, 4, 3, 1, 1, 0, 0], // 96
|
|||
[4, 1, 1, 1, 1, 3, 0, 0], // 97
|
|||
[4, 1, 1, 3, 1, 1, 0, 0], // 98
|
|||
[1, 1, 3, 1, 4, 1, 0, 0], // 99
|
|||
[1, 1, 4, 1, 3, 1, 0, 0], // 100
|
|||
[3, 1, 1, 1, 4, 1, 0, 0], // 101
|
|||
[4, 1, 1, 1, 3, 1, 0, 0], // 102
|
|||
[2, 1, 1, 4, 1, 2, 0, 0], // 103
|
|||
[2, 1, 1, 2, 1, 4, 0, 0], // 104
|
|||
[2, 1, 1, 2, 3, 2, 0, 0], // 105
|
|||
[2, 3, 3, 1, 1, 1, 2, 0] // 106
|
|||
] |
|||
|
@ -0,0 +1,723 @@ |
|||
/** |
|||
* @export |
|||
* @param {string} name 微信api的名称 ,如 uniAsyncPromise("getSystemInfo",options) |
|||
* @param {object} options 除了success 和 fail 的其他参数 |
|||
* @returns |
|||
*/ |
|||
export function uniAsyncPromise(name, options) { |
|||
return new Promise((resolve, reject) => { |
|||
uni[name]({ |
|||
...(options || {}), |
|||
// ...options,
|
|||
success: (res) => { |
|||
resolve(res); |
|||
}, |
|||
fail: (err) => { |
|||
reject(err); |
|||
} |
|||
}); |
|||
}); |
|||
} |
|||
//微信小程序向蓝牙打印机发送数据进行打印的坑:
|
|||
//小程序api向蓝牙打印机发送数据打印,发送的任何内容都应该要转成二进制数据,而且蓝牙打印的文本编码是GBK的,发送中文需转成GBK编码再转成二进制数据发送
|
|||
//发送打印机指令也要转成二进制数据发送
|
|||
//蓝牙打印机一次接收的二级制数据有限制,不同的系统不同的蓝牙设备限制可能不同,微信建议一次20个字节,需做递归分包发送
|
|||
//发送完要打印的内容后,一定要发送一个打印的指令才能顺利打印 (有些指令就不需要)
|
|||
|
|||
//一、初始化蓝牙、开始检索蓝牙设备
|
|||
// { allowDuplicatesKey: true, interval: 500}
|
|||
export function openBlue() { |
|||
return uniAsyncPromise('openBluetoothAdapter') |
|||
} |
|||
|
|||
export function startBluetoothDevicesDiscovery(option) { |
|||
console.log('开始蓝牙扫描'); |
|||
uniAsyncPromise('startBluetoothDevicesDiscovery', option).then((res) => { |
|||
console.log('正在搜寻蓝牙设备', res); |
|||
}); |
|||
} |
|||
|
|||
export function getConnectedBluetoothDevices(option) { |
|||
console.log('开始获取已连接设备'); |
|||
return uniAsyncPromise('getConnectedBluetoothDevices', option) |
|||
} |
|||
//二、
|
|||
/** |
|||
* |
|||
* |
|||
* @export |
|||
* @param {function} getDevices uni.getBluetoothDevices的监听回调函数 |
|||
*/ |
|||
export function onfindBlueDevices(getDevices) { |
|||
//监听寻找到新设备的事件
|
|||
uni.onBluetoothDeviceFound((devices)=>{ |
|||
//获取在蓝牙模块生效期间所有已发现的蓝牙设备
|
|||
uniAsyncPromise('getBluetoothDevices').then((res) => { |
|||
getDevices && getDevices(res.devices); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* @export |
|||
* @param {function} stopBlueDevicesDiscovery 关闭蓝牙扫描 |
|||
*/ |
|||
export function stopBlueDevicesDiscovery() { |
|||
//监听寻找到新设备的事件
|
|||
console.log('停止蓝牙扫描'); |
|||
return uniAsyncPromise('stopBluetoothDevicesDiscovery').then((res) => { |
|||
console.log('停止搜寻蓝牙设备', res); |
|||
}); |
|||
} |
|||
|
|||
|
|||
|
|||
//三、连接蓝牙设备
|
|||
/** |
|||
* @export |
|||
* @param {function} createBLEConnection |
|||
* @param {number} deviceId 蓝牙设备id |
|||
*/ |
|||
export function createBLEConnection(deviceId, sucess, fail) { |
|||
//连接蓝牙设备
|
|||
console.log('连接蓝牙设备', deviceId); |
|||
uniAsyncPromise("createBLEConnection", { |
|||
deviceId |
|||
}) |
|||
.then(res => { |
|||
//连接成功可选择停止搜索蓝牙
|
|||
//stopBlueDevicesDiscovery();
|
|||
console.log('连接成功'); |
|||
sucess && sucess({ |
|||
res: res, |
|||
}); |
|||
}) |
|||
.catch(res => { |
|||
console.log('连接设备异常' + res); |
|||
fail && fail({ |
|||
res: res, |
|||
}); |
|||
}) |
|||
/*.finally(res=>{ |
|||
console.log('连接成功'); |
|||
sucess && sucess({ |
|||
res: res, |
|||
}); |
|||
});*/ |
|||
} |
|||
|
|||
export function closeBLEConnection(deviceId) { |
|||
console.log('断开蓝牙设备', deviceId); |
|||
uniAsyncPromise("closeBLEConnection", { |
|||
deviceId |
|||
}) |
|||
.then(res => { |
|||
console.log('BLEDisconnect complete', res); |
|||
}) |
|||
.catch(res => { |
|||
console.log('断开设备异常' + res); |
|||
}) |
|||
/*.finally(res=>{ |
|||
console.log('BLEDisconnect complete', res); |
|||
}); */ |
|||
} |
|||
|
|||
//四、连接成功后, 获取蓝牙设备的service服务
|
|||
// uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})
|
|||
export function getBLEDeviceServices(deviceId, success, fail) { |
|||
console.log('获取ServiceId', deviceId); |
|||
//加延迟避免取不到service
|
|||
setTimeout(()=>{ |
|||
uniAsyncPromise("getBLEDeviceServices", { |
|||
deviceId:deviceId |
|||
}) |
|||
.then(res => { |
|||
console.log('服务', res); |
|||
success && success({ |
|||
serviceId: res.services, |
|||
}); |
|||
}) |
|||
.catch((res) => { |
|||
//getBLEDeviceServices(deviceId, success, fail);
|
|||
console.log('获取ServiceId异常' + res); |
|||
fail && fail({ |
|||
res: res, |
|||
}); |
|||
}); |
|||
},1000) |
|||
} |
|||
|
|||
//五、获取的service服务可能有多个,递归获取特征值(最后要用的是能读,能写,能监听的那个值的uuid作为特征值id)
|
|||
/** |
|||
* |
|||
* |
|||
* @export |
|||
* @param {number} deviceId 蓝牙设备id |
|||
* @param {array} services uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})获取的res.services |
|||
* @param {function} success 成功取得有用特征值uuid的回调函数 |
|||
*/ |
|||
export function getDeviceCharacteristics(deviceId, services, success, fail) { |
|||
//services = services.slice(0);
|
|||
console.log('获取Characteristics', deviceId, services); |
|||
if (services.length) { |
|||
const serviceId = services.shift().uuid; |
|||
console.log('ServceID ', serviceId); |
|||
uniAsyncPromise('getBLEDeviceCharacteristics', { |
|||
deviceId, |
|||
serviceId, |
|||
}) |
|||
.then((res) => { |
|||
console.log('getBLEDeviceCharacteristics', deviceId, serviceId, res); |
|||
let finished = false; |
|||
let write = false; |
|||
let notify = false; |
|||
let indicate = false; |
|||
var readId; |
|||
var writeId; |
|||
//有斑马品牌的一款打印机中res.characteristics的所有uuid都是相同的,找所有的properties存在(notify || indicate) && write这种情况就说明这个uuid是可用的(不确保所有的打印机都能用这种方式取得uuid,在主要测试得凯盛诺打印机res.characteristic只有一个uuid,所以也能用这个方式)
|
|||
for (var i = 0; i < res.characteristics.length; i++) { |
|||
if (!notify) { |
|||
notify = res.characteristics[i].properties.notify; |
|||
if (notify) readId = res.characteristics[i].uuid; |
|||
} |
|||
if (!indicate) { |
|||
indicate = res.characteristics[i].properties.indicate; |
|||
if (indicate) readId = res.characteristics[i].uuid; |
|||
} |
|||
if (!write) { |
|||
write = res.characteristics[i].properties.write; |
|||
writeId = res.characteristics[i].uuid; |
|||
} |
|||
if ((notify || indicate) && write) { |
|||
/* 获取蓝牙特征值uuid */ |
|||
success && |
|||
success({ |
|||
serviceId, |
|||
writeId: writeId, |
|||
readId: readId, |
|||
}); |
|||
finished = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (!finished) { |
|||
getDeviceCharacteristics(deviceId, services, success, fail); |
|||
} |
|||
}) |
|||
.catch((res) => { |
|||
getDeviceCharacteristics(deviceId, services, success, fail); |
|||
}); |
|||
} else { |
|||
fail && fail(); |
|||
} |
|||
} |
|||
|
|||
//六、启动notify 蓝牙监听功能 然后使用 uni.onBLECharacteristicValueChange用来监听蓝牙设备传递数据
|
|||
/** |
|||
* @export |
|||
* @param {object} options |
|||
* { |
|||
deviceId,//蓝牙设备id
|
|||
serviceId,//服务id
|
|||
characteristicId,//可用特征值uuid
|
|||
} |
|||
* @param {function} onChange 监听蓝牙设备传递数据回调函数 |
|||
*/ |
|||
export function onGetBLECharacteristicValueChange(options, onChange = function() {}) { |
|||
console.log('deviceId ', options.deviceId); |
|||
console.log('serviceId ', options.serviceId); |
|||
console.log('characteristicId ', options.characteristicId); |
|||
uniAsyncPromise('notifyBLECharacteristicValueChange', { |
|||
state: true, |
|||
...options, |
|||
}).then((res) => { |
|||
console.log('onBLECharacteristicValueChange '); |
|||
uni.onBLECharacteristicValueChange(onChange); |
|||
}); |
|||
} |
|||
|
|||
//七、发送数据(递归分包发送)
|
|||
/** |
|||
* @export |
|||
* @param {object} options |
|||
* { |
|||
deviceId, |
|||
serviceId, |
|||
characteristicId, |
|||
value [ArrayBuffer], |
|||
lasterSuccess, |
|||
onceLength |
|||
} |
|||
*/ |
|||
|
|||
export function sendDataToDevice(options) { |
|||
let byteLength = options.value.byteLength; |
|||
//这里默认一次20个字节发送
|
|||
const speed = options.onceLength; //20;
|
|||
console.log("send data 20"); |
|||
console.log(options); |
|||
if (byteLength > 0) { |
|||
uniAsyncPromise('writeBLECharacteristicValue', { |
|||
...options, |
|||
value: options.value.slice(0, byteLength > speed ? speed : byteLength), |
|||
}) |
|||
.then((res) => { |
|||
if (byteLength > speed) { |
|||
sendDataToDevice({ |
|||
...options, |
|||
value: options.value.slice(speed, byteLength), |
|||
}); |
|||
} else { |
|||
options.lasterSuccess && options.lasterSuccess(); |
|||
} |
|||
}) |
|||
.catch((res) => { |
|||
console.log(res); |
|||
}); |
|||
} |
|||
} |
|||
export function charToArrayBuffer(str) { |
|||
var out = new ArrayBuffer(str.length); |
|||
var uint8 = new Uint8Array(out); |
|||
var strs = str.split(''); |
|||
for (var i = 0; i < strs.length; i++) { |
|||
uint8[i] = strs[i].charCodeAt(); |
|||
} |
|||
return uint8; |
|||
} |
|||
export function charToArray(str) { |
|||
var arr = []; |
|||
var strs = str.split(''); |
|||
for (var i = 0; i < strs.length; i++) { |
|||
arr[i] = strs[i].charCodeAt(); |
|||
} |
|||
return arr; |
|||
} |
|||
//打印二维码
|
|||
/** |
|||
* @export |
|||
* @param {object} options |
|||
* { |
|||
deviceId, |
|||
serviceId, |
|||
characteristicId, |
|||
value,//ArrayBuffer:二维码的数据
|
|||
} |
|||
*/ |
|||
export function printQR(options) { |
|||
//打印二维码的十进制指令data:
|
|||
let data = [29, 107, 97, 7, 4, options.value.byteLength, 0]; |
|||
sendDataToDevice({ |
|||
...options, |
|||
value: new Uint8Array(data).buffer, |
|||
lasterSuccess: () => { |
|||
//指令发送成功后,发送二维码的数据
|
|||
sendDataToDevice(options); |
|||
}, |
|||
}); |
|||
} |
|||
|
|||
function grayPixle(pix) { |
|||
return pix[0] * 0.299 + pix[1] * 0.587 + pix[2] * 0.114; |
|||
} |
|||
|
|||
export function overwriteImageData(data) { |
|||
let sendWidth = data.width, |
|||
sendHeight = data.height; |
|||
const threshold = data.threshold || 180; |
|||
let sendImageData = new ArrayBuffer((sendWidth * sendHeight) / 8); |
|||
sendImageData = new Uint8Array(sendImageData); |
|||
let pix = data.imageData; |
|||
const part = []; |
|||
let index = 0; |
|||
for (let i = 0; i < pix.length; i += 32) { |
|||
//横向每8个像素点组成一个字节(8位二进制数)。
|
|||
for (let k = 0; k < 8; k++) { |
|||
const grayPixle1 = grayPixle(pix.slice(i + k * 4, i + k * 4 + (4 - 1))); |
|||
//阈值调整
|
|||
if (grayPixle1 > threshold) { |
|||
//灰度值大于threshold位 白色 为第k位0不打印
|
|||
part[k] = 0; |
|||
} else { |
|||
part[k] = 1; |
|||
} |
|||
} |
|||
let temp = 0; |
|||
for (let a = 0; a < part.length; a++) { |
|||
temp += part[a] * Math.pow(2, part.length - 1 - a); |
|||
} |
|||
//开始不明白以下算法什么意思,了解了字节才知道,一个字节是8位的二进制数,part这个数组存的0和1就是二进制的0和1,传输到打印的位图数据的一个字节是0-255之间的十进制数,以下是用权相加法转十进制数,理解了这个就用上面的for循环替代了
|
|||
// const temp =
|
|||
// part[0] * 128 +
|
|||
// part[1] * 64 +
|
|||
// part[2] * 32 +
|
|||
// part[3] * 16 +
|
|||
// part[4] * 8 +
|
|||
// part[5] * 4 +
|
|||
// part[6] * 2 +
|
|||
// part[7] * 1;
|
|||
sendImageData[index++] = temp; |
|||
} |
|||
return { |
|||
array: Array.from(sendImageData), |
|||
width: sendWidth / 8, |
|||
height: sendHeight, |
|||
}; |
|||
} |
|||
/** |
|||
* printImage |
|||
* @param {object} opt |
|||
* { |
|||
deviceId,//蓝牙设备id
|
|||
serviceId,//服务id
|
|||
characteristicId,//可用特征值uuid
|
|||
lasterSuccess , //最后完成的回调
|
|||
} |
|||
*/ |
|||
export function printImage(opt = {}, imageInfo = {}) { |
|||
let arr = imageInfo.array, |
|||
width = imageInfo.width; |
|||
const writeArray = []; |
|||
const xl = width % 256; |
|||
const xh = width / 256; |
|||
//分行发送图片数据,用的十进制指令
|
|||
const command = [29, 118, 48, 0, xl, xh, 1, 0]; //1D 76 30 00 w h
|
|||
const enter = [13, 10]; |
|||
for (let i = 0; i < arr.length / width; i++) { |
|||
const subArr = arr.slice(i * width, i * width + width); |
|||
const tempArr = command.concat(subArr); |
|||
writeArray.push(new Uint8Array(tempArr)); |
|||
} |
|||
writeArray.push(new Uint8Array(enter)); |
|||
//console.log(writeArray);
|
|||
const print = (options, writeArray) => { |
|||
if (writeArray.length) { |
|||
console.log("send"); |
|||
sendDataToDevice({ |
|||
...options, |
|||
value: writeArray.shift().buffer, |
|||
lasterSuccess: () => { |
|||
if (writeArray.length) { |
|||
print(options, writeArray); |
|||
} else { |
|||
options.lasterSuccess && options.lasterSuccess(); |
|||
} |
|||
}, |
|||
}); |
|||
} |
|||
}; |
|||
console.log("start print"); |
|||
print(opt, writeArray); |
|||
} |
|||
|
|||
/* 16hex insert 0 */ |
|||
function Hex2Str(num) { |
|||
if (num.toString(16).length < 2) return "0" + num.toString(16); |
|||
else |
|||
return num.toString(16); |
|||
} |
|||
/*****CPCL指令接口****/ |
|||
|
|||
/** |
|||
* 配置项如下 |
|||
* |
|||
* width: 标签纸的宽度,单位像素點 |
|||
* height: 标签纸的高度,单位像素點 |
|||
* 8像素=1mm |
|||
* printNum: 打印张数,默认为1 |
|||
* rotation:页面整体旋转 1-90度 2-180度 3-270度 其他-不旋转 |
|||
*/ |
|||
export function CreatCPCLPage(width, height, printNum, rotation = 0, offset = 0) { |
|||
var strCmd = '! ' + offset + ' 200 200 ' + height + ' ' + printNum + '\n'; |
|||
strCmd += "PAGE-WIDTH " + width + '\n'; |
|||
if (rotation == 1) |
|||
strCmd += "ZPROTATE90\n"; |
|||
else if (rotation == 2) |
|||
strCmd += "ZPROTATE180\n"; |
|||
else if (rotation == 3) |
|||
strCmd += "ZPROTATE270\n"; |
|||
else |
|||
strCmd += "ZPROTATE0\n"; |
|||
return strCmd; |
|||
} |
|||
|
|||
/** |
|||
* 打印文字 |
|||
* x: 文字方块左上角X座标,单位dot |
|||
* y: 文字方块左上角Y座标,单位dot |
|||
* fontName,fontSize: 字体,取值: 參考文檔 |
|||
* rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转 |
|||
* content: 文字内容 |
|||
*/ |
|||
export function addCPCLText(x, y, fontName, fontSize, rotation, content) { |
|||
//console.log(fontName,fontSize,rotation, content);
|
|||
var strCmd = ''; |
|||
if (rotation == 1) { |
|||
strCmd += 'T90 '; |
|||
} |
|||
if (rotation == 2) { |
|||
strCmd += 'T180 '; |
|||
} |
|||
if (rotation == 3) { |
|||
strCmd += 'T270 '; |
|||
} else { |
|||
strCmd += 'T '; |
|||
} |
|||
strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 打印一维码 |
|||
* |
|||
* x: 文字方块左上角X座标,单位dot |
|||
* y: 文字方块左上角Y座标,单位dot |
|||
* codeType: 条码类型,取值为128、UPCA、UPCA2、UPCA5、UPCE、UPCE2、UPC5、EAN13、EAN13+2、EAN13+5、 |
|||
* EAN8、EAN8+2、EAN8+5、39、39C、F39、F39C、93、CODABAR、CODABAR16、ITF、I2OF5 |
|||
* h: 条码高度,单位dot |
|||
* rotation: 顺时针旋转角度,取值如下: |
|||
* - 0 不旋转 |
|||
* - 1 顺时针旋转90度 |
|||
* |
|||
* narrow: 窄条码比例因子(dot) 取值: 參考文檔 |
|||
* wide: 宽条码比例因子(dot) 取值: 參考文檔 |
|||
* content: 文字内容 |
|||
* |
|||
*/ |
|||
export function addCPCLBarCode(x, y, codeType, h, rotation, narrow, wide, content) { |
|||
var strCmd = ''; |
|||
if (rotation == 0) |
|||
strCmd += 'B '; |
|||
else |
|||
strCmd += 'VB '; |
|||
strCmd += codeType + ' ' + narrow + ' ' + wide + ' ' + h + ' ' + x + ' ' + y + ' ' + content + '\n' |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 打印二维码 |
|||
* |
|||
* x: 文字方块左上角X座标,单位dot |
|||
* y: 文字方块左上角Y座标,单位dot |
|||
* level: 错误纠正能力等级,取值为L(7%)、M(15%)、Q(25%)、H(30%) |
|||
* ver: 1-10 版本,根据内容调整以获取合适容量 |
|||
* scale: 1-10 放大倍数 |
|||
* content: 文字内容 |
|||
* |
|||
*/ |
|||
export function addCPCLQRCode(x, y, level, ver, scale, content) { |
|||
var strCmd = 'B QR ' + x + ' ' + y + ' M ' + ver + ' U ' + scale + '\n' + level + 'A,' + content + '\n'; |
|||
strCmd += 'ENDQR\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 放大指令 |
|||
* scaleX: 横向放大倍数 1,2,3等整数 |
|||
* scaleY: 纵向放大倍数 1,2,3等整数 |
|||
*/ |
|||
export function addCPCLSETMAG(scaleX, scaleY) { |
|||
var strCmd = 'SETMAG ' + scaleX + ' ' + scaleY + '\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 对齐指令 0-左对齐 1-右对齐 2-居中 |
|||
*/ |
|||
export function addCPCLLocation(set) { |
|||
var strCmd = ''; |
|||
if (set == 1) { |
|||
strCmd += 'RIGHT\n'; |
|||
} else if (set == 2) { |
|||
strCmd += 'CENTER\n'; |
|||
} else { |
|||
strCmd += 'LEFT\n'; |
|||
} |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 反白线 x0,y0,x1,y1,width |
|||
*/ |
|||
export function addCPCLInverseLine(x0, y0, x1, y1, width) { |
|||
var strCmd = 'IL ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 画线 x0,y0,x1,y1,width |
|||
*/ |
|||
export function addCPCLLine(x0, y0, x1, y1, width) { |
|||
var strCmd = 'L ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 画框 x0,y0,x1,y1,width |
|||
*/ |
|||
export function addCPCLBox(x0, y0, x1, y1, width) { |
|||
var strCmd = 'BOX ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 字体加粗 |
|||
*/ |
|||
export function addCPCLSETBOLD(bold) { |
|||
var strCmd = 'SETBOLD ' + bold + '\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 字体下划线 |
|||
*/ |
|||
export function addCPCLUNDERLINE(c) { |
|||
var strCmd = 'UNDERLINE '; |
|||
if (c) strCmd += 'ON\n'; |
|||
else if (c) strCmd += 'OFF\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 水印打印灰度等级 0-255 |
|||
*/ |
|||
export function addCPCLBACKGROUND(level) { |
|||
var strCmd = 'BACKGROUND '; |
|||
if (level > 255 || level < 0) level = 255; |
|||
strCmd += level + '\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 打印水印文字 |
|||
* x: 文字方块左上角X座标,单位dot |
|||
* y: 文字方块左上角Y座标,单位dot |
|||
* fontName,fontSize: 字体,取值: 參考文檔 |
|||
* rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转 |
|||
* content: 文字内容 |
|||
*/ |
|||
export function addCPCLBKVText(x, y, fontName, fontSize, rotation, content) { |
|||
//console.log(fontName,fontSize,rotation, content);
|
|||
var strCmd = ''; |
|||
if (rotation == 1) { |
|||
strCmd += 'BKT90 '; |
|||
} |
|||
if (rotation == 2) { |
|||
strCmd += 'BKT180 '; |
|||
} |
|||
if (rotation == 3) { |
|||
strCmd += 'BKT270 '; |
|||
} else { |
|||
strCmd += 'BKT '; |
|||
} |
|||
strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
|
|||
/** |
|||
* 标签缝隙定位指令 |
|||
*/ |
|||
export function addCPCLGAP() { |
|||
var strCmd = 'GAP-SENSE\nFORM\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 标签右黑标检测指令 |
|||
*/ |
|||
export function addCPCLSENSE() { |
|||
var strCmd = 'BAR-SENSE\nFORM\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 标签左黑标检测指令 |
|||
*/ |
|||
export function addCPCLSENSELEFT() { |
|||
var strCmd = 'BAR-SENSE LEFT\nFORM\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 打印指令 |
|||
*/ |
|||
export function addCPCLPrint() { |
|||
var strCmd = 'PRINT\n'; |
|||
return strCmd; |
|||
}; |
|||
|
|||
/** |
|||
* 图片打印指令 |
|||
* x: 文字方块左上角X座标,单位dot |
|||
* y: 文字方块左上角Y座标,单位dot |
|||
* data{ |
|||
threshold,//0/1提取的灰度级
|
|||
width,//图像宽度
|
|||
height,//图像高度
|
|||
imageData , //图像数据
|
|||
} |
|||
*/ |
|||
export function addCPCLImageCmd(x, y, data) { |
|||
var strImgCmd = ''; |
|||
const threshold = data.threshold || 180; |
|||
let myBitmapWidth = data.width, |
|||
myBitmapHeight = data.height; |
|||
let len = parseInt((myBitmapWidth + 7) / 8); //一行的数据长度
|
|||
//console.log('len=',len);
|
|||
//console.log('myBitmapWidth=',myBitmapWidth);
|
|||
//console.log('myBitmapHeight=',myBitmapHeight);
|
|||
let ndata = 0; |
|||
let i = 0; |
|||
let j = 0; |
|||
let sendImageData = new ArrayBuffer(len * myBitmapHeight); |
|||
sendImageData = new Uint8Array(sendImageData); |
|||
let pix = data.imageData; |
|||
console.log('pix=', pix); |
|||
|
|||
for (i = 0; i < myBitmapHeight; i++) { |
|||
for (j = 0; j < len; j++) { |
|||
sendImageData[ndata + j] = 0; |
|||
} |
|||
for (j = 0; j < myBitmapWidth; j++) { |
|||
const grayPixle1 = grayPixle(pix.slice((i * myBitmapWidth + j) * 4, (i * myBitmapWidth + j) * 4 + 3)); |
|||
if (grayPixle1 < threshold) |
|||
sendImageData[ndata + parseInt(j / 8)] |= (0x80 >> (j % 8)); |
|||
|
|||
} |
|||
ndata += len; |
|||
} |
|||
//console.log('sendImageData=',sendImageData);
|
|||
//CPCL指令图片数据
|
|||
strImgCmd += 'EG ' + len + ' ' + myBitmapHeight + ' ' + x + ' ' + y + ' '; |
|||
for (i = 0; i < sendImageData.length; i++) { |
|||
strImgCmd += Hex2Str(sendImageData[i]); |
|||
} |
|||
strImgCmd += '\n'; |
|||
//console.log(strImgCmd);
|
|||
return strImgCmd; |
|||
} |
|||
/** |
|||
* toast显示捕获的蓝牙异常 |
|||
*/ |
|||
export function catchToast(err) { |
|||
const errMsg = { |
|||
10000: '未初始化蓝牙模块', |
|||
10001: '蓝牙未打开', |
|||
10002: '没有找到指定设备', |
|||
10003: '连接失败', |
|||
10004: '没有找到指定服务', |
|||
10005: '没有找到指定特征值', |
|||
10006: '当前连接已断开', |
|||
10007: '当前特征值不支持此操作', |
|||
10008: '系统上报异常', |
|||
10009: '系统版本低于 4.3 不支持BLE' |
|||
}; |
|||
let coode = err.errCode ? err.errCode.toString() : ''; |
|||
let msg = errMsg[coode]; |
|||
plus.nativeUI.toast(msg || coode, { |
|||
align: 'center', |
|||
verticalAlign: 'center' |
|||
}); |
|||
} |
@ -0,0 +1,23 @@ |
|||
var barcode = require('./barcode'); |
|||
var qrcode = require('./qrcode'); |
|||
|
|||
function convert_length(length) { |
|||
return Math.round(wx.getSystemInfoSync().windowWidth * length / 750); |
|||
} |
|||
|
|||
function barc(id, code, width, height) { |
|||
barcode.code128(wx.createCanvasContext(id), code, convert_length(width), convert_length(height)) |
|||
} |
|||
|
|||
function qrc(id, code, width, height) { |
|||
qrcode.api.draw(code, { |
|||
ctx: wx.createCanvasContext(id), |
|||
width: convert_length(width), |
|||
height: convert_length(height) |
|||
}) |
|||
} |
|||
|
|||
module.exports = { |
|||
barcode: barc, |
|||
qrcode: qrc |
|||
} |
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,778 @@ |
|||
var QR = (function () { |
|||
|
|||
// alignment pattern
|
|||
var adelta = [ |
|||
0, 11, 15, 19, 23, 27, 31, // force 1 pat
|
|||
16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24, |
|||
26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28 |
|||
]; |
|||
|
|||
// version block
|
|||
var vpat = [ |
|||
0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d, |
|||
0x928, 0xb78, 0x45d, 0xa17, 0x532, 0x9a6, 0x683, 0x8c9, |
|||
0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75, |
|||
0x250, 0x9d5, 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64, |
|||
0x541, 0xc69 |
|||
]; |
|||
|
|||
// final format bits with mask: level << 3 | mask
|
|||
var fmtword = [ |
|||
0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, //L
|
|||
0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, //M
|
|||
0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, //Q
|
|||
0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b //H
|
|||
]; |
|||
|
|||
// 4 per version: number of blocks 1,2; data width; ecc width
|
|||
var eccblocks = [ |
|||
1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17, |
|||
1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28, |
|||
1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22, |
|||
1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16, |
|||
1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22, |
|||
2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28, |
|||
2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26, |
|||
2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26, |
|||
2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24, |
|||
2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28, |
|||
4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24, |
|||
2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28, |
|||
4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22, |
|||
3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24, |
|||
5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24, |
|||
5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30, |
|||
1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28, |
|||
5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28, |
|||
3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26, |
|||
3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28, |
|||
4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30, |
|||
2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24, |
|||
4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30, |
|||
6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30, |
|||
8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30, |
|||
10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30, |
|||
8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30, |
|||
3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30, |
|||
7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30, |
|||
5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30, |
|||
13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30, |
|||
17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30, |
|||
17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30, |
|||
13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30, |
|||
12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30, |
|||
6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30, |
|||
17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30, |
|||
4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30, |
|||
20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30, |
|||
19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30 |
|||
]; |
|||
|
|||
// Galois field log table
|
|||
var glog = [ |
|||
0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, |
|||
0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71, |
|||
0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, |
|||
0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6, |
|||
0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, |
|||
0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, |
|||
0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d, |
|||
0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, |
|||
0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18, |
|||
0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, |
|||
0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, |
|||
0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2, |
|||
0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6, |
|||
0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a, |
|||
0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, |
|||
0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf |
|||
]; |
|||
|
|||
// Galios field exponent table
|
|||
var gexp = [ |
|||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, |
|||
0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, |
|||
0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, |
|||
0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, |
|||
0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, |
|||
0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, |
|||
0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, |
|||
0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, |
|||
0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, |
|||
0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, |
|||
0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, |
|||
0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, |
|||
0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, |
|||
0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09, |
|||
0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, |
|||
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00 |
|||
]; |
|||
|
|||
// Working buffers:
|
|||
// data input and ecc append, image working buffer, fixed part of image, run lengths for badness
|
|||
var strinbuf=[], eccbuf=[], qrframe=[], framask=[], rlens=[]; |
|||
// Control values - width is based on version, last 4 are from table.
|
|||
var version, width, neccblk1, neccblk2, datablkw, eccblkwid; |
|||
var ecclevel = 2; |
|||
// set bit to indicate cell in qrframe is immutable. symmetric around diagonal
|
|||
function setmask(x, y) |
|||
{ |
|||
var bt; |
|||
if (x > y) { |
|||
bt = x; |
|||
x = y; |
|||
y = bt; |
|||
} |
|||
// y*y = 1+3+5...
|
|||
bt = y; |
|||
bt *= y; |
|||
bt += y; |
|||
bt >>= 1; |
|||
bt += x; |
|||
framask[bt] = 1; |
|||
} |
|||
|
|||
// enter alignment pattern - black to qrframe, white to mask (later black frame merged to mask)
|
|||
function putalign(x, y) |
|||
{ |
|||
var j; |
|||
|
|||
qrframe[x + width * y] = 1; |
|||
for (j = -2; j < 2; j++) { |
|||
qrframe[(x + j) + width * (y - 2)] = 1; |
|||
qrframe[(x - 2) + width * (y + j + 1)] = 1; |
|||
qrframe[(x + 2) + width * (y + j)] = 1; |
|||
qrframe[(x + j + 1) + width * (y + 2)] = 1; |
|||
} |
|||
for (j = 0; j < 2; j++) { |
|||
setmask(x - 1, y + j); |
|||
setmask(x + 1, y - j); |
|||
setmask(x - j, y - 1); |
|||
setmask(x + j, y + 1); |
|||
} |
|||
} |
|||
|
|||
//========================================================================
|
|||
// Reed Solomon error correction
|
|||
// exponentiation mod N
|
|||
function modnn(x) |
|||
{ |
|||
while (x >= 255) { |
|||
x -= 255; |
|||
x = (x >> 8) + (x & 255); |
|||
} |
|||
return x; |
|||
} |
|||
|
|||
var genpoly = []; |
|||
|
|||
// Calculate and append ECC data to data block. Block is in strinbuf, indexes to buffers given.
|
|||
function appendrs(data, dlen, ecbuf, eclen) |
|||
{ |
|||
var i, j, fb; |
|||
|
|||
for (i = 0; i < eclen; i++) |
|||
strinbuf[ecbuf + i] = 0; |
|||
for (i = 0; i < dlen; i++) { |
|||
fb = glog[strinbuf[data + i] ^ strinbuf[ecbuf]]; |
|||
if (fb != 255) /* fb term is non-zero */ |
|||
for (j = 1; j < eclen; j++) |
|||
strinbuf[ecbuf + j - 1] = strinbuf[ecbuf + j] ^ gexp[modnn(fb + genpoly[eclen - j])]; |
|||
else |
|||
for( j = ecbuf ; j < ecbuf + eclen; j++ ) |
|||
strinbuf[j] = strinbuf[j + 1]; |
|||
strinbuf[ ecbuf + eclen - 1] = fb == 255 ? 0 : gexp[modnn(fb + genpoly[0])]; |
|||
} |
|||
} |
|||
|
|||
//========================================================================
|
|||
// Frame data insert following the path rules
|
|||
|
|||
// check mask - since symmetrical use half.
|
|||
function ismasked(x, y) |
|||
{ |
|||
var bt; |
|||
if (x > y) { |
|||
bt = x; |
|||
x = y; |
|||
y = bt; |
|||
} |
|||
bt = y; |
|||
bt += y * y; |
|||
bt >>= 1; |
|||
bt += x; |
|||
return framask[bt]; |
|||
} |
|||
|
|||
//========================================================================
|
|||
// Apply the selected mask out of the 8.
|
|||
function applymask(m) |
|||
{ |
|||
var x, y, r3x, r3y; |
|||
|
|||
switch (m) { |
|||
case 0: |
|||
for (y = 0; y < width; y++) |
|||
for (x = 0; x < width; x++) |
|||
if (!((x + y) & 1) && !ismasked(x, y)) |
|||
qrframe[x + y * width] ^= 1; |
|||
break; |
|||
case 1: |
|||
for (y = 0; y < width; y++) |
|||
for (x = 0; x < width; x++) |
|||
if (!(y & 1) && !ismasked(x, y)) |
|||
qrframe[x + y * width] ^= 1; |
|||
break; |
|||
case 2: |
|||
for (y = 0; y < width; y++) |
|||
for (r3x = 0, x = 0; x < width; x++, r3x++) { |
|||
if (r3x == 3) |
|||
r3x = 0; |
|||
if (!r3x && !ismasked(x, y)) |
|||
qrframe[x + y * width] ^= 1; |
|||
} |
|||
break; |
|||
case 3: |
|||
for (r3y = 0, y = 0; y < width; y++, r3y++) { |
|||
if (r3y == 3) |
|||
r3y = 0; |
|||
for (r3x = r3y, x = 0; x < width; x++, r3x++) { |
|||
if (r3x == 3) |
|||
r3x = 0; |
|||
if (!r3x && !ismasked(x, y)) |
|||
qrframe[x + y * width] ^= 1; |
|||
} |
|||
} |
|||
break; |
|||
case 4: |
|||
for (y = 0; y < width; y++) |
|||
for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < width; x++, r3x++) { |
|||
if (r3x == 3) { |
|||
r3x = 0; |
|||
r3y = !r3y; |
|||
} |
|||
if (!r3y && !ismasked(x, y)) |
|||
qrframe[x + y * width] ^= 1; |
|||
} |
|||
break; |
|||
case 5: |
|||
for (r3y = 0, y = 0; y < width; y++, r3y++) { |
|||
if (r3y == 3) |
|||
r3y = 0; |
|||
for (r3x = 0, x = 0; x < width; x++, r3x++) { |
|||
if (r3x == 3) |
|||
r3x = 0; |
|||
if (!((x & y & 1) + !(!r3x | !r3y)) && !ismasked(x, y)) |
|||
qrframe[x + y * width] ^= 1; |
|||
} |
|||
} |
|||
break; |
|||
case 6: |
|||
for (r3y = 0, y = 0; y < width; y++, r3y++) { |
|||
if (r3y == 3) |
|||
r3y = 0; |
|||
for (r3x = 0, x = 0; x < width; x++, r3x++) { |
|||
if (r3x == 3) |
|||
r3x = 0; |
|||
if (!(((x & y & 1) + (r3x && (r3x == r3y))) & 1) && !ismasked(x, y)) |
|||
qrframe[x + y * width] ^= 1; |
|||
} |
|||
} |
|||
break; |
|||
case 7: |
|||
for (r3y = 0, y = 0; y < width; y++, r3y++) { |
|||
if (r3y == 3) |
|||
r3y = 0; |
|||
for (r3x = 0, x = 0; x < width; x++, r3x++) { |
|||
if (r3x == 3) |
|||
r3x = 0; |
|||
if (!(((r3x && (r3x == r3y)) + ((x + y) & 1)) & 1) && !ismasked(x, y)) |
|||
qrframe[x + y * width] ^= 1; |
|||
} |
|||
} |
|||
break; |
|||
} |
|||
return; |
|||
} |
|||
|
|||
// Badness coefficients.
|
|||
var N1 = 3, N2 = 3, N3 = 40, N4 = 10; |
|||
|
|||
// Using the table of the length of each run, calculate the amount of bad image
|
|||
// - long runs or those that look like finders; called twice, once each for X and Y
|
|||
function badruns(length) |
|||
{ |
|||
var i; |
|||
var runsbad = 0; |
|||
for (i = 0; i <= length; i++) |
|||
if (rlens[i] >= 5) |
|||
runsbad += N1 + rlens[i] - 5; |
|||
// BwBBBwB as in finder
|
|||
for (i = 3; i < length - 1; i += 2) |
|||
if (rlens[i - 2] == rlens[i + 2] |
|||
&& rlens[i + 2] == rlens[i - 1] |
|||
&& rlens[i - 1] == rlens[i + 1] |
|||
&& rlens[i - 1] * 3 == rlens[i] |
|||
// white around the black pattern? Not part of spec
|
|||
&& (rlens[i - 3] == 0 // beginning
|
|||
|| i + 3 > length // end
|
|||
|| rlens[i - 3] * 3 >= rlens[i] * 4 || rlens[i + 3] * 3 >= rlens[i] * 4) |
|||
) |
|||
runsbad += N3; |
|||
return runsbad; |
|||
} |
|||
|
|||
// Calculate how bad the masked image is - blocks, imbalance, runs, or finders.
|
|||
function badcheck() |
|||
{ |
|||
var x, y, h, b, b1; |
|||
var thisbad = 0; |
|||
var bw = 0; |
|||
|
|||
// blocks of same color.
|
|||
for (y = 0; y < width - 1; y++) |
|||
for (x = 0; x < width - 1; x++) |
|||
if ((qrframe[x + width * y] && qrframe[(x + 1) + width * y] |
|||
&& qrframe[x + width * (y + 1)] && qrframe[(x + 1) + width * (y + 1)]) // all black
|
|||
|| !(qrframe[x + width * y] || qrframe[(x + 1) + width * y] |
|||
|| qrframe[x + width * (y + 1)] || qrframe[(x + 1) + width * (y + 1)])) // all white
|
|||
thisbad += N2; |
|||
|
|||
// X runs
|
|||
for (y = 0; y < width; y++) { |
|||
rlens[0] = 0; |
|||
for (h = b = x = 0; x < width; x++) { |
|||
if ((b1 = qrframe[x + width * y]) == b) |
|||
rlens[h]++; |
|||
else |
|||
rlens[++h] = 1; |
|||
b = b1; |
|||
bw += b ? 1 : -1; |
|||
} |
|||
thisbad += badruns(h); |
|||
} |
|||
|
|||
// black/white imbalance
|
|||
if (bw < 0) |
|||
bw = -bw; |
|||
|
|||
var big = bw; |
|||
var count = 0; |
|||
big += big << 2; |
|||
big <<= 1; |
|||
while (big > width * width) |
|||
big -= width * width, count++; |
|||
thisbad += count * N4; |
|||
|
|||
// Y runs
|
|||
for (x = 0; x < width; x++) { |
|||
rlens[0] = 0; |
|||
for (h = b = y = 0; y < width; y++) { |
|||
if ((b1 = qrframe[x + width * y]) == b) |
|||
rlens[h]++; |
|||
else |
|||
rlens[++h] = 1; |
|||
b = b1; |
|||
} |
|||
thisbad += badruns(h); |
|||
} |
|||
return thisbad; |
|||
} |
|||
|
|||
function genframe(instring) |
|||
{ |
|||
var x, y, k, t, v, i, j, m; |
|||
|
|||
// find the smallest version that fits the string
|
|||
t = instring.length; |
|||
version = 0; |
|||
do { |
|||
version++; |
|||
k = (ecclevel - 1) * 4 + (version - 1) * 16; |
|||
neccblk1 = eccblocks[k++]; |
|||
neccblk2 = eccblocks[k++]; |
|||
datablkw = eccblocks[k++]; |
|||
eccblkwid = eccblocks[k]; |
|||
k = datablkw * (neccblk1 + neccblk2) + neccblk2 - 3 + (version <= 9); |
|||
if (t <= k) |
|||
break; |
|||
} while (version < 40); |
|||
|
|||
// FIXME - insure that it fits insted of being truncated
|
|||
width = 17 + 4 * version; |
|||
|
|||
// allocate, clear and setup data structures
|
|||
v = datablkw + (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2; |
|||
for( t = 0; t < v; t++ ) |
|||
eccbuf[t] = 0; |
|||
strinbuf = instring.slice(0); |
|||
|
|||
for( t = 0; t < width * width; t++ ) |
|||
qrframe[t] = 0; |
|||
|
|||
for( t = 0 ; t < (width * (width + 1) + 1) / 2; t++) |
|||
framask[t] = 0; |
|||
|
|||
// insert finders - black to frame, white to mask
|
|||
for (t = 0; t < 3; t++) { |
|||
k = 0; |
|||
y = 0; |
|||
if (t == 1) |
|||
k = (width - 7); |
|||
if (t == 2) |
|||
y = (width - 7); |
|||
qrframe[(y + 3) + width * (k + 3)] = 1; |
|||
for (x = 0; x < 6; x++) { |
|||
qrframe[(y + x) + width * k] = 1; |
|||
qrframe[y + width * (k + x + 1)] = 1; |
|||
qrframe[(y + 6) + width * (k + x)] = 1; |
|||
qrframe[(y + x + 1) + width * (k + 6)] = 1; |
|||
} |
|||
for (x = 1; x < 5; x++) { |
|||
setmask(y + x, k + 1); |
|||
setmask(y + 1, k + x + 1); |
|||
setmask(y + 5, k + x); |
|||
setmask(y + x + 1, k + 5); |
|||
} |
|||
for (x = 2; x < 4; x++) { |
|||
qrframe[(y + x) + width * (k + 2)] = 1; |
|||
qrframe[(y + 2) + width * (k + x + 1)] = 1; |
|||
qrframe[(y + 4) + width * (k + x)] = 1; |
|||
qrframe[(y + x + 1) + width * (k + 4)] = 1; |
|||
} |
|||
} |
|||
|
|||
// alignment blocks
|
|||
if (version > 1) { |
|||
t = adelta[version]; |
|||
y = width - 7; |
|||
for (;;) { |
|||
x = width - 7; |
|||
while (x > t - 3) { |
|||
putalign(x, y); |
|||
if (x < t) |
|||
break; |
|||
x -= t; |
|||
} |
|||
if (y <= t + 9) |
|||
break; |
|||
y -= t; |
|||
putalign(6, y); |
|||
putalign(y, 6); |
|||
} |
|||
} |
|||
|
|||
// single black
|
|||
qrframe[8 + width * (width - 8)] = 1; |
|||
|
|||
// timing gap - mask only
|
|||
for (y = 0; y < 7; y++) { |
|||
setmask(7, y); |
|||
setmask(width - 8, y); |
|||
setmask(7, y + width - 7); |
|||
} |
|||
for (x = 0; x < 8; x++) { |
|||
setmask(x, 7); |
|||
setmask(x + width - 8, 7); |
|||
setmask(x, width - 8); |
|||
} |
|||
|
|||
// reserve mask-format area
|
|||
for (x = 0; x < 9; x++) |
|||
setmask(x, 8); |
|||
for (x = 0; x < 8; x++) { |
|||
setmask(x + width - 8, 8); |
|||
setmask(8, x); |
|||
} |
|||
for (y = 0; y < 7; y++) |
|||
setmask(8, y + width - 7); |
|||
|
|||
// timing row/col
|
|||
for (x = 0; x < width - 14; x++) |
|||
if (x & 1) { |
|||
setmask(8 + x, 6); |
|||
setmask(6, 8 + x); |
|||
} |
|||
else { |
|||
qrframe[(8 + x) + width * 6] = 1; |
|||
qrframe[6 + width * (8 + x)] = 1; |
|||
} |
|||
|
|||
// version block
|
|||
if (version > 6) { |
|||
t = vpat[version - 7]; |
|||
k = 17; |
|||
for (x = 0; x < 6; x++) |
|||
for (y = 0; y < 3; y++, k--) |
|||
if (1 & (k > 11 ? version >> (k - 12) : t >> k)) { |
|||
qrframe[(5 - x) + width * (2 - y + width - 11)] = 1; |
|||
qrframe[(2 - y + width - 11) + width * (5 - x)] = 1; |
|||
} |
|||
else { |
|||
setmask(5 - x, 2 - y + width - 11); |
|||
setmask(2 - y + width - 11, 5 - x); |
|||
} |
|||
} |
|||
|
|||
// sync mask bits - only set above for white spaces, so add in black bits
|
|||
for (y = 0; y < width; y++) |
|||
for (x = 0; x <= y; x++) |
|||
if (qrframe[x + width * y]) |
|||
setmask(x, y); |
|||
|
|||
// convert string to bitstream
|
|||
// 8 bit data to QR-coded 8 bit data (numeric or alphanum, or kanji not supported)
|
|||
v = strinbuf.length; |
|||
|
|||
// string to array
|
|||
for( i = 0 ; i < v; i++ ) |
|||
eccbuf[i] = strinbuf.charCodeAt(i); |
|||
strinbuf = eccbuf.slice(0); |
|||
|
|||
// calculate max string length
|
|||
x = datablkw * (neccblk1 + neccblk2) + neccblk2; |
|||
if (v >= x - 2) { |
|||
v = x - 2; |
|||
if (version > 9) |
|||
v--; |
|||
} |
|||
|
|||
// shift and repack to insert length prefix
|
|||
i = v; |
|||
if (version > 9) { |
|||
strinbuf[i + 2] = 0; |
|||
strinbuf[i + 3] = 0; |
|||
while (i--) { |
|||
t = strinbuf[i]; |
|||
strinbuf[i + 3] |= 255 & (t << 4); |
|||
strinbuf[i + 2] = t >> 4; |
|||
} |
|||
strinbuf[2] |= 255 & (v << 4); |
|||
strinbuf[1] = v >> 4; |
|||
strinbuf[0] = 0x40 | (v >> 12); |
|||
} |
|||
else { |
|||
strinbuf[i + 1] = 0; |
|||
strinbuf[i + 2] = 0; |
|||
while (i--) { |
|||
t = strinbuf[i]; |
|||
strinbuf[i + 2] |= 255 & (t << 4); |
|||
strinbuf[i + 1] = t >> 4; |
|||
} |
|||
strinbuf[1] |= 255 & (v << 4); |
|||
strinbuf[0] = 0x40 | (v >> 4); |
|||
} |
|||
// fill to end with pad pattern
|
|||
i = v + 3 - (version < 10); |
|||
while (i < x) { |
|||
strinbuf[i++] = 0xec; |
|||
// buffer has room if (i == x) break;
|
|||
strinbuf[i++] = 0x11; |
|||
} |
|||
|
|||
// calculate and append ECC
|
|||
|
|||
// calculate generator polynomial
|
|||
genpoly[0] = 1; |
|||
for (i = 0; i < eccblkwid; i++) { |
|||
genpoly[i + 1] = 1; |
|||
for (j = i; j > 0; j--) |
|||
genpoly[j] = genpoly[j] |
|||
? genpoly[j - 1] ^ gexp[modnn(glog[genpoly[j]] + i)] : genpoly[j - 1]; |
|||
genpoly[0] = gexp[modnn(glog[genpoly[0]] + i)]; |
|||
} |
|||
for (i = 0; i <= eccblkwid; i++) |
|||
genpoly[i] = glog[genpoly[i]]; // use logs for genpoly[] to save calc step
|
|||
|
|||
// append ecc to data buffer
|
|||
k = x; |
|||
y = 0; |
|||
for (i = 0; i < neccblk1; i++) { |
|||
appendrs(y, datablkw, k, eccblkwid); |
|||
y += datablkw; |
|||
k += eccblkwid; |
|||
} |
|||
for (i = 0; i < neccblk2; i++) { |
|||
appendrs(y, datablkw + 1, k, eccblkwid); |
|||
y += datablkw + 1; |
|||
k += eccblkwid; |
|||
} |
|||
// interleave blocks
|
|||
y = 0; |
|||
for (i = 0; i < datablkw; i++) { |
|||
for (j = 0; j < neccblk1; j++) |
|||
eccbuf[y++] = strinbuf[i + j * datablkw]; |
|||
for (j = 0; j < neccblk2; j++) |
|||
eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))]; |
|||
} |
|||
for (j = 0; j < neccblk2; j++) |
|||
eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))]; |
|||
for (i = 0; i < eccblkwid; i++) |
|||
for (j = 0; j < neccblk1 + neccblk2; j++) |
|||
eccbuf[y++] = strinbuf[x + i + j * eccblkwid]; |
|||
strinbuf = eccbuf; |
|||
|
|||
// pack bits into frame avoiding masked area.
|
|||
x = y = width - 1; |
|||
k = v = 1; // up, minus
|
|||
/* inteleaved data and ecc codes */ |
|||
m = (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2; |
|||
for (i = 0; i < m; i++) { |
|||
t = strinbuf[i]; |
|||
for (j = 0; j < 8; j++, t <<= 1) { |
|||
if (0x80 & t) |
|||
qrframe[x + width * y] = 1; |
|||
do { // find next fill position
|
|||
if (v) |
|||
x--; |
|||
else { |
|||
x++; |
|||
if (k) { |
|||
if (y != 0) |
|||
y--; |
|||
else { |
|||
x -= 2; |
|||
k = !k; |
|||
if (x == 6) { |
|||
x--; |
|||
y = 9; |
|||
} |
|||
} |
|||
} |
|||
else { |
|||
if (y != width - 1) |
|||
y++; |
|||
else { |
|||
x -= 2; |
|||
k = !k; |
|||
if (x == 6) { |
|||
x--; |
|||
y -= 8; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
v = !v; |
|||
} while (ismasked(x, y)); |
|||
} |
|||
} |
|||
|
|||
// save pre-mask copy of frame
|
|||
strinbuf = qrframe.slice(0); |
|||
t = 0; // best
|
|||
y = 30000; // demerit
|
|||
// for instead of while since in original arduino code
|
|||
// if an early mask was "good enough" it wouldn't try for a better one
|
|||
// since they get more complex and take longer.
|
|||
for (k = 0; k < 8; k++) { |
|||
applymask(k); // returns black-white imbalance
|
|||
x = badcheck(); |
|||
if (x < y) { // current mask better than previous best?
|
|||
y = x; |
|||
t = k; |
|||
} |
|||
if (t == 7) |
|||
break; // don't increment i to a void redoing mask
|
|||
qrframe = strinbuf.slice(0); // reset for next pass
|
|||
} |
|||
if (t != k) // redo best mask - none good enough, last wasn't t
|
|||
applymask(t); |
|||
|
|||
// add in final mask/ecclevel bytes
|
|||
y = fmtword[t + ((ecclevel - 1) << 3)]; |
|||
// low byte
|
|||
for (k = 0; k < 8; k++, y >>= 1) |
|||
if (y & 1) { |
|||
qrframe[(width - 1 - k) + width * 8] = 1; |
|||
if (k < 6) |
|||
qrframe[8 + width * k] = 1; |
|||
else |
|||
qrframe[8 + width * (k + 1)] = 1; |
|||
} |
|||
// high byte
|
|||
for (k = 0; k < 7; k++, y >>= 1) |
|||
if (y & 1) { |
|||
qrframe[8 + width * (width - 7 + k)] = 1; |
|||
if (k) |
|||
qrframe[(6 - k) + width * 8] = 1; |
|||
else |
|||
qrframe[7 + width * 8] = 1; |
|||
} |
|||
|
|||
// return image
|
|||
return qrframe; |
|||
} |
|||
|
|||
var _canvas = null, |
|||
_size = null; |
|||
|
|||
var api = { |
|||
|
|||
get ecclevel () { |
|||
return ecclevel; |
|||
}, |
|||
|
|||
set ecclevel (val) { |
|||
ecclevel = val; |
|||
}, |
|||
|
|||
get size () { |
|||
return _size; |
|||
}, |
|||
|
|||
set size (val) { |
|||
_size = val |
|||
}, |
|||
|
|||
get canvas () { |
|||
return _canvas; |
|||
}, |
|||
|
|||
set canvas (el) { |
|||
_canvas = el; |
|||
}, |
|||
|
|||
getFrame: function (string) { |
|||
return genframe(string); |
|||
}, |
|||
|
|||
draw: function (string, canvas, size, ecc) { |
|||
|
|||
ecclevel = ecc || ecclevel; |
|||
canvas = canvas || _canvas; |
|||
|
|||
if (!canvas) { |
|||
console.warn('No canvas provided to draw QR code in!') |
|||
return; |
|||
} |
|||
|
|||
size = size || _size || Math.min(canvas.width, canvas.height); |
|||
|
|||
var frame = genframe(string), |
|||
ctx = canvas.ctx, |
|||
px = Math.round(size / (width + 8)); |
|||
|
|||
var roundedSize = px * (width + 8), |
|||
offset = Math.floor((size - roundedSize) / 2); |
|||
|
|||
size = roundedSize; |
|||
|
|||
ctx.clearRect(0, 0, canvas.width, canvas.height); |
|||
ctx.setFillStyle('#000000'); |
|||
|
|||
for (var i = 0; i < width; i++) { |
|||
for (var j = 0; j < width; j++) { |
|||
if (frame[j * width + i]) { |
|||
ctx.fillRect(px * (4 + i) + offset, px * (4 + j) + offset, px, px); |
|||
} |
|||
} |
|||
} |
|||
ctx.draw(); |
|||
} |
|||
} |
|||
|
|||
module.exports = { |
|||
api: api |
|||
} |
|||
|
|||
})() |
@ -0,0 +1,171 @@ |
|||
//const gbk = require('./gbk.js');
|
|||
//console.log("sasas" + gbk);
|
|||
const formatTime = date => { |
|||
const year = date.getFullYear() |
|||
const month = date.getMonth() + 1 |
|||
const day = date.getDate() |
|||
const hour = date.getHours() |
|||
const minute = date.getMinutes() |
|||
const second = date.getSeconds() |
|||
|
|||
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') |
|||
} |
|||
|
|||
const formatNumber = n => { |
|||
n = n.toString() |
|||
return n[1] ? n : '0' + n |
|||
} |
|||
|
|||
/* |
|||
const hexStringToBuff = str => { //str='中国:WXHSH'
|
|||
const buffer = new ArrayBuffer((sumStrLength(str)) * 4) |
|||
const dataView = new DataView(buffer) |
|||
var data = str.toString(); |
|||
var p = 0; //ArrayBuffer 偏移量
|
|||
for (var i = 0; i < data.length; i++) { |
|||
if (isCN(data[i])) { //是中文
|
|||
//调用GBK 转码
|
|||
var t = gbk.encode(data[i]); |
|||
for (var j = 0; j < 2; j++) { |
|||
//var code = t[j * 2] + t[j * 2 + 1];
|
|||
var code = t[j * 3 + 1] + t[j * 3 + 2]; |
|||
var temp = parseInt(code, 16) |
|||
//var temp = strToHexCharCode(code);
|
|||
dataView.setUint8(p++, temp) |
|||
} |
|||
} else { |
|||
var temp = data.charCodeAt(i); |
|||
dataView.setUint8(p++, temp) |
|||
} |
|||
} |
|||
return buffer; |
|||
} |
|||
*/ |
|||
function toUnicode(s) { |
|||
var str = ""; |
|||
for (var i = 0; i < s.length; i++) { |
|||
str += "\\u" + s.charCodeAt(i).toString(16) + "\t"; |
|||
} |
|||
return str; |
|||
} |
|||
|
|||
function strToHexCharCode(str) { |
|||
if (str === "") |
|||
return ""; |
|||
var hexCharCode = []; |
|||
hexCharCode.push("0x"); |
|||
for (var i = 0; i < str.length; i++) { |
|||
hexCharCode.push((str.charCodeAt(i)).toString(16)); |
|||
} |
|||
return hexCharCode.join(""); |
|||
} |
|||
|
|||
function sumStrLength(str) { |
|||
var length = 0; |
|||
var data = str.toString(); |
|||
for (var i = 0; i < data.length; i++) { |
|||
if (isCN(data[i])) { //是中文
|
|||
length += 2; |
|||
} else { |
|||
length += 1; |
|||
} |
|||
} |
|||
return length; |
|||
} |
|||
|
|||
function isCN(str) { |
|||
if (/^[\u3220-\uFA29]+$/.test(str)) { |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
//汉字转码
|
|||
export function hexStringToArrayBuffer(str) { |
|||
const buffer = new ArrayBuffer((str.length / 2) + 1) |
|||
const dataView = new DataView(buffer) |
|||
for (var i = 0; i < str.length / 2; i++) { |
|||
var temp = parseInt(str[i * 2] + str[i * 2 + 1], 16) |
|||
dataView.setUint8(i, temp) |
|||
} |
|||
dataView.setUint8((str.length / 2), 0x0a) |
|||
return buffer; |
|||
} |
|||
|
|||
//返回八位数组
|
|||
function subString(str) { |
|||
var arr = []; |
|||
if (str.length > 8) { //大于8
|
|||
for (var i = 0; |
|||
(i * 8) < str.length; i++) { |
|||
var temp = str.substring(i * 8, 8 * i + 8); |
|||
arr.push(temp) |
|||
} |
|||
return arr; |
|||
} else { |
|||
return str |
|||
} |
|||
} |
|||
|
|||
//不带有汉字
|
|||
function hexStringToArrayBufferstr(str) { |
|||
let val = "" |
|||
for (let i = 0; i < str.length; i++) { |
|||
if (val === '') { |
|||
val = str.charCodeAt(i).toString(16) |
|||
} else { |
|||
val += ',' + str.charCodeAt(i).toString(16) |
|||
} |
|||
} |
|||
val += "," + "0x0a"; |
|||
console.log(val) |
|||
// 将16进制转化为ArrayBuffer
|
|||
return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function(h) { |
|||
return parseInt(h, 16) |
|||
})).buffer |
|||
} |
|||
|
|||
export function ab2hex(buffer) { |
|||
let hexArr = Array.prototype.map.call( |
|||
new Uint8Array(buffer), |
|||
function (bit) { |
|||
return ('00' + bit.toString(16)).slice(-2) |
|||
}) |
|||
return hexArr.join(''); |
|||
} |
|||
|
|||
// ArrayBuffer转为字符串,参数为ArrayBuffer对象
|
|||
export function ab2str(buf) { |
|||
return String.fromCharCode.apply(null, new Uint8Array(buf)); |
|||
} |
|||
|
|||
// 字符串转为ArrayBuffer对象,参数为字符串
|
|||
export function str2ab(str) { |
|||
var buf = new ArrayBuffer(str.length+1); // 补充/0
|
|||
var bufView = new Uint8Array(buf); |
|||
for (var i = 0, strLen = str.length; i < strLen; i++) { |
|||
bufView[i] = str.charCodeAt(i); |
|||
} |
|||
return buf; |
|||
} |
|||
|
|||
export function send0X0A() { |
|||
const buffer = new ArrayBuffer(1) |
|||
const dataView = new DataView(buffer) |
|||
dataView.setUint8(0, 0x0a) |
|||
return buffer; |
|||
} |
|||
|
|||
export function buf2hex(buffer) { |
|||
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join(''); |
|||
} |
|||
|
|||
// module.exports = {
|
|||
// hexStringToArrayBuffer: hexStringToArrayBuffer,
|
|||
// send0X0A: send0X0A,
|
|||
// ab2hex: ab2hex,
|
|||
// str2ab: str2ab,
|
|||
// ab2str: ab2str,
|
|||
// buf2hex: buf2hex
|
|||
// }
|
@ -1,157 +1,160 @@ |
|||
<!-- 基于z-paging封装个性化分页组件演示,可减少大量重复代码 --> |
|||
<template> |
|||
<!-- 这边统一设置z-paging,在页面中使用时就不用重复写 --> |
|||
<!-- 如果要在这里设置极简写法,这里的ref不能设置为paging,设置为其他名即可,因为极简写法会修改/调用第一个包含了ref="paging"的付view中的list和query --> |
|||
<!-- 极简写法在下方设置autowire-list-name="xxx" autowire-query-name="xxx"即可,与minimalism-demo.vue中的一致,并且不用再从这个组件转发到页面,只要遵循上一行的规则即可 --> |
|||
<z-paging ref="paging" v-model="list" fixed auto-show-back-to-top refresher-threshold="160rpx" @query="queryList" |
|||
:useVirtualList="useVirtualList" :useInnerList="useInnerList" :cellKeyName="cellKeyName" :innerListStyle="innerListStyle" :preloadPage="preloadPage" :cellHeightMode="cellHeightMode" :virtualScrollFps="virtualScrollFps" |
|||
:loading-more-loading-text="{'en':'英文的加载中','zh-cn':'中文的加载中','zh-hant-cn':'繁体的加载中'}"> |
|||
|
|||
<!-- 这里插入一个view到z-paging中,并且这个view会被z-paging标记为top固定在顶部 --> |
|||
<template #top> |
|||
<!-- 这里接收页面传进来的slot,这样相当于将页面传进来的slot传给z-paging的slot="top"了 --> |
|||
<slot name="top" /> |
|||
</template> |
|||
|
|||
<!-- 这里插入一个view到z-paging中,并且这个view会被z-paging标记为bottom固定在顶部 --> |
|||
<!-- vue3中用v-slot:bottom --> |
|||
<template #bottom> |
|||
<!-- 这里接收页面传进来的slot,这样相当于将页面传进来的slot传给z-paging的slot="bottom"了 --> |
|||
<slot name="bottom" /> |
|||
</template> |
|||
|
|||
<template #empty v-if="$slots.empty" > |
|||
<!-- 这里接收页面传进来的slot,这样相当于将页面传进来的slot传给z-paging的slot="empty"了 --> |
|||
<slot name="empty" /> |
|||
</template> |
|||
|
|||
<!-- 这个是插入虚拟列表/内置列表的cell --> |
|||
<template #cell="{item,index}"> |
|||
<slot name="cell" :item="item" :index="index"/> |
|||
</template> |
|||
<!-- 这边统一设置z-paging,在页面中使用时就不用重复写 --> |
|||
<!-- 如果要在这里设置极简写法,这里的ref不能设置为paging,设置为其他名即可,因为极简写法会修改/调用第一个包含了ref="paging"的付view中的list和query --> |
|||
<!-- 极简写法在下方设置autowire-list-name="xxx" autowire-query-name="xxx"即可,与minimalism-demo.vue中的一致,并且不用再从这个组件转发到页面,只要遵循上一行的规则即可 --> |
|||
<z-paging ref="paging" v-model="list" fixed auto-show-back-to-top refresher-threshold="160rpx" @query="queryList" :useVirtualList="useVirtualList" :useInnerList="useInnerList" :cellKeyName="cellKeyName" :innerListStyle="innerListStyle" :preloadPage="preloadPage" :cellHeightMode="cellHeightMode" :virtualScrollFps="virtualScrollFps" :loading-more-loading-text="{ en: '英文的加载中', 'zh-cn': '中文的加载中', 'zh-hant-cn': '繁体的加载中' }"> |
|||
<!-- 这里插入一个view到z-paging中,并且这个view会被z-paging标记为top固定在顶部 --> |
|||
<template #top> |
|||
<!-- 这里接收页面传进来的slot,这样相当于将页面传进来的slot传给z-paging的slot="top"了 --> |
|||
<slot name="top" /> |
|||
</template> |
|||
|
|||
<!-- 这里通过slot统一自定义了下拉刷新view和没有更多数据view,页面那边就不用再写下面两行了 --> |
|||
<!-- 自定义下拉刷新view(如果use-custom-refresher为true且不设置下面的slot="refresher",此时不用获取refresherStatus,会自动使用z-paging自带的下拉刷新view) --> |
|||
<template #refresher="{refresherStatus}"> |
|||
<!-- <custom-refresher :status="refresherStatus" /> --> |
|||
</template> |
|||
<!-- 自定义没有更多数据view --> |
|||
<template #loadingMoreNoMore> |
|||
<!-- <custom-nomore></custom-nomore> --> |
|||
<uni-load-more status="normore" /> |
|||
</template> |
|||
<!-- 这里插入一个view到z-paging中,并且这个view会被z-paging标记为bottom固定在顶部 --> |
|||
<!-- vue3中用v-slot:bottom --> |
|||
<template #bottom> |
|||
<!-- 这里接收页面传进来的slot,这样相当于将页面传进来的slot传给z-paging的slot="bottom"了 --> |
|||
<slot name="bottom" /> |
|||
</template> |
|||
|
|||
<!-- 这里接收页面传进来的普通slot,如列表数据等 --> |
|||
<slot /> |
|||
</z-paging> |
|||
<template #empty v-if="$slots.empty"> |
|||
<!-- 这里接收页面传进来的slot,这样相当于将页面传进来的slot传给z-paging的slot="empty"了 --> |
|||
<slot name="empty" /> |
|||
</template> |
|||
|
|||
<!-- 这个是插入虚拟列表/内置列表的cell --> |
|||
<template #cell="{ item, index }"> |
|||
<slot name="cell" :item="item" :index="index" /> |
|||
</template> |
|||
|
|||
<!-- 这里通过slot统一自定义了下拉刷新view和没有更多数据view,页面那边就不用再写下面两行了 --> |
|||
<!-- 自定义下拉刷新view(如果use-custom-refresher为true且不设置下面的slot="refresher",此时不用获取refresherStatus,会自动使用z-paging自带的下拉刷新view) --> |
|||
<template #refresher="{ refresherStatus }"> |
|||
<!-- <custom-refresher :status="refresherStatus" /> --> |
|||
</template> |
|||
<!-- 自定义没有更多数据view --> |
|||
<template #loadingMoreNoMore> |
|||
<!-- <custom-nomore></custom-nomore> --> |
|||
<u-loadmore status="normore" /> |
|||
</template> |
|||
|
|||
<!-- 这里接收页面传进来的普通slot,如列表数据等 --> |
|||
<slot /> |
|||
</z-paging> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: "my-paging", |
|||
data() { |
|||
return { |
|||
list: [] |
|||
}; |
|||
}, |
|||
props: { |
|||
//用于接收父组件v-model所绑定的list的值 |
|||
value: { |
|||
type: Array, |
|||
default: function() { |
|||
return []; |
|||
} |
|||
}, |
|||
//是否使用虚拟列表,默认为否 |
|||
useVirtualList: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
//是否在z-paging内部循环渲染列表(内置列表),默认为否。若use-virtual-list为true,则此项恒为true |
|||
useInnerList: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
//内置列表cell的key名称,仅nvue有效,在nvue中开启use-inner-list时必须填此项 |
|||
cellKeyName: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
//innerList样式 |
|||
innerListStyle: { |
|||
type: Object, |
|||
default: function() { |
|||
return {}; |
|||
} |
|||
}, |
|||
//预加载的列表可视范围(列表高度)页数,默认为12,即预加载当前页及上下各7页的cell。此数值越大,则虚拟列表中加载的dom越多,内存消耗越大(会维持在一个稳定值),但增加预加载页面数量可缓解快速滚动短暂白屏问题 |
|||
preloadPage: { |
|||
type: [Number, String], |
|||
default: 12 |
|||
}, |
|||
//虚拟列表cell高度模式,默认为fixed,也就是每个cell高度完全相同,将以第一个cell高度为准进行计算。可选值【dynamic】,即代表高度是动态非固定的,【dynamic】性能低于【fixed】。 |
|||
cellHeightMode: { |
|||
type: String, |
|||
default: 'fixed' |
|||
}, |
|||
//虚拟列表scroll取样帧率,默认为60,过高可能出现卡顿等问题 |
|||
virtualScrollFps: { |
|||
type: [Number, String], |
|||
default: 60 |
|||
}, |
|||
}, |
|||
watch: { |
|||
//监听页面v-mode传过来的值,同时传给z-paging |
|||
value(newVal) { |
|||
this.list = newVal; |
|||
}, |
|||
// #ifdef VUE3 |
|||
modelValue(newVal) { |
|||
this.list = newVal; |
|||
}, |
|||
// #endif |
|||
//监听z-paging给当前组件的值,同时传给页面 |
|||
list(newVal) { |
|||
//通过emit input修改页面中v-model绑定的值 |
|||
this.$emit('input', newVal); |
|||
// #ifdef VUE3 |
|||
this.$emit('update:modelValue', newVal); |
|||
// #endif |
|||
} |
|||
}, |
|||
methods: { |
|||
//监听z-paging的@query方法,通过emit传递给页面 |
|||
queryList(pageNo, pageSize) { |
|||
console.log("queryList",pageNo) |
|||
// this.$emit('query', pageNo, pageSize); |
|||
}, |
|||
//接收页面触发的reload方法,传给z-paging |
|||
reload(data) { |
|||
this.$refs.paging.reload(data); |
|||
}, |
|||
//接收页面触发的complete方法,传给z-paging |
|||
complete(data) { |
|||
this.$refs.paging.complete(data); |
|||
}, |
|||
/* |
|||
//如果是使用页面滚动,则需要添加以下三行,注意页面那边要引入mixins,与使用页面滚动示例写法相同。 |
|||
//接收页面触发的updatePageScrollTop方法,传给z-paging |
|||
updatePageScrollTop(data){ |
|||
this.$refs.paging.updatePageScrollTop(data); |
|||
}, |
|||
//接收页面触发的pageReachBottom方法,传给z-paging |
|||
pageReachBottom(){ |
|||
this.$refs.paging.pageReachBottom(); |
|||
}, |
|||
//接收页面触发的doChatRecordLoadMore方法,传给z-paging |
|||
doChatRecordLoadMore() { |
|||
this.$refs.paging.doChatRecordLoadMore(); |
|||
} |
|||
*/ |
|||
} |
|||
<script setup lang="ts"> |
|||
import { ref, getCurrentInstance, nextTick, onMounted, watch } from 'vue' |
|||
import { onLoad, onShow, onNavigationBarButtonTap, onReady, onBackPress, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app' |
|||
|
|||
const props = defineProps({ |
|||
value: { |
|||
type: Array, |
|||
default() { |
|||
return [] |
|||
} |
|||
}, |
|||
// 是否使用虚拟列表,默认为否 |
|||
useVirtualList: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// 是否在z-paging内部循环渲染列表(内置列表),默认为否。若use-virtual-list为true,则此项恒为true |
|||
useInnerList: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// 内置列表cell的key名称,仅nvue有效,在nvue中开启use-inner-list时必须填此项 |
|||
cellKeyName: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
// innerList样式 |
|||
innerListStyle: { |
|||
type: Object, |
|||
default() { |
|||
return {} |
|||
} |
|||
}, |
|||
// 预加载的列表可视范围(列表高度)页数,默认为12,即预加载当前页及上下各7页的cell。此数值越大,则虚拟列表中加载的dom越多,内存消耗越大(会维持在一个稳定值),但增加预加载页面数量可缓解快速滚动短暂白屏问题 |
|||
preloadPage: { |
|||
type: [Number, String], |
|||
default: 12 |
|||
}, |
|||
// 虚拟列表cell高度模式,默认为fixed,也就是每个cell高度完全相同,将以第一个cell高度为准进行计算。可选值【dynamic】,即代表高度是动态非固定的,【dynamic】性能低于【fixed】。 |
|||
cellHeightMode: { |
|||
type: String, |
|||
default: 'fixed' |
|||
}, |
|||
// 虚拟列表scroll取样帧率,默认为60,过高可能出现卡顿等问题 |
|||
virtualScrollFps: { |
|||
type: [Number, String], |
|||
default: 60 |
|||
} |
|||
}) |
|||
const list = ref([]) |
|||
const paging = ref() |
|||
// 监听页面v-mode传过来的值,同时传给z-paging |
|||
watch( |
|||
() => props.value, |
|||
(newVal) => { |
|||
list.value = newVal |
|||
} |
|||
) |
|||
// #ifdef VUE3 |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal) => { |
|||
list.value = newVal |
|||
} |
|||
) |
|||
// #endif |
|||
watch( |
|||
() => list.value, |
|||
(newVal) => { |
|||
// 通过emit input修改页面中v-model绑定的值 |
|||
emit('input', newVal) |
|||
// #ifdef VUE3 |
|||
emit('update:modelValue', newVal) |
|||
// #endif |
|||
} |
|||
) |
|||
|
|||
// 监听z-paging的@query方法,通过emit传递给页面 |
|||
const queryList = (pageNo, pageSize) => { |
|||
console.log('queryList', pageNo) |
|||
// this.$emit('query', pageNo, pageSize); |
|||
} |
|||
// 接收页面触发的reload方法,传给z-paging |
|||
const reload = (data) => { |
|||
paging.value.reload(data) |
|||
} |
|||
// 接收页面触发的complete方法,传给z-paging |
|||
const complete = (data) => { |
|||
console.log(data) |
|||
paging.value.complete(data) |
|||
} |
|||
/* |
|||
//如果是使用页面滚动,则需要添加以下三行,注意页面那边要引入mixins,与使用页面滚动示例写法相同。 |
|||
//接收页面触发的updatePageScrollTop方法,传给z-paging |
|||
updatePageScrollTop(data){ |
|||
this.$refs.paging.updatePageScrollTop(data); |
|||
}, |
|||
//接收页面触发的pageReachBottom方法,传给z-paging |
|||
pageReachBottom(){ |
|||
this.$refs.paging.pageReachBottom(); |
|||
}, |
|||
//接收页面触发的doChatRecordLoadMore方法,传给z-paging |
|||
doChatRecordLoadMore() { |
|||
this.$refs.paging.doChatRecordLoadMore(); |
|||
} |
|||
*/ |
|||
// 传递给父类 |
|||
const emit = defineEmits(['input', 'update:modelValue']) |
|||
defineExpose({ |
|||
reload, |
|||
complete |
|||
}) |
|||
</script> |
|||
|
|||
<style> |
|||
|
|||
</style> |
|||
<style></style> |
|||
|
@ -1,456 +1,443 @@ |
|||
<template name="show-modal"> |
|||
<view> |
|||
<u-modal v-model="show" :title-style="{color: 'red'}" :title="title" :showTitle="false" |
|||
:showConfirmButton="false" ref="modal"> |
|||
<view class="slot-content"> |
|||
<slot name="icon"> |
|||
<image class="icon" :src="icon" /> |
|||
</slot> |
|||
|
|||
<scroll-view scroll-y="true" style="max-height: 200px;"> |
|||
<rich-text class="content" :nodes="content"> |
|||
</rich-text> |
|||
</scroll-view> |
|||
|
|||
|
|||
<u-line></u-line> |
|||
<slot name="button"> |
|||
<view class="uni-flex uni-row u-col-center space-between" style="width: 100%;height: 48px;"> |
|||
<view v-if="showCancelButton" class="cance_button" @tap="$u.throttle(cancelClose, 500)"> |
|||
<text :style="{'color':cancelColor}">{{ cancelText }}</text> |
|||
</view> |
|||
<u-line direction="col" length="100%"></u-line> |
|||
<view v-if="showConfirmButton" class="confirm_button" @tap="$u.throttle(confirmClose, 500)"> |
|||
<text :style="{'color':confirmColor}">{{confirmText}}</text> |
|||
<text v-if="showConfirmCountdown">({{seconds}}s关闭)</text> |
|||
</view> |
|||
</view> |
|||
</slot> |
|||
</view> |
|||
</u-modal> |
|||
</view> |
|||
<view> |
|||
<u-modal v-model="show" :title-style="{ color: 'red' }" :title="title" :showTitle="false" :showConfirmButton="false" ref="modal"> |
|||
<view class="slot-content"> |
|||
<slot name="icon"> |
|||
<image class="icon" :src="icon" /> |
|||
</slot> |
|||
|
|||
<scroll-view scroll-y="true" style="max-height: 200px"> |
|||
<rich-text class="content" :nodes="content"> </rich-text> |
|||
</scroll-view> |
|||
|
|||
<view class="split_line"></view> |
|||
<slot name="button"> |
|||
<view class="uni-flex uni-row u-col-center space-between" style="width: 100%; height: 48px"> |
|||
<view v-if="showCancelButton" class="cance_button" @tap="$u.throttle(cancelClose, 500)"> |
|||
<text :style="{ color: cancelColor }">{{ cancelText }}</text> |
|||
</view> |
|||
<u-line direction="col" length="100%"></u-line> |
|||
<view v-if="showConfirmButton" class="confirm_button" @tap="$u.throttle(confirmClose, 500)"> |
|||
<text :style="{ color: confirmColor }">{{ confirmText }}</text> |
|||
<text v-if="showConfirmCountdown">({{ seconds }}s关闭)</text> |
|||
</view> |
|||
</view> |
|||
</slot> |
|||
</view> |
|||
</u-modal> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
/** |
|||
* modal 模态框 |
|||
* @description 弹出模态框,常用于消息提示、消息确认、在当前页面内完成特定的交互操作 |
|||
* */ |
|||
export default { |
|||
data() { |
|||
return { |
|||
timer: null, |
|||
show: false, // 是否显示 |
|||
iconType: '消息', |
|||
icon: '../../static/icons/error-circle.svg', |
|||
title: '', // 提示标题 |
|||
content: '', // 提示内容 |
|||
cancelText: '取消', // 取消按钮的文字 |
|||
confirmText: '确定', // 确认按钮文字 |
|||
showCancel: true, // 是否显示取消按钮,默认为 true |
|||
confirmColor: '#007aff', // 确定按钮颜色 |
|||
cancelColor: null, // 取消按钮颜色 |
|||
showConfirmButton: true, // 是否显示确认按钮 |
|||
showConfirmCountdown: true, // 是否显示确定倒计时 |
|||
showCancelButton: true, // 是否显示取消按钮 |
|||
showClose: false, |
|||
confirm: false, //为 true 时,表示用户点击了确定按钮 |
|||
cancel: false, //为 true 时,表示用户点击了取消 |
|||
seconds: 0, |
|||
success: () => {} // 回调方法 |
|||
} |
|||
}, |
|||
|
|||
|
|||
methods: { |
|||
open() { |
|||
this.show = true; |
|||
}, |
|||
close() { |
|||
this.$.refs.modal.popupClose(); |
|||
}, |
|||
confirmClose() { |
|||
if (this.show) { |
|||
this.show = false; |
|||
clearInterval(this.timer) //清空timer |
|||
this.$.refs.modal.popupClose(); |
|||
this.success({ |
|||
// cancel: false, |
|||
confirm: true, |
|||
}); |
|||
} |
|||
}, |
|||
|
|||
cancelClose() { |
|||
clearInterval(this.timer) //清空timer |
|||
this.$.refs.modal.popupClose(); |
|||
this.success({ |
|||
// cancel: true, |
|||
confirm: false, |
|||
}); |
|||
}, |
|||
|
|||
// 打开消息弹框(确定) |
|||
showConfirmMessageModal(mContent, callback) { |
|||
this.showConfirmModal("消息", mContent, callback); |
|||
}, |
|||
|
|||
// 打开成功弹框(确定) |
|||
showConfirmSuccessModal(mContent, callback) { |
|||
this.showConfirmModal("成功", mContent, callback); |
|||
}, |
|||
|
|||
// 打开失败弹框(确定) |
|||
showConfirmFailModal(mContent, callback) { |
|||
this.showConfirmModal("失败", mContent, callback); |
|||
}, |
|||
|
|||
// 打开警告弹框(确定) |
|||
showConfirmWarningModal(mContent, callback) { |
|||
this.showConfirmModal("警告", mContent, callback); |
|||
}, |
|||
|
|||
// 打开疑问弹框(确定) |
|||
showConfirmQuestionModal(mContent, callback) { |
|||
this.showConfirmModal("疑问", mContent, callback); |
|||
}, |
|||
|
|||
// 初始化弹框并打开(确定) |
|||
showConfirmModal(mIconType, mContent, callback) { |
|||
this.showModal({ |
|||
iconType: mIconType, |
|||
content: mContent, |
|||
showCancelButton: false, |
|||
success: function(res) { |
|||
if (callback != undefined) { |
|||
if (res.confirm == true) { |
|||
callback(true); |
|||
console.log('用户点击确定') |
|||
} else { |
|||
callback(false); |
|||
console.log('用户点击取消') |
|||
} |
|||
} |
|||
|
|||
} |
|||
}); |
|||
}, |
|||
|
|||
// 打开消息弹框(取消+确定) |
|||
showSelectMessageModal(mContent, callback) { |
|||
this.showSelectModal("消息", mContent, callback); |
|||
}, |
|||
|
|||
// 打开成功弹框(取消+确定) |
|||
showSelectSuccessModal(mContent, callback) { |
|||
this.showSelectModal("成功", mContent, callback); |
|||
}, |
|||
|
|||
// 打开失败弹框(取消+确定) |
|||
showSelectFailModal(mContent, callback) { |
|||
this.showSelectModal("失败", mContent, callback); |
|||
}, |
|||
|
|||
// 打开警告弹框(取消+确定) |
|||
showSelectWarningModal(mContent, callback) { |
|||
this.showSelectModal("警告", mContent, callback); |
|||
}, |
|||
|
|||
// 打开疑问弹框(取消+确定) |
|||
showSelectQuestionModal(mContent, callback) { |
|||
this.showSelectModal("疑问", mContent, callback); |
|||
}, |
|||
|
|||
// 初始化弹框并打开(取消+确定) |
|||
showSelectModal(mIconType, mContent, callback) { |
|||
this.showModal({ |
|||
iconType: mIconType, |
|||
content: mContent, |
|||
success: function(res) { |
|||
if (callback != undefined) { |
|||
if (res.confirm == true) { |
|||
callback(true); |
|||
console.log('用户点击确定') |
|||
} else { |
|||
callback(false); |
|||
console.log('用户点击取消') |
|||
} |
|||
} |
|||
|
|||
} |
|||
}); |
|||
}, |
|||
|
|||
// 打开消息弹框(确定+倒计时) |
|||
showConfirmCountdownMessageModal(mContent, callback) { |
|||
this.showConfirmCountdownModal("消息", mContent, callback); |
|||
}, |
|||
|
|||
// 打开成功弹框(确定+倒计时) |
|||
showConfirmCountdownSuccessModal(mContent, callback) { |
|||
this.showConfirmCountdownModal("成功", mContent, callback); |
|||
}, |
|||
|
|||
// 打开失败弹框(确定+倒计时) |
|||
showConfirmCountdownFailModal(mContent, callback) { |
|||
this.showConfirmCountdownModal("失败", mContent, callback); |
|||
}, |
|||
|
|||
// 打开警告弹框(确定+倒计时) |
|||
showConfirmCountdownWarningModal(mContent, callback) { |
|||
this.showConfirmCountdownModal("警告", mContent, callback); |
|||
}, |
|||
|
|||
// 打开疑问弹框(确定+倒计时) |
|||
showConfirmCountdownQuestionModal(mContent, callback) { |
|||
this.showConfirmCountdownModal("疑问", mContent, callback); |
|||
}, |
|||
|
|||
// 初始化弹框并打开(确定+倒计时) |
|||
showConfirmCountdownModal(mIconType, mContent, callback) { |
|||
this.showModal({ |
|||
iconType: mIconType, |
|||
content: mContent, |
|||
showCancelButton: false, |
|||
showConfirmCountdown: true, |
|||
success: function(res) { |
|||
if (callback != undefined) { |
|||
if (res.confirm == true) { |
|||
callback(true); |
|||
console.log('用户点击确定') |
|||
} else { |
|||
callback(false); |
|||
console.log('用户点击取消') |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
}, |
|||
|
|||
// 打开消息弹框(取消+确定+倒计时) |
|||
showSelectCountdownMessageModal(mContent, callback) { |
|||
this.showSelectCountdownModal("消息", mContent, callback); |
|||
}, |
|||
|
|||
// 打开成功弹框(取消+确定+倒计时) |
|||
showSelectCountdownSuccessModal(mContent, callback) { |
|||
this.showSelectCountdownModal("成功", mContent, callback); |
|||
}, |
|||
|
|||
// 打开失败弹框(取消+确定+倒计时) |
|||
showSelectCountdownFailModal(mContent, callback) { |
|||
this.showSelectCountdownModal("失败", mContent, callback); |
|||
}, |
|||
|
|||
// 打开警告弹框(取消+确定+倒计时) |
|||
showSelectCountdownWarningModal(mContent, callback) { |
|||
this.showSelectCountdownModal("警告", mContent, callback); |
|||
}, |
|||
|
|||
// 打开疑问弹框(取消+确定+倒计时) |
|||
showSelectCountdownQuestionModal(mContent, callback) { |
|||
this.showSelectCountdownModal("疑问", mContent, callback); |
|||
}, |
|||
|
|||
// 初始化弹框并打开(取消+确定+倒计时) |
|||
showSelectCountdownModal(mIconType, mContent, callback) { |
|||
this.showModal({ |
|||
iconType: mIconType, |
|||
content: mContent, |
|||
showConfirmCountdown: true, |
|||
success: function(res) { |
|||
if (callback != undefined) { |
|||
if (res.confirm == true) { |
|||
callback(true); |
|||
console.log('用户点击确定') |
|||
} else { |
|||
callback(false); |
|||
console.log('用户点击取消') |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
}, |
|||
|
|||
// 初始化弹框并打开 |
|||
showModal(data) { |
|||
if (data.iconType) { |
|||
this.iconType = data.iconType |
|||
switch (data.iconType) { |
|||
case '消息': |
|||
this.icon = '/static/icons/error-circle.svg'; |
|||
break; |
|||
case '成功': |
|||
this.icon = '/static/icons/checkmark-circle.svg'; |
|||
break; |
|||
case '失败': |
|||
this.icon = '/static/icons/close-circle.svg'; |
|||
break; |
|||
case '警告': |
|||
this.icon = '/static/icons/warning.svg'; |
|||
break; |
|||
case '疑问': |
|||
this.icon = '/static/icons/question-circle.svg'; |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
} |
|||
// image |
|||
if (data.title) { |
|||
this.title = data.title |
|||
} |
|||
if (data.content) { |
|||
console.log(data.content); |
|||
this.content = data.content; |
|||
} else { |
|||
this.content = '' |
|||
} |
|||
if (data.cancelText) { |
|||
this.cancelText = data.cancelText |
|||
} else { |
|||
this.cancelText = '取消' |
|||
} |
|||
if (data.confirmText) { |
|||
this.confirmText = data.confirmText |
|||
} else { |
|||
this.confirmText = '确定' |
|||
} |
|||
|
|||
if (data.showCancel === false || data.showCancel === true) { |
|||
this.showCancel = data.showCancel |
|||
} else { |
|||
this.showCancel = true |
|||
} |
|||
|
|||
if (data.confirmColor) { |
|||
this.confirmColor = data.confirmColor |
|||
} else { |
|||
this.confirmColor = '#007aff' |
|||
} |
|||
|
|||
if (data.cancelColor) { |
|||
this.cancelColor = data.cancelColor |
|||
} else { |
|||
this.cancelColor = '#666F83' |
|||
} |
|||
|
|||
if (data.showConfirmButton === false || data.showConfirmButton === true) { |
|||
this.showConfirmButton = data.showConfirmButton |
|||
} else { |
|||
this.showConfirmButton = true |
|||
} |
|||
|
|||
if (data.showConfirmCountdown === false || data.showConfirmCountdown === true) { |
|||
this.showConfirmCountdown = data.showConfirmCountdown |
|||
} else { |
|||
this.showConfirmCountdown = false |
|||
} |
|||
|
|||
if (data.showCancelButton === false || data.showCancelButton === true) { |
|||
this.showCancelButton = data.showCancelButton |
|||
} else { |
|||
this.showCancelButton = true |
|||
} |
|||
|
|||
if (data.success) { |
|||
this.success = data.success |
|||
} else { |
|||
this.success = () => {} |
|||
} |
|||
setTimeout(res => { |
|||
this.show = true; |
|||
}, 500) |
|||
if (this.showConfirmCountdown) { |
|||
this.startTimer(); |
|||
} |
|||
|
|||
}, |
|||
|
|||
startTimer() { |
|||
this.seconds = 3; |
|||
clearInterval(this.timer) |
|||
this.timer = setInterval(() => { |
|||
this.seconds-- |
|||
// console.log("倒计时时间", this.seconds); |
|||
if (this.seconds <= 0) { |
|||
this.timeUp() |
|||
return |
|||
} |
|||
}, 1000) |
|||
}, |
|||
|
|||
timeUp() { |
|||
// clearInterval(this.timer) |
|||
console.log('时间到') |
|||
this.confirmClose(); |
|||
}, |
|||
|
|||
}, |
|||
|
|||
|
|||
|
|||
} |
|||
/** |
|||
* modal 模态框 |
|||
* @description 弹出模态框,常用于消息提示、消息确认、在当前页面内完成特定的交互操作 |
|||
* */ |
|||
export default { |
|||
data() { |
|||
return { |
|||
timer: null, |
|||
show: false, // 是否显示 |
|||
iconType: '消息', |
|||
icon: '../../static/icons/error-circle.svg', |
|||
title: '', // 提示标题 |
|||
content: '', // 提示内容 |
|||
cancelText: '取消', // 取消按钮的文字 |
|||
confirmText: '确定', // 确认按钮文字 |
|||
showCancel: true, // 是否显示取消按钮,默认为 true |
|||
confirmColor: '#007aff', // 确定按钮颜色 |
|||
cancelColor: null, // 取消按钮颜色 |
|||
showConfirmButton: true, // 是否显示确认按钮 |
|||
showConfirmCountdown: true, // 是否显示确定倒计时 |
|||
showCancelButton: true, // 是否显示取消按钮 |
|||
showClose: false, |
|||
confirm: false, // 为 true 时,表示用户点击了确定按钮 |
|||
cancel: false, // 为 true 时,表示用户点击了取消 |
|||
seconds: 0, |
|||
success: () => {} // 回调方法 |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
open() { |
|||
this.show = true |
|||
}, |
|||
close() { |
|||
this.$.refs.modal.popupClose() |
|||
}, |
|||
confirmClose() { |
|||
if (this.show) { |
|||
this.show = false |
|||
clearInterval(this.timer) // 清空timer |
|||
this.success({ |
|||
// cancel: false, |
|||
confirm: true |
|||
}) |
|||
} |
|||
}, |
|||
|
|||
cancelClose() { |
|||
clearInterval(this.timer) // 清空timer |
|||
if(this.$refs.modal){ |
|||
this.$refs.modal.popupClose(); |
|||
} |
|||
this.success({ |
|||
// cancel: true, |
|||
confirm: false |
|||
}) |
|||
}, |
|||
|
|||
// 打开消息弹框(确定) |
|||
showConfirmMessageModal(mContent, callback) { |
|||
this.showConfirmModal('消息', mContent, callback) |
|||
}, |
|||
|
|||
// 打开成功弹框(确定) |
|||
showConfirmSuccessModal(mContent, callback) { |
|||
this.showConfirmModal('成功', mContent, callback) |
|||
}, |
|||
|
|||
// 打开失败弹框(确定) |
|||
showConfirmFailModal(mContent, callback) { |
|||
this.showConfirmModal('失败', mContent, callback) |
|||
}, |
|||
|
|||
// 打开警告弹框(确定) |
|||
showConfirmWarningModal(mContent, callback) { |
|||
this.showConfirmModal('警告', mContent, callback) |
|||
}, |
|||
|
|||
// 打开疑问弹框(确定) |
|||
showConfirmQuestionModal(mContent, callback) { |
|||
this.showConfirmModal('疑问', mContent, callback) |
|||
}, |
|||
|
|||
// 初始化弹框并打开(确定) |
|||
showConfirmModal(mIconType, mContent, callback) { |
|||
this.showModal({ |
|||
iconType: mIconType, |
|||
content: mContent, |
|||
showCancelButton: false, |
|||
success(res) { |
|||
if (callback != undefined) { |
|||
if (res.confirm == true) { |
|||
callback(true) |
|||
console.log('用户点击确定') |
|||
} else { |
|||
callback(false) |
|||
console.log('用户点击取消') |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
}, |
|||
|
|||
// 打开消息弹框(取消+确定) |
|||
showSelectMessageModal(mContent, callback) { |
|||
this.showSelectModal('消息', mContent, callback) |
|||
}, |
|||
|
|||
// 打开成功弹框(取消+确定) |
|||
showSelectSuccessModal(mContent, callback) { |
|||
this.showSelectModal('成功', mContent, callback) |
|||
}, |
|||
|
|||
// 打开失败弹框(取消+确定) |
|||
showSelectFailModal(mContent, callback) { |
|||
this.showSelectModal('失败', mContent, callback) |
|||
}, |
|||
|
|||
// 打开警告弹框(取消+确定) |
|||
showSelectWarningModal(mContent, callback) { |
|||
this.showSelectModal('警告', mContent, callback) |
|||
}, |
|||
|
|||
// 打开疑问弹框(取消+确定) |
|||
showSelectQuestionModal(mContent, callback) { |
|||
this.showSelectModal('疑问', mContent, callback) |
|||
}, |
|||
|
|||
// 初始化弹框并打开(取消+确定) |
|||
showSelectModal(mIconType, mContent, callback) { |
|||
this.showModal({ |
|||
iconType: mIconType, |
|||
content: mContent, |
|||
success(res) { |
|||
if (callback != undefined) { |
|||
if (res.confirm == true) { |
|||
callback(true) |
|||
console.log('用户点击确定') |
|||
} else { |
|||
callback(false) |
|||
console.log('用户点击取消') |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
}, |
|||
|
|||
// 打开消息弹框(确定+倒计时) |
|||
showConfirmCountdownMessageModal(mContent, callback) { |
|||
this.showConfirmCountdownModal('消息', mContent, callback) |
|||
}, |
|||
|
|||
// 打开成功弹框(确定+倒计时) |
|||
showConfirmCountdownSuccessModal(mContent, callback) { |
|||
this.showConfirmCountdownModal('成功', mContent, callback) |
|||
}, |
|||
|
|||
// 打开失败弹框(确定+倒计时) |
|||
showConfirmCountdownFailModal(mContent, callback) { |
|||
this.showConfirmCountdownModal('失败', mContent, callback) |
|||
}, |
|||
|
|||
// 打开警告弹框(确定+倒计时) |
|||
showConfirmCountdownWarningModal(mContent, callback) { |
|||
this.showConfirmCountdownModal('警告', mContent, callback) |
|||
}, |
|||
|
|||
// 打开疑问弹框(确定+倒计时) |
|||
showConfirmCountdownQuestionModal(mContent, callback) { |
|||
this.showConfirmCountdownModal('疑问', mContent, callback) |
|||
}, |
|||
|
|||
// 初始化弹框并打开(确定+倒计时) |
|||
showConfirmCountdownModal(mIconType, mContent, callback) { |
|||
this.showModal({ |
|||
iconType: mIconType, |
|||
content: mContent, |
|||
showCancelButton: false, |
|||
showConfirmCountdown: true, |
|||
success(res) { |
|||
if (callback != undefined) { |
|||
if (res.confirm == true) { |
|||
callback(true) |
|||
console.log('用户点击确定') |
|||
} else { |
|||
callback(false) |
|||
console.log('用户点击取消') |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
}, |
|||
|
|||
// 打开消息弹框(取消+确定+倒计时) |
|||
showSelectCountdownMessageModal(mContent, callback) { |
|||
this.showSelectCountdownModal('消息', mContent, callback) |
|||
}, |
|||
|
|||
// 打开成功弹框(取消+确定+倒计时) |
|||
showSelectCountdownSuccessModal(mContent, callback) { |
|||
this.showSelectCountdownModal('成功', mContent, callback) |
|||
}, |
|||
|
|||
// 打开失败弹框(取消+确定+倒计时) |
|||
showSelectCountdownFailModal(mContent, callback) { |
|||
this.showSelectCountdownModal('失败', mContent, callback) |
|||
}, |
|||
|
|||
// 打开警告弹框(取消+确定+倒计时) |
|||
showSelectCountdownWarningModal(mContent, callback) { |
|||
this.showSelectCountdownModal('警告', mContent, callback) |
|||
}, |
|||
|
|||
// 打开疑问弹框(取消+确定+倒计时) |
|||
showSelectCountdownQuestionModal(mContent, callback) { |
|||
this.showSelectCountdownModal('疑问', mContent, callback) |
|||
}, |
|||
|
|||
// 初始化弹框并打开(取消+确定+倒计时) |
|||
showSelectCountdownModal(mIconType, mContent, callback) { |
|||
this.showModal({ |
|||
iconType: mIconType, |
|||
content: mContent, |
|||
showConfirmCountdown: true, |
|||
success(res) { |
|||
if (callback != undefined) { |
|||
if (res.confirm == true) { |
|||
callback(true) |
|||
console.log('用户点击确定') |
|||
} else { |
|||
callback(false) |
|||
console.log('用户点击取消') |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
}, |
|||
|
|||
// 初始化弹框并打开 |
|||
showModal(data) { |
|||
if (data.iconType) { |
|||
this.iconType = data.iconType |
|||
switch (data.iconType) { |
|||
case '消息': |
|||
this.icon = '/static/icons/error-circle.svg' |
|||
break |
|||
case '成功': |
|||
this.icon = '/static/icons/checkmark-circle.svg' |
|||
break |
|||
case '失败': |
|||
this.icon = '/static/icons/close-circle.svg' |
|||
break |
|||
case '警告': |
|||
this.icon = '/static/icons/warning.svg' |
|||
break |
|||
case '疑问': |
|||
this.icon = '/static/icons/question-circle.svg' |
|||
break |
|||
default: |
|||
break |
|||
} |
|||
} |
|||
// image |
|||
if (data.title) { |
|||
this.title = data.title |
|||
} |
|||
if (data.content) { |
|||
console.log(data.content) |
|||
this.content = data.content |
|||
} else { |
|||
this.content = '' |
|||
} |
|||
if (data.cancelText) { |
|||
this.cancelText = data.cancelText |
|||
} else { |
|||
this.cancelText = '取消' |
|||
} |
|||
if (data.confirmText) { |
|||
this.confirmText = data.confirmText |
|||
} else { |
|||
this.confirmText = '确定' |
|||
} |
|||
|
|||
if (data.showCancel === false || data.showCancel === true) { |
|||
this.showCancel = data.showCancel |
|||
} else { |
|||
this.showCancel = true |
|||
} |
|||
|
|||
if (data.confirmColor) { |
|||
this.confirmColor = data.confirmColor |
|||
} else { |
|||
this.confirmColor = '#007aff' |
|||
} |
|||
|
|||
if (data.cancelColor) { |
|||
this.cancelColor = data.cancelColor |
|||
} else { |
|||
this.cancelColor = '#666F83' |
|||
} |
|||
|
|||
if (data.showConfirmButton === false || data.showConfirmButton === true) { |
|||
this.showConfirmButton = data.showConfirmButton |
|||
} else { |
|||
this.showConfirmButton = true |
|||
} |
|||
|
|||
if (data.showConfirmCountdown === false || data.showConfirmCountdown === true) { |
|||
this.showConfirmCountdown = data.showConfirmCountdown |
|||
} else { |
|||
this.showConfirmCountdown = false |
|||
} |
|||
|
|||
if (data.showCancelButton === false || data.showCancelButton === true) { |
|||
this.showCancelButton = data.showCancelButton |
|||
} else { |
|||
this.showCancelButton = true |
|||
} |
|||
|
|||
if (data.success) { |
|||
this.success = data.success |
|||
} else { |
|||
this.success = () => {} |
|||
} |
|||
setTimeout((res) => { |
|||
this.show = true |
|||
}, 500) |
|||
if (this.showConfirmCountdown) { |
|||
this.startTimer() |
|||
} |
|||
}, |
|||
|
|||
startTimer() { |
|||
this.seconds = 3 |
|||
clearInterval(this.timer) |
|||
this.timer = setInterval(() => { |
|||
this.seconds-- |
|||
// console.log("倒计时时间", this.seconds); |
|||
if (this.seconds <= 0) { |
|||
this.timeUp() |
|||
} |
|||
}, 1000) |
|||
}, |
|||
|
|||
timeUp() { |
|||
// clearInterval(this.timer) |
|||
console.log('时间到') |
|||
this.confirmClose() |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
.slot-content { |
|||
font-size: 36rpx; |
|||
display: flex; //弹性布局 |
|||
flex-direction: column; //垂直排列 |
|||
align-items: center; //子元素居中 |
|||
// background-image: url() |
|||
} |
|||
|
|||
.icon { |
|||
width: 70rpx; |
|||
height: 70rpx; |
|||
opacity: 1; //透明度 |
|||
margin-top: 16px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 35rpx; |
|||
} |
|||
|
|||
.content { |
|||
margin-top: 16px; |
|||
margin-bottom: 16px; |
|||
margin-left: 8px; |
|||
margin-right: 8px; |
|||
font-size: 32rpx; |
|||
text-align: center; |
|||
word-wrap: break-word; |
|||
word-break: break-all; |
|||
white-space: pre-line; |
|||
|
|||
|
|||
} |
|||
|
|||
.cance_button { |
|||
width: 100%; |
|||
margin-top: 10px; |
|||
margin-bottom: 10px; |
|||
font-size: 32rpx; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.confirm_button { |
|||
width: 100%; |
|||
margin-top: 10px; |
|||
margin-bottom: 10px; |
|||
font-size: 32rpx; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.confirm_text { |
|||
// color: $uni-color-primary; |
|||
} |
|||
|
|||
.def_text { |
|||
color: $uni-color-primary; |
|||
} |
|||
.slot-content { |
|||
font-size: 36rpx; |
|||
display: flex; //弹性布局 |
|||
flex-direction: column; //垂直排列 |
|||
align-items: center; //子元素居中 |
|||
// background-image: url() |
|||
} |
|||
|
|||
.icon { |
|||
width: 70rpx; |
|||
height: 70rpx; |
|||
opacity: 1; //透明度 |
|||
margin-top: 16px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 35rpx; |
|||
} |
|||
|
|||
.content { |
|||
margin-top: 16px; |
|||
margin-bottom: 16px; |
|||
margin-left: 8px; |
|||
margin-right: 8px; |
|||
font-size: 32rpx; |
|||
text-align: center; |
|||
word-wrap: break-word; |
|||
word-break: break-all; |
|||
white-space: pre-line; |
|||
} |
|||
|
|||
.cance_button { |
|||
width: 100%; |
|||
margin-top: 10px; |
|||
margin-bottom: 10px; |
|||
font-size: 32rpx; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.confirm_button { |
|||
width: 100%; |
|||
margin-top: 10px; |
|||
margin-bottom: 10px; |
|||
font-size: 32rpx; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.confirm_text { |
|||
// color: $uni-color-primary; |
|||
} |
|||
|
|||
.def_text { |
|||
color: $uni-color-primary; |
|||
} |
|||
</style> |
|||
|
@ -0,0 +1,13 @@ |
|||
/// <reference types="vite/client" />
|
|||
|
|||
declare module '*.vue' { |
|||
import { DefineComponent } from 'vue' |
|||
|
|||
const component: DefineComponent<{}, {}, any> |
|||
export default component |
|||
} |
|||
|
|||
interface ImportMetaEnv { |
|||
VITE_TITLE: string |
|||
VITE_BASE_URL: string |
|||
} |
@ -0,0 +1,95 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> |
|||
<title></title> |
|||
<script src="../../api/img-to-base64.js"></script> |
|||
<script type="text/javascript"> |
|||
document.addEventListener('plusready', function() { |
|||
//console.log("所有plus api都应该在此事件发生后调用,否则会出现plus is undefined。") |
|||
|
|||
|
|||
}); |
|||
|
|||
</script> |
|||
<style> |
|||
.box { |
|||
font-size: 14px; |
|||
display: flex; |
|||
margin-top: 60px; |
|||
|
|||
} |
|||
|
|||
.left { |
|||
border-top: 1px solid #b1b1b1; |
|||
border-left: 1px solid #b1b1b1; |
|||
flex: 1; |
|||
} |
|||
|
|||
.left-item { |
|||
display: flex; |
|||
} |
|||
|
|||
.bold-font { |
|||
font-weight: bold; |
|||
} |
|||
.font-30 { |
|||
font-size: 30px; |
|||
} |
|||
.font-20 { |
|||
font-size: 20px; |
|||
} |
|||
.bold-label { |
|||
font-weight: bold; |
|||
font-size: 15px; |
|||
} |
|||
|
|||
.label { |
|||
border-bottom: 1px solid #b1b1b1; |
|||
border-right: 1px solid #b1b1b1; |
|||
width: 60px; |
|||
padding: 0px 5px; |
|||
height: 49px; |
|||
line-height: 49px; |
|||
} |
|||
|
|||
.value { |
|||
border-bottom: 1px solid #b1b1b1; |
|||
border-right: 1px solid #b1b1b1; |
|||
padding: 0px 5px; |
|||
height: 49px; |
|||
flex: 1; |
|||
width: 0px; |
|||
display: flex; |
|||
align-items: center; |
|||
word-break: break-all; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.right { |
|||
width: 300px; |
|||
} |
|||
|
|||
.image { |
|||
width: calc(100% - 1px); |
|||
height: 149px; |
|||
border-bottom: 1px solid #b1b1b1; |
|||
border-top: 1px solid #b1b1b1; |
|||
border-right: 1px solid #b1b1b1; |
|||
} |
|||
|
|||
.image img { |
|||
width: 147px; |
|||
height: 147px; |
|||
border: 1px solid #b1b1b1; |
|||
/* width: calc(100% - 4px); |
|||
height: calc(100% - 4px); */ |
|||
margin: 1px; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
mainBody |
|||
</body> |
|||
</html> |
@ -0,0 +1,67 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> |
|||
<title></title> |
|||
<script src="../../api/img-to-base64.js"></script> |
|||
<script type="text/javascript"> |
|||
document.addEventListener('plusready', function() { |
|||
//console.log("所有plus api都应该在此事件发生后调用,否则会出现plus is undefined。") |
|||
|
|||
|
|||
}); |
|||
</script> |
|||
<style> |
|||
.box { |
|||
font-size: 13px; |
|||
/* padding: 10px; */ |
|||
/* border: 1px solid #dedede; */ |
|||
} |
|||
|
|||
|
|||
.left { |
|||
flex: 1; |
|||
border-bottom: 1px solid #b1b1b1; |
|||
} |
|||
.left-item { |
|||
display: flex; |
|||
border-top: 1px solid #b1b1b1; |
|||
border-left: 1px solid #b1b1b1; |
|||
border-right: 1px solid #b1b1b1; |
|||
} |
|||
|
|||
.left-item div{ |
|||
padding: 10px 10px; |
|||
font-size: 16px; |
|||
} |
|||
.left-item .label{ |
|||
width: 100px; |
|||
padding: 10px 10px; |
|||
border-right: 1px solid #b1b1b1; |
|||
} |
|||
|
|||
.relative { |
|||
margin-bottom: 10px; |
|||
position: relative; |
|||
} |
|||
|
|||
.q { |
|||
position: absolute; |
|||
font-size: 15rem; |
|||
color: rgba(0, 0, 0, 0.1); |
|||
width: calc(100% - 100px); |
|||
right: 0px; |
|||
top: 0px; |
|||
text-align: center; |
|||
height: 100%; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
mainBody |
|||
</body> |
|||
</html> |
@ -0,0 +1,67 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> |
|||
<title></title> |
|||
<script src="../../api/img-to-base64.js"></script> |
|||
<script type="text/javascript"> |
|||
document.addEventListener('plusready', function() { |
|||
//console.log("所有plus api都应该在此事件发生后调用,否则会出现plus is undefined。") |
|||
|
|||
|
|||
}); |
|||
</script> |
|||
<style> |
|||
.box { |
|||
font-size: 13px; |
|||
/* padding: 10px; */ |
|||
/* border: 1px solid #dedede; */ |
|||
} |
|||
|
|||
|
|||
.left { |
|||
flex: 1; |
|||
border-bottom: 1px solid #b1b1b1; |
|||
} |
|||
.left-item { |
|||
display: flex; |
|||
border-top: 1px solid #b1b1b1; |
|||
border-left: 1px solid #b1b1b1; |
|||
border-right: 1px solid #b1b1b1; |
|||
} |
|||
|
|||
.left-item div{ |
|||
padding: 10px 10px; |
|||
font-size: 16px; |
|||
} |
|||
.left-item .label{ |
|||
width: 100px; |
|||
padding: 10px 10px; |
|||
border-right: 1px solid #b1b1b1; |
|||
} |
|||
|
|||
.relative { |
|||
margin-bottom: 10px; |
|||
position: relative; |
|||
} |
|||
|
|||
.q { |
|||
position: absolute; |
|||
font-size: 15rem; |
|||
color: rgba(0, 0, 0, 0.1); |
|||
width: calc(100% - 100px); |
|||
right: 0px; |
|||
top: 0px; |
|||
text-align: center; |
|||
height: 100%; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
mainBody |
|||
</body> |
|||
</html> |
@ -1,74 +0,0 @@ |
|||
import App from './App' |
|||
import store from './store' |
|||
import './router/my_router.js'; //引入拦截
|
|||
import VueClipboard from 'vue-clipboard2' //复制粘贴
|
|||
import uView from './uni_modules/vk-uview-ui';// 引入 uView UI
|
|||
import comMessage from './mycomponents/common/comMessage.vue' |
|||
|
|||
// #ifndef VUE3
|
|||
import Vue from 'vue' |
|||
console.log("Vuew2222"); |
|||
Vue.config.productionTip = false |
|||
Vue.prototype.$store = store |
|||
Vue.prototype.$adpid = "1111111111" |
|||
Vue.prototype.$backgroundAudioData = { |
|||
playing: false, |
|||
playTime: 0, |
|||
formatedPlayTime: '00:00:00' |
|||
} |
|||
App.mpType = 'app' |
|||
const app = new Vue({ |
|||
store, |
|||
...App |
|||
}) |
|||
app.$mount() |
|||
// #endif
|
|||
|
|||
import { |
|||
createSSRApp |
|||
} from "vue"; |
|||
export function createApp() { |
|||
const app = createSSRApp(App); |
|||
app.use(store) |
|||
app.use(VueClipboard) |
|||
app.use(uView) |
|||
app.component('comMessage', comMessage) |
|||
console.log("网络22请求") |
|||
// startApp(app);
|
|||
return { |
|||
app, |
|||
}; |
|||
} |
|||
|
|||
export function startApp(app) { |
|||
uni.request({ |
|||
url: `./static/config.json?t=${new Date().getTime()}`, |
|||
method: 'get', |
|||
data: {}, |
|||
success: (res) => { |
|||
if (res.data != "") { |
|||
//在配置中读url,company等信息
|
|||
// app.config.globalProperties.$baseInfo = res.data.baseInfo;
|
|||
// getApp().globalData.dev_url = res.data.baseInfo.dev.value;
|
|||
// getApp().globalData.request_url = res.data.baseInfo.request_url.value;
|
|||
// getApp().globalData.tenantId = res.data.baseInfo.tenantId.value;
|
|||
// app.config.globalProperties.$recepit_configList = res.data.recepit_configList;
|
|||
// getApp().globalData.recepit_configList = res.data.recepit_configList;
|
|||
// getApp().globalData.feed_configList = res.data.feed_configList;
|
|||
// getApp().globalData.isDevelopment = res.data.baseInfo.isDevelopment.value
|
|||
// Vue.prototype.$dev_url = res.data.baseInfo.dev.value;
|
|||
// console.log("网络",res.data.baseInfo.request_url.value)
|
|||
// console.log("开发环境12",res.data.baseInfo.isDevelopment.value)
|
|||
// uni.setStorageSync("request_url",res.data.baseInfo.request_url.value)
|
|||
// uni.setStorageSync("isDevelopment",res.data.baseInfo.isDevelopment.value)
|
|||
} |
|||
}, |
|||
fail: (error) => { |
|||
|
|||
} |
|||
}) |
|||
|
|||
return { |
|||
startApp |
|||
}; |
|||
} |
@ -0,0 +1,48 @@ |
|||
import { createSSRApp } from 'vue' |
|||
import * as Pinia from 'pinia' |
|||
// @ts-ignore
|
|||
import uView from 'vk-uview-ui' |
|||
import App from './App.vue' |
|||
import comMessage from '@/mycomponents/common/comMessage.vue' |
|||
import noclick from './common/noclick.js' |
|||
|
|||
|
|||
import tab from './plugins/tab' |
|||
import modal from './plugins/modal' |
|||
import time from './plugins/time' |
|||
import storage from './plugins/storage' |
|||
|
|||
|
|||
// unocss
|
|||
import 'uno.css' |
|||
|
|||
import { accessTimeInAnHour, getNowFormatDate } from "./utils/dateTime"; |
|||
export function createApp() { |
|||
const app = createSSRApp(App) |
|||
app.use(Pinia.createPinia()) |
|||
app.use(uView) |
|||
// 解决onLaunch和onLoad异步问题
|
|||
app.config.globalProperties.$onLaunched = new Promise(resolve => { |
|||
app.config.globalProperties.$isResolve = resolve |
|||
}) |
|||
|
|||
// 页签操作
|
|||
app.config.globalProperties.$tab = tab |
|||
// 模态框对象
|
|||
app.config.globalProperties.$modal = modal |
|||
// 时间对象
|
|||
app.config.globalProperties.$time = time |
|||
// 节流
|
|||
app.config.globalProperties.$throttle = noclick.throttle; |
|||
// 缓存
|
|||
app.config.globalProperties.$storage = storage |
|||
app.component('ComMessage', comMessage) |
|||
|
|||
|
|||
|
|||
return { |
|||
app, |
|||
// uni-app 官方文档示例 https://zh.uniapp.dcloud.io/tutorial/vue3-pinia.html#%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86-pinia
|
|||
Pinia // 此处必须将 Pinia 返回
|
|||
} |
|||
} |
@ -1,147 +1,110 @@ |
|||
<template> |
|||
<view :class="dataContent.scaned?'scan_view':''" style="background-color: #ffffff;margin-bottom: 1px; "> |
|||
<view class="uni-flex uni-row space-between" style="align-items: center"> |
|||
<view> |
|||
<pack v-if="isShowPack && dataContent.packingNumber" :packingCode="dataContent.packingNumber"></pack> |
|||
<batch v-if="isShowBatch && dataContent.batch" :batch="dataContent.batch"></batch> |
|||
<location title="来源库位" v-if="isShowFromLocation" :locationCode="dataContent.locationCode"></location> |
|||
<to-location title="目标库位" v-if="isShowToLocation" :locationCode="dataContent.toLocationCode"> |
|||
</to-location> |
|||
</view> |
|||
<view> |
|||
<!-- <qty v-if="dataContent.record==null ||dataContent.record==undefined " :dataContent="dataContent" |
|||
<view :class="dataContent.scaned ? 'scan_view' : ''"> |
|||
<view class="uni-flex uni-row space-between" style="align-items: center; padding: 20rpx"> |
|||
<view> |
|||
<pack v-if="isShowParentPack && dataContent.parentNumber" title="父包装" :packingCode="dataContent.parentNumber"></pack> |
|||
<pack v-if="isShowPack && dataContent.packingNumber" :isShowPackingNumberProps="isShowPackingNumberProps" :packingCode="dataContent.packingNumber"></pack> |
|||
<batch v-if="isShowBatch && dataContent.batch" :batch="dataContent.batch"></batch> |
|||
<location title="来源库位" v-if="isShowFromLocation" :locationCode="dataContent.locationCode"></location> |
|||
<to-location title="目标库位" v-if="isShowToLocation" :locationCode="dataContent.toLocationCode"> </to-location> |
|||
</view> |
|||
<view class="uni-flex" style="flex-direction: column"> |
|||
<view class="uni-flex uni-row u-align-start"> |
|||
<!-- <qty v-if="dataContent.record==null ||dataContent.record==undefined " :dataContent="dataContent" |
|||
:isShowStdPack="isShowStdPack" :isShowStatus="isShowStatus"></qty> --> |
|||
<qty v-if="dataContent.handleQty==0 || dataContent.handleQty==undefined" :dataContent="dataContent" |
|||
:isShowStdPack="isShowStdPack" :isShowStatus="isShowStatus"></qty> |
|||
<compare-qty v-else :dataContent="dataContent" :recommendQty="Number( dataContent.qty)" |
|||
:handleQty="Number (dataContent.handleQty)" :isShowStdPack="isShowStdPack"> |
|||
</compare-qty> |
|||
<view class="uni-flex uni-row" style="vertical-align:center" v-if="isDevlement()"> |
|||
<text style="font-size: 30rpx;color: #2979ff; " @click="copy">复制采购</text> |
|||
<text style="font-size: 30rpx;color: #2979ff;" @click="copyPro">|制品</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<!-- <u-line></u-line> --> |
|||
</view> |
|||
</template> |
|||
<qty v-if="dataContent.handleQty == 0 || dataContent.handleQty == undefined" :dataContent="dataContent" :isShowStdPack="isShowStdPack" :isShowStatus="isShowStatus"></qty> |
|||
<compare-qty v-else :dataContent="dataContent" :recommendQty="Number(dataContent.qty)" :handleQty="Number(dataContent.handleQty)" :isShowStdPack="isShowStdPack" :isShowStatus="isShowStatus"> </compare-qty> |
|||
|
|||
<script> |
|||
import pack from '@/mycomponents/balance/pack.vue' |
|||
import location from '@/mycomponents/balance/location.vue' |
|||
import toLocation from '@/mycomponents/balance/toLocation.vue' |
|||
import batch from '@/mycomponents/balance/batch.vue' |
|||
import qty from '@/mycomponents/qty/qty.vue' |
|||
import recommendQty from '@/mycomponents/qty/recommendQty.vue' |
|||
import compareQty from '@/mycomponents/qty/compareQty.vue' |
|||
import config from '@/static/config.js' |
|||
<!-- <view class="uni-flex uni-row" style="vertical-align: center" v-if="isDevlement()"> |
|||
<image style="width: 26rpx; height: 26rpx; margin-top: 40rpx" src="/static/icons/icon_copy.svg" alt="" @click="copy" /> |
|||
</view> --> |
|||
</view> |
|||
<!-- <view class="" v-if="dataContent.inventoryStatus"> |
|||
<move-status :fromInventoryStatus="dataContent.inventoryStatus"> </move-status> |
|||
</view> --> |
|||
</view> |
|||
</view> |
|||
<!-- <u-line></u-line> --> |
|||
</view> |
|||
</template> |
|||
|
|||
export default { |
|||
components: { |
|||
pack, |
|||
location, |
|||
toLocation, |
|||
batch, |
|||
qty, |
|||
recommendQty, |
|||
compareQty, |
|||
}, |
|||
<script setup lang="ts"> |
|||
import pack from '@/mycomponents/balance/pack.vue' |
|||
import location from '@/mycomponents/balance/location.vue' |
|||
import toLocation from '@/mycomponents/balance/toLocation.vue' |
|||
import batch from '@/mycomponents/balance/batch.vue' |
|||
import qty from '@/mycomponents/qty/qty.vue' |
|||
import compareQty from '@/mycomponents/qty/compareQty.vue' |
|||
import config from '@/static/config.js' |
|||
import moveStatus from '@/mycomponents/balance/moveStatus.vue' |
|||
|
|||
data() { |
|||
return { |
|||
const props = defineProps({ |
|||
dataContent: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowFromLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStdPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowToLocation: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
isShowParentPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowPackingNumberProps: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}) |
|||
const copy = () => { |
|||
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100 |
|||
const content = `HPQ;V1.0;I${props.dataContent.itemCode};P${props.dataContent.packingNumber};B${props.dataContent.batch};Q${props.dataContent.qty}` |
|||
|
|||
} |
|||
}, |
|||
props: { |
|||
dataContent: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowFromLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStdPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowToLocation: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
}, |
|||
watch: { |
|||
uni.setClipboardData({ |
|||
data: content, |
|||
success: () => { |
|||
uni.showToast({ |
|||
title: '复制采购标签成功' |
|||
}) |
|||
} |
|||
}) |
|||
} |
|||
const copyPro = () => { |
|||
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100 |
|||
const content = `HMQ;V1.0;I${props.dataContent.itemCode};P${props.dataContent.packingNumber};B${props.dataContent.batch};Q${props.dataContent.qty}` |
|||
|
|||
}, |
|||
methods: { |
|||
copy() { |
|||
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100 |
|||
var content = "HPQ;V1.0;I" + this.dataContent.itemCode + ";P" + this.dataContent.packingNumber + ";B" + |
|||
this.dataContent.batch + ";Q" + this.dataContent.qty |
|||
// #ifdef H5 |
|||
this.$copyText(content).then( |
|||
res => { |
|||
uni.showToast({ |
|||
title: '复制成功', |
|||
icon: 'none' |
|||
}) |
|||
} |
|||
) |
|||
// #endif |
|||
// #ifndef H5 |
|||
uni.setClipboardData({ |
|||
data: content, |
|||
success: () => { |
|||
uni.showToast({ |
|||
title: '复制采购标签成功' |
|||
}) |
|||
} |
|||
}) |
|||
// #endif |
|||
}, |
|||
copyPro() { |
|||
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100 |
|||
var content = "HMQ;V1.0;I" + this.dataContent.itemCode + ";P" + this.dataContent.packingNumber + ";B" + |
|||
this.dataContent.batch + ";Q" + this.dataContent.qty |
|||
// #ifdef H5 |
|||
this.$copyText(content).then( |
|||
res => { |
|||
uni.showToast({ |
|||
title: '复制成功', |
|||
icon: 'none' |
|||
}) |
|||
} |
|||
) |
|||
// #endif |
|||
// #ifndef H5 |
|||
uni.setClipboardData({ |
|||
data: content, |
|||
success: () => { |
|||
uni.showToast({ |
|||
title: '复制制品标签成功' |
|||
}) |
|||
} |
|||
}) |
|||
// #endif |
|||
}, |
|||
isDevlement() { |
|||
return config.isDevelopment; |
|||
} |
|||
} |
|||
} |
|||
uni.setClipboardData({ |
|||
data: content, |
|||
success: () => { |
|||
uni.showToast({ |
|||
title: '复制制品标签成功' |
|||
}) |
|||
} |
|||
}) |
|||
} |
|||
const isDevlement = () => { |
|||
return config.isDevelopment |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
|||
<style></style> |
|||
|
@ -1,54 +1,49 @@ |
|||
<!--发料任务卡片--> |
|||
<template> |
|||
<!-- <page-meta root-font-size="18px"></page-meta> --> |
|||
<uni-popup ref="popupItems" type="center"> |
|||
<scroll-view scroll-y="true" style="background-color: #EEEEEE;height: 90vh;"> |
|||
<item :dataContent="balanceItems[0]"></item> |
|||
<view class="popinpop count_shadow" style="width: 90vw;margin: 20rpx 20rpx 30rpx 20rpx;" |
|||
v-for="(item, index) in balanceItems" :key="item.id" @click="callback(item)"> |
|||
<balance :dataContent="item"></balance> |
|||
</view> |
|||
</scroll-view> |
|||
</uni-popup> |
|||
<!-- <page-meta root-font-size="18px"></page-meta> --> |
|||
<u-popup v-model="show" mode="center"> |
|||
<scroll-view scroll-y="true" style="background-color: #eeeeee; height: 90vh"> |
|||
<item style="margin: 10rpx" :dataContent="balanceItems[0]"></item> |
|||
<view class="popinpop count_shadow" style="width: 90vw; margin: 20rpx 20rpx 30rpx 20rpx" v-for="(item, index) in balanceItems" :key="item.id" @click="callback(item)"> |
|||
<balance :dataContent="item" :isShowStatus="false"></balance> |
|||
</view> |
|||
<view class="page-footer"> |
|||
<view class="uni-flex space-between" style="width: 100%"> |
|||
<!-- <view class=" uni-flex uni-row"> --> |
|||
<button class="btn_single_reject" hover-class="btn_commit_after" @click="close">关闭</button> |
|||
<!-- </view> --> |
|||
</view> |
|||
</view> |
|||
</scroll-view> |
|||
</u-popup> |
|||
</template> |
|||
|
|||
<script> |
|||
import item from '@/mycomponents/item/item.vue' |
|||
import balance from '@/mycomponents/balance/balance.vue' |
|||
<script setup lang="ts"> |
|||
import { ref, getCurrentInstance } from 'vue' |
|||
import item from '@/mycomponents/item/item.vue' |
|||
import balance from '@/mycomponents/balance/balance.vue' |
|||
|
|||
export default { |
|||
name: "balanceSelect", |
|||
emits: ['onSelectItem'], |
|||
components: { |
|||
item, |
|||
balance |
|||
}, |
|||
data() { |
|||
return { |
|||
balanceItems: [], |
|||
}; |
|||
}, |
|||
// 此处定义传入的数据 |
|||
props: { |
|||
// datacontent: { |
|||
// type: Object, |
|||
// value: null |
|||
// } |
|||
}, |
|||
methods: { |
|||
openPopup(items) { |
|||
this.balanceItems = items; |
|||
this.$refs['popupItems'].open("center"); |
|||
}, |
|||
const balanceItems = ref([]) |
|||
const show = ref(false) |
|||
const openPopup = (items) => { |
|||
if (Array.isArray(items)) { |
|||
balanceItems.value = items |
|||
} else { |
|||
balanceItems.value = [items] |
|||
} |
|||
show.value = true |
|||
} |
|||
|
|||
callback(item) { |
|||
this.$emit("onSelectItem", item); |
|||
this.$refs['popupItems'].close(); |
|||
}, |
|||
const callback = (item) => { |
|||
emit('onSelectItem', item) |
|||
show.value = false |
|||
} |
|||
|
|||
} |
|||
} |
|||
const close = () => { |
|||
show.value = false |
|||
} |
|||
const emit = defineEmits(['onSelectItem']) |
|||
defineExpose({ openPopup }) |
|||
</script> |
|||
|
|||
<style scoped lang="scss"> |
|||
</style> |
|||
<style scoped lang="scss"></style> |
|||
|
@ -1,24 +1,19 @@ |
|||
<template> |
|||
<view class="card_view "> |
|||
<text class="card_batch card_content ">批次</text> |
|||
<text class="card_content ">{{batch}}</text> |
|||
<view class="card_view"> |
|||
<text class="card_batch">批次</text> |
|||
<text class="card_content">{{batch}}</text> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return {} |
|||
}, |
|||
props: { |
|||
batch: { |
|||
type: String, |
|||
default: "" |
|||
} |
|||
}, |
|||
|
|||
} |
|||
<script setup lang="ts"> |
|||
const props = defineProps({ |
|||
batch: { |
|||
type: String, |
|||
default: "" |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style> |
|||
<style scoped> |
|||
|
|||
</style> |
|||
|
@ -1,37 +1,26 @@ |
|||
<template> |
|||
<view class="business_view"> |
|||
<text class="card_business">{{businessTypeDesc(bussinessType)}}</text> |
|||
<text class="card_business_content">{{number}}</text> |
|||
</view> |
|||
<view class="card_view"> |
|||
<text class="card_business">业务类型</text> |
|||
<text class="card_business_content">{{ businessTypeDesc(bussinessType) }}</text> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { |
|||
getBusinessTypeDesc |
|||
} from '@/common/directory.js'; |
|||
export default { |
|||
data() { |
|||
return {} |
|||
}, |
|||
props: { |
|||
bussinessType: { |
|||
type: String, |
|||
default: "" |
|||
}, |
|||
number: { |
|||
type: String, |
|||
default: "" |
|||
} |
|||
}, |
|||
methods:{ |
|||
businessTypeDesc(type){ |
|||
return getBusinessTypeDesc(type) |
|||
} |
|||
|
|||
} |
|||
<script setup lang="ts"> |
|||
import { getBusinessTypeName } from '@/common/directory.js' |
|||
|
|||
} |
|||
const props = defineProps({ |
|||
bussinessType: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
number: { |
|||
type: String, |
|||
default: '' |
|||
} |
|||
}) |
|||
const businessTypeDesc = (type) => { |
|||
return getBusinessTypeName(type) |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
|||
<style></style> |
|||
|
@ -1,80 +1,59 @@ |
|||
<template> |
|||
<view :class="detail.scaned?'scan_view':''" style="background-color: #ffffff;"> |
|||
<view class="space_between center" > |
|||
<view style="word-break: break-all;width: 60%;"> |
|||
<pack v-if="isShowPack" :packingCode="detail.packingNumber"></pack> |
|||
<batch v-if="isShowBatch" :batch="detail.batch"></batch> |
|||
<location v-if="isShowLocation" :locationCode="detail.fromLocationCode"></location> |
|||
</view> |
|||
<view style="word-break: break-all;"> |
|||
<recommend-qty v-if="detail.record==null || detail.record==undefined" :dataContent="detail" |
|||
:isShowStdPack="false"></recommend-qty> |
|||
|
|||
<compare-qty v-else :dataContent="detail" :recommendQty="detail.qty" :handleQty="detail.record.qty" |
|||
:isShowStdPack="false"> |
|||
</compare-qty> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view :class="detail.scaned ? 'scan_view' : ''" style="background-color: #ffffff"> |
|||
<view class="space_between center"> |
|||
<view style="word-break: break-all; width: 60%"> |
|||
<pack title="外包装" v-if="detail.parentPackingNumber" :packingCode="detail.parentPackingNumber"></pack> |
|||
<pack v-if="isShowPack" :packingCode="detail.packingNumber"></pack> |
|||
<batch v-if="isShowBatch" :batch="detail.batch"></batch> |
|||
<location v-if="isShowLocation" :locationCode="detail.fromLocationCode"></location> |
|||
</view> |
|||
<view style="word-break: break-all"> |
|||
<recommend-qty v-if="detail.record == null || detail.record == undefined" :dataContent="detail" :isShowStatus="isShowStatus" :isShowStdPack="true"></recommend-qty> |
|||
|
|||
<compare-qty v-else :dataContent="detail" :recommendQty="detail.qty" :handleQty="detail.record.qty" :isShowStatus="isShowStatus" :isShowStdPack="true"> </compare-qty> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import pack from '@/mycomponents/balance/pack.vue' |
|||
import location from '@/mycomponents/balance/location.vue' |
|||
import batch from '@/mycomponents/balance/batch.vue' |
|||
import recommendQty from '@/mycomponents/qty/recommendQty.vue' |
|||
import compareQty from '@/mycomponents/qty/compareQty.vue' |
|||
|
|||
export default { |
|||
components: { |
|||
pack, |
|||
location, |
|||
batch, |
|||
recommendQty, |
|||
compareQty |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
|
|||
} |
|||
}, |
|||
props: { |
|||
detail: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
|
|||
}, |
|||
watch: { |
|||
|
|||
}, |
|||
methods: { |
|||
|
|||
} |
|||
} |
|||
<script setup lang="ts"> |
|||
import pack from '@/mycomponents/balance/pack.vue' |
|||
import location from '@/mycomponents/balance/location.vue' |
|||
import batch from '@/mycomponents/balance/batch.vue' |
|||
import recommendQty from '@/mycomponents/qty/recommendQty.vue' |
|||
import compareQty from '@/mycomponents/qty/compareQty.vue' |
|||
|
|||
const props = defineProps({ |
|||
detail: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style> |
|||
.recommend { |
|||
position: absolute; |
|||
left: 25px; |
|||
top: 70px; |
|||
width: 10px; |
|||
height: 30px; |
|||
opacity: 1; |
|||
|
|||
} |
|||
.recommend { |
|||
position: absolute; |
|||
left: 25px; |
|||
top: 70px; |
|||
width: 10px; |
|||
height: 30px; |
|||
opacity: 1; |
|||
} |
|||
</style> |
|||
|
@ -0,0 +1,64 @@ |
|||
<template> |
|||
<view :class="detail.scaned?'scan_view':''" style="background-color: #ffffff;"> |
|||
<view class="space_between center"> |
|||
<view style="word-break: break-all;width: 60%;"> |
|||
<pack title='外包装' v-if="detail.parentPackingNumber" |
|||
:packingCode="detail.parentPackingNumber"></pack> |
|||
<pack v-if="isShowPack" :packingCode="detail.packingNumber"></pack> |
|||
<batch v-if="isShowBatch" :batch="detail.batch"></batch> |
|||
<location v-if="isShowLocation" :locationCode="detail.fromLocationCode"></location> |
|||
</view> |
|||
<view style="word-break: break-all;"> |
|||
<recommend-qty v-if="detail.record==null || detail.record==undefined" :dataContent="detail" |
|||
:isShowStatus='isShowStatus' :isShowStdPack="true" :isShowCount='false'></recommend-qty> |
|||
|
|||
<compare-qty v-else :dataContent="detail" :recommendQty="detail.qty" :handleQty="detail.record.qty" |
|||
:isShowStatus='isShowStatus' :isShowStdPack="true"> |
|||
</compare-qty> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import pack from '@/mycomponents/balance/pack.vue' |
|||
import location from '@/mycomponents/balance/location.vue' |
|||
import batch from '@/mycomponents/balance/batch.vue' |
|||
import recommendQty from '@/mycomponents/qty/recommendQty.vue' |
|||
import compareQty from '@/mycomponents/qty/compareQty.vue' |
|||
|
|||
const props = defineProps({ |
|||
detail: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
}) |
|||
</script> |
|||
|
|||
<style> |
|||
.recommend { |
|||
position: absolute; |
|||
left: 25px; |
|||
top: 70px; |
|||
width: 10px; |
|||
height: 30px; |
|||
opacity: 1; |
|||
|
|||
} |
|||
</style> |
@ -0,0 +1,27 @@ |
|||
<template> |
|||
<view class="card_view"> |
|||
<text class="card_level">{{ title }}</text> |
|||
<text class="card_big_content" style="font-size: 40rpx">{{ getPriorityName1() }}</text> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { getPriorityName } from '@/common/directory.js' |
|||
|
|||
const props = defineProps({ |
|||
priority: { |
|||
type: Number, |
|||
default: 2 |
|||
}, |
|||
title: { |
|||
type: String, |
|||
default: '优先级' |
|||
} |
|||
}) |
|||
|
|||
const getPriorityName1 = () => { |
|||
return getPriorityName(props.priority) |
|||
} |
|||
</script> |
|||
|
|||
<style></style> |
@ -0,0 +1,21 @@ |
|||
<template> |
|||
<view class="card_view"> |
|||
<text class="card_light">{{ title }}</text> |
|||
<text class="card_content">{{ lightCode }}</text> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
const props = defineProps({ |
|||
lightCode: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
title: { |
|||
type: String, |
|||
default: '灯码' |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style></style> |
@ -1,31 +1,23 @@ |
|||
<template> |
|||
<view class="card_view "> |
|||
<text class="card_location card_content ">{{title}}</text> |
|||
<text class="card_content ">{{locationCode}}</text> |
|||
</view> |
|||
<view class="card_view"> |
|||
<text class="card_location">{{ title }}</text> |
|||
<text class="card_big_content" style="font-size: 40rpx">{{ locationCode }}</text> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
components: { |
|||
}, |
|||
data() { |
|||
return {} |
|||
}, |
|||
props: { |
|||
locationCode: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
title: { |
|||
type: String, |
|||
default: '库位' |
|||
}, |
|||
|
|||
}, |
|||
|
|||
} |
|||
<script setup lang="ts"> |
|||
const props = defineProps({ |
|||
locationCode: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
title: { |
|||
type: String, |
|||
default: '库位' |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style> |
|||
<style scoped> |
|||
|
|||
</style> |
|||
|
@ -1,34 +1,33 @@ |
|||
<template> |
|||
<view class="card_view"> |
|||
<text class="card_packing_code card_content ">箱码</text> |
|||
<text class="card_content ">{{packingCode}}</text> |
|||
</view> |
|||
<view class="card_view" v-if="ShowPackingNumber"> |
|||
<text class="card_packing_code">{{ title }}</text> |
|||
<text class="card_content">{{ packingCode }}</text> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
components: { |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
|
|||
} |
|||
}, |
|||
props: { |
|||
packingCode: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
}, |
|||
watch: { |
|||
|
|||
}, |
|||
methods: { |
|||
|
|||
} |
|||
} |
|||
<script setup lang="ts"> |
|||
import {getSwitchInfoByCode} from '@/common/basic.js'; |
|||
import {onMounted} from "vue"; |
|||
import {ref} from "vue"; |
|||
const props = defineProps({ |
|||
packingCode: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
title: { |
|||
type: String, |
|||
default: '包装' |
|||
} |
|||
}) |
|||
const ShowPackingNumber = ref(true) |
|||
onMounted(()=>{ |
|||
ShowPackingNumber.value = getSwitchInfoByCode('ShowPackingNumber') |
|||
}) |
|||
</script> |
|||
|
|||
<style> |
|||
<style lang="scss" scoped> |
|||
.card_packing_code { |
|||
|
|||
padding: 0; |
|||
} |
|||
</style> |
|||
|
@ -1,59 +1,40 @@ |
|||
<template> |
|||
<view :class="dataContent.scaned?'scan_view':''"> |
|||
<balance :dataContent="dataContent" :isShowStdPack="false" :isShowPack="isShowPack" |
|||
:isShowFromLocation="isShowLocation"></balance> |
|||
<production-info :dataContent="packageContent"></production-info> |
|||
</view> |
|||
<view :class="dataContent.scaned ? 'scan_view' : ''"> |
|||
<balance :dataContent="dataContent" :isShowStdPack="false" :isShowPack="isShowPack" :isShowFromLocation="isShowLocation"></balance> |
|||
<production-info :dataContent="packageContent"></production-info> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import balance from '@/mycomponents/balance/balance.vue' |
|||
import productionInfo from '@/mycomponents/production/productionInfo.vue' |
|||
|
|||
export default { |
|||
components: { |
|||
balance, |
|||
productionInfo |
|||
}, |
|||
data() { |
|||
return { |
|||
<script setup lang="ts"> |
|||
import balance from '@/mycomponents/balance/balance.vue' |
|||
import productionInfo from '@/mycomponents/production/productionInfo.vue' |
|||
|
|||
} |
|||
}, |
|||
props: { |
|||
dataContent: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
packageContent: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStdPack: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}, |
|||
watch: { |
|||
|
|||
}, |
|||
methods: { |
|||
|
|||
} |
|||
} |
|||
const props = defineProps({ |
|||
dataContent: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
packageContent: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStdPack: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
|||
<style></style> |
|||
|
@ -1,84 +1,56 @@ |
|||
<template> |
|||
<view :class="detail.scaned?'scan_view':''" style="background-color: #fff;"> |
|||
<view class="uni-flex uni-row space-between center "> |
|||
<view class="uni-flex uni-row " style="width: 60%;margin-left: 30rpx;" > |
|||
<view style=" width: 25rpx;color: #32C1E8;"> |
|||
推荐 |
|||
</view> |
|||
<view style="word-break: break-all"> |
|||
<pack v-if="isShowPack" :packingCode="detail.packingNumber"></pack> |
|||
<batch v-if="isShowBatch" :batch="detail.batch"></batch> |
|||
<location v-if="isShowLocation" :locationCode="detail.fromLocationCode"></location> |
|||
</view> |
|||
</view> |
|||
<view style="word-break: break-all"> |
|||
<recommend-qty v-if="detail.Records==null || detail.Records.length==0" :dataContent="detail" |
|||
:isShowStdPack="false" :isShowStatus="false"></recommend-qty> |
|||
<compare-qty v-else :dataContent="detail" :recommendQty="Number( detail.qty)" |
|||
:handleQty="Number(detail.handleQty)" :isShowStdPack="false" :isShowStatus="false"> |
|||
</compare-qty> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view :class="detail.scaned ? 'scan_view' : ''" style="background-color: #fff"> |
|||
<view class="uni-flex uni-row space-between center"> |
|||
<view class="uni-flex uni-row" style="width: 60%"> |
|||
<view style="width: 20rpx; color: #1677ff; margin-right: 20rpx; font-size: 24rpx"> 推荐 </view> |
|||
<view style="word-break: break-all"> |
|||
<pack v-if="isShowPack" :packingCode="detail.packingNumber"></pack> |
|||
<batch v-if="isShowBatch" :batch="detail.batch"></batch> |
|||
<location v-if="isShowLocation" :locationCode="detail.fromLocationCode"></location> |
|||
</view> |
|||
</view> |
|||
<view style="word-break: break-all"> |
|||
<recommend-qty v-if="detail.Records == null || detail.Records.length == 0" :dataContent="detail" :isShowStdPack="false" :isShowStatus="false"></recommend-qty> |
|||
<compare-qty v-else :dataContent="detail" :recommendQty="Number(detail.qty)" :handleQty="Number(detail.handleQty)" :isShowStdPack="false" :isShowStatus="false"> </compare-qty> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import pack from '@/mycomponents/balance/pack.vue' |
|||
import location from '@/mycomponents/balance/location.vue' |
|||
import batch from '@/mycomponents/balance/batch.vue' |
|||
import recommendQty from '@/mycomponents/qty/recommendQty.vue' |
|||
import compareQty from '@/mycomponents/qty/compareQty.vue' |
|||
|
|||
export default { |
|||
components: { |
|||
pack, |
|||
location, |
|||
batch, |
|||
recommendQty, |
|||
compareQty |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
|
|||
} |
|||
}, |
|||
props: { |
|||
detail: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
|
|||
}, |
|||
watch: { |
|||
|
|||
}, |
|||
methods: { |
|||
|
|||
} |
|||
} |
|||
<script setup lang="ts"> |
|||
import pack from '@/mycomponents/balance/pack.vue' |
|||
import location from '@/mycomponents/balance/location.vue' |
|||
import batch from '@/mycomponents/balance/batch.vue' |
|||
import recommendQty from '@/mycomponents/qty/recommendQty.vue' |
|||
import compareQty from '@/mycomponents/qty/compareQty.vue' |
|||
|
|||
const props = defineProps({ |
|||
detail: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style> |
|||
.recommend { |
|||
position: absolute; |
|||
left: 25px; |
|||
top: 70px; |
|||
width: 10px; |
|||
height: 30px; |
|||
opacity: 1; |
|||
|
|||
} |
|||
.recommend { |
|||
position: absolute; |
|||
left: 25px; |
|||
top: 70px; |
|||
width: 10px; |
|||
height: 30px; |
|||
opacity: 1; |
|||
} |
|||
</style> |
|||
|
@ -0,0 +1,55 @@ |
|||
<template> |
|||
<view> |
|||
<view class="uni-flex uni-row space-between center "> |
|||
<view class="uni-flex uni-row " style="width: 60%;" > |
|||
<view style=" width: 25rpx;color: #32C1E8;"> |
|||
推荐 |
|||
</view> |
|||
<view style="word-break: break-all"> |
|||
<pack v-if="isShowPack&&detail.packingNumber" :packingCode="detail.packingNumber"></pack> |
|||
<batch v-if="isShowBatch&&detail.batch" :batch="detail.batch"></batch> |
|||
<location v-if="isShowLocation" :locationCode="detail.fromLocationCode"></location> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import pack from '@/mycomponents/balance/pack.vue' |
|||
import location from '@/mycomponents/balance/location.vue' |
|||
import batch from '@/mycomponents/balance/batch.vue' |
|||
import recommendQty from '@/mycomponents/qty/recommendQty.vue' |
|||
import compareQty from '@/mycomponents/qty/compareQty.vue' |
|||
const props = defineProps({ |
|||
detail: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
|
|||
}) |
|||
</script> |
|||
|
|||
<style> |
|||
.recommend { |
|||
position: absolute; |
|||
left: 25px; |
|||
top: 70px; |
|||
width: 10px; |
|||
height: 30px; |
|||
opacity: 1; |
|||
|
|||
} |
|||
</style> |
@ -1,31 +1,19 @@ |
|||
<template> |
|||
<view class="card_view "> |
|||
<text class="card_to_location card_content ">{{title}}</text> |
|||
<text class="card_content ">{{locationCode}}</text> |
|||
</view> |
|||
<view class="card_view"> |
|||
<text class="card_to_location">{{ title }}</text> |
|||
<text class="card_big_content">{{ locationCode }}</text> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
components: { |
|||
}, |
|||
data() { |
|||
return {} |
|||
}, |
|||
props: { |
|||
locationCode: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
title: { |
|||
type: String, |
|||
default: '库位' |
|||
}, |
|||
|
|||
}, |
|||
|
|||
} |
|||
<script setup lang="ts"> |
|||
const props = defineProps({ |
|||
locationCode: { |
|||
type: String |
|||
}, |
|||
title: { |
|||
type: String, |
|||
default: '库位' |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
|||
<style></style> |
|||
|
@ -0,0 +1,40 @@ |
|||
<template> |
|||
<view class="flex uni-row"> |
|||
<view class="" > |
|||
<u-checkbox size="50" v-model="checkAll" @change="checkAllItems" > |
|||
</u-checkbox> |
|||
</view> |
|||
<view> |
|||
<text style="margin-left: 10rpx; font-size: 35rpx;font-weight: bold;">全选({{checkCount}}/{{allCount}})</text> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import {nextTick, ref} from 'vue' |
|||
const props = defineProps({ |
|||
checkCount: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
allCount: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
}) |
|||
const emit = defineEmits(['checkAllItems']) |
|||
const checkAll = ref(false) |
|||
|
|||
const checkAllItems = ()=>{ |
|||
checkAll.value = !checkAll.value |
|||
emit('checkAllItems', checkAll.value) |
|||
} |
|||
const changeCheckAllState = ()=>{ |
|||
nextTick(()=>{ |
|||
checkAll.value = props.checkCount == props.allCount |
|||
}) |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
@ -1,31 +1,25 @@ |
|||
<template> |
|||
<view class="default_goscan"> |
|||
<image class="img_goscan" src="@/static/icons_ui/default_blank.png"></image> |
|||
<button @click="goScan"> |
|||
<image src="@/static/icons_ui/icon_add.svg"></image> |
|||
去扫描 |
|||
</button> |
|||
</view> |
|||
<view class="default_goscan"> |
|||
<image class="img_goscan" src="@/static/icons_ui/default_blank.png"></image> |
|||
<button @click="goScan"> |
|||
<image src="@/static/icons_ui/icon_add.svg"></image> |
|||
{{ title }} |
|||
</button> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
|
|||
} |
|||
}, |
|||
created() { |
|||
|
|||
}, |
|||
methods: { |
|||
goScan(content) { |
|||
this.$emit("goScan", ''); |
|||
} |
|||
} |
|||
} |
|||
<script setup lang="ts"> |
|||
const props = defineProps({ |
|||
title: { |
|||
type: String, |
|||
default: '去扫描' |
|||
} |
|||
}) |
|||
const goScan = (content) => { |
|||
emit('goScan', '') |
|||
} |
|||
// 传递给父类 |
|||
const emit = defineEmits(['goScan']) |
|||
</script> |
|||
|
|||
|
|||
<style> |
|||
</style> |
|||
<style></style> |
|||
|
File diff suppressed because it is too large
@ -1,68 +1,57 @@ |
|||
<template> |
|||
<view class="uni-flex u-col-center" style="padding-top: 15rpx; |
|||
padding-bottom: 15rpx; |
|||
padding-left: 10rpx; |
|||
padding-right: 10rpx; |
|||
font-size:32rpx;"> |
|||
<text style="font-size: 35rpx;">{{title}} </text> |
|||
<view class="uni-flex u-col-center" @click="showLocation"> |
|||
<text style="color:#3FBAFF;font-size: 35rpx;" v-if="containerCode==''&&isShowEdit==true">  请扫描</text> |
|||
<text style="color:#3FBAFF; font-size: 35rpx;">  {{containerCode}}</text> |
|||
<image v-if="isShowEdit" style="width: 45rpx;height: 45rpx;" src="/static/icons/icons_edit.svg"></image> |
|||
</view> |
|||
<winScanContainer ref="scanContainer" :title="title" @getContainer='getContainer'></winScanContainer> |
|||
</view> |
|||
<view class="uni-flex u-col-center" style="padding-top: 15rpx; padding-bottom: 15rpx; padding-left: 10rpx; padding-right: 10rpx; font-size: 32rpx"> |
|||
<text style="font-size: 35rpx">{{ title }} </text> |
|||
<view class="uni-flex u-col-center" @click="showLocation"> |
|||
<text style="color: #3fbaff; font-size: 35rpx" v-if="containerCode == '' && isShowEdit == true">  请扫描</text> |
|||
<text style="color: #3fbaff; font-size: 35rpx">  {{ containerCode }}</text> |
|||
<image v-if="isShowEdit" style="width: 45rpx; height: 45rpx" src="/static/icons/icons_edit.svg"></image> |
|||
</view> |
|||
<winScanContainer ref="scanContainer" :title="title" @getContainer="getContainer"></winScanContainer> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import winScanContainer from "@/mycomponents/scan/winScanContainer.vue" |
|||
<script setup lang="ts"> |
|||
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue' |
|||
import winScanContainer from '@/mycomponents/scan/winScanContainer.vue' |
|||
|
|||
export default { |
|||
components: { |
|||
winScanContainer |
|||
}, |
|||
data() { |
|||
return { |
|||
defaultContainerCode: "" |
|||
} |
|||
}, |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
default: "需求库位" |
|||
}, |
|||
containerCode: { |
|||
type: String, |
|||
default: "" |
|||
}, |
|||
isShowEdit: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
}, |
|||
const defaultContainerCode = ref('') |
|||
const props = defineProps({ |
|||
title: { |
|||
type: String, |
|||
default: '需求库位' |
|||
}, |
|||
containerCode: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
isShowEdit: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}) |
|||
watch( |
|||
() => props.containerCode, |
|||
(val) => { |
|||
if (val != '') { |
|||
defaultContainerCode.value = val |
|||
} |
|||
}, |
|||
{ |
|||
immediate: true, |
|||
deep: true |
|||
} |
|||
) |
|||
|
|||
watch: { |
|||
containerCode: { |
|||
handler(newName, oldName) { |
|||
if (this.containerCode != "") { |
|||
this.defaultContainerCode = this.containerCode; |
|||
} |
|||
}, |
|||
immediate: true, |
|||
deep: true |
|||
} |
|||
}, |
|||
methods: { |
|||
showLocation() { |
|||
this.$refs.scanContainer.openScanPopup(); |
|||
}, |
|||
//扫描源库位 |
|||
getContainer(containerInfo) { |
|||
this.$emit("getContainer", containerInfo) |
|||
} |
|||
} |
|||
} |
|||
const showLocation = () => { |
|||
scanContainer.value.openScanPopup() |
|||
} |
|||
// 扫描源库位 |
|||
const getContainer = (containerInfo) => { |
|||
emit('getContainer', containerInfo) |
|||
} |
|||
|
|||
// 传递给父类 |
|||
const emit = defineEmits(['getContainer']) |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
|||
<style></style> |
|||
|
@ -1,162 +1,165 @@ |
|||
<template> |
|||
<view class="" style="background-color: #fff;"> |
|||
<uni-collapse ref="collapse1" @change=""> |
|||
<uni-collapse-item :open="true"> |
|||
<template v-slot:title> |
|||
<item-compare-qty :dataContent="dataContent" :handleQty="dataContent.handleQty" :isShowStdPack="false"> |
|||
</item-compare-qty> |
|||
</template> |
|||
<u-line></u-line> |
|||
<view class="" v-for="(item,index) in dataContent.subList"> |
|||
<uni-swipe-action ref="swipeAction"> |
|||
<uni-swipe-action-item @click="swipeClick($event,item)" |
|||
:right-options="item.scaned?scanOptions:detailOptions" |
|||
style='padding:0px 0px 5px 0px;align-items: center;'> |
|||
<recommend :detail="item" :isShowToLocation="false"> |
|||
</recommend> |
|||
</uni-swipe-action-item> |
|||
</uni-swipe-action> |
|||
</view> |
|||
</uni-collapse-item> |
|||
</uni-collapse> |
|||
<balance-qty-edit ref="qtyEdit" :settingParam="settingParam" @confirm="confirm"></balance-qty-edit> |
|||
<win-scan-location ref="scanLocationCode" title="目标库位" @getLocation='getLocation' |
|||
:locationTypeList="locationTypeList"></win-scan-location> |
|||
<comMessage ref="message"></comMessage> |
|||
</view> |
|||
<view class="" style="background-color: #fff"> |
|||
<u-collapse ref="collapse"> |
|||
<u-collapse-item :open="true"> |
|||
<template v-slot:title> |
|||
<item-compare-qty :dataContent="dataContent" :handleQty="dataContent.handleQty" :isShowStdPack="false" style="width: 100%"> </item-compare-qty> |
|||
</template> |
|||
<u-swipe-action :show="item.show" :index="index" v-for="(item, index) in dataContent.subList" :key="index" :options="item.scaned ? scanOptions : detailOptions" bg-color="rgba(255,255,255,0)" @click="(...event) => swipeClick(event, item)"> |
|||
<recommend :detail="item" :isShowFromLocation="isShowFromLocation" :isShowStatus="isShowStatus" :isShowToLocation="isShowToLocation"></recommend> |
|||
</u-swipe-action> |
|||
</u-collapse-item> |
|||
</u-collapse> |
|||
<balance-qty-edit ref="qtyEdit" :settingParam="settingParam" :queryBalance="queryBalance" @confirm="confirm"></balance-qty-edit> |
|||
<win-scan-location ref="scanLocationCode" title="目标库位" @getLocation="getLocation" :locationAreaTypeList="locationAreaTypeList"></win-scan-location> |
|||
<com-message ref="comMessageRef" /> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue' |
|||
import recommend from '@/mycomponents/recommend/recommend.vue' |
|||
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue' |
|||
import winScanLocation from "@/mycomponents/scan/winScanLocation.vue" |
|||
import { |
|||
getDetailOption, |
|||
getPurchaseReceiptOption |
|||
} from '@/common/array.js'; |
|||
<script setup lang="ts"> |
|||
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue' |
|||
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue' |
|||
import recommend from '@/mycomponents/recommend/recommend.vue' |
|||
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue' |
|||
import winScanLocation from '@/mycomponents/scan/winScanLocation.vue' |
|||
import { getDetailOption, getPurchaseReceiptOption } from '@/common/array.js' |
|||
|
|||
export default { |
|||
emits: ['openDetail', "updateData"], |
|||
components: { |
|||
itemCompareQty, |
|||
recommend, |
|||
balanceQtyEdit, |
|||
winScanLocation |
|||
}, |
|||
props: { |
|||
dataContent: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
settingParam: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
locationTypeList: { |
|||
type: Array, |
|||
default: [] |
|||
}, |
|||
}, |
|||
watch: { |
|||
dataContent: { |
|||
handler(newName, oldName) { |
|||
if (this.dataContent.subList.length > 0) { |
|||
if (this.$refs.collapse1 != undefined && this.$refs.collapse1 != null) { |
|||
this.$nextTick(res => { |
|||
this.$refs.collapse1.resize() |
|||
}) |
|||
} |
|||
} |
|||
}, |
|||
immediate: true, |
|||
deep: true |
|||
} |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
option: [], |
|||
showItem: {}, |
|||
locatonItem: {}, |
|||
editItem: {}, |
|||
detailOptions: [], |
|||
scanOptions: [] |
|||
} |
|||
}, |
|||
|
|||
mounted() { |
|||
if (this.detailOptions.length == 0) { |
|||
this.detailOptions = getDetailOption(); |
|||
} |
|||
if (this.scanOptions.length == 0) { |
|||
this.scanOptions = getPurchaseReceiptOption(this.settingParam.allowModifyQty, this.settingParam |
|||
.allowModifyLocation) |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
swipeClick(e, item) { |
|||
if (e.content.text == "详情") { |
|||
this.detail(item) |
|||
} else if (e.content.text == "编辑") { |
|||
this.edit(item) |
|||
} else if (e.content.text == "库位") { |
|||
this.showLocation(item) |
|||
} else if (e.content.text == "移除") { |
|||
this.remove(item) |
|||
} |
|||
}, |
|||
edit(item) { |
|||
this.editItem = item; |
|||
this.$refs.qtyEdit.openEditPopup(item.balance, item.handleQty); |
|||
}, |
|||
|
|||
detail(item) { |
|||
this.$emit('openDetail', item); |
|||
// this.showItem = item; |
|||
// this.$refs.jobDetailPopup.openPopup(item) |
|||
}, |
|||
remove(item) { |
|||
this.$refs.message.showQuestionMessage("确定移除扫描信息?", |
|||
res => { |
|||
if (res) { |
|||
item.scaned = false |
|||
item.balance = {} |
|||
item.handleQty = null; |
|||
this.$forceUpdate() |
|||
this.$emit('remove', item) |
|||
} |
|||
}); |
|||
}, |
|||
confirm(qty) { |
|||
this.editItem.handleQty = qty; |
|||
this.$emit('updateData') |
|||
}, |
|||
showLocation(item) { |
|||
this.locatonItem = item; |
|||
this.$refs.scanLocationCode.openScanPopup(); |
|||
}, |
|||
//扫描源库位 |
|||
getLocation(location, code) { |
|||
this.locatonItem.toLocationCode = code; |
|||
this.$emit('updateData') |
|||
}, |
|||
} |
|||
} |
|||
const props = defineProps({ |
|||
dataContent: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
settingParam: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowFromLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowToLocation: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
locationAreaTypeList: { |
|||
type: Array, |
|||
default: null |
|||
}, |
|||
queryBalance: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}) |
|||
const option = ref([]) |
|||
const showItem = ref({}) |
|||
const editItem = ref({}) |
|||
const locatonItem = ref({}) |
|||
const detailOptions = ref([]) |
|||
const scanOptions = ref([]) |
|||
const comMessageRef = ref() |
|||
const collapse = ref() |
|||
const qtyEdit = ref() |
|||
const scanLocationCode = ref() |
|||
const dataContent = ref(props.dataContent) |
|||
dataContent.value.subList.forEach((item) => { |
|||
item.show = false |
|||
}) |
|||
// 监视属性 |
|||
watch( |
|||
() => props.dataContent, |
|||
(val) => { |
|||
if (val.subList.length > 0) { |
|||
if (collapse.value != undefined && collapse.value != null) { |
|||
nextTick((res) => { |
|||
setTimeout(()=>{ |
|||
collapse.value.init() |
|||
},500) |
|||
}) |
|||
} |
|||
} |
|||
}, |
|||
{ |
|||
immediate: true, |
|||
deep: true |
|||
} |
|||
) |
|||
onMounted(() => { |
|||
if (detailOptions.value.length == 0) { |
|||
detailOptions.value = getDetailOption() |
|||
} |
|||
if (scanOptions.value.length == 0) { |
|||
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, false) |
|||
} |
|||
nextTick((res) => { |
|||
collapse.value.init() |
|||
}) |
|||
showLocation() |
|||
}) |
|||
const swipeClick = (params, item) => { |
|||
let text = '' |
|||
if (item.scaned) { |
|||
text = scanOptions.value[params[1]].text |
|||
} else { |
|||
text = detailOptions.value[params[1]].text |
|||
} |
|||
if (text == '详情') { |
|||
detail(item) |
|||
} else if (text == '编辑') { |
|||
edit(item) |
|||
} else if (text == '库位') { |
|||
showLocation(item) |
|||
} else if (text == '移除') { |
|||
remove(item) |
|||
} |
|||
} |
|||
const edit = (item) => { |
|||
editItem.value = item |
|||
qtyEdit.value.openEditPopup(item, item.handleQty) |
|||
} |
|||
const detail = (item) => { |
|||
emit('openDetail', item) |
|||
} |
|||
const remove = (item) => { |
|||
comMessageRef.value.showQuestionMessage('确定移除扫描信息?', (res) => { |
|||
if (res) { |
|||
item.scaned = false |
|||
item.balance = {} |
|||
item.handleQty = null |
|||
emit('remove', item) |
|||
} |
|||
}) |
|||
} |
|||
const confirm = (qty) => { |
|||
editItem.value.handleQty = qty |
|||
emit('updateData') |
|||
} |
|||
const showLocation = (item) => { |
|||
locatonItem.value = item |
|||
scanLocationCode.value.openScanPopup() |
|||
} |
|||
// 扫描源库位 |
|||
const getLocation = () => { |
|||
locatonItem.value.LocationCode = code |
|||
emit('updateData') |
|||
} |
|||
// 传递给父类 |
|||
const emit = defineEmits(['openDetail', 'remove', 'updateData']) |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
|||
<style></style> |
|||
|
@ -0,0 +1,173 @@ |
|||
<template> |
|||
<view style="background-color: #fff;"> |
|||
<u-collapse ref="collapse1Ref" @change=""> |
|||
<u-collapse-item :open="true"> |
|||
<template #title> |
|||
<item-compare-qty :dataContent="dataContent" |
|||
:handleQty="dataContent.handleQty" :isShowStdPack="false"> |
|||
</item-compare-qty> |
|||
</template> |
|||
<view class="" v-for="(item,index) in dataContent.subList" :key="index"> |
|||
<u-swipe-action ref="swipeAction" |
|||
:options="item.scaned?scanOptions:detailOptions" |
|||
@click="(...event)=>swipeClick(event,item,'parent')" |
|||
v-if='index==0'> |
|||
<recommend :detail="item" :isShowFromLocation="isShowFromLocation" |
|||
:isShowStatus="isShowStatus" :isShowToLocation="isShowToLocation"> |
|||
</recommend> |
|||
</u-swipe-action> |
|||
</view> |
|||
</u-collapse-item> |
|||
</u-collapse> |
|||
|
|||
|
|||
<balance-qty-edit ref="qtyEdit" :settingParam="settingParam" :queryBalance="queryBalance" |
|||
@confirm="confirm"></balance-qty-edit> |
|||
<win-scan-location ref="scanLocationCode" title="目标库位" @getLocation='getLocation' |
|||
:locationAreaTypeList="locationAreaTypeList"></win-scan-location> |
|||
<comMessage ref="message"></comMessage> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import config from '@/static/config.js' |
|||
import ItemCompareQty from '@/mycomponents/item/itemCompareQty.vue' |
|||
import Recommend from '@/mycomponents/recommend/recommend.vue' |
|||
import BalanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue' |
|||
import WinScanLocation from "@/mycomponents/scan/winScanLocation.vue" |
|||
|
|||
import { |
|||
getDetailOption, |
|||
getPurchaseReceiptOption, |
|||
} from '@/common/array.js'; |
|||
|
|||
|
|||
import { ref, watch, onMounted, nextTick } from 'vue'; |
|||
|
|||
const props = defineProps({ |
|||
dataContent: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
settingParam: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowFromLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowToLocation: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
locationAreaTypeList: { |
|||
type: Array, |
|||
default: null |
|||
}, |
|||
queryBalance: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['openDetail', 'remove', 'updateData']); |
|||
|
|||
const showItem = ref({}); |
|||
const locatonItem = ref({}); |
|||
const editItem = ref({}); |
|||
const detailOptions = ref([]); |
|||
const scanOptions = ref([]); |
|||
const options = ref([]); |
|||
|
|||
const collapse1Ref = ref(null); |
|||
const qtyEditRef = ref(null); |
|||
const messageRef = ref(null); |
|||
const scanLocationCodeRef = ref(null); |
|||
|
|||
watch(() => props.dataContent, (newDataContent, oldDataContent) => { |
|||
if (newDataContent?.subList?.length > 0) { |
|||
nextTick(() => { |
|||
setTimeout(() => { |
|||
if (collapse1Ref.value) { |
|||
collapse1Ref.value.resize(); |
|||
} |
|||
}, 500); |
|||
}); |
|||
} |
|||
}, { immediate: true, deep: true }); |
|||
|
|||
onMounted(() => { |
|||
if (detailOptions.value.length === 0) { |
|||
detailOptions.value = getDetailOption(); |
|||
} |
|||
if (scanOptions.value.length === 0) { |
|||
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, false); |
|||
} |
|||
}); |
|||
|
|||
const swipeClick = (e, item) => { |
|||
if (e.content.text === "详情") { |
|||
detail(item); |
|||
} else if (e.content.text === "编辑") { |
|||
edit(item); |
|||
} else if (e.content.text === "库位") { |
|||
showLocation(item); |
|||
} else if (e.content.text === "移除") { |
|||
remove(item); |
|||
} |
|||
}; |
|||
|
|||
const edit = (item) => { |
|||
editItem.value = item; |
|||
qtyEditRef.value.openEditPopup(item.balance, item.handleQty); |
|||
}; |
|||
|
|||
const detail = (item) => { |
|||
emit('openDetail', item); |
|||
}; |
|||
|
|||
const remove = (item) => { |
|||
messageRef.value.showQuestionMessage("确定移除扫描信息?", (res) => { |
|||
if (res) { |
|||
item.scaned = false; |
|||
item.balance = {}; |
|||
item.handleQty = null; |
|||
emit('remove', item); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
const confirm = (qty) => { |
|||
editItem.value.handleQty = qty; |
|||
emit('updateData'); |
|||
}; |
|||
|
|||
const showLocation = (item) => { |
|||
locatonItem.value = item; |
|||
scanLocationCodeRef.value.openScanPopup(); |
|||
}; |
|||
|
|||
const getLocation = (location, code) => { |
|||
locatonItem.value.toLocationCode = code; |
|||
emit('updateData'); |
|||
}; |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
@ -0,0 +1,138 @@ |
|||
<template> |
|||
<view class="" style="background-color: #fff"> |
|||
<u-collapse ref="collapse"> |
|||
<u-collapse-item :open="true"> |
|||
<template v-slot:title> |
|||
<itemCompareQty :dataContent="dataContent" :handleQty="dataContent.handleQty" :isShowPackUnit="true" style="flex: 1"></itemCompareQty> |
|||
</template> |
|||
<package-list :dataContent="dataContent.subList" |
|||
:isEdit="settingParam.allowModifyQty == 'TRUE'" |
|||
:settingParam="settingParam" |
|||
@collapseChange="collapseChange" @updateData="updateData" |
|||
:isShowStatus="isShowStatus" :isShowPackListStatus="isShowPackListStatus"> |
|||
</package-list> |
|||
</u-collapse-item> |
|||
</u-collapse> |
|||
<recommend-qty-edit ref="receiptEdit" :dataContent="editItem" :settingParam="settingParam" @confirm="confirm"> </recommend-qty-edit> |
|||
<com-message ref="comMessageRef" /> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue' |
|||
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue' |
|||
import recommend from '@/mycomponents/recommend/recommend.vue' |
|||
import recommendQtyEdit from '@/mycomponents/qty/recommendQtyEdit.vue' |
|||
import packageList from '@/mycomponents/package/packageList.vue' |
|||
|
|||
import { getDetailOption, getPurchaseReceiptOption } from '@/common/array.js' |
|||
|
|||
const props = defineProps({ |
|||
dataContent: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
settingParam: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
locationAreaTypeList: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
isShowStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowPackListStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}) |
|||
const showItem = ref({}) |
|||
const editItem = ref({ |
|||
record: {} |
|||
}) |
|||
const locatonItem = ref({}) |
|||
const detailOptions = ref([]) |
|||
const scanOptions = ref([]) |
|||
const comMessageRef = ref() |
|||
const collapse = ref() |
|||
const receiptEdit = ref() |
|||
// 监视属性 |
|||
watch( |
|||
() => props.dataContent, |
|||
(val) => { |
|||
if (val.subList.length > 0) { |
|||
if (collapse.value != undefined && collapse.value != null) { |
|||
nextTick((res) => { |
|||
collapse.value.init() |
|||
}) |
|||
} |
|||
} |
|||
}, |
|||
{ |
|||
deep: true |
|||
} |
|||
) |
|||
onMounted(() => { |
|||
if (detailOptions.value.length == 0) { |
|||
detailOptions.value = getDetailOption() |
|||
} |
|||
if (scanOptions.value.length == 0) { |
|||
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, props.settingParam.allowModifyLocation) |
|||
} |
|||
}) |
|||
|
|||
const collapseChange = () => { |
|||
setTimeout(() => { |
|||
resizeCollapse() |
|||
}, 500) |
|||
} |
|||
const resizeCollapse = (object) => { |
|||
nextTick(() => { |
|||
collapse.value.init() |
|||
}) |
|||
} |
|||
const refreshCollapse = () => { |
|||
nextTick((r) => { |
|||
collapse.value.forEach((r) => { |
|||
r.childrens.forEach((i) => { |
|||
i.init() |
|||
}) |
|||
r.init() |
|||
}) |
|||
}) |
|||
} |
|||
const swipeClick = (e, item) => { |
|||
if (e.content.text == '编辑') { |
|||
edit(item) |
|||
} else if (e.content.text == '移除') { |
|||
remove(item) |
|||
} |
|||
} |
|||
const edit = (item) => { |
|||
editItem = item |
|||
receiptEdit.value.openTaskEditPopup(item.qty, item.handleQty, item.labelQty) |
|||
} |
|||
const remove = (item) => { |
|||
comMessageRef.value.showQuestionMessage('确定移除扫描信息?', (res) => { |
|||
if (res) { |
|||
item.scaned = false |
|||
item.handleQty = null |
|||
emit('remove', item) |
|||
} |
|||
}) |
|||
} |
|||
const confirm = (qty) => { |
|||
editItem.value.handleQty = qty |
|||
emit('updateData') |
|||
} |
|||
const updateData = () => { |
|||
emit('updateData') |
|||
} |
|||
// 传递给父类 |
|||
const emit = defineEmits(['remove', 'updateData']) |
|||
</script> |
|||
|
|||
<style></style> |
@ -0,0 +1,151 @@ |
|||
<!-- 采购上架任务详情按批次显示详情的组件 --> |
|||
<template> |
|||
<view class="" style="background-color: #fff;"> |
|||
<u-collapse ref="collapseRef"> |
|||
<u-collapse-item :open="true"> |
|||
<template #title> |
|||
<itemCompareQty :dataContent="dataContent" :handleQty="dataContent.handleQty" |
|||
:isShowPackUnit="true"></itemCompareQty> |
|||
</template> |
|||
<package-list :dataContent="dataContent.subList" |
|||
:isEdit="settingParam.allowModifyQty=='TRUE'" |
|||
:settingParam="settingParam" |
|||
@collapseChange="collapseChange" |
|||
@updateData="updateData" |
|||
:isShowStatus="isShowStatus" |
|||
:isShowPackListStatus="isShowPackListStatus" |
|||
></package-list> |
|||
</u-collapse-item> |
|||
</u-collapse> |
|||
<recommend-qty-edit ref="receiptEditRef" :dataContent="editItem" :settingParam="settingParam" @confirm="confirm"> |
|||
</recommend-qty-edit> |
|||
<comMessage ref="messageRef"></comMessage> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue' |
|||
import recommend from '@/mycomponents/recommend/recommend.vue' |
|||
import recommendQtyEdit from '@/mycomponents/qty/recommendQtyEdit.vue' |
|||
import jobDetailPopup from '@/mycomponents/detail/jobDetailPopup.vue' |
|||
import receiptDetailInfoPopup from '@/pages/purchaseReceipt/coms/receiptDetailInfoPopup.vue' |
|||
import pack from '@/mycomponents/balance/pack.vue' |
|||
import detailList from '@/mycomponents/detail/detailList.vue' |
|||
import packageList from '@/mycomponents/package/packageList.vue' |
|||
|
|||
import { |
|||
getDetailOption, |
|||
getPurchaseReceiptOption |
|||
} from '@/common/array.js'; |
|||
|
|||
import { ref, onMounted, nextTick } from 'vue'; |
|||
|
|||
const props = defineProps({ |
|||
dataContent: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
settingParam: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
locationAreaTypeList: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
isShowStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowPackListStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
}); |
|||
|
|||
const showItem = ref({}); |
|||
const editItem = ref({ record: {} }); |
|||
const locatonItem = ref({}); |
|||
const detailOptions = ref([]); |
|||
const scanOptions = ref([]); |
|||
const options = ref([]); |
|||
|
|||
const collapseRef = ref(null); |
|||
const receiptEditRef = ref(null); |
|||
const messageRef = ref(null); |
|||
|
|||
|
|||
onMounted(() => { |
|||
if (detailOptions.value.length === 0) { |
|||
detailOptions.value = getDetailOption(); |
|||
} |
|||
if (scanOptions.value.length === 0) { |
|||
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, props.settingParam.allowModifyLocation); |
|||
} |
|||
}); |
|||
|
|||
|
|||
const collapseChange = () => { |
|||
setTimeout(() => { |
|||
resizeCollapse(); |
|||
}, 500); |
|||
}; |
|||
|
|||
const resizeCollapse = () => { |
|||
nextTick(() => { |
|||
if (collapseRef.value) { |
|||
collapseRef.value.init(); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
const refreshCollapse = () => { |
|||
nextTick(() => { |
|||
if (collapseRef.value) { |
|||
collapseRef.value.forEach(r => { |
|||
r.childrens.forEach(i => { |
|||
i.init(); |
|||
}); |
|||
r.init(); |
|||
}); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
const swipeClick = (e, item) => { |
|||
if (e.content.text === "编辑") { |
|||
edit(item); |
|||
} else if (e.content.text === "移除") { |
|||
remove(item); |
|||
} |
|||
}; |
|||
|
|||
const edit = (item) => { |
|||
editItem.value = item; |
|||
receiptEditRef.value.openTaskEditPopup(item.qty, item.handleQty, item.labelQty); |
|||
}; |
|||
|
|||
const remove = (item) => { |
|||
messageRef.value.showQuestionMessage("确定移除扫描信息?", (res) => { |
|||
if (res) { |
|||
item.scaned = false; |
|||
item.handleQty = null; |
|||
emit('remove', item); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
const confirm = (qty) => { |
|||
editItem.value.handleQty = qty; |
|||
emit('updateData'); |
|||
}; |
|||
|
|||
const updateData = () => { |
|||
emit('updateData'); |
|||
}; |
|||
|
|||
const emit = defineEmits(['remove', 'updateData']); |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
@ -0,0 +1,178 @@ |
|||
<template> |
|||
<view class="" style="background-color: #fff;"> |
|||
<u-collapse ref="collapse1" @change=""> |
|||
<u-collapse-item :open="true"> |
|||
<template v-slot:title> |
|||
<item-compare-qty :dataContent="dataContent" :handleQty="dataContent.handleQty" |
|||
:isShowStdPack="false"> |
|||
</item-compare-qty> |
|||
</template> |
|||
|
|||
<view class="" v-for="(item,index) in dataContent.subList" :key="index"> |
|||
<u-swipe-action ref="swipeAction" |
|||
@click="(...event)=>swipeClick(event,item)" |
|||
style='padding:0px 0px 5px 0px;align-items: center;' |
|||
:options="item.scaned?scanOptions:detailOptions"> |
|||
<recommend :detail="item" :isShowFromLocation="isShowFromLocation" |
|||
:isShowStatus="isShowStatus" :isShowToLocation="isShowToLocation"> |
|||
</recommend> |
|||
</u-swipe-action> |
|||
</view> |
|||
</u-collapse-item> |
|||
</u-collapse> |
|||
<recommend-qty-edit ref="receiptEdit" :dataContent="editItem" :settingParam="settingParam" @confirm="confirm"> |
|||
</recommend-qty-edit> |
|||
<win-scan-location ref="scanLocationCode" title="目标库位" @getLocation='getLocation' |
|||
:locationAreaTypeList="locationAreaTypeList"></win-scan-location> |
|||
<comMessage ref="message"></comMessage> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue' |
|||
import recommend from '@/mycomponents/recommend/recommend.vue' |
|||
import recommendQtyEdit from '@/mycomponents/qty/recommendQtyEdit.vue' |
|||
import winScanLocation from "@/mycomponents/scan/winScanLocation.vue" |
|||
import { |
|||
getDetailOption, |
|||
getPurchaseReceiptOption |
|||
} from '@/common/array.js'; |
|||
|
|||
import { ref, watch, onMounted, nextTick } from 'vue'; |
|||
|
|||
const props = defineProps({ |
|||
dataContent: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
settingParam: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowFromLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowToLocation: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
locationAreaTypeList: { |
|||
type: Array, |
|||
default: null |
|||
}, |
|||
queryBalance: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}); |
|||
|
|||
const collapse1 = ref(null); |
|||
const receiptEdit = ref(null); |
|||
const message = ref(null); |
|||
const scanLocationCode = ref(null); |
|||
|
|||
const option = ref([]); |
|||
const showItem = ref({}); |
|||
const locatonItem = ref({}); |
|||
const editItem = ref({}); |
|||
const detailOptions = ref([]); |
|||
const scanOptions = ref([]); |
|||
|
|||
watch(() => props.dataContent, (newDataContent, oldDataContent) => { |
|||
if (newDataContent?.subList.length > 0) { |
|||
nextTick(() => { |
|||
setTimeout(() => { |
|||
if (collapse1.value) { |
|||
collapse1.value.resize(); |
|||
} |
|||
}, 500); |
|||
}); |
|||
} |
|||
}, { immediate: true, deep: true }); |
|||
|
|||
onMounted(() => { |
|||
if (detailOptions.value.length === 0) { |
|||
detailOptions.value = getDetailOption(); |
|||
} |
|||
if (scanOptions.value.length === 0) { |
|||
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, false); |
|||
} |
|||
// showLocation(); |
|||
}); |
|||
|
|||
const swipeClick = (e, item) => { |
|||
switch (e.content.text) { |
|||
case "详情": |
|||
detail(item); |
|||
break; |
|||
case "编辑": |
|||
edit(item); |
|||
break; |
|||
case "库位": |
|||
showLocation(item); |
|||
break; |
|||
case "移除": |
|||
remove(item); |
|||
break; |
|||
} |
|||
}; |
|||
|
|||
const edit = (item) => { |
|||
editItem.value = item; |
|||
receiptEdit.value.openTaskEditPopup(item.qty, item.handleQty, item.labelQty); |
|||
}; |
|||
|
|||
const detail = (item) => { |
|||
emit('openDetail', item); |
|||
// showItem.value = item; |
|||
// jobDetailPopup.value.openPopup(item); |
|||
}; |
|||
|
|||
const remove = (item) => { |
|||
message.value.showQuestionMessage("确定移除扫描信息?", (res) => { |
|||
if (res) { |
|||
item.scaned = false; |
|||
item.balance = {}; |
|||
item.handleQty = null; |
|||
emit('remove', item); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
const confirm = (qty) => { |
|||
editItem.value.handleQty = qty; |
|||
emit('updateData'); |
|||
}; |
|||
|
|||
const showLocation = (item) => { |
|||
locatonItem.value = item; |
|||
scanLocationCode.value.openScanPopup(); |
|||
}; |
|||
|
|||
const getLocation = (location, code) => { |
|||
locatonItem.value.toLocationCode = code; |
|||
emit('updateData'); |
|||
}; |
|||
|
|||
const emit = defineEmits(['openDetail', 'remove', 'updateData']); |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
@ -0,0 +1,185 @@ |
|||
<template> |
|||
<view class="" style="background-color: #fff;"> |
|||
<u-collapse ref="collapse1" > |
|||
<u-collapse-item :open="true"> |
|||
<template v-slot:title> |
|||
<item-compare-qty :dataContent="dataContent" :handleQty="dataContent.handleQty" |
|||
:isShowStdPack="false"> |
|||
</item-compare-qty> |
|||
</template> |
|||
<view class="" v-for="(item,index) in dataContent.subList" :key="index"> |
|||
<u-swipe-action ref="swipeAction" |
|||
:options="item.scaned?scanOptions:detailOptions" |
|||
style='padding:0px 0px 5px 0px;align-items: center;' |
|||
@click="(...event)=>swipeClick(event,item)"> |
|||
<view v-if="item.isRecommend" class="uni-flex" style="flex-direction: row; align-items: center;background-color: antiquewhite;"> |
|||
<view class="" style="font-size: 32rpx; color: black; font-weight: bold; text-align: center;"> |
|||
推 荐 |
|||
</view> |
|||
<recommend :detail="item" :isShowStatus="isShowStatus" :isShowFromLocation="isShowFromLocation" :isShowToLocation="isShowToLocation" style="flex:1" :isShowBatch='item.batch ? true:false' :isShowPack='isShowPack'> |
|||
</view> |
|||
<view v-else class="uni-flex" style="flex-direction: row; align-items: center;background-color: antiquewhite; margin-top: 5rpx;"> |
|||
<view class="" style="font-size: 32rpx; color: red; font-weight: bold; text-align: center;"> |
|||
实 |
|||
际 |
|||
</view> |
|||
<recommend :detail="item" :isShowStatus="isShowStatus" :isShowFromLocation="isShowFromLocation" :isShowToLocation="isShowToLocation" style="flex:1" :isShowBatch='item.batch? true:false' :isShowPack='isShowPack'></recommend> |
|||
</view> |
|||
</u-swipe-action> |
|||
</view> |
|||
</u-collapse-item> |
|||
</u-collapse> |
|||
<<recommend-qty-edit ref="recommendQtyEditRef" :dataContent="editItem" :handleQty="editItem.qty" @confirm="confirm" :settingParam='settingParam' |
|||
:isShowStatus="isShowStatus"></recommend-qty-edit> |
|||
<win-scan-location ref="scanLocationCode" title="目标库位" @getLocation='getLocation' |
|||
:locationAreaTypeList="locationAreaTypeList"></win-scan-location> |
|||
<comMessage ref="message"></comMessage> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import {ref, watch, onMounted, nextTick} from 'vue' |
|||
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue' |
|||
import recommend from '@/mycomponents/recommend/recommend.vue' |
|||
import recommendQtyEdit from '@/mycomponents/qty/recommendQtyEdit.vue' |
|||
import winScanLocation from '@/mycomponents/scan/winScanLocation.vue' |
|||
import { |
|||
getDetailOption, |
|||
getPurchaseReceiptOption |
|||
} from '@/common/array.js' |
|||
|
|||
|
|||
const props = defineProps({ |
|||
dataContent: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
settingParam: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
locationAreaTypeList: { |
|||
type: Array, |
|||
default: null |
|||
}, |
|||
queryBalance: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}) |
|||
const emit = defineEmits(['openDetail', 'remove', 'updateData']) |
|||
|
|||
const collapse1 = ref(null) |
|||
const qtyEdit = ref(null) |
|||
const message = ref(null) |
|||
const scanLocationCode = ref(null) |
|||
|
|||
const option = ref([]) |
|||
const showItem = ref({}) |
|||
const locatonItem = ref({}) |
|||
const editItem = ref({}) |
|||
const detailOptions = ref([]) |
|||
const scanOptions = ref([]) |
|||
|
|||
const recommendQtyEditRef = ref() |
|||
|
|||
watch(() => props.dataContent, (newDataContent, oldDataContent) => { |
|||
if (newDataContent?.subList.length > 0) { |
|||
nextTick(() => { |
|||
setTimeout(() => { |
|||
if (collapse1.value) { |
|||
collapse1.value.init() |
|||
} |
|||
}, 500) |
|||
}) |
|||
} |
|||
}, { immediate: true, deep: true }) |
|||
|
|||
onMounted(() => { |
|||
if (scanOptions.value.length === 0) { |
|||
scanOptions.value = getPurchaseReceiptOption(props.settingParam.allowModifyQty, false) |
|||
} |
|||
// showLocation(); |
|||
if(import.meta.env.VITE_MANAGE_MODEL=='BY_PACKAGING'){ |
|||
if (detailOptions.value.length == 0) { |
|||
detailOptions.value = getDetailOption() |
|||
} |
|||
}else { |
|||
scanOptions.value.splice(0,1) |
|||
} |
|||
}) |
|||
|
|||
const swipeClick = (e, item) => { |
|||
switch (e.content.text) { |
|||
case '详情': |
|||
detail(item) |
|||
break |
|||
case '编辑': |
|||
edit(item) |
|||
break |
|||
case '库位': |
|||
showLocation(item) |
|||
break |
|||
case '移除': |
|||
remove(item) |
|||
break |
|||
} |
|||
} |
|||
const edit = (item) => { |
|||
editItem.value = item |
|||
qtyEdit.value.openEditPopup(item.balance, item.handleQty) |
|||
recommendQtyEditRef.value.openTaskEditPopup(item.qty,item.handleQty,item.labelQty) |
|||
} |
|||
|
|||
const detail = (item) => { |
|||
emit('openDetail', item) |
|||
// showItem.value = item; |
|||
// jobDetailPopup.value.openPopup(item); |
|||
} |
|||
|
|||
const remove = (item) => { |
|||
message.value.showQuestionMessage('确定移除扫描信息?', (res) => { |
|||
if (res) { |
|||
item.scaned = false |
|||
item.balance = {} |
|||
item.handleQty = null |
|||
emit('remove', item) |
|||
} |
|||
}) |
|||
} |
|||
|
|||
const confirm = (qty) => { |
|||
editItem.value.handleQty = qty |
|||
emit('updateData') |
|||
} |
|||
|
|||
const showLocation = (item) => { |
|||
locatonItem.value = item |
|||
scanLocationCode.value.openScanPopup() |
|||
} |
|||
|
|||
const getLocation = (location, code) => { |
|||
locatonItem.value.toLocationCode = code |
|||
emit('updateData') |
|||
} |
|||
|
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
@ -0,0 +1,229 @@ |
|||
<template> |
|||
<view class="" style="background-color: #fff;"> |
|||
<item-compare-qty :dataContent="dataContent" :handleQty="dataContent.handleQty" |
|||
:isShowStdPack="false"> |
|||
</item-compare-qty> |
|||
<view class="" v-for="(item,index) in dataContent.subList" :key="index"> |
|||
<uni-swipe-action ref="swipeAction" |
|||
style='padding:0px 0px 5px 0px;align-items: center;' |
|||
:options="(item.scaned&&isEdit)?editAndRemoveOptions : item.scaned? removeOptions:options" |
|||
@click="(...event)=>swipeClick(event,item)"> |
|||
<view v-if="item.isRecommend" class="uni-flex" style="flex-direction: row;"> |
|||
<view class="" |
|||
style="font-size: 32rpx; color: black; font-weight: bold; text-align: center;background-color: antiquewhite;display: flex;align-items: center;justify-content: center;padding: 0px 10rpx;"> |
|||
推<br/> |
|||
荐 |
|||
</view> |
|||
<view class="" style="flex:1;"> |
|||
<batch v-if="item.batch" :batch="item.batch"></batch> |
|||
<location v-if="item.fromLocationCode" title="来源库位" |
|||
:locationCode="item.fromLocationCode"></location> |
|||
</view> |
|||
<text style="font-size: 30rpx;color: #2979ff; " @click="copy(item)" v-if="isDevlement()">复制</text> |
|||
</view> |
|||
<view v-else class="uni-flex" style="flex-direction: row; margin-top: 5rpx;"> |
|||
<view class="" |
|||
style="font-size: 32rpx; color: black; font-weight: bold; text-align: center;background-color: antiquewhite;display: flex;align-items: center;justify-content: center;padding: 0px 10rpx;"> |
|||
实<br/> |
|||
际 |
|||
</view> |
|||
<view class="scan_view" style="flex:1;"> |
|||
<location v-if="item.fromLocationCode" title="来源库位" |
|||
:locationCode="item.fromLocationCode"></location> |
|||
</view> |
|||
<!-- <recommend :detail="item" :isShowStatus="isShowStatus" :isShowToLocation="false"> |
|||
</recommend> --> |
|||
</view> |
|||
</uni-swipe-action> |
|||
</view> |
|||
|
|||
<balance-qty-edit ref="qtyEdit" :settingParam="settingParam" :queryBalance="queryBalance" |
|||
@confirm="confirm"></balance-qty-edit> |
|||
<win-scan-location ref="scanLocationCode" title="目标库位" @getLocation='getLocation' |
|||
:locationAreaTypeList="locationAreaTypeList"></win-scan-location> |
|||
<comMessage ref="message"></comMessage> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue' |
|||
import recommend from '@/mycomponents/recommend/recommend.vue' |
|||
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue' |
|||
import winScanLocation from "@/mycomponents/scan/winScanLocation.vue" |
|||
import location from '@/mycomponents/balance/location.vue' |
|||
import toLocation from '@/mycomponents/balance/toLocation.vue' |
|||
import batch from '@/mycomponents/balance/batch.vue' |
|||
import config from '@/static/config.js' |
|||
|
|||
import { |
|||
getRemoveOption, |
|||
getEditRemoveOption |
|||
} from '@/common/array.js'; |
|||
|
|||
import { ref, watch, onMounted, nextTick } from 'vue'; |
|||
|
|||
const props = defineProps({ |
|||
dataContent: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
settingParam: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
locationAreaTypeList: { |
|||
type: Array, |
|||
default: null |
|||
}, |
|||
queryBalance: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowStatus: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isEdit: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}); |
|||
const emit = defineEmits(['openDetail', 'remove', 'updateData']); |
|||
|
|||
const collapse1 = ref(null); |
|||
const qtyEdit = ref(null); |
|||
const message = ref(null); |
|||
const scanLocationCode = ref(null); |
|||
|
|||
const option = ref([]); |
|||
const showItem = ref({}); |
|||
const locatonItem = ref({}); |
|||
const editItem = ref({}); |
|||
const detailOptions = ref([]); |
|||
const scanOptions = ref([]); |
|||
const options = ref([]); |
|||
const removeOptions = ref([]); |
|||
const editAndRemoveOptions = ref([]); |
|||
|
|||
watch(() => props.dataContent, (newDataContent, oldDataContent) => { |
|||
if (newDataContent?.subList.length > 0) { |
|||
nextTick(() => { |
|||
setTimeout(() => { |
|||
if (collapse1.value) { |
|||
collapse1.value.resize(); |
|||
} |
|||
}, 500); |
|||
}); |
|||
} |
|||
}, { immediate: true, deep: true }); |
|||
|
|||
onMounted(() => { |
|||
removeOptions.value = getRemoveOption(); |
|||
editAndRemoveOptions.value = getEditRemoveOption(); |
|||
// showLocation(); |
|||
}); |
|||
|
|||
const swipeClick = (e, item) => { |
|||
switch (e.content.text) { |
|||
case "详情": |
|||
detail(item); |
|||
break; |
|||
case "编辑": |
|||
edit(item); |
|||
break; |
|||
case "库位": |
|||
showLocation(item); |
|||
break; |
|||
case "移除": |
|||
remove(item); |
|||
break; |
|||
} |
|||
}; |
|||
|
|||
const edit = (item) => { |
|||
editItem.value = item; |
|||
qtyEdit.value.openEditPopup(item.balance, item.handleQty); |
|||
}; |
|||
|
|||
const detail = (item) => { |
|||
emit('openDetail', item); |
|||
// showItem.value = item; |
|||
// jobDetailPopup.value.openPopup(item); |
|||
}; |
|||
|
|||
const remove = (item) => { |
|||
message.value.showQuestionMessage("确定移除扫描信息?", (res) => { |
|||
if (res) { |
|||
item.scaned = false; |
|||
item.balance = {}; |
|||
item.handleQty = null; |
|||
emit('remove', item); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
const confirm = (qty) => { |
|||
editItem.value.handleQty = qty; |
|||
emit('updateData'); |
|||
}; |
|||
|
|||
const showLocation = (item) => { |
|||
locatonItem.value = item; |
|||
scanLocationCode.value.openScanPopup(); |
|||
}; |
|||
|
|||
const getLocation = (location, code) => { |
|||
locatonItem.value.toLocationCode = code; |
|||
emit('updateData'); |
|||
}; |
|||
|
|||
const isDevlement = () => { |
|||
return config.isDevelopment; |
|||
}; |
|||
|
|||
const copy = (detail) => { |
|||
console.log(detail); |
|||
const content = `HPQ;V1.0;I${detail.itemCode};P${detail.packingNumber};B${detail.batch};Q${detail.qty}`; |
|||
// #ifdef H5 |
|||
navigator.clipboard.writeText(content).then( |
|||
() => { |
|||
uni.showToast({ |
|||
title: '复制采购标签成功', |
|||
icon: 'none' |
|||
}); |
|||
}, |
|||
() => { |
|||
uni.showToast({ |
|||
title: '复制失败', |
|||
icon: 'none' |
|||
}); |
|||
} |
|||
); |
|||
// #endif |
|||
// #ifndef H5 |
|||
uni.setClipboardData({ |
|||
data: content, |
|||
success: () => { |
|||
uni.showToast({ |
|||
title: '复制采购标签成功' |
|||
}); |
|||
} |
|||
}); |
|||
// #endif |
|||
}; |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
@ -1,151 +1,135 @@ |
|||
<template> |
|||
<view class="" style="background-color: #fff;"> |
|||
<!-- <comReturnRequestInfo :workShopCode="dataContent.workshopCode" :dataContent="requestItem"> |
|||
</comReturnRequestInfo> --> |
|||
<uni-collapse ref="collapse1" @change=""> |
|||
<uni-collapse-item :open="true"> |
|||
<template v-slot:title> |
|||
<item-compare-qty |
|||
:dataContent="dataContent" |
|||
:handleQty="Number(dataContent.handleQty)" |
|||
:isShowStdPack="false"> |
|||
</item-compare-qty> |
|||
</template> |
|||
<u-line /> |
|||
<view class="" v-for="(item,index) in dataContent.subList"> |
|||
<uni-swipe-action ref="swipeAction"> |
|||
<uni-swipe-action-item @click="swipeClick($event,item)" |
|||
:right-options="item.scaned?scanOptions:detailOptions"> |
|||
<recommend :detail="item" :record="item.record" :isShowPack="isShowPack" |
|||
:isShowBatch="isShowBatch" :isShowFromLocation="isShowLocation"></recommend> |
|||
</uni-swipe-action-item> |
|||
</uni-swipe-action> |
|||
</view> |
|||
</uni-collapse-item> |
|||
</uni-collapse> |
|||
<balance-qty-edit ref="qtyEdit" :settingParam="settingParam" @confirm="confirm"></balance-qty-edit> |
|||
<comMessage ref="message"></comMessage> |
|||
</view> |
|||
<view class="" style="background-color: #fff"> |
|||
<u-collapse ref="collapse"> |
|||
<u-collapse-item :open="true"> |
|||
<template v-slot:title> |
|||
<item-compare-qty :dataContent="dataContent" :handleQty="Number(dataContent.handleQty)" :isShowStdPack="false" style="flex: 1"> </item-compare-qty> |
|||
</template> |
|||
<u-swipe-action :show="item.show" :index="index" v-for="(item, index) in dataContent.subList" :key="index" :options="item.scaned ? scanOptions : detailOptions" bg-color="rgba(255,255,255,0)" @click="(...event) => swipeClick(event, item)"> |
|||
<recommend :detail="item" :record="item.record" :isShowPack="isShowPack" :isShowBatch="isShowBatch" :isShowFromLocation="isShowLocation"></recommend> |
|||
</u-swipe-action> |
|||
</u-collapse-item> |
|||
</u-collapse> |
|||
<balance-qty-edit ref="qtyEdit" :settingParam="settingParam" @confirm="confirm"></balance-qty-edit> |
|||
<com-message ref="comMessageRef" /> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue' |
|||
import recommend from '@/mycomponents/recommend/recommend.vue' |
|||
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue' |
|||
import comReturnRequestInfo from '@/pages/productionReturn/coms/comReturnRequestInfo.vue' |
|||
import { |
|||
getDetailOption, |
|||
getDetailEditRemoveOption, |
|||
getDetailRemoveOption |
|||
} from '@/common/array.js'; |
|||
<script setup lang="ts"> |
|||
import { ref, getCurrentInstance, onMounted, watch, nextTick } from 'vue' |
|||
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue' |
|||
import recommend from '@/mycomponents/recommend/recommend.vue' |
|||
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue' |
|||
import comReturnRequestInfo from '@/pages/productionReturn/coms/comReturnRequestInfo.vue' |
|||
import { getDetailOption, getDetailEditRemoveOption, getDetailRemoveOption } from '@/common/array.js' |
|||
|
|||
export default { |
|||
emits: ['openDetail'], |
|||
components: { |
|||
itemCompareQty, |
|||
recommend, |
|||
balanceQtyEdit, |
|||
comReturnRequestInfo |
|||
}, |
|||
props: { |
|||
dataContent: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
settingParam: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
}, |
|||
watch: { |
|||
dataContent(newVal) { |
|||
var test =this.dataContent |
|||
this.requestItem = newVal.subList[0]; |
|||
}, |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
option: [], |
|||
showItem: {}, |
|||
editItem: { |
|||
record: { |
|||
|
|||
} |
|||
}, |
|||
detailOptions: [], |
|||
scanOptions: [], |
|||
requestItem:{} |
|||
} |
|||
}, |
|||
|
|||
mounted() { |
|||
if (this.detailOptions.length == 0) { |
|||
this.detailOptions = getDetailOption(); |
|||
} |
|||
if (this.scanOptions.length == 0) { |
|||
this.scanOptions = getDetailEditRemoveOption(); |
|||
// if (this.dataContent.allowModifyQty == 1) { |
|||
// this.scanOptions = getDetailEditRemoveOption(); |
|||
// } else { |
|||
// this.scanOptions = getDetailRemoveOption(); |
|||
// } |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
swipeClick(e, item) { |
|||
if (e.content.text == "详情") { |
|||
this.detail(item) |
|||
} else if (e.content.text == "编辑") { |
|||
this.edit(item) |
|||
} else if (e.content.text == "移除") { |
|||
this.remove(item) |
|||
} |
|||
}, |
|||
edit(item) { |
|||
this.editItem = item; |
|||
this.$refs.qtyEdit.openEditPopup(item.balance, item.record.qty); |
|||
}, |
|||
|
|||
detail(item) { |
|||
this.$emit('openDetail', item); |
|||
// this.showItem = item; |
|||
// this.$refs.jobDetailPopup.openPopup(item) |
|||
}, |
|||
remove(item) { |
|||
this.$refs.message.showQuestionMessage("确定移除扫描信息?", |
|||
res => { |
|||
if (res) { |
|||
item.scaned = false |
|||
item.record = {} |
|||
item.balance = {} |
|||
item.inventoryStatus = item.RecommendInventoryStatus |
|||
// item.record.qty = 0; |
|||
this.$forceUpdate() |
|||
this.$emit('remove', item) |
|||
} |
|||
}); |
|||
}, |
|||
confirm(qty) { |
|||
this.editItem.record.qty = qty; |
|||
this.$emit('updateData') |
|||
} |
|||
} |
|||
} |
|||
const props = defineProps({ |
|||
dataContent: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
settingParam: { |
|||
type: Object, |
|||
default: {} |
|||
}, |
|||
isShowPack: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowBatch: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
isShowLocation: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}) |
|||
const option = ref([]) |
|||
const showItem = ref({}) |
|||
const editItem = ref({ |
|||
record: {} |
|||
}) |
|||
const detailOptions = ref([]) |
|||
const scanOptions = ref([]) |
|||
const requestItem = ref({}) |
|||
const qtyEdit = ref() |
|||
const comMessageRef = ref() |
|||
const dataContent = ref([]) |
|||
const collapse = ref() |
|||
dataContent.value = props.dataContent |
|||
dataContent.value.subList.forEach((item) => { |
|||
item.show = false |
|||
}) |
|||
onMounted(() => { |
|||
if (detailOptions.value.length == 0) { |
|||
detailOptions.value = getDetailOption() |
|||
} |
|||
if (scanOptions.value.length == 0) { |
|||
scanOptions.value = getDetailEditRemoveOption() |
|||
} |
|||
}) |
|||
// 监视属性 |
|||
watch( |
|||
() => props.dataContent, |
|||
(val) => { |
|||
requestItem.value = val.subList[0] |
|||
dataContent.value = val |
|||
dataContent.value.subList.forEach((item) => { |
|||
item.show = false |
|||
}) |
|||
nextTick(() => { |
|||
collapse.value.init() |
|||
}) |
|||
}, |
|||
{ |
|||
immediate: true, |
|||
deep: true |
|||
} |
|||
) |
|||
const swipeClick = (params, item) => { |
|||
let text = '' |
|||
if (item.scaned) { |
|||
text = scanOptions.value[params[1]].text |
|||
} else { |
|||
text = detailOptions.value[params[1]].text |
|||
} |
|||
if (text == '详情') { |
|||
detail(item) |
|||
} else if (text == '编辑') { |
|||
edit(item) |
|||
} else if (text == '移除') { |
|||
remove(item) |
|||
} |
|||
} |
|||
const edit = (item) => { |
|||
editItem.value = item |
|||
qtyEdit.value.openEditPopup(item.balance, item.record.qty) |
|||
} |
|||
const detail = (item) => { |
|||
emit('openDetail', item) |
|||
} |
|||
const remove = (item) => { |
|||
comMessageRef.value.showQuestionMessage('确定移除扫描信息?', (res) => { |
|||
if (res) { |
|||
item.scaned = false |
|||
item.record = {} |
|||
item.balance = {} |
|||
item.inventoryStatus = item.RecommendInventoryStatus |
|||
emit('remove', item) |
|||
} |
|||
}) |
|||
} |
|||
const confirm = (qty) => { |
|||
editItem.value.record.qty = qty |
|||
emit('updateData') |
|||
} |
|||
// 传递给父类 |
|||
const emit = defineEmits(['openDetail', 'remove', 'updateData']) |
|||
</script> |
|||
|
|||
<style> |
|||
::v-deep .u-arrow-down-icon { |
|||
margin-right: 0px !important; |
|||
} |
|||
</style> |
|||
|
@ -1,65 +1,48 @@ |
|||
<template> |
|||
<view class="pop_detail" style="height:80%"> |
|||
<com-item :dataContent="dataContent"></com-item> |
|||
<u-line></u-line> |
|||
<scroll-view style="height:320px "> |
|||
<detail-item-info :dataContent="dataContent"></detail-item-info> |
|||
<u-line></u-line> |
|||
<detail-recommend-info :dataContent="dataContent"></detail-recommend-info> |
|||
<u-line></u-line> |
|||
<view v-if="dataContent.record!=undefined"> |
|||
<detail-handle-info :dataContent="dataContent"> |
|||
</detail-handle-info> |
|||
<u-line></u-line> |
|||
</view> |
|||
<slot> |
|||
<!-- 每个任务的详情 --> |
|||
</slot> |
|||
</scroll-view> |
|||
|
|||
<view class="uni-flex u-row-center "> |
|||
<view class="close_button" @click="closePopup"> |
|||
关闭</view> |
|||
<!-- button 滚动不好使 --> |
|||
</view> |
|||
</view> |
|||
<view class="pop_detail" style="height: 80%"> |
|||
<view class="u-p-t-20 u-p-b-20"> |
|||
<com-item :dataContent="dataContent"></com-item> |
|||
</view> |
|||
<view class="split_line"></view> |
|||
<scroll-view style="height: 320px" scroll-y> |
|||
<detail-item-info :dataContent="dataContent"></detail-item-info> |
|||
<view class="split_line"></view> |
|||
<detail-recommend-info :dataContent="dataContent"></detail-recommend-info> |
|||
<view class="split_line"></view> |
|||
<view v-if="dataContent.record != undefined"> |
|||
<detail-handle-info :dataContent="dataContent"> </detail-handle-info> |
|||
<view class="split_line"></view> |
|||
</view> |
|||
<slot> |
|||
<!-- 每个任务的详情 --> |
|||
</slot> |
|||
</scroll-view> |
|||
|
|||
<view class="uni-flex u-row-center u-p-t-20 u-p-b-20"> |
|||
<view class="close_button" @click="closePopup"> 关闭</view> |
|||
<!-- button 滚动不好使 --> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import comItem from '@/mycomponents/item/item.vue' |
|||
import detailItemInfo from '@/mycomponents/detail/detailItemInfo.vue' |
|||
import detailRecommendInfo from '@/mycomponents/detail/detailRecommendInfo.vue' |
|||
import detailHandleInfo from '@/mycomponents/detail/detailHandleInfo.vue' |
|||
|
|||
export default { |
|||
emits: ['onClose'], |
|||
components: { |
|||
comItem, |
|||
detailItemInfo, |
|||
detailRecommendInfo, |
|||
detailHandleInfo |
|||
}, |
|||
data() { |
|||
return {} |
|||
}, |
|||
|
|||
mounted() {}, |
|||
props: { |
|||
dataContent: { |
|||
type: Object, |
|||
default: {} |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
closePopup() { |
|||
this.$emit('onClose') |
|||
}, |
|||
} |
|||
} |
|||
<script setup lang="ts"> |
|||
import comItem from '@/mycomponents/item/item.vue' |
|||
import detailItemInfo from '@/mycomponents/detail/detailItemInfo.vue' |
|||
import detailRecommendInfo from '@/mycomponents/detail/detailRecommendInfo.vue' |
|||
import detailHandleInfo from '@/mycomponents/detail/detailHandleInfo.vue' |
|||
|
|||
const props = defineProps({ |
|||
dataContent: { |
|||
type: Object, |
|||
default: {} |
|||
} |
|||
}) |
|||
const closePopup = () => { |
|||
emit('onClose') |
|||
} |
|||
|
|||
// 传递给父类 |
|||
const emit = defineEmits(['onClose']) |
|||
</script> |
|||
|
|||
<style> |
|||
|
|||
|
|||
</style> |
|||
<style></style> |
|||
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue