Compare commits
5 Commits
Author | SHA1 | Date |
---|---|---|
chris | 9d073a9d06 | 2 weeks ago |
chris | 32ddbd1316 | 1 month ago |
chris | f8fe327ee5 | 3 months ago |
chris | 98e2511339 | 4 months ago |
chris | 97edff90ce | 4 months ago |
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
Binary file not shown.
Before Width: | Height: | Size: 39 KiB |
@ -0,0 +1,6 @@
|
||||
import mathJax from './mathJax'
|
||||
|
||||
export default function registerDirectives (app) {
|
||||
// 注册全局指令
|
||||
app.directive(mathJax.name, mathJax.inserted)
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
// 该指令只支持H5
|
||||
import renderMath from '@/utils/mathJax/renderMath.js'
|
||||
|
||||
export default {
|
||||
name: 'math',
|
||||
inserted (el, binding) {
|
||||
if (!binding.value) return;
|
||||
// console.log(binding.value)
|
||||
// console.log(Reflect.ownKeys(el.__vnode.el))
|
||||
// console.log(el.__vnode)
|
||||
el.__vnode.el.innerHTML = renderMath(binding.value)
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
declare namespace UniCrazyGlobalTypes {
|
||||
interface UniCrazyRouterParams {
|
||||
passedParams?: object | null;
|
||||
routeParams?: object | null;
|
||||
}
|
||||
}
|
||||
|
||||
declare namespace UniApp {
|
||||
interface RedirectToOptions extends UniCrazyGlobalTypes.UniCrazyRouterParams {}
|
||||
interface ReLaunchOptions extends UniCrazyGlobalTypes.UniCrazyRouterParams {}
|
||||
interface SwitchTabOptions extends UniCrazyGlobalTypes.UniCrazyRouterParams {}
|
||||
interface NavigateBackOptions extends UniCrazyGlobalTypes.UniCrazyRouterParams {}
|
||||
interface NavigateToOptions extends UniCrazyGlobalTypes.UniCrazyRouterParams {}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/// <reference path="./global.d.ts" />
|
||||
type to = {
|
||||
url: string;
|
||||
query?: object | null;
|
||||
jumpType: string;
|
||||
search?: string;
|
||||
} & UniCrazyGlobalTypes.UniCrazyRouterParams;
|
||||
type from = ({
|
||||
url: string;
|
||||
query?: object | null;
|
||||
search?: string;
|
||||
} & UniCrazyGlobalTypes.UniCrazyRouterParams) | null | undefined;
|
||||
interface callWithNext {
|
||||
(hook: (to: to, from: from, next: Function) => void) : Function;
|
||||
}
|
||||
interface callWithoutNext {
|
||||
(hook: (to: to, from: from) => void): Function;
|
||||
}
|
||||
interface normalCall {
|
||||
(call: Function): void;
|
||||
}
|
||||
export const beforeEach: callWithNext;
|
||||
export const afterEach: callWithoutNext;
|
||||
export const onError: callWithoutNext;
|
||||
export const afterNotNext: normalCall;
|
||||
interface uniCrazyRouter {
|
||||
beforeEach: callWithNext;
|
||||
afterEach: callWithoutNext;
|
||||
onError: callWithoutNext;
|
||||
afterNotNext: normalCall;
|
||||
install: any;
|
||||
}
|
||||
declare const uniCrazyRouter: uniCrazyRouter;
|
||||
export default uniCrazyRouter;
|
||||
// for Vue2
|
||||
declare module "vue/types/vue" {
|
||||
interface Vue {
|
||||
$routeParams?: object | null;
|
||||
$passedParams?: object | null;
|
||||
}
|
||||
}
|
||||
|
||||
// for Vue3
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
$routeParams?: object | null;
|
||||
$passedParams?: object | null;
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,49 @@
|
||||
/// <reference path="./global.d.ts" />
|
||||
type to = {
|
||||
url: string;
|
||||
query?: object | null;
|
||||
jumpType: string;
|
||||
search?: string;
|
||||
} & UniCrazyGlobalTypes.UniCrazyRouterParams;
|
||||
type from = ({
|
||||
url: string;
|
||||
query?: object | null;
|
||||
search?: string;
|
||||
} & UniCrazyGlobalTypes.UniCrazyRouterParams) | null | undefined;
|
||||
interface callWithNext {
|
||||
(hook: (to: to, from: from, next: Function) => void) : Function;
|
||||
}
|
||||
interface callWithoutNext {
|
||||
(hook: (to: to, from: from) => void): Function;
|
||||
}
|
||||
interface normalCall {
|
||||
(call: Function): void;
|
||||
}
|
||||
export const beforeEach: callWithNext;
|
||||
export const afterEach: callWithoutNext;
|
||||
export const onError: callWithoutNext;
|
||||
export const afterNotNext: normalCall;
|
||||
interface uniCrazyRouter {
|
||||
beforeEach: callWithNext;
|
||||
afterEach: callWithoutNext;
|
||||
onError: callWithoutNext;
|
||||
afterNotNext: normalCall;
|
||||
install: any;
|
||||
}
|
||||
declare const uniCrazyRouter: uniCrazyRouter;
|
||||
export default uniCrazyRouter;
|
||||
// for Vue2
|
||||
declare module "vue/types/vue" {
|
||||
interface Vue {
|
||||
$routeParams?: object | null;
|
||||
$passedParams?: object | null;
|
||||
}
|
||||
}
|
||||
|
||||
// for Vue3
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
$routeParams?: object | null;
|
||||
$passedParams?: object | null;
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "相机测试",
|
||||
"id": "DeltaPhone-Camera",
|
||||
"version": "1.4",
|
||||
"description": "相机测试",
|
||||
"_dp_type": "nativeplugin",
|
||||
"_dp_nativeplugin": {
|
||||
"android": {
|
||||
"plugins": [{
|
||||
"type": "module",
|
||||
"name": "DeltaPhone-Camera",
|
||||
"class": "com.deltaphone.cameramodule.CameraModule"
|
||||
}],
|
||||
"integrateType": "aar"
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "身份证相机",
|
||||
"id": "yun-camerax",
|
||||
"version": "1.3.0",
|
||||
"description": "自定义身份证相机",
|
||||
"_dp_type": "nativeplugin",
|
||||
"_dp_nativeplugin": {
|
||||
"android": {
|
||||
"plugins": [{
|
||||
"type": "module",
|
||||
"name": "yun-camerax-module",
|
||||
"class": "com.yun.camera.CameraModule"
|
||||
}],
|
||||
"integrateType": "aar",
|
||||
"minSdkVersion": "26",
|
||||
"useAndroidX": true,
|
||||
"dependencies": [
|
||||
"androidx.constraintlayout:constraintlayout:2.0.4",
|
||||
"androidx.camera:camera-core:1.1.0-alpha01",
|
||||
"androidx.camera:camera-camera2:1.1.0-alpha01",
|
||||
"androidx.camera:camera-lifecycle:1.1.0-alpha01",
|
||||
"androidx.camera:camera-view:1.0.0-alpha27"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,24 +1,20 @@
|
||||
{
|
||||
"name": "smart_campus",
|
||||
"version": "1.0.0",
|
||||
"id": "smart_campus",
|
||||
"name": "学情监测仪",
|
||||
"displayName": "学情监测仪",
|
||||
"version": "0.0.0.9",
|
||||
"description": "",
|
||||
"main": "main.js",
|
||||
"dependencies": {
|
||||
"html2canvas": "^1.4.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"js-tokens": "^4.0.0",
|
||||
"uni-crazy-router": "^1.1.3",
|
||||
"vite": "^5.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"postcss": "^8.4.38",
|
||||
"katex": "^0.16.11",
|
||||
"postcss-pxtorpx-pro": "^2.0.0",
|
||||
"uni-crazy-router": "^1.1.3",
|
||||
"uni-vite-plugin-h5-prod-effect": "^1.0.1",
|
||||
"unocss": "^0.59.4",
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "chris",
|
||||
"license": "ISC"
|
||||
"devDependencies": {
|
||||
"vite-plugin-commonjs": "^0.10.1",
|
||||
"vite-plugin-require": "^1.2.14"
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
.search-btn {
|
||||
// margin-top: 15px;
|
||||
// margin-left: 20px;
|
||||
// margin-bottom: 15px;
|
||||
// margin-left: 50%;
|
||||
// transform: translateX(-50%);
|
||||
}
|
||||
|
||||
// 隐藏canvas
|
||||
uni-canvas {
|
||||
// position: absolute;
|
||||
// top: -1000px;
|
||||
// left: -1000px;
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,13 +0,0 @@
|
||||
import { defineConfig } from "unocss";
|
||||
|
||||
const rules = [
|
||||
[/^mg-([\.\d]+)$/, ([_, num]) => ({ margin: `${num}px` })],
|
||||
[/^mg-t-([\.\d]+)$/, ([_, num]) => ({ marginTop: `${num}px` })],
|
||||
[/^mg-b-([\.\d]+)$/, ([_, num]) => ({ marginBottom: `${num}px` })],
|
||||
[/^mg-r-([\.\d]+)$/, ([_, num]) => ({ marginRight: `${num}px` })],
|
||||
[/^mg-l-([\.\d]+)$/, ([_, num]) => ({ marginLeft: `${num}px` })]
|
||||
]
|
||||
|
||||
export default defineConfig({
|
||||
rules,
|
||||
})
|
@ -0,0 +1,90 @@
|
||||
import katex from "katex";
|
||||
import splitAtDelimiters from "./splitAtDelimiters";
|
||||
|
||||
const renderMathInText = function(text, optionsCopy) {
|
||||
const data = splitAtDelimiters(text, optionsCopy.delimiters);
|
||||
if (data.length === 1 && data[0].type === 'text') {
|
||||
// There is no formula in the text.
|
||||
// Let's return null which means there is no need to replace
|
||||
// the current text node with a new one.
|
||||
return data[0].data;
|
||||
}
|
||||
|
||||
let html = ''
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i].type === "text") {
|
||||
html += data[i].data;
|
||||
} else {
|
||||
let math = data[i].data;
|
||||
// Override any display mode defined in the settings with that
|
||||
// defined by the text itself
|
||||
optionsCopy.displayMode = data[i].display;
|
||||
try {
|
||||
if (optionsCopy.preProcess) {
|
||||
math = optionsCopy.preProcess(math);
|
||||
}
|
||||
html += katex.renderToString(math, optionsCopy);
|
||||
} catch (e) {
|
||||
if (!(e instanceof katex.ParseError)) {
|
||||
throw e;
|
||||
}
|
||||
optionsCopy.errorCallback(
|
||||
"KaTeX auto-render: Failed to parse `" + data[i].data +
|
||||
"` with ",
|
||||
e
|
||||
);
|
||||
html += data[i].rawData;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
const renderMath = function(text, options) {
|
||||
if (!text) {
|
||||
throw new Error("No text provided to render");
|
||||
}
|
||||
|
||||
const optionsCopy = {};
|
||||
|
||||
// Object.assign(optionsCopy, option)
|
||||
for (const option in options) {
|
||||
if (options.hasOwnProperty(option)) {
|
||||
optionsCopy[option] = options[option];
|
||||
}
|
||||
}
|
||||
|
||||
// default options
|
||||
optionsCopy.delimiters = optionsCopy.delimiters || [
|
||||
{left: "$$", right: "$$", display: true},
|
||||
{left: "\\(", right: "\\)", display: false},
|
||||
// LaTeX uses $…$, but it ruins the display of normal `$` in text:
|
||||
{left: "$", right: "$", display: false},
|
||||
// $ must come after $$
|
||||
|
||||
// Render AMS environments even if outside $$…$$ delimiters.
|
||||
{left: "\\begin{equation}", right: "\\end{equation}", display: true},
|
||||
{left: "\\begin{align}", right: "\\end{align}", display: true},
|
||||
{left: "\\begin{alignat}", right: "\\end{alignat}", display: true},
|
||||
{left: "\\begin{gather}", right: "\\end{gather}", display: true},
|
||||
{left: "\\begin{CD}", right: "\\end{CD}", display: true},
|
||||
|
||||
{left: "\\[", right: "\\]", display: true},
|
||||
];
|
||||
optionsCopy.ignoredTags = optionsCopy.ignoredTags || [
|
||||
"script", "noscript", "style", "textarea", "pre", "code", "option",
|
||||
];
|
||||
optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
|
||||
optionsCopy.errorCallback = optionsCopy.errorCallback || console.error;
|
||||
|
||||
// Enable sharing of global macros defined via `\gdef` between different
|
||||
// math elements within a single call to `renderMathInElement`.
|
||||
optionsCopy.macros = optionsCopy.macros || {};
|
||||
|
||||
return renderMathInText(text, optionsCopy);
|
||||
};
|
||||
|
||||
export default renderMath;
|
@ -0,0 +1,85 @@
|
||||
/* eslint no-constant-condition:0 */
|
||||
const findEndOfMath = function(delimiter, text, startIndex) {
|
||||
// Adapted from
|
||||
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
|
||||
let index = startIndex;
|
||||
let braceLevel = 0;
|
||||
|
||||
const delimLength = delimiter.length;
|
||||
|
||||
while (index < text.length) {
|
||||
const character = text[index];
|
||||
|
||||
if (braceLevel <= 0 &&
|
||||
text.slice(index, index + delimLength) === delimiter) {
|
||||
return index;
|
||||
} else if (character === "\\") {
|
||||
index++;
|
||||
} else if (character === "{") {
|
||||
braceLevel++;
|
||||
} else if (character === "}") {
|
||||
braceLevel--;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
const escapeRegex = function(string) {
|
||||
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
||||
};
|
||||
|
||||
const amsRegex = /^\\begin{/;
|
||||
|
||||
const splitAtDelimiters = function(text, delimiters) {
|
||||
let index;
|
||||
const data = [];
|
||||
|
||||
const regexLeft = new RegExp(
|
||||
"(" + delimiters.map((x) => escapeRegex(x.left)).join("|") + ")"
|
||||
);
|
||||
|
||||
while (true) {
|
||||
index = text.search(regexLeft);
|
||||
if (index === -1) {
|
||||
break;
|
||||
}
|
||||
if (index > 0) {
|
||||
data.push({
|
||||
type: "text",
|
||||
data: text.slice(0, index),
|
||||
});
|
||||
text = text.slice(index); // now text starts with delimiter
|
||||
}
|
||||
// ... so this always succeeds:
|
||||
const i = delimiters.findIndex((delim) => text.startsWith(delim.left));
|
||||
index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);
|
||||
if (index === -1) {
|
||||
break;
|
||||
}
|
||||
const rawData = text.slice(0, index + delimiters[i].right.length);
|
||||
const math = amsRegex.test(rawData)
|
||||
? rawData
|
||||
: text.slice(delimiters[i].left.length, index);
|
||||
data.push({
|
||||
type: "math",
|
||||
data: math,
|
||||
rawData,
|
||||
display: delimiters[i].display,
|
||||
});
|
||||
text = text.slice(index + delimiters[i].right.length);
|
||||
}
|
||||
|
||||
if (text !== "") {
|
||||
data.push({
|
||||
type: "text",
|
||||
data: text,
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export default splitAtDelimiters;
|
@ -0,0 +1,9 @@
|
||||
export function createScript(src) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.onload = () => resolve(script);
|
||||
script.onerror = () => reject(new Error(`Script load error for ${src}`));
|
||||
document.head.append(script);
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue