首次提交
@ -0,0 +1,5 @@
|
||||
node_modules/
|
||||
Android-SDK*/
|
||||
uni_modules/
|
||||
unpackage/
|
||||
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"version" : "1.0",
|
||||
"configurations" : [
|
||||
{
|
||||
"openVueDevtools" : true,
|
||||
"playground" : "standard",
|
||||
"type" : "uni-app:app-android"
|
||||
},
|
||||
{
|
||||
"app-plus" : {
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"type" : "uniCloud"
|
||||
},
|
||||
{
|
||||
"openVueDevtools" : true,
|
||||
"type" : "uni-app:app-ios"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
import request from '@/utils/network/request';
|
||||
|
||||
/**
|
||||
* 登录接口
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function login (params) {
|
||||
return request({
|
||||
url: '/api/user.ashx?act=studentlogin',
|
||||
method: 'GET',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 登出接口
|
||||
*/
|
||||
export function logout () {
|
||||
return request({
|
||||
url: '',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
export function getImgData(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url,
|
||||
method: 'GET',
|
||||
responseType: 'arraybuffer',
|
||||
success: (e) => {
|
||||
const imgData = uni.arrayBufferToBase64(e.data)
|
||||
const imgBase64 = 'data:image/png;base64,' + imgData
|
||||
// resolve(e.data)
|
||||
resolve(imgBase64)
|
||||
},
|
||||
fail: (error) => {
|
||||
console.log(error)
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
import request from '@/utils/network/request';
|
||||
|
||||
/**
|
||||
* 获取学校列表
|
||||
*/
|
||||
export function getSchoolList() {
|
||||
return request({
|
||||
url: '/api/user.ashx?act=getschoollist',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取年纪列表
|
||||
*/
|
||||
export function getGradeList () {
|
||||
return request({
|
||||
url: '/api/user.ashx?act=getgradelist',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取科目列表
|
||||
*/
|
||||
export function getSubjectList () {
|
||||
return request({
|
||||
url: '/api/user.ashx?act=getsubjectlist',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取知识点
|
||||
*/
|
||||
export function getKnowledgeList (data) {
|
||||
return request({
|
||||
url: '/api/user.ashx?act=getknowledgelist',
|
||||
method: 'GET',
|
||||
data
|
||||
})
|
||||
}
|
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,4 @@
|
||||
@import './common/config.scss';
|
||||
@import './common/function.scss';
|
||||
@import './common/mixins.scss';
|
||||
@import './common/setting.scss';
|
@ -0,0 +1,4 @@
|
||||
$namespace: 'ch';
|
||||
$element-separator: '__';
|
||||
$modifier-separator: '--';
|
||||
$state-prefix: 'is-';
|
@ -0,0 +1,43 @@
|
||||
@function selectorToString ($selector) {
|
||||
$selector: inspect($selector);
|
||||
$selector: str-slice($selector, 2, -2);
|
||||
@return $selector;
|
||||
}
|
||||
|
||||
// 选择器是否包含修饰符连接符 --
|
||||
@function containsModifier($selector) {
|
||||
$selector: selectorToString($selector);
|
||||
|
||||
@if (str-index($selector, $modifier-separator)) {
|
||||
@return true;
|
||||
} @else {
|
||||
@return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 选择器是否包含状态前缀 .is
|
||||
@function containWhenFlag($selector) {
|
||||
$selector: selectorToString($selector);
|
||||
|
||||
@if (str-index($selector, '.' + $state-prefix)) {
|
||||
@return true;
|
||||
} @else {
|
||||
@return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 选择器是否包含伪类选择器
|
||||
@function containPseudoClass($selector) {
|
||||
$selector: selectorToString($selector);
|
||||
|
||||
@if (str-index($selector, ':')) {
|
||||
@return true;
|
||||
} @else {
|
||||
@return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 选择器是否包含 -- 或 .is 或伪类选择器
|
||||
@function hitAllSpecialNestRule($selector) {
|
||||
@return containsModifier($selector) or containWhenFlag($selector) or containPseudoClass($selector);
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
// 声明块
|
||||
@mixin b($block) {
|
||||
$B: $namespace + '-' + $block !global;
|
||||
|
||||
.#{$B} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
// 声明元素
|
||||
@mixin e($element) {
|
||||
$E: $element !global;
|
||||
$selector: &;
|
||||
$currentSelector: '';
|
||||
|
||||
@each $unit in $element {
|
||||
$currentSelector: #{$currentSelector + '.' + $B + $element-separator + $unit + ','}
|
||||
}
|
||||
|
||||
@if hitAllSpecialNestRule($selector) {
|
||||
@at-root {
|
||||
#{$selector} {
|
||||
#{$currentSelector} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
} @else {
|
||||
@at-root {
|
||||
#{$currentSelector} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 声明修饰符
|
||||
@mixin m($modifier) {
|
||||
$selector: &;
|
||||
$currentSelector: '';
|
||||
|
||||
@each $unit in $modifier {
|
||||
$currentSelector: #{$currentSelector + $selector + $modifier-separator + $unit + ','}
|
||||
}
|
||||
|
||||
@at-root {
|
||||
#{$currentSelector} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
$main-width: 1400px;
|
@ -0,0 +1,5 @@
|
||||
@import './content/base.scss';
|
||||
@import './content/atoms.scss';
|
||||
@import './content/layout.scss';
|
||||
@import './content/module.scss';
|
||||
@import './content/cover.scss';
|
@ -0,0 +1,48 @@
|
||||
@for $i from 1 through 10 {
|
||||
$pd: $i*5;
|
||||
$mg: $i*5;
|
||||
|
||||
.pd-#{$pd} {
|
||||
padding: $pd + px;
|
||||
}
|
||||
|
||||
.pd-t-#{$pd} {
|
||||
padding-top: $pd + px;
|
||||
}
|
||||
|
||||
.pd-b-#{$pd} {
|
||||
padding-bottom: $pd + px;
|
||||
}
|
||||
|
||||
.pd-l-#{$pd} {
|
||||
padding-left: $pd + px;
|
||||
}
|
||||
|
||||
.pd-r-#{$pd} {
|
||||
padding-right: $pd + px;
|
||||
}
|
||||
|
||||
.mg-#{$mg} {
|
||||
margin: $mg + px;
|
||||
}
|
||||
|
||||
.mg-t-#{$mg} {
|
||||
margin-top: $mg + px;
|
||||
}
|
||||
|
||||
.mg-b-#{$mg} {
|
||||
margin-bottom: $mg + px;
|
||||
}
|
||||
|
||||
.mg-l-#{$mg} {
|
||||
margin-left: $mg + px;
|
||||
}
|
||||
|
||||
.mg-r-#{$mg} {
|
||||
margin-right: $mg + px;
|
||||
}
|
||||
}
|
||||
|
||||
.ptr {
|
||||
cursor: pointer;
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
@import './base/reset.scss';
|
||||
@import './base/typography.scss';
|
@ -0,0 +1,67 @@
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// a {
|
||||
// text-decoration: none;
|
||||
// color : inherit;
|
||||
// cursor : pointer;
|
||||
// }
|
||||
|
||||
// button {
|
||||
// background-color: transparent;
|
||||
// color : inherit;
|
||||
// border-width : 0;
|
||||
// padding : 0;
|
||||
// cursor : pointer;
|
||||
// }
|
||||
|
||||
// figure {
|
||||
// margin: 0;
|
||||
// }
|
||||
|
||||
// input::-moz-focus-inner {
|
||||
// border : 0;
|
||||
// padding: 0;
|
||||
// margin : 0;
|
||||
// }
|
||||
|
||||
// ul,
|
||||
// ol,
|
||||
// dd {
|
||||
// margin : 0;
|
||||
// padding : 0;
|
||||
// list-style: none;
|
||||
// }
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin : 0;
|
||||
font-size : inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
// cite {
|
||||
// font-style: normal;
|
||||
// }
|
||||
|
||||
// fieldset {
|
||||
// border-width: 0;
|
||||
// padding : 0;
|
||||
// margin : 0;
|
||||
// }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-size: $uni-font-size-base;
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
// :root {
|
||||
// --vt-c-white: #ffffff;
|
||||
// --vt-c-white-soft: #f8f8f8;
|
||||
// --vt-c-white-mute: #f2f2f2;
|
||||
|
||||
// --vt-c-black: #181818;
|
||||
// --vt-c-black-soft: #222222;
|
||||
// --vt-c-black-mute: #282828;
|
||||
|
||||
// --vt-c-indigo: #2c3e50;
|
||||
|
||||
// --vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
||||
// --vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
||||
// --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
||||
// --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
||||
|
||||
// --vt-c-text-light-1: var(--vt-c-indigo);
|
||||
// --vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
||||
// --vt-c-text-dark-1: var(--vt-c-white);
|
||||
// --vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
||||
// }
|
||||
|
||||
// /* semantic color variables for this project */
|
||||
// :root {
|
||||
// --color-background: var(--vt-c-white);
|
||||
// --color-background-soft: var(--vt-c-white-soft);
|
||||
// --color-background-mute: var(--vt-c-white-mute);
|
||||
|
||||
// --color-border: var(--vt-c-divider-light-2);
|
||||
// --color-border-hover: var(--vt-c-divider-light-1);
|
||||
|
||||
// --color-heading: var(--vt-c-text-light-1);
|
||||
// --color-text: var(--vt-c-text-light-1);
|
||||
|
||||
// --section-gap: 160px;
|
||||
// }
|
||||
|
||||
// @media (prefers-color-scheme: dark) {
|
||||
// :root {
|
||||
// --color-background: var(--vt-c-black);
|
||||
// --color-background-soft: var(--vt-c-black-soft);
|
||||
// --color-background-mute: var(--vt-c-black-mute);
|
||||
|
||||
// --color-border: var(--vt-c-divider-dark-2);
|
||||
// --color-border-hover: var(--vt-c-divider-dark-1);
|
||||
|
||||
// --color-heading: var(--vt-c-text-dark-1);
|
||||
// --color-text: var(--vt-c-text-dark-2);
|
||||
// }
|
||||
// }
|
||||
|
||||
// body {
|
||||
// min-height: 100vh;
|
||||
// color: var(--color-text);
|
||||
// background: var(--color-background);
|
||||
// transition: color 0.5s, background-color 0.5s;
|
||||
// line-height: 1.5;
|
||||
// font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
|
||||
// Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
// font-size: 14px;
|
||||
// text-rendering: optimizeLegibility;
|
||||
// -webkit-font-smoothing: antialiased;
|
||||
// -moz-osx-font-smoothing: grayscale;
|
||||
// }
|
@ -0,0 +1,13 @@
|
||||
@import './cover/button.scss';
|
||||
@import './cover/input.scss';
|
||||
@import './cover/form.scss';
|
||||
@import './cover/section.scss';
|
||||
@import './cover/list.scss';
|
||||
// @import './cover/nav-bar.scss';
|
||||
@import './cover/segmented-control.scss';
|
||||
@import './cover/select.scss';
|
||||
@import './cover/base.scss';
|
||||
@import './cover/check-list.scss';
|
||||
@import './cover/checkbox.scss';
|
||||
@import './cover/pagination.scss';
|
||||
@import './cover/load-more.scss';
|
@ -0,0 +1,4 @@
|
||||
text {
|
||||
font-size: $uni-font-size-base;
|
||||
line-height: $uni-font-size-base * 1.2;
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
uni-button {
|
||||
font-size: $uni-font-size-base!important;
|
||||
// height: 66px;
|
||||
// line-height: 66px!important;
|
||||
}
|
||||
|
||||
uni-button[size="mini"] {
|
||||
font-size: $uni-font-size-sm!important;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
.checklist-box {
|
||||
&.is--tag {
|
||||
padding: 20px 35px!important;
|
||||
}
|
||||
}
|
||||
|
||||
.checklist-text {
|
||||
font-size: $uni-font-size-base!important;
|
||||
line-height: $uni-font-size-base!important;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
.uni-checkbox-input {
|
||||
height: 34px!important;
|
||||
width: 34px!important;
|
||||
|
||||
svg {
|
||||
font-size: 40px!important;
|
||||
width: 34px!important;
|
||||
height: 34px!important;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
.uni-forms-item {
|
||||
&.is-direction-left {
|
||||
margin-bottom: 28px!important;
|
||||
}
|
||||
|
||||
.uni-forms-item__error {
|
||||
font-size: 22px!important;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
$input-font-size: 34px;
|
||||
|
||||
.uni-easyinput__content-input {
|
||||
height: 68px!important;
|
||||
font-size: $input-font-size!important;
|
||||
}
|
||||
|
||||
.uni-easyinput__placeholder-class {
|
||||
font-size: $uni-font-size-base!important;
|
||||
}
|
||||
|
||||
.uni-easyinput {
|
||||
.uni-icons {
|
||||
font-size: $input-font-size!important;
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
.uni-list-item__container {
|
||||
padding: 20rpx 26rpx!important;
|
||||
padding-left: 26rpx!important;
|
||||
}
|
||||
|
||||
.uni-list-item__content-title {
|
||||
font-size: $uni-font-size-base!important;
|
||||
}
|
||||
|
||||
.uni-list-item__content-note {
|
||||
font-size: $uni-font-size-sm!important;
|
||||
}
|
||||
|
||||
.uni-icon-wrapper {
|
||||
font-size: $uni-font-size-sm!important;
|
||||
}
|
||||
|
||||
.uni-list-item__extra-text {
|
||||
font-size: $uni-font-size-base!important;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
.uni-load-more {
|
||||
height: $uni-font-size-mini * 3!important;
|
||||
}
|
||||
|
||||
.uni-load-more__text {
|
||||
font-size: $uni-font-size-mini!important;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
.uni-pagination__total {
|
||||
font-size: $uni-font-size-mini!important;
|
||||
}
|
||||
|
||||
.uni-pagination__btn,
|
||||
.uni-pagination__child-btn,
|
||||
.uni-pagination__num {
|
||||
font-size: $uni-font-size-mini!important;
|
||||
line-height: $uni-font-size-mini * 1.5!important;
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
// .uni-section-header {
|
||||
// padding: 20rpx 16rpx !important;
|
||||
// }
|
||||
|
||||
// .uni-section__content-title {
|
||||
// font-size: 24rpx!important;
|
||||
// }
|
||||
|
||||
.uni-section__content-title {
|
||||
font-size: $uni-font-size-base!important;
|
||||
}
|
||||
|
||||
.uni-section-header__decoration {
|
||||
&.line {
|
||||
height: $uni-font-size-base - 8px!important;
|
||||
margin-right: 12px!important;
|
||||
}
|
||||
}
|
||||
|
||||
.uni-section-header {
|
||||
padding: 20px!important;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
.segmented-control {
|
||||
height: 56px!important;
|
||||
|
||||
.segmented-control__text {
|
||||
line-height: 46px;
|
||||
font-size: $uni-font-size-base!important;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
.uni-select__input-placeholder,
|
||||
.uni-select__selector-item,
|
||||
.uni-select__input-text{
|
||||
font-size: $uni-font-size-base!important;
|
||||
}
|
||||
|
||||
.uni-select__input-box,
|
||||
.uni-select {
|
||||
height: 66px!important;
|
||||
}
|
||||
|
||||
.uni-select__selector-item {
|
||||
line-height: 55px!important;
|
||||
}
|
||||
|
||||
.uni-select {
|
||||
background-color: #fff;
|
||||
|
||||
.uni-icons {
|
||||
font-size: 32px!important;
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
@import './layout/flex.scss';
|
@ -0,0 +1,73 @@
|
||||
@include b('flex') {
|
||||
display: flex;
|
||||
|
||||
@include m('row') {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
@include m('row-reverse') {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
@include m('column') {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@include m('column-reverse') {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
@include m('wrap') {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
@include m('wrap-reverse') {
|
||||
flex-wrap: wrap-reverse;
|
||||
}
|
||||
|
||||
@each $a in ['between', 'around', 'center', 'start', 'end '] {
|
||||
@if $a == 'between' or $a == 'around' {
|
||||
@include m('justify-#{$a}') {
|
||||
justify-content: space-#{$a};
|
||||
}
|
||||
} @else {
|
||||
@include m('justify-#{$a}') {
|
||||
justify-content: #{$a};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@each $a in ['stretch', 'center', 'start', 'end ', 'baseline'] {
|
||||
@if $a == 'start' or $a == 'end' {
|
||||
@include m('items-#{$a}') {
|
||||
align-items: flex-#{$a};
|
||||
}
|
||||
} @else {
|
||||
@include m('items-#{$a}') {
|
||||
align-items: #{$a};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@each $a in ['stretch', 'center', 'start', 'end ', 'between', 'around'] {
|
||||
@if $a == 'start' or $a == 'end' {
|
||||
@include m('align-#{$a}') {
|
||||
align-content: flex-#{$a};
|
||||
}
|
||||
} @else if $a == 'between' or $a == 'around'{
|
||||
@include m('align-#{$a}') {
|
||||
align-content: space-#{$a};
|
||||
}
|
||||
} @else {
|
||||
@include m('align-#{$a}') {
|
||||
align-content: #{$a};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@for $i from 1 through 24 {
|
||||
@include m(#{$i}) {
|
||||
flex: #{$i};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
@import './module/form.scss';
|
||||
@import './module/avatar.scss';
|
||||
@import './module/ep-footer.scss'
|
@ -0,0 +1,42 @@
|
||||
$boxSize-small: 80px;
|
||||
$boxSize-middle: 120px;
|
||||
$boxSize-large: 150px;
|
||||
|
||||
@include b('avatar-uploader') {
|
||||
@include e('box') {
|
||||
width: $boxSize-middle;
|
||||
height: $boxSize-middle;
|
||||
overflow: hidden;
|
||||
border-radius: 4px;
|
||||
border: 1px dashed var(--el-border-color-dark);
|
||||
background-color: var(--el-fill-color-lighter);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
@include m('middle') {
|
||||
width: $boxSize-middle;
|
||||
height: $boxSize-middle;
|
||||
}
|
||||
|
||||
@include m('small') {
|
||||
width: $boxSize-small;
|
||||
height: $boxSize-small;
|
||||
}
|
||||
|
||||
@include m('large') {
|
||||
width: $boxSize-large;
|
||||
height: $boxSize-large;
|
||||
}
|
||||
}
|
||||
|
||||
@include e('img') {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
@include e('icon') {
|
||||
font-size: 20px;
|
||||
color: var(--el-text-color-secondary )
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
.ep-footer {
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
.ep-footer__list {
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
padding: 20px 0;
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.ep-footer__module {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
+ .ep-footer__module {
|
||||
margin-left: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
.ep-footer__title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ep-footer__item {
|
||||
line-height: 22px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ep-footer__copyright {
|
||||
color: #fff;
|
||||
line-height: 40px;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
$explainFontSize: 12px;
|
||||
|
||||
.form-item-explain {
|
||||
font-size: $explainFontSize;
|
||||
color: var(--el-color-info-dark-2);
|
||||
line-height: 1.5;
|
||||
margin-top: $explainFontSize * 1.4;
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
@import './common.scss';
|
||||
@import './content.scss';
|
@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<view class="ch-flex-item" :class="flexCls">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, defineProps } from 'vue';
|
||||
|
||||
const props = defineProps([
|
||||
'flex'
|
||||
])
|
||||
|
||||
const flexCls = computed(() => {
|
||||
return props.flex ? `ch-flex--${props.flex}` : ''
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './ch-flex-item.scss'
|
||||
</style>
|
@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<view class="ch-flex" :class="flexClassList">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, defineProps } from 'vue'
|
||||
|
||||
const props = defineProps([
|
||||
'direction',
|
||||
'wrap',
|
||||
'justify',
|
||||
'items',
|
||||
'align'
|
||||
])
|
||||
|
||||
const flexClassList = computed(() => {
|
||||
const direction = props.direction ? `ch-flex--${props.direction}` : '';
|
||||
const wrap = props.wrap ? `ch-flex--${props.wrap}` : '';
|
||||
const justify = props.justify ? `ch-flex--justify-${props.justify}` : '';
|
||||
const items = props.items ? `ch-flex--items-${props.items}` : '';
|
||||
const align = props.align ? `ch-flex--algin-${props.align}` : '';
|
||||
return Array.from(new Set([direction, wrap, justify, items, align])).join(' ');
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './ch-flex.scss';
|
||||
</style>
|
@ -0,0 +1,46 @@
|
||||
.img-item,
|
||||
.select-btn {
|
||||
height: 300rpx;
|
||||
width: 300rpx;
|
||||
border-radius: 5rpx;
|
||||
overflow: hidden;
|
||||
border: 1px solid $uni-border-color;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.img-item {
|
||||
position: relative;
|
||||
|
||||
+ .img-item {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
image {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.del-btn {
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
right: 2px;
|
||||
z-index: 99;
|
||||
}
|
||||
}
|
||||
|
||||
.img-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.select-btn {
|
||||
margin-left: 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.uni-icons {
|
||||
color: $uni-border-color!important;
|
||||
}
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<view class="ch-image-uploader">
|
||||
<ch-flex class="img-list" justify="center" items="center" @click.native="handleSelect">
|
||||
<block v-for="item in imageList" key="item.name">
|
||||
<view class="img-item" data-type="img">
|
||||
<uni-icons type="clear" class="del-btn" size="50" v-if="showClose" data-type="delete" @click="delImg(item.name)"></uni-icons>
|
||||
<image :src="item.path" mode="aspectFit"></image>
|
||||
</view>
|
||||
</block>
|
||||
<view class="select-btn" data-type="btn" v-if="showBtn">
|
||||
<uni-icons type="plusempty" data-type="add" size="70"/>
|
||||
</view>
|
||||
</ch-flex>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup name="ch-image-uploader">
|
||||
import { ref, defineProps, reactive, toRefs, watchEffect, watch, computed, defineEmits, defineExpose } from 'vue';
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
defineExpose({
|
||||
upload
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 8
|
||||
},
|
||||
extList: {
|
||||
type: Array,
|
||||
default: () => ['png', 'jepg', 'jpg']
|
||||
},
|
||||
sourceType: {
|
||||
type: Array,
|
||||
default: () => ['album', 'camera']
|
||||
},
|
||||
showClose: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
const data = reactive({
|
||||
imageList: []
|
||||
})
|
||||
|
||||
const { imageList } = toRefs(data);
|
||||
|
||||
const showBtn = computed(() => {
|
||||
return (props.limit <= 1 && imageList.value.length <= 0)
|
||||
|| (props.limit > 1 && imageList.value.length <= props.limit - 1)
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
imageList.value = props.modelValue;
|
||||
})
|
||||
|
||||
function handleSelect (e) {
|
||||
const type = e.target.dataset.type || false;
|
||||
|
||||
if (!type || (type === 'img' && props.limit > 1)) return;
|
||||
if (type === 'delete') {
|
||||
delImg();
|
||||
return;
|
||||
}
|
||||
|
||||
uni.chooseImage({
|
||||
count: props.limit,
|
||||
extension: props.extList,
|
||||
sourceType: props.sourceType,
|
||||
success: (res) => {
|
||||
if (props.limit > 1) {
|
||||
const newImageList = filterImage(res.tempFiles)
|
||||
imageList.value = [...imageList.value, ...newImageList]
|
||||
} else {
|
||||
imageList.value = res.tempFiles
|
||||
}
|
||||
emit('update:modelValue', imageList.value)
|
||||
},
|
||||
fail: (res) => {
|
||||
uni.showToast({
|
||||
icon: 'error',
|
||||
title: '选择失败'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 上传
|
||||
function upload () {
|
||||
const files = formatImageFiles(imageList.value);
|
||||
console.log(files)
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: props.url,
|
||||
files,
|
||||
name: 'task-image',
|
||||
success: (uploadFileRes) => {
|
||||
uni.showToast({
|
||||
title: '上传成功'
|
||||
})
|
||||
resolve(uploadFileRes)
|
||||
},
|
||||
fail: (error) => {
|
||||
uni.showToast({
|
||||
icon: 'fail',
|
||||
title: '上传失败'
|
||||
})
|
||||
reject(error)
|
||||
console.log('上传失败', error)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function delImg (delName) {
|
||||
imageList.value = imageList.value.filter(item => item.name !== delName)
|
||||
}
|
||||
|
||||
// 格式化image列表
|
||||
function formatImageFiles (fileList) {
|
||||
return imageList.value.map(item => {
|
||||
return {
|
||||
name: item.name,
|
||||
size: item.size,
|
||||
uri: item.path,
|
||||
file: item
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 过滤重复的图片
|
||||
function filterImage (images) {
|
||||
return images.filter(item => {
|
||||
const result = imageList.value.find(img => img.name === item.name );
|
||||
return !result;
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './ch-image-uploader.scss';
|
||||
</style>
|
@ -0,0 +1,26 @@
|
||||
button {
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: $uni-font-size-lg;
|
||||
align-self: center;
|
||||
margin-left: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.uni-navbar {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.uni-navbar::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background-color: #fff;
|
||||
background: linear-gradient(90deg, #000, #fff, #000);
|
||||
z-index: 99;
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<uni-nav-bar :height="height" fixed statusBar="true" :rightWidth="rWidth" :border="false" :dark="true">
|
||||
<block v-slot:left>
|
||||
<button type="primary" @click="clickBack">
|
||||
<uni-icons type="undo-filled" color="#fff" size="30"></uni-icons>
|
||||
</button>
|
||||
</block>
|
||||
<view class="nav-title" v-if="props.title">{{props.title}}</view>
|
||||
<slot v-else></slot>
|
||||
<block v-slot:right>
|
||||
<slot name="right"></slot>
|
||||
</block>
|
||||
</uni-nav-bar>
|
||||
</template>
|
||||
|
||||
<script setup name="ChNavBar">
|
||||
import { reactive, defineProps, computed } from 'vue';
|
||||
import { back } from '@/useModules/useNavigate.js'
|
||||
|
||||
const props = defineProps([
|
||||
'title',
|
||||
'height',
|
||||
'backFn',
|
||||
'rightWidth'
|
||||
])
|
||||
|
||||
const data = reactive({
|
||||
|
||||
})
|
||||
|
||||
const rWidth = computed(() => `${props.rightWidth || 110}rpx`)
|
||||
|
||||
function clickBack () {
|
||||
const fn = props.backFn || back;
|
||||
fn();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './ch-nav-bar.scss';
|
||||
</style>
|
@ -0,0 +1,11 @@
|
||||
.ch-nav-btn {
|
||||
background-color: $uni-color-primary;
|
||||
font-size: $uni-font-size-sm;
|
||||
line-height: 1.8;
|
||||
border-radius: 8px;
|
||||
padding: 0 12rpx;
|
||||
|
||||
&:active {
|
||||
background-color: transparentize($uni-color-primary, 0.3);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<view class="ch-nav-btn">
|
||||
<uni-icons v-if="props.showIcon || props.icon" :type="props.icon" :size="props.iconSize" :color="props.color"/>
|
||||
<slot/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup name="ChNavBtn">
|
||||
import { defineProps } from 'vue';
|
||||
|
||||
const props = defineProps([
|
||||
'icon',
|
||||
'iconSize',
|
||||
'showIcon',
|
||||
'color'
|
||||
])
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import 'ch-nav-btn.scss';
|
||||
</style>
|
@ -0,0 +1,193 @@
|
||||
/**
|
||||
* 修改自https://github.com/song940/node-escpos/blob/master/commands.js
|
||||
* ESC/POS _ (Constants)
|
||||
*/
|
||||
var _ = {
|
||||
LF: [0x0a],
|
||||
FS: [0x1c],
|
||||
FF: [0x0c],
|
||||
GS: [0x1d],
|
||||
DLE: [0x10],
|
||||
EOT: [0x04],
|
||||
NUL: [0x00],
|
||||
ESC: [0x1b],
|
||||
EOL: '\n',
|
||||
};
|
||||
|
||||
/**
|
||||
* [FEED_CONTROL_SEQUENCES Feed control sequences]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.FEED_CONTROL_SEQUENCES = {
|
||||
CTL_LF: [0x0a], // Print and line feed
|
||||
CTL_GLF: [0x4a, 0x00], // Print and feed paper (without spaces between lines)
|
||||
CTL_FF: [0x0c], // Form feed
|
||||
CTL_CR: [0x0d], // Carriage return
|
||||
CTL_HT: [0x09], // Horizontal tab
|
||||
CTL_VT: [0x0b], // Vertical tab
|
||||
};
|
||||
|
||||
_.CHARACTER_SPACING = {
|
||||
CS_DEFAULT: [0x1b, 0x20, 0x00],
|
||||
CS_SET: [0x1b, 0x20]
|
||||
};
|
||||
|
||||
_.LINE_SPACING = {
|
||||
LS_DEFAULT: [0x1b, 0x32],
|
||||
LS_SET: [0x1b, 0x33]
|
||||
};
|
||||
|
||||
/**
|
||||
* [HARDWARE Printer hardware]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.HARDWARE = {
|
||||
HW_INIT: [0x1b, 0x40], // Clear data in buffer and reset modes
|
||||
HW_SELECT: [0x1b, 0x3d, 0x01], // Printer select
|
||||
HW_RESET: [0x1b, 0x3f, 0x0a, 0x00], // Reset printer hardware
|
||||
};
|
||||
|
||||
/**
|
||||
* [CASH_DRAWER Cash Drawer]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.CASH_DRAWER = {
|
||||
CD_KICK_2: [0x1b, 0x70, 0x00], // Sends a pulse to pin 2 []
|
||||
CD_KICK_5: [0x1b, 0x70, 0x01], // Sends a pulse to pin 5 []
|
||||
};
|
||||
|
||||
/**
|
||||
* [MARGINS Margins sizes]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.MARGINS = {
|
||||
BOTTOM: [0x1b, 0x4f], // Fix bottom size
|
||||
LEFT: [0x1b, 0x6c], // Fix left size
|
||||
RIGHT: [0x1b, 0x51], // Fix right size
|
||||
};
|
||||
|
||||
/**
|
||||
* [PAPER Paper]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.PAPER = {
|
||||
PAPER_FULL_CUT: [0x1d, 0x56, 0x00], // Full cut paper
|
||||
PAPER_PART_CUT: [0x1d, 0x56, 0x01], // Partial cut paper
|
||||
PAPER_CUT_A: [0x1d, 0x56, 0x41], // Partial cut paper
|
||||
PAPER_CUT_B: [0x1d, 0x56, 0x42], // Partial cut paper
|
||||
};
|
||||
|
||||
/**
|
||||
* [TEXT_FORMAT Text format]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.TEXT_FORMAT = {
|
||||
TXT_NORMAL: [0x1b, 0x21, 0x00], // Normal text
|
||||
TXT_2HEIGHT: [0x1b, 0x21, 0x10], // Double height text
|
||||
TXT_2WIDTH: [0x1b, 0x21, 0x20], // Double width text
|
||||
TXT_4SQUARE: [0x1b, 0x21, 0x30], // Double width & height text
|
||||
|
||||
TXT_UNDERL_OFF: [0x1b, 0x2d, 0x00], // Underline font OFF
|
||||
TXT_UNDERL_ON: [0x1b, 0x2d, 0x01], // Underline font 1-dot ON
|
||||
TXT_UNDERL2_ON: [0x1b, 0x2d, 0x02], // Underline font 2-dot ON
|
||||
TXT_BOLD_OFF: [0x1b, 0x45, 0x00], // Bold font OFF
|
||||
TXT_BOLD_ON: [0x1b, 0x45, 0x01], // Bold font ON
|
||||
TXT_ITALIC_OFF: [0x1b, 0x35], // Italic font ON
|
||||
TXT_ITALIC_ON: [0x1b, 0x34], // Italic font ON
|
||||
|
||||
TXT_FONT_A: [0x1b, 0x4d, 0x00], // Font type A
|
||||
TXT_FONT_B: [0x1b, 0x4d, 0x01], // Font type B
|
||||
TXT_FONT_C: [0x1b, 0x4d, 0x02], // Font type C
|
||||
|
||||
TXT_ALIGN_LT: [0x1b, 0x61, 0x00], // Left justification
|
||||
TXT_ALIGN_CT: [0x1b, 0x61, 0x01], // Centering
|
||||
TXT_ALIGN_RT: [0x1b, 0x61, 0x02], // Right justification
|
||||
};
|
||||
|
||||
/**
|
||||
* [BARCODE_FORMAT Barcode format]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.BARCODE_FORMAT = {
|
||||
BARCODE_TXT_OFF: [0x1d, 0x48, 0x00], // HRI barcode chars OFF
|
||||
BARCODE_TXT_ABV: [0x1d, 0x48, 0x01], // HRI barcode chars above
|
||||
BARCODE_TXT_BLW: [0x1d, 0x48, 0x02], // HRI barcode chars below
|
||||
BARCODE_TXT_BTH: [0x1d, 0x48, 0x03], // HRI barcode chars both above and below
|
||||
|
||||
BARCODE_FONT_A: [0x1d, 0x66, 0x00], // Font type A for HRI barcode chars
|
||||
BARCODE_FONT_B: [0x1d, 0x66, 0x01], // Font type B for HRI barcode chars
|
||||
|
||||
BARCODE_HEIGHT: function (height) { // Barcode Height [1-255]
|
||||
return [0x1d, 0x68, height];
|
||||
},
|
||||
BARCODE_WIDTH: function (width) { // Barcode Width [2-6]
|
||||
return [0x1d, 0x77, width];
|
||||
},
|
||||
BARCODE_HEIGHT_DEFAULT: [0x1d, 0x68, 0x64], // Barcode height default:100
|
||||
BARCODE_WIDTH_DEFAULT: [0x1d, 0x77, 0x01], // Barcode width default:1
|
||||
|
||||
BARCODE_UPC_A: [0x1d, 0x6b, 0x00], // Barcode type UPC-A
|
||||
BARCODE_UPC_E: [0x1d, 0x6b, 0x01], // Barcode type UPC-E
|
||||
BARCODE_EAN13: [0x1d, 0x6b, 0x02], // Barcode type EAN13
|
||||
BARCODE_EAN8: [0x1d, 0x6b, 0x03], // Barcode type EAN8
|
||||
BARCODE_CODE39: [0x1d, 0x6b, 0x04], // Barcode type CODE39
|
||||
BARCODE_ITF: [0x1d, 0x6b, 0x05], // Barcode type ITF
|
||||
BARCODE_NW7: [0x1d, 0x6b, 0x06], // Barcode type NW7
|
||||
BARCODE_CODE93: [0x1d, 0x6b, 0x48], // Barcode type CODE93
|
||||
BARCODE_CODE128: [0x1d, 0x6b, 0x49], // Barcode type CODE128
|
||||
};
|
||||
|
||||
/**
|
||||
* [IMAGE_FORMAT Image format]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.IMAGE_FORMAT = {
|
||||
S_RASTER_N: [0x1d, 0x76, 0x30, 0x00], // Set raster image normal size
|
||||
S_RASTER_2W: [0x1d, 0x76, 0x30, 0x01], // Set raster image double width
|
||||
S_RASTER_2H: [0x1d, 0x76, 0x30, 0x02], // Set raster image double height
|
||||
S_RASTER_Q: [0x1d, 0x76, 0x30, 0x03], // Set raster image quadruple
|
||||
};
|
||||
|
||||
/**
|
||||
* [BITMAP_FORMAT description]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.BITMAP_FORMAT = {
|
||||
BITMAP_S8: [0x1b, 0x2a, 0x00],
|
||||
BITMAP_D8: [0x1b, 0x2a, 0x01],
|
||||
BITMAP_S24: [0x1b, 0x2a, 0x20],
|
||||
BITMAP_D24: [0x1b, 0x2a, 0x21]
|
||||
};
|
||||
|
||||
/**
|
||||
* [GSV0_FORMAT description]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.GSV0_FORMAT = {
|
||||
GSV0_NORMAL: [0x1d, 0x76, 0x30, 0x00],
|
||||
GSV0_DW: [0x1d, 0x76, 0x30, 0x01],
|
||||
GSV0_DH: [0x1d, 0x76, 0x30, 0x02],
|
||||
GSV0_DWDH: [0x1d, 0x76, 0x30, 0x03]
|
||||
};
|
||||
|
||||
/**
|
||||
* [BEEP description]
|
||||
* @type {string}
|
||||
*/
|
||||
_.BEEP = [0x1b, 0x42]; // Printer Buzzer pre hex
|
||||
|
||||
/**
|
||||
* [COLOR description]
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
_.COLOR = {
|
||||
0: [0x1b, 0x72, 0x00], // black
|
||||
1: [0x1b, 0x72, 0x01] // red
|
||||
};
|
||||
|
||||
/**
|
||||
* [exports description]
|
||||
* @type {[type]}
|
||||
*/
|
||||
module.exports = _;
|
@ -0,0 +1,7 @@
|
||||
import ChNavBar from '@/components/ch-nav-bar/ch-nav-bar.vue'
|
||||
import ChNavBtn from '@/components/ch-nav-btn/ch-nav-btn.vue'
|
||||
|
||||
export default function registerComponents (app) {
|
||||
app.component(ChNavBar.name, ChNavBar);
|
||||
app.component(ChNavBtn.name, ChNavBtn);
|
||||
}
|
After Width: | Height: | Size: 926 B |
After Width: | Height: | Size: 3.9 KiB |
@ -0,0 +1,341 @@
|
||||
<template>
|
||||
<view>
|
||||
<button @click="searchBle">搜索蓝牙</button>
|
||||
<view style="margin-top: 30upx;" :key="index" v-for="(item,index) in devices">
|
||||
<button style="width: 400upx; color: #0081FF;" @click="onConn(item)">{{item.name}}</button>
|
||||
</view>
|
||||
<button style="margin-top: 100upx;" @click="senBleLabel()">标签打印</button>
|
||||
<textarea auto-height placeholder-style="color:#F76260" placeholder="请输入票据信息" v-model="piaojuText" />
|
||||
<button style="margin-top: 100upx;" @click="senBleLabel2()">票据打印</button>
|
||||
|
||||
<canvas :style="{width: canvasWidth +'px', height: canvasHeight +'px'}" canvas-id="firstCanvas" id="firstCanvas" class="firstCanvas" />
|
||||
</view>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import tsc from '@/static/libs/tsc.js'
|
||||
import esc from '@/static/libs/esc.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
devices: [],
|
||||
currDev: null,
|
||||
connId: '',
|
||||
piaojuText:'',
|
||||
|
||||
tableDomId: '',
|
||||
tableImgPath: '',
|
||||
|
||||
canvasWidth: 800,
|
||||
canvasHeight: 600,
|
||||
|
||||
msg: ''
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
msg(){
|
||||
uni.showToast({
|
||||
title: this.msg
|
||||
})
|
||||
}
|
||||
},
|
||||
onReady() {
|
||||
this.renderFinish()
|
||||
},
|
||||
methods: {
|
||||
destroyed: function() {
|
||||
console.log("destroyed----------")
|
||||
if (this.connId != '') {
|
||||
uni.closeBLEConnection({
|
||||
deviceId: this.connId,
|
||||
success(res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
searchBle() {
|
||||
var that = this
|
||||
console.log("initBule")
|
||||
uni.openBluetoothAdapter({
|
||||
success(res) {
|
||||
console.log("打开 蓝牙模块")
|
||||
console.log(res)
|
||||
that.onDevice()
|
||||
uni.getBluetoothAdapterState({
|
||||
success: function(res) {
|
||||
console.log(res)
|
||||
if (res.available) {
|
||||
if (res.discovering) {
|
||||
that.stopFindBule()
|
||||
}
|
||||
//搜索蓝牙
|
||||
//开始搜寻附近的蓝牙外围设备
|
||||
console.log("开始搜寻附近的蓝牙外围设备")
|
||||
uni.startBluetoothDevicesDiscovery({
|
||||
success(res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
|
||||
} else {
|
||||
console.log('本机蓝牙不可用')
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
onDevice(){
|
||||
console.log("监听寻找到新设备的事件---------------")
|
||||
var that = this
|
||||
//监听寻找到新设备的事件
|
||||
uni.onBluetoothDeviceFound(function(devices) {
|
||||
console.log('--------------new-----------------------'+JSON.stringify(devices))
|
||||
var re = JSON.parse(JSON.stringify(devices))
|
||||
console.log(re.devices[0].name + " " + re.devices[0].deviceId)
|
||||
let name = re.devices[0].name
|
||||
if (name != "未知设备") {
|
||||
let deviceId = re.devices[0].deviceId
|
||||
that.devices.push({
|
||||
name: name,
|
||||
deviceId: deviceId,
|
||||
services: []
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
|
||||
stopFindBule() {
|
||||
console.log("停止搜寻附近的蓝牙外围设备---------------")
|
||||
uni.stopBluetoothDevicesDiscovery({
|
||||
success(res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
},
|
||||
onConn(item) {
|
||||
var that = this
|
||||
console.log("连接蓝牙---------------" + item.deviceId)
|
||||
let deviceId = item.deviceId
|
||||
uni.createBLEConnection({
|
||||
deviceId: deviceId,
|
||||
complete(res) {
|
||||
if (res.errMsg == "createBLEConnection:ok") {
|
||||
console.log("连接蓝牙-[" + item.name + "]--成功")
|
||||
that.connId = deviceId;
|
||||
that.currDev = item
|
||||
setTimeout(function() {
|
||||
that.getBLEServices(deviceId)
|
||||
}, 2000)
|
||||
} else {
|
||||
console.log(res)
|
||||
}
|
||||
//连接成功 关闭搜索
|
||||
that.stopFindBule()
|
||||
|
||||
},
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
getBLEServices(_deviceId) {
|
||||
var that = this;
|
||||
let deviceId = _deviceId
|
||||
console.log("获取蓝牙设备所有服务(service)。---------------")
|
||||
|
||||
uni.getBLEDeviceServices({
|
||||
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
|
||||
deviceId: deviceId,
|
||||
complete(res) {
|
||||
console.log(res)
|
||||
let serviceId = ""
|
||||
|
||||
for (var s = 0; s < res.services.length; s++) {
|
||||
console.log(res.services[s].uuid)
|
||||
let serviceId = res.services[s].uuid
|
||||
uni.getBLEDeviceCharacteristics({
|
||||
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
|
||||
deviceId: deviceId,
|
||||
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
|
||||
serviceId: serviceId,
|
||||
success(res) {
|
||||
var re = JSON.parse(JSON.stringify(res))
|
||||
|
||||
console.log('deviceId = [' + deviceId + '] serviceId = [' + serviceId + ']')
|
||||
for (var c = 0; c < re.characteristics.length; c++) {
|
||||
if (re.characteristics[c].properties.write == true) {
|
||||
let uuid = re.characteristics[c].uuid
|
||||
console.log(' deviceId = [' + deviceId + '] serviceId = [' + serviceId + '] characteristics=[' +
|
||||
uuid)
|
||||
|
||||
for (var index in that.devices) {
|
||||
if (that.devices[index].deviceId == deviceId) {
|
||||
that.devices[index].services.push({
|
||||
serviceId: serviceId,
|
||||
characteristicId: uuid
|
||||
})
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
console.log(JSON.stringify(that.devices))
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
},
|
||||
fail(res) {
|
||||
console.log(res)
|
||||
},
|
||||
})
|
||||
|
||||
},
|
||||
senBlData(deviceId, serviceId, characteristicId,uint8Array) {
|
||||
console.log('************deviceId = [' + deviceId + '] serviceId = [' + serviceId + '] characteristics=[' +characteristicId+ "]")
|
||||
var uint8Buf = Array.from(uint8Array);
|
||||
function split_array(datas,size){
|
||||
var result = {};
|
||||
var j = 0
|
||||
if(datas.length < size) {
|
||||
size = datas.length
|
||||
}
|
||||
for (var i = 0; i < datas.length; i += size) {
|
||||
result[j] = datas.slice(i, i + size)
|
||||
j++
|
||||
}
|
||||
//result[j] = datas
|
||||
console.log(result)
|
||||
return result
|
||||
}
|
||||
var sendloop = split_array(uint8Buf, 20);
|
||||
// console.log(sendloop.length)
|
||||
function realWriteData(sendloop, i) {
|
||||
var data = sendloop[i]
|
||||
if(typeof(data) == "undefined"){
|
||||
return
|
||||
}
|
||||
//console.log("第【" + i + "】次写数据"+data)
|
||||
var buffer = new ArrayBuffer(data.length)
|
||||
var dataView = new DataView(buffer)
|
||||
for (var j = 0; j < data.length; j++) {
|
||||
dataView.setUint8(j, data[j]);
|
||||
}
|
||||
uni.writeBLECharacteristicValue({
|
||||
deviceId,
|
||||
serviceId,
|
||||
characteristicId,
|
||||
value: buffer,
|
||||
success(res) {
|
||||
console.log('发送成功',i)
|
||||
setTimeout(()=>{
|
||||
realWriteData(sendloop, i + 1);
|
||||
},100)
|
||||
//realWriteData(sendloop, i + 1);
|
||||
|
||||
},
|
||||
fail(e) {
|
||||
console.log('发送数据失败')
|
||||
console.log(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
var i = 0;
|
||||
realWriteData(sendloop, i);
|
||||
},
|
||||
senBleLabel() {
|
||||
//标签模式
|
||||
|
||||
uni.canvasGetImageData({
|
||||
canvasId: 'firstCanvas',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: this.canvasWidth,
|
||||
height: this.canvasHeight,
|
||||
success: (res)=> {
|
||||
uni.hideLoading()
|
||||
|
||||
let deviceId = this.currDev.deviceId;
|
||||
let serviceId = this.currDev.services[0].serviceId;
|
||||
let characteristicId = this.currDev.services[0].characteristicId;
|
||||
|
||||
var command = tsc.jpPrinter.createNew()
|
||||
command.init()
|
||||
command.setSize(80, 60)
|
||||
//command.setBox(0,0,800,600,1)
|
||||
command.setGap(2)
|
||||
command.setCls()
|
||||
command.setText(50, 10, "TSS24.BF2", 1, 1, "打印测试")
|
||||
command.setQR(50, 50, "L", 5, "A", "https://www.baidu.com")
|
||||
command.setBitmap(100, 0, 0, res)
|
||||
//command.setBitmap2(100, 100, 0,res)
|
||||
command.setBox(5, 5, 795, 595, 1)
|
||||
command.setPagePrint()
|
||||
console.log('command.getData()')
|
||||
//console.log(command.getData())
|
||||
this.senBlData(deviceId, serviceId, characteristicId,command.getData())
|
||||
},
|
||||
fail: function(res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
senBleLabel2(){
|
||||
//票据模式
|
||||
let deviceId = this.currDev.deviceId;
|
||||
let serviceId = this.currDev.services[0].serviceId;
|
||||
let characteristicId = this.currDev.services[0].characteristicId;
|
||||
var command = esc.jpPrinter.createNew()
|
||||
command.init()
|
||||
command.setText(this.piaojuText);
|
||||
command.setPrintAndFeedRow(1)
|
||||
this.senBlData(deviceId, serviceId, characteristicId,command.getData())
|
||||
},
|
||||
renderFinish() {
|
||||
let filePath = '../../static/logo.png'
|
||||
let that = this
|
||||
const firstCanvas = uni.createCanvasContext('firstCanvas', this);
|
||||
let scla = 1
|
||||
uni.getImageInfo({
|
||||
src: filePath,
|
||||
success(res) {
|
||||
that.canvasWidth = res.width * scla
|
||||
that.canvasHeight = res.height * scla
|
||||
console.log(res, that.canvasWidth, that.canvasHeight)
|
||||
firstCanvas.drawImage(filePath, 0, 0, that.canvasWidth, that.canvasHeight);
|
||||
firstCanvas.draw();
|
||||
that.$nextTick(() => { //获取画布像素数据
|
||||
|
||||
})
|
||||
},
|
||||
fail(res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
After Width: | Height: | Size: 99 KiB |
@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<ch-flex class="question-item" justify="center" items="center">
|
||||
<checkbox ref="checkRef" :value="item.questionid.toString()" />
|
||||
<uni-card @click="checkQues(item.questionid)">
|
||||
<view class="question__sort-content">{{ item.questioncontent }}</view>
|
||||
<view class="question__info">
|
||||
<text>{{ item.gradename }}</text>
|
||||
<text>{{ item.addtime }}</text>
|
||||
<text>{{ item.subjectname }}</text>
|
||||
</view>
|
||||
</uni-card>
|
||||
</ch-flex>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, defineEmits, watch, ref, computed, onMounted } from 'vue';
|
||||
|
||||
const props = defineProps([
|
||||
'item'
|
||||
]);
|
||||
|
||||
const emit = defineEmits(['clickItem', 'change'])
|
||||
|
||||
const checkValue = ref(null);
|
||||
const checkStatus = ref(false);
|
||||
const checkRef = ref(null)
|
||||
|
||||
onMounted(() => {
|
||||
console.log(checkRef)
|
||||
})
|
||||
|
||||
watch(checkValue, (newValue) => {
|
||||
console.log('change')
|
||||
emit('change', newValue)
|
||||
})
|
||||
|
||||
function checkQues(id) {
|
||||
emit('clickItem', id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$lineHeight: $uni-font-size-base * 1.5;
|
||||
|
||||
.question__sort-content {
|
||||
font-size: $uni-font-size-base;
|
||||
line-height: $lineHeight;
|
||||
height: $lineHeight;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.question__info {
|
||||
> text {
|
||||
font-size: $uni-font-size-mini;
|
||||
color: $uni-secondary-color;
|
||||
+ text {
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,193 @@
|
||||
/**
|
||||
* 修改自https://github.com/song940/node-escpos/blob/master/commands.js
|
||||
* ESC/POS _ (Constants)
|
||||
*/
|
||||
var _ = {
|
||||
LF: [0x0a],
|
||||
FS: [0x1c],
|
||||
FF: [0x0c],
|
||||
GS: [0x1d],
|
||||
DLE: [0x10],
|
||||
EOT: [0x04],
|
||||
NUL: [0x00],
|
||||
ESC: [0x1b],
|
||||
EOL: '\n',
|
||||
};
|
||||
|
||||
/**
|
||||
* [FEED_CONTROL_SEQUENCES Feed control sequences]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.FEED_CONTROL_SEQUENCES = {
|
||||
CTL_LF: [0x0a], // Print and line feed
|
||||
CTL_GLF: [0x4a, 0x00], // Print and feed paper (without spaces between lines)
|
||||
CTL_FF: [0x0c], // Form feed
|
||||
CTL_CR: [0x0d], // Carriage return
|
||||
CTL_HT: [0x09], // Horizontal tab
|
||||
CTL_VT: [0x0b], // Vertical tab
|
||||
};
|
||||
|
||||
_.CHARACTER_SPACING = {
|
||||
CS_DEFAULT: [0x1b, 0x20, 0x00],
|
||||
CS_SET: [0x1b, 0x20]
|
||||
};
|
||||
|
||||
_.LINE_SPACING = {
|
||||
LS_DEFAULT: [0x1b, 0x32],
|
||||
LS_SET: [0x1b, 0x33]
|
||||
};
|
||||
|
||||
/**
|
||||
* [HARDWARE Printer hardware]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.HARDWARE = {
|
||||
HW_INIT: [0x1b, 0x40], // Clear data in buffer and reset modes
|
||||
HW_SELECT: [0x1b, 0x3d, 0x01], // Printer select
|
||||
HW_RESET: [0x1b, 0x3f, 0x0a, 0x00], // Reset printer hardware
|
||||
};
|
||||
|
||||
/**
|
||||
* [CASH_DRAWER Cash Drawer]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.CASH_DRAWER = {
|
||||
CD_KICK_2: [0x1b, 0x70, 0x00], // Sends a pulse to pin 2 []
|
||||
CD_KICK_5: [0x1b, 0x70, 0x01], // Sends a pulse to pin 5 []
|
||||
};
|
||||
|
||||
/**
|
||||
* [MARGINS Margins sizes]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.MARGINS = {
|
||||
BOTTOM: [0x1b, 0x4f], // Fix bottom size
|
||||
LEFT: [0x1b, 0x6c], // Fix left size
|
||||
RIGHT: [0x1b, 0x51], // Fix right size
|
||||
};
|
||||
|
||||
/**
|
||||
* [PAPER Paper]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.PAPER = {
|
||||
PAPER_FULL_CUT: [0x1d, 0x56, 0x00], // Full cut paper
|
||||
PAPER_PART_CUT: [0x1d, 0x56, 0x01], // Partial cut paper
|
||||
PAPER_CUT_A: [0x1d, 0x56, 0x41], // Partial cut paper
|
||||
PAPER_CUT_B: [0x1d, 0x56, 0x42], // Partial cut paper
|
||||
};
|
||||
|
||||
/**
|
||||
* [TEXT_FORMAT Text format]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.TEXT_FORMAT = {
|
||||
TXT_NORMAL: [0x1b, 0x21, 0x00], // Normal text
|
||||
TXT_2HEIGHT: [0x1b, 0x21, 0x10], // Double height text
|
||||
TXT_2WIDTH: [0x1b, 0x21, 0x20], // Double width text
|
||||
TXT_4SQUARE: [0x1b, 0x21, 0x30], // Double width & height text
|
||||
|
||||
TXT_UNDERL_OFF: [0x1b, 0x2d, 0x00], // Underline font OFF
|
||||
TXT_UNDERL_ON: [0x1b, 0x2d, 0x01], // Underline font 1-dot ON
|
||||
TXT_UNDERL2_ON: [0x1b, 0x2d, 0x02], // Underline font 2-dot ON
|
||||
TXT_BOLD_OFF: [0x1b, 0x45, 0x00], // Bold font OFF
|
||||
TXT_BOLD_ON: [0x1b, 0x45, 0x01], // Bold font ON
|
||||
TXT_ITALIC_OFF: [0x1b, 0x35], // Italic font ON
|
||||
TXT_ITALIC_ON: [0x1b, 0x34], // Italic font ON
|
||||
|
||||
TXT_FONT_A: [0x1b, 0x4d, 0x00], // Font type A
|
||||
TXT_FONT_B: [0x1b, 0x4d, 0x01], // Font type B
|
||||
TXT_FONT_C: [0x1b, 0x4d, 0x02], // Font type C
|
||||
|
||||
TXT_ALIGN_LT: [0x1b, 0x61, 0x00], // Left justification
|
||||
TXT_ALIGN_CT: [0x1b, 0x61, 0x01], // Centering
|
||||
TXT_ALIGN_RT: [0x1b, 0x61, 0x02], // Right justification
|
||||
};
|
||||
|
||||
/**
|
||||
* [BARCODE_FORMAT Barcode format]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.BARCODE_FORMAT = {
|
||||
BARCODE_TXT_OFF: [0x1d, 0x48, 0x00], // HRI barcode chars OFF
|
||||
BARCODE_TXT_ABV: [0x1d, 0x48, 0x01], // HRI barcode chars above
|
||||
BARCODE_TXT_BLW: [0x1d, 0x48, 0x02], // HRI barcode chars below
|
||||
BARCODE_TXT_BTH: [0x1d, 0x48, 0x03], // HRI barcode chars both above and below
|
||||
|
||||
BARCODE_FONT_A: [0x1d, 0x66, 0x00], // Font type A for HRI barcode chars
|
||||
BARCODE_FONT_B: [0x1d, 0x66, 0x01], // Font type B for HRI barcode chars
|
||||
|
||||
BARCODE_HEIGHT: function (height) { // Barcode Height [1-255]
|
||||
return [0x1d, 0x68, height];
|
||||
},
|
||||
BARCODE_WIDTH: function (width) { // Barcode Width [2-6]
|
||||
return [0x1d, 0x77, width];
|
||||
},
|
||||
BARCODE_HEIGHT_DEFAULT: [0x1d, 0x68, 0x64], // Barcode height default:100
|
||||
BARCODE_WIDTH_DEFAULT: [0x1d, 0x77, 0x01], // Barcode width default:1
|
||||
|
||||
BARCODE_UPC_A: [0x1d, 0x6b, 0x00], // Barcode type UPC-A
|
||||
BARCODE_UPC_E: [0x1d, 0x6b, 0x01], // Barcode type UPC-E
|
||||
BARCODE_EAN13: [0x1d, 0x6b, 0x02], // Barcode type EAN13
|
||||
BARCODE_EAN8: [0x1d, 0x6b, 0x03], // Barcode type EAN8
|
||||
BARCODE_CODE39: [0x1d, 0x6b, 0x04], // Barcode type CODE39
|
||||
BARCODE_ITF: [0x1d, 0x6b, 0x05], // Barcode type ITF
|
||||
BARCODE_NW7: [0x1d, 0x6b, 0x06], // Barcode type NW7
|
||||
BARCODE_CODE93: [0x1d, 0x6b, 0x48], // Barcode type CODE93
|
||||
BARCODE_CODE128: [0x1d, 0x6b, 0x49], // Barcode type CODE128
|
||||
};
|
||||
|
||||
/**
|
||||
* [IMAGE_FORMAT Image format]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.IMAGE_FORMAT = {
|
||||
S_RASTER_N: [0x1d, 0x76, 0x30, 0x00], // Set raster image normal size
|
||||
S_RASTER_2W: [0x1d, 0x76, 0x30, 0x01], // Set raster image double width
|
||||
S_RASTER_2H: [0x1d, 0x76, 0x30, 0x02], // Set raster image double height
|
||||
S_RASTER_Q: [0x1d, 0x76, 0x30, 0x03], // Set raster image quadruple
|
||||
};
|
||||
|
||||
/**
|
||||
* [BITMAP_FORMAT description]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.BITMAP_FORMAT = {
|
||||
BITMAP_S8: [0x1b, 0x2a, 0x00],
|
||||
BITMAP_D8: [0x1b, 0x2a, 0x01],
|
||||
BITMAP_S24: [0x1b, 0x2a, 0x20],
|
||||
BITMAP_D24: [0x1b, 0x2a, 0x21]
|
||||
};
|
||||
|
||||
/**
|
||||
* [GSV0_FORMAT description]
|
||||
* @type {Object}
|
||||
*/
|
||||
_.GSV0_FORMAT = {
|
||||
GSV0_NORMAL: [0x1d, 0x76, 0x30, 0x00],
|
||||
GSV0_DW: [0x1d, 0x76, 0x30, 0x01],
|
||||
GSV0_DH: [0x1d, 0x76, 0x30, 0x02],
|
||||
GSV0_DWDH: [0x1d, 0x76, 0x30, 0x03]
|
||||
};
|
||||
|
||||
/**
|
||||
* [BEEP description]
|
||||
* @type {string}
|
||||
*/
|
||||
_.BEEP = [0x1b, 0x42]; // Printer Buzzer pre hex
|
||||
|
||||
/**
|
||||
* [COLOR description]
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
_.COLOR = {
|
||||
0: [0x1b, 0x72, 0x00], // black
|
||||
1: [0x1b, 0x72, 0x01] // red
|
||||
};
|
||||
|
||||
/**
|
||||
* [exports description]
|
||||
* @type {[type]}
|
||||
*/
|
||||
export default _;
|