Compare commits

..

10 Commits

Author SHA1 Message Date
323f44b896 test 2024-11-03 20:59:28 +08:00
3fc0df1a94 init 2024-11-01 18:27:15 +08:00
7e443e7e76 test 2024-10-30 22:19:33 +08:00
wenpeng
2d952ddc5d csv 2024-10-25 10:43:59 +08:00
919325202b ii 2024-10-24 21:29:34 +08:00
wenpeng
2134398e49 test 2024-10-23 16:28:48 +08:00
wenpeng
d79ce01586 test 2024-10-23 15:19:54 +08:00
wenpeng
fca3bdf29f 测试智荟宝 2024-10-21 18:03:30 +08:00
wenpeng
b777133751 新增npm命令 2024-10-21 11:53:43 +08:00
wenpeng
1eab67953c 新增美管加demo 2024-10-21 11:49:04 +08:00
30 changed files with 1446 additions and 247 deletions

9
.env
View File

@ -6,10 +6,11 @@ SMSCODE=1660
ZHB_ACCOUNT=18571458300
ZHB_PASSWORD=1
# ZHB_BASE_URL="https://shengyibao.meiguanjia.net/shair/components/shair-web/base-system/index.html#"
ZHB_ADMIN_URL="https://shengyibao.meiguanjia.net/shair/components/shair-web/base-system/index.html#"
ZHB_BASE_URL="https://shengyibao.meiguanjia.net/young/"
ZHB_H5_URL="http://shengyibao.meiguanjia.net/h5/index.html#tenantId=1578151&view=0"
MGJ_ACCOUNT=小美美业
MGJ_ACCOUNT=美管加演示
MGJ_PASSWORD=1
MGJ_BASE_URL="https://vip1.meiguanjia.net/shair/?v=mgj"
# MGJ_BASE_URL="https://vip1.meiguanjia.net/shair/?v=mgj"
MGJ_BASE_URL="https://young.meiguanjia.net/young/"

3
.gitignore vendored
View File

@ -4,4 +4,7 @@ node_modules/
/blob-report/
/playwright/.cache/
.auth/
.images/
*.traineddata
/tessdata/**/*.traineddata

880
package-lock.json generated
View File

@ -1,129 +1,755 @@
{
"name": "playwright-demo",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "playwright-demo",
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
"@faker-js/faker": "^9.0.3",
"@playwright/test": "^1.48.1",
"@types/node": "^22.7.5",
"dotenv": "^16.4.5"
}
},
"node_modules/@faker-js/faker": {
"version": "9.0.3",
"resolved": "https://registry.npmmirror.com/@faker-js/faker/-/faker-9.0.3.tgz",
"integrity": "sha512-lWrrK4QNlFSU+13PL9jMbMKLJYXDFu3tQfayBsMXX7KL/GiQeqfB1CzHkqD5UHBUtPAuPo6XwGbMFNdVMZObRA==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/fakerjs"
}
],
"license": "MIT",
"engines": {
"node": ">=18.0.0",
"npm": ">=9.0.0"
}
},
"node_modules/@playwright/test": {
"version": "1.48.1",
"resolved": "https://registry.npmmirror.com/@playwright/test/-/test-1.48.1.tgz",
"integrity": "sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright": "1.48.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@types/node": {
"version": "22.7.5",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-22.7.5.tgz",
"integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.19.2"
}
},
"node_modules/dotenv": {
"version": "16.4.5",
"resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.4.5.tgz",
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/playwright": {
"version": "1.48.1",
"resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.48.1.tgz",
"integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.48.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/playwright-core": {
"version": "1.48.1",
"resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.48.1.tgz",
"integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"dev": true,
"license": "MIT"
}
}
"name": "playwright-demo",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "playwright-demo",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"csv-parse": "^5.5.6",
"sharp": "^0.33.5",
"tesseract.js": "^5.1.1"
},
"devDependencies": {
"@faker-js/faker": "^9.0.3",
"@playwright/test": "^1.48.1",
"@types/node": "^22.7.5",
"dotenv": "^16.4.5"
}
},
"node_modules/@emnapi/runtime": {
"version": "1.3.1",
"resolved": "https://registry.npmmirror.com/@emnapi/runtime/-/runtime-1.3.1.tgz",
"integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==",
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@faker-js/faker": {
"version": "9.0.3",
"resolved": "https://registry.npmmirror.com/@faker-js/faker/-/faker-9.0.3.tgz",
"integrity": "sha512-lWrrK4QNlFSU+13PL9jMbMKLJYXDFu3tQfayBsMXX7KL/GiQeqfB1CzHkqD5UHBUtPAuPo6XwGbMFNdVMZObRA==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/fakerjs"
}
],
"license": "MIT",
"engines": {
"node": ">=18.0.0",
"npm": ">=9.0.0"
}
},
"node_modules/@img/sharp-darwin-arm64": {
"version": "0.33.5",
"resolved": "https://registry.npmmirror.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
"integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-darwin-arm64": "1.0.4"
}
},
"node_modules/@img/sharp-darwin-x64": {
"version": "0.33.5",
"resolved": "https://registry.npmmirror.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz",
"integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-darwin-x64": "1.0.4"
}
},
"node_modules/@img/sharp-libvips-darwin-arm64": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz",
"integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"darwin"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-darwin-x64": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz",
"integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"darwin"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-arm": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz",
"integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==",
"cpu": [
"arm"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-arm64": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
"integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-s390x": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz",
"integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==",
"cpu": [
"s390x"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-x64": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz",
"integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz",
"integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz",
"integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-linux-arm": {
"version": "0.33.5",
"resolved": "https://registry.npmmirror.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz",
"integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==",
"cpu": [
"arm"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-arm": "1.0.5"
}
},
"node_modules/@img/sharp-linux-arm64": {
"version": "0.33.5",
"resolved": "https://registry.npmmirror.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
"integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-arm64": "1.0.4"
}
},
"node_modules/@img/sharp-linux-s390x": {
"version": "0.33.5",
"resolved": "https://registry.npmmirror.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz",
"integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==",
"cpu": [
"s390x"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-s390x": "1.0.4"
}
},
"node_modules/@img/sharp-linux-x64": {
"version": "0.33.5",
"resolved": "https://registry.npmmirror.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz",
"integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-x64": "1.0.4"
}
},
"node_modules/@img/sharp-linuxmusl-arm64": {
"version": "0.33.5",
"resolved": "https://registry.npmmirror.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz",
"integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-arm64": "1.0.4"
}
},
"node_modules/@img/sharp-linuxmusl-x64": {
"version": "0.33.5",
"resolved": "https://registry.npmmirror.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz",
"integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-x64": "1.0.4"
}
},
"node_modules/@img/sharp-wasm32": {
"version": "0.33.5",
"resolved": "https://registry.npmmirror.com/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz",
"integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==",
"cpu": [
"wasm32"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
"optional": true,
"dependencies": {
"@emnapi/runtime": "^1.2.0"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-ia32": {
"version": "0.33.5",
"resolved": "https://registry.npmmirror.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz",
"integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==",
"cpu": [
"ia32"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-x64": {
"version": "0.33.5",
"resolved": "https://registry.npmmirror.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz",
"integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==",
"cpu": [
"x64"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@playwright/test": {
"version": "1.48.1",
"resolved": "https://registry.npmmirror.com/@playwright/test/-/test-1.48.1.tgz",
"integrity": "sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright": "1.48.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@types/node": {
"version": "22.7.5",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-22.7.5.tgz",
"integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.19.2"
}
},
"node_modules/bmp-js": {
"version": "0.1.0",
"resolved": "https://registry.npmmirror.com/bmp-js/-/bmp-js-0.1.0.tgz",
"integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==",
"license": "MIT"
},
"node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmmirror.com/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
},
"engines": {
"node": ">=12.5.0"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"license": "MIT"
},
"node_modules/color-string": {
"version": "1.9.1",
"resolved": "https://registry.npmmirror.com/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"license": "MIT",
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"node_modules/csv-parse": {
"version": "5.5.6",
"resolved": "https://registry.npmmirror.com/csv-parse/-/csv-parse-5.5.6.tgz",
"integrity": "sha512-uNpm30m/AGSkLxxy7d9yRXpJQFrZzVWLFBkS+6ngPcZkw/5k3L/jjFuj7tVnEpRn+QgmiXr21nDlhCiUK4ij2A==",
"license": "MIT"
},
"node_modules/detect-libc": {
"version": "2.0.3",
"resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.0.3.tgz",
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
"license": "Apache-2.0",
"engines": {
"node": ">=8"
}
},
"node_modules/dotenv": {
"version": "16.4.5",
"resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.4.5.tgz",
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/idb-keyval": {
"version": "6.2.1",
"resolved": "https://registry.npmmirror.com/idb-keyval/-/idb-keyval-6.2.1.tgz",
"integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==",
"license": "Apache-2.0"
},
"node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
"license": "MIT"
},
"node_modules/is-electron": {
"version": "2.2.2",
"resolved": "https://registry.npmmirror.com/is-electron/-/is-electron-2.2.2.tgz",
"integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==",
"license": "MIT"
},
"node_modules/is-url": {
"version": "1.2.4",
"resolved": "https://registry.npmmirror.com/is-url/-/is-url-1.2.4.tgz",
"integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==",
"license": "MIT"
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"license": "MIT",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/opencollective-postinstall": {
"version": "2.0.3",
"resolved": "https://registry.npmmirror.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
"integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
"license": "MIT",
"bin": {
"opencollective-postinstall": "index.js"
}
},
"node_modules/playwright": {
"version": "1.48.1",
"resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.48.1.tgz",
"integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.48.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/playwright-core": {
"version": "1.48.1",
"resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.48.1.tgz",
"integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
"license": "MIT"
},
"node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/sharp": {
"version": "0.33.5",
"resolved": "https://registry.npmmirror.com/sharp/-/sharp-0.33.5.tgz",
"integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"color": "^4.2.3",
"detect-libc": "^2.0.3",
"semver": "^7.6.3"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-darwin-arm64": "0.33.5",
"@img/sharp-darwin-x64": "0.33.5",
"@img/sharp-libvips-darwin-arm64": "1.0.4",
"@img/sharp-libvips-darwin-x64": "1.0.4",
"@img/sharp-libvips-linux-arm": "1.0.5",
"@img/sharp-libvips-linux-arm64": "1.0.4",
"@img/sharp-libvips-linux-s390x": "1.0.4",
"@img/sharp-libvips-linux-x64": "1.0.4",
"@img/sharp-libvips-linuxmusl-arm64": "1.0.4",
"@img/sharp-libvips-linuxmusl-x64": "1.0.4",
"@img/sharp-linux-arm": "0.33.5",
"@img/sharp-linux-arm64": "0.33.5",
"@img/sharp-linux-s390x": "0.33.5",
"@img/sharp-linux-x64": "0.33.5",
"@img/sharp-linuxmusl-arm64": "0.33.5",
"@img/sharp-linuxmusl-x64": "0.33.5",
"@img/sharp-wasm32": "0.33.5",
"@img/sharp-win32-ia32": "0.33.5",
"@img/sharp-win32-x64": "0.33.5"
}
},
"node_modules/simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmmirror.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"license": "MIT",
"dependencies": {
"is-arrayish": "^0.3.1"
}
},
"node_modules/tesseract.js": {
"version": "5.1.1",
"resolved": "https://registry.npmmirror.com/tesseract.js/-/tesseract.js-5.1.1.tgz",
"integrity": "sha512-lzVl/Ar3P3zhpUT31NjqeCo1f+D5+YfpZ5J62eo2S14QNVOmHBTtbchHm/YAbOOOzCegFnKf4B3Qih9LuldcYQ==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"bmp-js": "^0.1.0",
"idb-keyval": "^6.2.0",
"is-electron": "^2.2.2",
"is-url": "^1.2.4",
"node-fetch": "^2.6.9",
"opencollective-postinstall": "^2.0.3",
"regenerator-runtime": "^0.13.3",
"tesseract.js-core": "^5.1.1",
"wasm-feature-detect": "^1.2.11",
"zlibjs": "^0.3.1"
}
},
"node_modules/tesseract.js-core": {
"version": "5.1.1",
"resolved": "https://registry.npmmirror.com/tesseract.js-core/-/tesseract.js-core-5.1.1.tgz",
"integrity": "sha512-KX3bYSU5iGcO1XJa+QGPbi+Zjo2qq6eBhNjSGR5E5q0JtzkoipJKOUQD7ph8kFyteCEfEQ0maWLu8MCXtvX5uQ==",
"license": "Apache-2.0"
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"license": "MIT"
},
"node_modules/tslib": {
"version": "2.8.0",
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.0.tgz",
"integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==",
"license": "0BSD",
"optional": true
},
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"dev": true,
"license": "MIT"
},
"node_modules/wasm-feature-detect": {
"version": "1.8.0",
"resolved": "https://registry.npmmirror.com/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz",
"integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==",
"license": "Apache-2.0"
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"license": "BSD-2-Clause"
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"license": "MIT",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/zlibjs": {
"version": "0.3.1",
"resolved": "https://registry.npmmirror.com/zlibjs/-/zlibjs-0.3.1.tgz",
"integrity": "sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==",
"license": "MIT",
"engines": {
"node": "*"
}
}
}
}

View File

@ -6,7 +6,10 @@
"hlk_codegen": "npx playwright codegen https://hlk.meiguanjia.net/#/",
"mgj_codegen": "npx playwright codegen https://vip1.meiguanjia.net/shair/?v=mgj",
"zhb_codegen": "npx playwright codegen https://shengyibao.meiguanjia.net/young/",
"ui": "npx playwright test --ui"
"zhb_csv-50": "npx playwright test ./tests/zhb/csv-demo.spec.js:13 --repeat-each=50",
"ui": "npx playwright test --ui",
"pwi": "npm ci && npx playwright install",
"pwu": "npx playwright install --with-deps"
},
"keywords": [],
"author": "",
@ -17,5 +20,10 @@
"@playwright/test": "^1.48.1",
"@types/node": "^22.7.5",
"dotenv": "^16.4.5"
},
"dependencies": {
"csv-parse": "^5.5.6",
"sharp": "^0.33.5",
"tesseract.js": "^5.1.1"
}
}

View File

@ -6,7 +6,6 @@ const path = require('path');
// Read from ".env" file.
dotenv.config({ path: path.resolve(__dirname, '.env') });
const hlkAuthFile = path.join(__dirname, '.auth/hlk_admin.json');
const zhbAuthFile = path.join(__dirname, '.auth/zhb_admin.json');
const mgjAuthFile = path.join(__dirname, '.auth/mgj_admin.json');
/**
@ -27,7 +26,7 @@ module.exports = defineConfig({
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
workers: process.env.CI ? 1 : 1,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
@ -66,7 +65,6 @@ module.exports = defineConfig({
use: {
baseURL: process.env.ZHB_BASE_URL,
...devices['Desktop Chrome'],
storageState: zhbAuthFile,
},
testMatch: '**/tests/zhb/**.spec.js',
dependencies: ['zhb_setup'],

View File

@ -1,8 +1,8 @@
const { test, expect } = require('./fixtures/common');
const { Customer } = require('./pom/hlk/customer');
const { Customer } = require('./pom/customer');
const { faker } = require('@faker-js/faker/locale/zh_CN');
for (let i = 0; i < 10; i++) {
for (let i = 0; i < 3; i++) {
test(`登录touch和h5创建顾客购买会员卡使用顾客账号到h5商城购买货品${i}`, async ({
touchPage,
h5Page,
@ -44,8 +44,12 @@ for (let i = 0; i < 10; i++) {
await h5Page.locator('.back').click();
await h5Page.locator('.bar_item', { hasText: '商城' }).click();
await expect(h5Page.locator('.title', { hasText: '商城' })).toBeVisible();
await h5Page.waitForTimeout(2000);
await h5Page.reload();
await h5Page.locator('.bar_item', { hasText: '商城' }).click();
await expect(h5Page.locator('.title', { hasText: '商城' })).toBeVisible();
await h5Page.locator('.li span', { hasText: '全部' }).click();
await h5Page.locator('.p-item').first().click();
await h5Page.locator('.p-item').nth(2).click();
await h5Page.waitForLoadState();
await h5Page.getByText('立即购买').click();
await h5Page

View File

@ -1,5 +1,5 @@
const { test: base, expect } = require('./base');
const { H5LoginPage } = require('../pom/hlk/h5LoginPage');
const { H5LoginPage } = require('../pom/h5LoginPage');
const test = base.extend({
/**

View File

@ -1,5 +1,5 @@
const { test: base, expect } = require('./base');
const { CustomerPage } = require('../pom/hlk/customerPage');
const { CustomerPage } = require('../pom/customerPage');
const test = base.extend({
/**

View File

@ -1,97 +1,56 @@
const { test, expect } = require('./fixture/common');
const { Customer } = require('./pom/customerPage');
test('demo', async ({ zhbPage, customerPage }) => {
const $area = zhbPage
.locator('.area')
.filter({ has: zhbPage.locator('.area-name', { hasText: '二楼' }) });
const $$room = $area.locator('.room-list .room');
test('demo', async ({ mgjPage, customerPage }) => {
await test.step('创建顾客', async () => {
await expect(mgjPage.locator('#autoStationTip').getByText('我知道了')).toBeVisible();
await mgjPage.locator('#autoStationTip').getByText('我知道了').click();
await mgjPage.locator('#tab_main li').filter({ hasText: '顾客' }).click();
const customer = new Customer();
await customerPage.createCustomer(customer);
});
await zhbPage.locator('#tab_main li').filter({ hasText: '顾客' }).click();
const customer = new Customer();
await customerPage.createCustomer(customer);
await test.step('开单结算,购买第一个项目', async () => {
await mgjPage.getByText('去开单').click();
await mgjPage.locator('span').filter({ hasText: '确认开单' }).click();
const firstEnabledElement = mgjPage
.locator('#createService .content ul .am-clickable:not(.am-disabled)')
.first();
await mgjPage.waitForTimeout(1000);
await firstEnabledElement.click();
let useRoomName;
await test.step('购买商品', async () => {
await zhbPage.locator('#tab_main li').filter({ hasText: '营业' }).click();
const $emptyRoom = $$room.filter({ has: zhbPage.getByText('空房') }).first();
useRoomName = await $emptyRoom.locator('.roomName').innerText();
expect(useRoomName).not.toBeNull();
await $emptyRoom.click();
await expect(async () => {
await zhbPage.getByRole('button', { name: '选择顾客' }).click();
await expect(zhbPage.locator('#page_searchMember').getByText('创建会员')).toBeVisible();
}).toPass();
await zhbPage
.getByRole('textbox', { name: '输入会员手机号或姓名或卡号搜索' })
.fill(customer.phone, { delay: 100 });
await zhbPage.locator('#page_searchMember svg').click();
await expect(
mgjPage.locator('#cashierTotalPanel span').filter({ hasText: /结\s算/ })
).toBeVisible();
const $customerTr = zhbPage
.locator('.list-warp')
.filter({ has: zhbPage.locator('.name', { hasText: customer.name }) });
await $customerTr.locator('.list-body').first().click();
await mgjPage.waitForTimeout(1000);
await zhbPage.getByText('项目开单').click();
await expect(zhbPage.locator('#page_roomDetail').getByText('服务项目')).toBeVisible();
await zhbPage.getByText('选择', { exact: true }).nth(1).click();
await expect(zhbPage.locator('#serviceSelector').getByText('项目选择')).toBeVisible();
await zhbPage.getByText('臻品足疗 (10101)').click();
await zhbPage.locator('#serviceSelector').getByText('确认').click();
await zhbPage
.locator('div')
.filter({ hasText: /^匠星足浴$/ })
.locator('span')
.first()
// 选择第一个项目
await mgjPage.locator('.cashierItems .am-clickable').first().click();
await expect(mgjPage.locator('.cashierBox tbody tr.am-clickable').first()).toBeVisible();
await mgjPage
.locator('#cashierTotalPanel span')
.filter({ hasText: /结\s算/ })
.click();
await zhbPage.getByRole('button', { name: '完成开单' }).click();
await expect(zhbPage.getByRole('button', { name: '结账' })).toBeVisible();
await zhbPage.getByRole('button', { name: '结账' }).click();
await zhbPage.locator('#page_footBathPay').getByText('结算签字').click();
await expect(async () => {
await zhbPage.locator('#page_footBathPay li').filter({ hasText: '现金' }).click();
await expect(zhbPage.locator('#page_footBathPay li').filter({ hasText: '现金' })).toHaveClass(
/selected/
);
await zhbPage
.locator('#page_footBathPay span')
const $signature = mgjPage.locator('#page_pay').getByText('结算签字');
await $signature.click();
await expect($signature).not.toHaveClass(/checked/, { timeout: 2000 });
}).toPass();
await expect(async () => {
const $cashBtn = mgjPage.locator('#page_pay .pay_cash');
await $cashBtn.click();
await expect(mgjPage.locator('#page_pay .pay_cash.selected')).toBeVisible();
await mgjPage
.locator('#page_pay span')
.filter({ hasText: /结\s算/ })
.click();
await expect(zhbPage.getByText('顾客满意度点评')).toBeVisible({ timeout: 2000 });
await expect(mgjPage.getByText('顾客满意度点评')).toBeVisible({ timeout: 2000 });
}).toPass();
await zhbPage.getByText('不想评价').click();
await expect(zhbPage.locator('#page_footBathPay').getByText('立即返回')).not.toBeVisible();
});
await test.step('起钟下钟,清理房间', async () => {
const $cleanRoom = $$room.filter({
has: zhbPage.locator('.roomName', { hasText: new RegExp(`^${useRoomName}$`) }),
});
await expect($cleanRoom).toContainText('已结清');
await $cleanRoom.click();
await zhbPage.getByText('技师操作').click();
await zhbPage.getByText('起钟', { exact: true }).click();
await zhbPage.getByText('起钟成功!').click();
await zhbPage.getByText('技师操作').click();
await zhbPage.getByText('下钟', { exact: true }).click();
await zhbPage
.locator('div')
.filter({ hasText: /^确认返回$/ })
.locator('div')
.first()
.click();
await zhbPage.getByRole('button', { name: '不需要' }).click();
await expect($cleanRoom).toContainText('打扫');
await $cleanRoom.click();
await zhbPage
.locator('div')
.filter({ hasText: /^确定取消$/ })
.locator('div')
.first()
.click();
await expect($cleanRoom).toContainText('空房');
await mgjPage.getByText('不想评价').click();
await expect(mgjPage.locator('#page_footBathPay').getByText('立即返回')).not.toBeVisible();
});
});

View File

@ -5,8 +5,8 @@ export const test = base.extend({
/**
* @type {CustomerPage}
*/
customerPage: async ({ zhbPage }, use) => {
const customerPage = new CustomerPage(zhbPage);
customerPage: async ({ mgjPage }, use) => {
const customerPage = new CustomerPage(mgjPage);
await use(customerPage);
},
});

View File

@ -0,0 +1,14 @@
const { test: base, expect } = require('./base');
const { H5LoginPage } = require('../pom/hlk/h5LoginPage');
const test = base.extend({
/**
* @type {H5LoginPage}
*/
h5LoginPage: async ({ h5Page }, use) => {
const h5LoginPage = new H5LoginPage(h5Page);
await use(h5LoginPage);
},
});
module.exports = { test, expect };

View File

@ -46,7 +46,7 @@ export class CustomerPage {
.locator('span')
.first()
.click();
await this.page.getByText('创建', { exact: true }).click();
await this.page.getByText('创建并选择').click();
await expect(this.page.getByText('用户资料创建成功!')).toBeVisible();
await this.page.getByText('以后再说').click();
await expect(this.page.getByText('以后再说')).not.toBeVisible();

View File

@ -0,0 +1,19 @@
class H5LoginPage {
constructor(page) {
this.page = page;
this.$account = this.page.locator('.input', { hasText: '请输入手机号码' }).locator('input');
this.$SMSCode = this.page.locator('.input', { hasText: '请输入验证码' }).locator('input');
this.$loginBtn = this.page.locator('uni-button').filter({ hasText: /^登录$/ });
}
login = async (account) => {
await this.page.locator('.login_btn').click();
await this.$account.click();
await this.$account.fill(account);
await this.$SMSCode.fill(process.env.SMSCODE);
await this.page.getByText('同意隐私协议').click();
await this.$loginBtn.click();
};
}
module.exports = { H5LoginPage };

View File

@ -2,15 +2,16 @@ const { test: setup, expect } = require('@playwright/test');
const path = require('path');
const mgjAuthFile = path.join(__dirname, '../../.auth/mgj_admin.json');
setup('mgj管理员登录', async ({ page,baseURL }) => {
setup('mgj管理员登录', async ({ page, baseURL }) => {
const account = process.env.MGJ_ACCOUNT;
const password = process.env.MGJ_PASSWORD;
await page.goto(baseURL);
await page.getByPlaceholder('请输入您的用户名').fill(account);
await page.getByText('点击此处帐号登录').click();
await page.getByPlaceholder('用户名').fill(account);
await page.getByPlaceholder('请输入密码').fill(password);
await page.getByText('登录', { exact: true }).click();
await expect(page.getByRole('link', { name: '管理层' })).toBeVisible();
await page.locator('#shopSelect').getByText('一店').click();
await expect(page.locator('#autoStationTip').getByText('我知道了')).toBeVisible();
await page.context().storageState({ path: mgjAuthFile });
});

View File

@ -1,6 +1,7 @@
const { test: setup, expect } = require('@playwright/test');
const path = require('path');
const zhbAuthFile = path.join(__dirname, '../../.auth/zhb_admin.json');
const zhbAuthFile = '.auth/zhb.json';
const zhbAdminAuthFile = '.auth/zhb_admin.json';
setup('zhb总部管理员登录', async ({ page, baseURL }) => {
const account = process.env.ZHB_ACCOUNT;
@ -18,3 +19,22 @@ setup('zhb总部管理员登录', async ({ page, baseURL }) => {
await expect(page.locator('#tab_main li').filter({ hasText: '营业' })).toBeVisible();
await page.context().storageState({ path: zhbAuthFile });
});
// setup('zhb管理页面登录', async ({ page }) => {
// const account = process.env.ZHB_ACCOUNT;
// const password = process.env.ZHB_PASSWORD;
// const baseURL = process.env.ZHB_ADMIN_URL;
// await page.goto(baseURL);
// await page.getByPlaceholder('账户').fill(account);
// await page.getByPlaceholder('密码').fill(password);
// await page.getByRole('button', { name: '登 录' }).click();
// await expect(page.locator('a').filter({ hasText: /^收银$/ })).toBeVisible();
// await page
// .locator('a')
// .filter({ hasText: /^顾客$/ })
// .click();
// await expect(page.getByText('顾客概要分析')).toBeVisible();
// await page.context().storageState({ path: zhbAdminAuthFile });
// });

42
tests/utils/helper.js Normal file
View File

@ -0,0 +1,42 @@
const sharp = require('sharp');
const Tesseract = require('tesseract.js');
const path = require('path');
/**
* 处理图像并进行验证码识别
* @param {string} inputImageName - 输入图像文件名位于 .images 文件夹内
* @param {string} outputImageName - 输出处理后图像的文件名位于 .images 文件夹内
* @returns {Promise<string>} - 返回识别的文本结果
*/
async function processAndRecognizeCaptcha(inputImagePath, outputImagePath) {
try {
// 图像处理
await sharp(inputImagePath)
// .sharpen()
.modulate({
brightness: 1.2, // 增加亮度
contrast: 1.5, // 增强对比度
})
.resize(800) // 调整图像宽度为800像素保持纵横比
.grayscale() // 转换为灰度图
.threshold(128) // 二值化阈值设定为128
.toFile(outputImagePath);
console.log('图像处理完成:', outputImagePath);
// 图像识别
const {
data: { text },
} = await Tesseract.recognize(outputImagePath, 'eng', {
langPath: './tessdata',
});
console.log('识别结果:', text.trim());
return text.replace(/\s+/g, '').trim(); // 返回识别的文本结果
} catch (err) {
console.error('处理或识别出错:', err);
throw err; // 将错误抛出以供调用者处理
}
}
module.exports = { processAndRecognizeCaptcha };

118
tests/zhb/csv-demo.spec.js Normal file
View File

@ -0,0 +1,118 @@
const path = require('path');
const { parse } = require('csv-parse/sync');
const fs = require('fs');
const { faker } = require('@faker-js/faker');
const { test, expect } = require('./fixture/common');
const { Customer } = require('./pom/customerPage');
const records = parse(fs.readFileSync(path.join(__dirname, 'zhb.csv')), {
columns: true,
skip_empty_lines: true,
});
test('csv', async ({ zhbPage }, workerInfo) => {
console.log(records.length);
const $area = zhbPage
.locator('.area')
.filter({ has: zhbPage.locator('.area-name', { hasText: '二楼' }) });
const $$room = $area.locator('.room-list .room');
// 随机csv文件中的任意一个顾客
const record = records[faker.number.int({ min: 0, max: records.length - 1 })];
const { name, phone } = record;
console.log({ name, phone });
const customer = new Customer({ name: name, phone: name });
// 使用房间名称
let useRoomName;
await test.step('购买商品', async () => {
await zhbPage.locator('#tab_main li').filter({ hasText: '营业' }).click();
const $emptyRoom = $$room
.filter({ has: zhbPage.getByText('空房') })
.nth(workerInfo.workerIndex % 3);
useRoomName = await $emptyRoom.locator('.roomName').innerText();
expect(useRoomName).not.toBeNull();
await $emptyRoom.click();
await expect(async () => {
if (await zhbPage.locator('.close > .iconfont').first().isVisible()) {
await zhbPage.locator('.close > .iconfont').first().click();
}
await zhbPage.getByRole('button', { name: '选择顾客' }).click({ timeout: 3000 });
await expect(zhbPage.locator('#page_searchMember').getByText('创建会员')).toBeVisible();
}).toPass();
await zhbPage
.getByRole('textbox', { name: '输入会员手机号或姓名或卡号搜索' })
.fill(customer.phone, { delay: 100 });
await zhbPage.locator('#page_searchMember svg').click();
const $customerTr = zhbPage
.locator('.list-warp')
.filter({ has: zhbPage.locator('.name', { hasText: customer.name }) });
await $customerTr.locator('.list-body').first().click();
await zhbPage.getByText('项目开单').click();
await expect(zhbPage.locator('#page_roomDetail').getByText('服务项目')).toBeVisible();
await zhbPage.getByText('选择', { exact: true }).nth(1).click();
await expect(zhbPage.locator('#serviceSelector').getByText('项目选择')).toBeVisible();
await zhbPage
.locator('.goods-content-item')
.nth(faker.number.int({ min: 0, max: 14 }))
.click();
await zhbPage.locator('#serviceSelector').getByText('确认').click();
await zhbPage
.locator('div')
.filter({ hasText: /^明星足浴$/ })
.locator('span')
.first()
.click();
await zhbPage.getByRole('button', { name: '完成开单' }).click();
await expect(zhbPage.getByRole('button', { name: '结账' })).toBeVisible({ timeout: 30_000 });
await zhbPage.getByRole('button', { name: '结账' }).click();
await zhbPage.locator('#page_footBathPay').getByText('结算签字').click();
await expect(async () => {
await zhbPage.locator('#page_footBathPay li').filter({ hasText: '现金' }).click();
await expect(zhbPage.locator('#page_footBathPay li').filter({ hasText: '现金' })).toHaveClass(
/selected/
);
await zhbPage
.locator('#page_footBathPay span')
.filter({ hasText: /结\s算/ })
.click();
await expect(zhbPage.getByText('顾客满意度点评')).toBeVisible({ timeout: 2000 });
}).toPass();
await zhbPage.getByText('不想评价').click();
await zhbPage.locator('#page_footBathPay').getByText('立即返回').click();
});
await test.step('起钟下钟,清理房间', async () => {
const $cleanRoom = $$room.filter({
has: zhbPage.locator('.roomName', { hasText: new RegExp(`^${useRoomName}$`) }),
});
await expect($cleanRoom).toContainText('已结清');
await $cleanRoom.click();
await zhbPage.getByText('技师操作').click();
await zhbPage.getByText('起钟', { exact: true }).click();
await zhbPage.getByText('起钟成功!').click();
await zhbPage.getByText('技师操作').click();
await zhbPage.getByText('下钟', { exact: true }).click();
await zhbPage
.locator('div')
.filter({ hasText: /^确认返回$/ })
.locator('div')
.first()
.click();
await zhbPage.getByRole('button', { name: '不需要' }).click();
await expect($cleanRoom).toContainText('打扫');
await $cleanRoom.click();
await zhbPage
.locator('div')
.filter({ hasText: /^确定取消$/ })
.locator('div')
.first()
.click();
await expect($cleanRoom).toContainText('空房');
});
});

View File

@ -1,25 +1,33 @@
const { faker } = require('@faker-js/faker');
const { test, expect } = require('./fixture/common');
const { Customer } = require('./pom/customerPage');
test('demo', async ({ zhbPage, customerPage }) => {
test(`demo`, async ({ zhbPage, customerPage }, workerInfo) => {
const $area = zhbPage
.locator('.area')
.filter({ has: zhbPage.locator('.area-name', { hasText: '二楼' }) });
const $$room = $area.locator('.room-list .room');
await zhbPage.locator('#tab_main li').filter({ hasText: '顾客' }).click();
const customer = new Customer();
await customerPage.createCustomer(customer);
await test.step('创建顾客', async () => {
await zhbPage.locator('#tab_main li').filter({ hasText: '顾客' }).click();
await customerPage.createCustomer(customer);
});
let useRoomName;
await test.step('购买商品', async () => {
await zhbPage.locator('#tab_main li').filter({ hasText: '营业' }).click();
const $emptyRoom = $$room.filter({ has: zhbPage.getByText('空房') }).first();
const $emptyRoom = $$room
.filter({ has: zhbPage.getByText('空房') })
.nth(workerInfo.workerIndex % 3);
useRoomName = await $emptyRoom.locator('.roomName').innerText();
expect(useRoomName).not.toBeNull();
await $emptyRoom.click();
await expect(async () => {
await zhbPage.getByRole('button', { name: '选择顾客' }).click();
if (await zhbPage.locator('.close > .iconfont').first().isVisible()) {
await zhbPage.locator('.close > .iconfont').first().click();
}
await zhbPage.getByRole('button', { name: '选择顾客' }).click({ timeout: 3000 });
await expect(zhbPage.locator('#page_searchMember').getByText('创建会员')).toBeVisible();
}).toPass();
await zhbPage
@ -36,16 +44,19 @@ test('demo', async ({ zhbPage, customerPage }) => {
await expect(zhbPage.locator('#page_roomDetail').getByText('服务项目')).toBeVisible();
await zhbPage.getByText('选择', { exact: true }).nth(1).click();
await expect(zhbPage.locator('#serviceSelector').getByText('项目选择')).toBeVisible();
await zhbPage.getByText('臻品足疗 (10101)').click();
await zhbPage
.locator('.goods-content-item')
.nth(faker.number.int({ min: 0, max: 14 }))
.click();
await zhbPage.locator('#serviceSelector').getByText('确认').click();
await zhbPage
.locator('div')
.filter({ hasText: /^星足浴$/ })
.filter({ hasText: /^星足浴$/ })
.locator('span')
.first()
.click();
await zhbPage.getByRole('button', { name: '完成开单' }).click();
await expect(zhbPage.getByRole('button', { name: '结账' })).toBeVisible();
await expect(zhbPage.getByRole('button', { name: '结账' })).toBeVisible({ timeout: 30_000 });
await zhbPage.getByRole('button', { name: '结账' }).click();
await zhbPage.locator('#page_footBathPay').getByText('结算签字').click();
@ -62,7 +73,7 @@ test('demo', async ({ zhbPage, customerPage }) => {
}).toPass();
await zhbPage.getByText('不想评价').click();
await expect(zhbPage.locator('#page_footBathPay').getByText('立即返回')).not.toBeVisible();
await zhbPage.locator('#page_footBathPay').getByText('立即返回').click();
});
await test.step('起钟下钟,清理房间', async () => {
@ -95,3 +106,97 @@ test('demo', async ({ zhbPage, customerPage }) => {
await expect($cleanRoom).toContainText('空房');
});
});
test.skip('h5 demo', async ({
zhbAdminPage,
// zhbPage,
h5Page,
h5LoginPage,
// customerPage
}) => {
// const customer = new Customer();
// await test.step('创建顾客', async () => {
// await zhbPage.locator('#tab_main li').filter({ hasText: '顾客' }).click();
// await customerPage.createCustomer(customer);
// });
// await test.step('搜索顾客进行开卡', async () => {
// await zhbPage.getByRole('textbox', { name: '输入会员手机号或姓名搜索' }).fill(customer.phone);
// await zhbPage.locator('#page_member svg').click();
// await zhbPage
// .locator('.searchresultBox tbody tr')
// .first()
// .locator('#page_member')
// .getByText('详情')
// .click();
// await expect(zhbPage.getByText('会员卡 点击卡片即可用卡进行结算哦~')).toBeVisible();
// await zhbPage
// .locator('p')
// .filter({ hasText: '会员卡 点击卡片即可用卡进行结算哦~' })
// .locator('span')
// .nth(2)
// .click();
// await zhbPage.locator('#page_memberCard').getByText('5000元储值卡', { exact: true }).click();
// await expect(zhbPage.locator('#page_memberCard .cashierBox tbody tr').first()).toBeVisible();
// await zhbPage
// .locator('#page_memberCard')
// .getByText(/结\s算/)
// .click();
// await expect(async () => {
// const $signature = zhbPage.locator('#page_pay').getByText('结算签字');
// await $signature.click();
// await expect($signature).not.toHaveClass(/checked/, { timeout: 2000 });
// }).toPass();
// await expect(async () => {
// const $cashBtn = zhbPage.locator('#page_pay .pay_cash');
// await $cashBtn.click();
// await expect(zhbPage.locator('#page_pay .pay_cash.selected')).toBeVisible();
// await zhbPage
// .locator('#page_pay span')
// .filter({ hasText: /结\s算/ })
// .click();
// await expect(zhbPage.locator('#payConfirm').getByText('立即返回')).not.toBeVisible({
// timeout: 2000,
// });
// }).toPass();
// });
const $smsCodeInput = h5Page.getByRole('textbox', { name: '验证码', exact: true });
await test.step('获取手机验证码', async () => {
const graphCode = await h5LoginPage.sendSmsCode('17770898274');
await h5Page.getByRole('textbox', { name: '请输入图形验证码' }).fill(graphCode);
await h5Page.locator('#setup_loginForm').getByText('获取验证码').nth(1).first().tap();
await expect(h5Page.getByText('重新发送')).toBeVisible();
});
let smsCode;
await test.step('获取短信验证码', async () => {
await zhbAdminPage
.locator('a')
.filter({ hasText: /^管理$/ })
.click();
await zhbAdminPage.locator('.menu-item').getByText('短信发送记录', { exact: true }).click();
const $smsCodeTr = zhbAdminPage
.locator('#routerView iframe')
.contentFrame()
.locator('.table-responsive tbody tr')
.filter({ hasText: '17770898274' })
.first()
.locator('td')
.nth(2);
await expect($smsCodeTr).toBeVisible();
const text = await $smsCodeTr.innerText();
smsCode = text.match(/验证码是(\d{4})/)[1];
});
expect(smsCode).not.toBeUndefined();
await test.step('使用短信验证码登录h5', async () => {
await h5Page.getByRole('textbox', { name: '验证码', exact: true }).fill(smsCode);
await h5Page.locator('#setup_loginForm span').first().tap();
await h5Page.getByText('绑定', { exact: true }).tap();
await h5Page.waitForTimeout(5000);
});
});

View File

@ -1,12 +1,13 @@
const { test: base, expect } = require('@playwright/test');
const authFile = '.auth/zhb_admin.json';
const { test: base, expect, devices } = require('@playwright/test');
const zhbAuthFile = '.auth/zhb.json';
const zhbAdminAuthFile = '.auth/zhb_admin.json';
const test = base.extend({
/**
* @type {import('@playwright/test').Page}
*/
zhbPage: async ({ browser, baseURL }, use) => {
const context = await browser.newContext({
storageState: authFile,
storageState: zhbAuthFile,
});
const page = await context.newPage();
await page.goto(baseURL);
@ -17,6 +18,47 @@ const test = base.extend({
await page.close();
await context.close();
},
/**
* @type {import('@playwright/test').Page}
*/
zhbAdminPage: async ({ browser }, use) => {
const baseURL = process.env.ZHB_ADMIN_URL;
const account = process.env.ZHB_ACCOUNT;
const password = process.env.ZHB_PASSWORD;
const context = await browser.newContext({
storageState: zhbAdminAuthFile,
});
const page = await context.newPage();
await page.goto(baseURL);
console.log(baseURL);
await page.getByPlaceholder('账户').fill(account);
await page.getByPlaceholder('密码').fill(password);
await page.getByRole('button', { name: '登 录' }).click();
await expect(page.locator('a').filter({ hasText: /^收银$/ })).toBeVisible();
await use(page);
await page.close();
await context.close();
},
/**
* @type {import('@playwright/test').Page}
*/
h5Page: async ({ browser }, use) => {
const baseURL = process.env.ZHB_H5_URL;
const iPhone = devices['iPhone 14'];
const context = await browser.newContext({
...iPhone,
storageState: undefined,
hasTouch: true,
isMobile: true, // 设置为移动设备
viewport: iPhone.viewport, // 使用 iPhone 的视口配置
});
const page = await context.newPage();
await page.goto(baseURL);
await use(page);
},
});
module.exports = {

View File

@ -1,6 +1,8 @@
const { mergeTests } = require('@playwright/test');
const { test: baseTest } = require('./base');
const { test: h5LoginTest } = require('./h5Fixture');
const { test: customerTest } = require('./customerFixture');
export const test = mergeTests(customerTest);
export const test = mergeTests(baseTest, customerTest, h5LoginTest);
export { expect } from '@playwright/test';

View File

@ -0,0 +1,14 @@
const { test: base, expect } = require('./base');
const { H5LoginPage } = require('../pom/h5LoginPage');
const test = base.extend({
/**
* @type {H5LoginPage}
*/
h5LoginPage: async ({ h5Page }, use) => {
const h5LoginPage = new H5LoginPage(h5Page);
await use(h5LoginPage);
},
});
module.exports = { test, expect };

View File

@ -4,7 +4,7 @@ const { expect } = require('@playwright/test');
export class Customer {
constructor({
name = faker.person.fullName(),
phone = faker.helpers.fromRegExp(/1[3-9][0-9]{6}/),
phone = faker.helpers.fromRegExp(/123[0-5]{8}/),
} = {}) {
this.name = name;
this.phone = phone;
@ -12,9 +12,6 @@ export class Customer {
}
export class CustomerPage {
/**
* @param {import('@playwright/test').Page} page
*/
constructor(page) {
this.page = page;
}
@ -34,7 +31,7 @@ export class CustomerPage {
await this.page.getByPlaceholder('请输入手机号码').click();
await expect(this.page.getByText('请输入数字')).toBeVisible();
await this.page.getByPlaceholder('在此输入').click();
await this.page.keyboard.type(customer.phone, { delay: 100 });
await this.page.keyboard.type(customer.phone, { delay: 50 });
// await this.page.getByPlaceholder('在此输入').type(customer.phone, { delay: 100 });
await this.page.locator('#maskBoard').getByText('确认').click();
await expect(this.page.getByPlaceholder('请输入手机号码')).toHaveValue(customer.phone, {

View File

@ -0,0 +1,25 @@
const { processAndRecognizeCaptcha } = require('../../utils/helper');
class H5LoginPage {
constructor(page) {
this.page = page;
this.$account = this.page.getByPlaceholder('此处请输入手机号');
this.$GraphCode = this.page.getByRole('textbox', { name: '请输入图形验证码' });
this.$SmsCode = this.page.getByRole('textbox', { name: '验证码', exact: true });
this.$loginBtn = this.page.locator('uni-button').filter({ hasText: /^登录$/ });
}
sendSmsCode = async (account) => {
const imagePath = '.images/captcha.png';
const outputImagePath = '.images/output-captcha.png';
await this.$account.fill(account);
const $graph = this.page.getByRole('img', { name: '图形验证码' });
await $graph.waitFor();
await $graph.screenshot({ path: imagePath });
return await processAndRecognizeCaptcha(imagePath, outputImagePath);
};
}
module.exports = { H5LoginPage };

201
tests/zhb/zhb.csv Normal file
View File

@ -0,0 +1,201 @@
name,phone
郸志国,12334502225
纵佳琪,12352301430
马熙瑶,12350424001
应国平,12314501244
委强,12322301255
吕苡沫,12314440133
柴沐辰,12311131155
史国香,12333211154
易天娇,12351430503
靖敬彪,12321535101
贡秀珍,12352123355
悉艺涵,12311403141
丁国芳,12343515153
喻芳,12311322132
析晨阳,12344201554
酒建国,12332133555
窦智杰,12304133243
玉子豪,12314500535
渠建军,12314142045
甲婷婷,12340453445
巫娟,12320023214
扈斌,12324211053
位杰,12311524133
斛沐阳,12311151435
驹志国,12305534111
盘美方,12322214351
柯婷,12314322025
马涛,12340204331
东政君,12332111030
梁玉兰,12355420144
安丽,12302350005
赫俊杰,12341541431
尉迟海燕,12313530222
礼国珍,12321141225
行梓豪,12343224431
拉国荣,12351411412
练国栋,12312010324
戎沐宸,12343432310
翟宇,12344114011
桂梓晨,12340344054
斋志明,12305321102
及万佳,12335454335
前雪,12345534331
伦英,12321322045
柏立伟,12345251522
招欣怡,12324401040
首茗泽,12323330351
计乙萍,12303514002
线婷方,12324501502
九秀珍,12344040353
茂蒙,12312210221
红婷方,12340215445
扈倩,12354532031
原立伟,12342524245
祖丽芳,12322124425
蓬雨欣,12340321430
定瑜,12350252355
望丽萍,12311313430
铁家豪,12352502012
闳雅鑫,12313242150
单于燕,12314042132
杜奕泽,12345103503
尉丽芳,12323404415
徭国平,12321014220
羽志国,12311511234
弥安琪,12322541510
阮梓玥,12302200542
呼波,12351535225
玉呈轩,12304451524
针熙瑶,12354523544
帖国平,12305535553
班天娇,12330411042
藏秀珍,12304203153
计国琴,12351531450
鄢国珍,12343500300
屈国兰,12313202405
齐子欣,12355341152
曹安琪,12355140413
甫建华,12354544421
苗丽芬,12311142041
完倩,12324441204
綦雯静,12304221302
蔺志明,12322530542
磨晨阳,12315334001
友秀珍,12312034423
历燕,12330435540
飞文昊,12315150424
萧鹏,12333512443
用中海,12334505210
竭智杰,12312530202
次国琴,12331300513
乙一诺,12304041145
析志明,12340411012
曲红,12320421131
闫馨羽,12332235531
卷语桐,12305350101
旷丹,12351401021
植玉梅,12340034300
祖国栋,12310142153
乙艺涵,12301532402
海芳,12313345003
枝敬彪,12324501125
雍国秀,12340243412
章佳紫林,12320333352
充丽萍,12322423001
百雅鑫,12333040513
鹿治涛,12324533401
慎文韬,12350423141
谯梓涵,12301052044
针振东,12353344501
绍奕辰,12350005540
仉文昊,12332320502
元梓玥,12335424410
祝浩宇,12311335301
来斌,12300325534
刁志明,12320244541
首兰英,12311150011
练安琪,12342301055
唐雯静,12312505520
郝天娇,12312520301
庄丽芳,12353444410
源依诺,12342341501
诸丽芬,12312415203
朱慧,12344511420
绍国辉,12341315304
肥志明,12304445132
包文韬,12330305102
钱倩,12350342140
樊丽芳,12332020302
钱雨欣,12304114004
鱼静,12331411232
速宇泽,12331502245
叔沐宸,12335305514
进国英,12314454234
费慧,12304155020
漆治文,12352421501
示雪,12353154301
劳颖,12343235112
谈馥君,12343113130
兆呈轩,12320135205
萧文韬,12304320034
漫军,12321552123
施国珍,12330141235
纳静怡,12341035053
贰阳,12305451142
呼义轩,12315402403
植语桐,12335354425
路国荣,12304330054
支梓豪,12333434504
蔚宇航,12321411124
第宇航,12342053534
校海燕,12301142130
纳喇诗雨,12323221524
浑呈轩,12351243530
弓梓馨,12353030231
常玉梅,12352425540
冀丽萍,12343501540
北民,12321312355
栋勇,12321145441
原桂兰,12352325455
陈榕融,12315235050
况伟,12353031413
丁浩辰,12345310354
郭斌,12352334430
巴蒙,12344251134
可艳,12310255512
玄浩辰,12331503043
沙呈轩,12302013431
荤成,12344214445
林熙瑶,12305423343
葛梓睿,12314114055
湛斌,12345150514
由静,12300130254
侯振东,12324015213
贺单,12301145101
所宇轩,12331420152
颜颖,12300005420
咎玉梅,12352454144
占俊杰,12324402343
觉罗秀珍,12311240034
范姜丽,12330542141
弘梓浩,12343343451
通雨欣,12331513024
丘梓诚,12344112043
贵梓晨,12311414030
狄悦,12332305454
穆凤英,12335205455
金智杰,12301542505
蒙癸霖,12305252022
诺兰英,12303005354
帛娟,12304243114
在国英,12355121223
严芳,12355412233
狄治文,12320503352
律雨欣,12345523042
偶敬彪,12332433431
求佳琪,12300144202
唐中海,12351305521
第治涛,12300442432
壬家明,12335343552
1 name phone
2 郸志国 12334502225
3 纵佳琪 12352301430
4 马熙瑶 12350424001
5 应国平 12314501244
6 委强 12322301255
7 吕苡沫 12314440133
8 柴沐辰 12311131155
9 史国香 12333211154
10 易天娇 12351430503
11 靖敬彪 12321535101
12 贡秀珍 12352123355
13 悉艺涵 12311403141
14 丁国芳 12343515153
15 喻芳 12311322132
16 析晨阳 12344201554
17 酒建国 12332133555
18 窦智杰 12304133243
19 玉子豪 12314500535
20 渠建军 12314142045
21 甲婷婷 12340453445
22 巫娟 12320023214
23 扈斌 12324211053
24 位杰 12311524133
25 斛沐阳 12311151435
26 驹志国 12305534111
27 盘美方 12322214351
28 柯婷 12314322025
29 马涛 12340204331
30 东政君 12332111030
31 梁玉兰 12355420144
32 安丽 12302350005
33 赫俊杰 12341541431
34 尉迟海燕 12313530222
35 礼国珍 12321141225
36 行梓豪 12343224431
37 拉国荣 12351411412
38 练国栋 12312010324
39 戎沐宸 12343432310
40 翟宇 12344114011
41 桂梓晨 12340344054
42 斋志明 12305321102
43 及万佳 12335454335
44 前雪 12345534331
45 伦英 12321322045
46 柏立伟 12345251522
47 招欣怡 12324401040
48 首茗泽 12323330351
49 计乙萍 12303514002
50 线婷方 12324501502
51 九秀珍 12344040353
52 茂蒙 12312210221
53 红婷方 12340215445
54 扈倩 12354532031
55 原立伟 12342524245
56 祖丽芳 12322124425
57 蓬雨欣 12340321430
58 定瑜 12350252355
59 望丽萍 12311313430
60 铁家豪 12352502012
61 闳雅鑫 12313242150
62 单于燕 12314042132
63 杜奕泽 12345103503
64 尉丽芳 12323404415
65 徭国平 12321014220
66 羽志国 12311511234
67 弥安琪 12322541510
68 阮梓玥 12302200542
69 呼波 12351535225
70 玉呈轩 12304451524
71 针熙瑶 12354523544
72 帖国平 12305535553
73 班天娇 12330411042
74 藏秀珍 12304203153
75 计国琴 12351531450
76 鄢国珍 12343500300
77 屈国兰 12313202405
78 齐子欣 12355341152
79 曹安琪 12355140413
80 甫建华 12354544421
81 苗丽芬 12311142041
82 完倩 12324441204
83 綦雯静 12304221302
84 蔺志明 12322530542
85 磨晨阳 12315334001
86 友秀珍 12312034423
87 历燕 12330435540
88 飞文昊 12315150424
89 萧鹏 12333512443
90 用中海 12334505210
91 竭智杰 12312530202
92 次国琴 12331300513
93 乙一诺 12304041145
94 析志明 12340411012
95 曲红 12320421131
96 闫馨羽 12332235531
97 卷语桐 12305350101
98 旷丹 12351401021
99 植玉梅 12340034300
100 祖国栋 12310142153
101 乙艺涵 12301532402
102 海芳 12313345003
103 枝敬彪 12324501125
104 雍国秀 12340243412
105 章佳紫林 12320333352
106 充丽萍 12322423001
107 百雅鑫 12333040513
108 鹿治涛 12324533401
109 慎文韬 12350423141
110 谯梓涵 12301052044
111 针振东 12353344501
112 绍奕辰 12350005540
113 仉文昊 12332320502
114 元梓玥 12335424410
115 祝浩宇 12311335301
116 来斌 12300325534
117 刁志明 12320244541
118 首兰英 12311150011
119 练安琪 12342301055
120 唐雯静 12312505520
121 郝天娇 12312520301
122 庄丽芳 12353444410
123 源依诺 12342341501
124 诸丽芬 12312415203
125 朱慧 12344511420
126 绍国辉 12341315304
127 肥志明 12304445132
128 包文韬 12330305102
129 钱倩 12350342140
130 樊丽芳 12332020302
131 钱雨欣 12304114004
132 鱼静 12331411232
133 速宇泽 12331502245
134 叔沐宸 12335305514
135 进国英 12314454234
136 费慧 12304155020
137 漆治文 12352421501
138 示雪 12353154301
139 劳颖 12343235112
140 谈馥君 12343113130
141 兆呈轩 12320135205
142 萧文韬 12304320034
143 漫军 12321552123
144 施国珍 12330141235
145 纳静怡 12341035053
146 贰阳 12305451142
147 呼义轩 12315402403
148 植语桐 12335354425
149 路国荣 12304330054
150 支梓豪 12333434504
151 蔚宇航 12321411124
152 第宇航 12342053534
153 校海燕 12301142130
154 纳喇诗雨 12323221524
155 浑呈轩 12351243530
156 弓梓馨 12353030231
157 常玉梅 12352425540
158 冀丽萍 12343501540
159 北民 12321312355
160 栋勇 12321145441
161 原桂兰 12352325455
162 陈榕融 12315235050
163 况伟 12353031413
164 丁浩辰 12345310354
165 郭斌 12352334430
166 巴蒙 12344251134
167 可艳 12310255512
168 玄浩辰 12331503043
169 沙呈轩 12302013431
170 荤成 12344214445
171 林熙瑶 12305423343
172 葛梓睿 12314114055
173 湛斌 12345150514
174 由静 12300130254
175 侯振东 12324015213
176 贺单 12301145101
177 所宇轩 12331420152
178 颜颖 12300005420
179 咎玉梅 12352454144
180 占俊杰 12324402343
181 觉罗秀珍 12311240034
182 范姜丽 12330542141
183 弘梓浩 12343343451
184 通雨欣 12331513024
185 丘梓诚 12344112043
186 贵梓晨 12311414030
187 狄悦 12332305454
188 穆凤英 12335205455
189 金智杰 12301542505
190 蒙癸霖 12305252022
191 诺兰英 12303005354
192 帛娟 12304243114
193 在国英 12355121223
194 严芳 12355412233
195 狄治文 12320503352
196 律雨欣 12345523042
197 偶敬彪 12332433431
198 求佳琪 12300144202
199 唐中海 12351305521
200 第治涛 12300442432
201 壬家明 12335343552