>;
2 |
3 | interface HttpError {
4 | title: string;
5 | description: string;
6 | }
7 |
8 | interface Statistics {
9 | name: string;
10 | times: number;
11 | }
12 |
--------------------------------------------------------------------------------
/types/list.d.ts:
--------------------------------------------------------------------------------
1 | interface Tag {
2 | info?: string[];
3 | normal?: string[];
4 | warning?: string[];
5 | error?: string[];
6 | }
7 |
8 | interface ListItem {
9 | name: string;
10 | path: string;
11 | introduction: Texts;
12 | disabled?: boolean;
13 | warning?: string;
14 | tags: Tag;
15 | }
16 |
--------------------------------------------------------------------------------
/types/scale/16pf.d.ts:
--------------------------------------------------------------------------------
1 | type SPFFactor =
2 | | "A"
3 | | "C"
4 | | "E"
5 | | "F"
6 | | "G"
7 | | "H"
8 | | "I"
9 | | "L"
10 | | "M"
11 | | "N"
12 | | "O"
13 | | "Q1"
14 | | "Q2"
15 | | "Q3"
16 | | "Q4"
17 | | "B";
18 |
19 | interface SPFQuestion extends CommonQuestion {
20 | factor: SPFFactor;
21 | }
22 |
23 | type SPFRange = number | [number, number];
24 |
25 | interface SPFNormItem {
26 | ranges: SPFRange[];
27 | mean: number;
28 | standard_deviation: number;
29 | }
30 |
31 | type SPFNorm = { [K in SPFFactor]: SPFNormItem };
32 |
33 | interface SPFFirstPersonalityFactor {
34 | factor: SPFFactor;
35 | name: string;
36 | occupations: string;
37 | characteristic: Characteristic;
38 | }
39 |
40 | interface SPFSecondPersonalityFactor {
41 | key: "X1" | "X2" | "X3" | "X4";
42 | name: string;
43 | expression: string;
44 | characteristic: Characteristic;
45 | }
46 |
47 | interface SPFInterpretation {
48 | normal_range: [number, number];
49 | norm: SPFNorm;
50 | first_personality_factor: SPFFirstPersonalityFactor[];
51 | second_personality_factor: [
52 | SPFSecondPersonalityFactor,
53 | SPFSecondPersonalityFactor,
54 | SPFSecondPersonalityFactor,
55 | SPFSecondPersonalityFactor,
56 | ];
57 | }
58 |
59 | interface SPFValue {
60 | factor: SPFFactor;
61 | // 因为选项可能存在多个 0,不能直接用 point 作为 radio 的值
62 | optionIndex: number;
63 | point: number;
64 | }
65 |
66 | // 原始分结果
67 | type SPFResult = { [K in SPFFactor]: number };
68 |
69 | interface SPFResultState {
70 | factor: SPFFactor;
71 | label: string;
72 | total: number;
73 | }
74 |
--------------------------------------------------------------------------------
/types/scale/epq-rsc.d.ts:
--------------------------------------------------------------------------------
1 | type EpqRscDimension = "P" | "E" | "N" | "L";
2 |
3 | type EpqRscNormGender = {
4 | [K in EpqRscDimension]: { M: number; SD: number };
5 | } & { range: [number, number | null] };
6 |
7 | interface EpqRscNorm {
8 | male: EpqRscNormGender[];
9 | female: EpqRscNormGender[];
10 | }
11 |
12 | interface Temperaments {
13 | sanguine: string[];
14 | choleric: string[];
15 | melancholic: string[];
16 | phlegmatic: string[];
17 | }
18 |
19 | type Temperament = keyof Temperaments;
20 |
21 | interface EpqRscHighLow {
22 | high: string[];
23 | low: string[];
24 | }
25 |
26 | interface EpqRscDimensionScoreInterpretation {
27 | osculant: string[];
28 | inclined: EpqRscHighLow;
29 | typical: EpqRscHighLow;
30 | }
31 |
32 | interface EpqRscDimensionInterpretation {
33 | label: string;
34 | notice?: string;
35 | supplementary?: string[];
36 | dimension: EpqRscDimensionScoreInterpretation;
37 | }
38 |
39 | interface EpqRscInterpretation {
40 | dimensions: { [K in EpqRscDimension]: EpqRscDimensionInterpretation };
41 | norm: EpqRscNorm;
42 | temperaments: Temperaments;
43 | }
44 |
45 | interface EpqRscValue {
46 | dimension: EpqRscDimension;
47 | point: number;
48 | }
49 |
50 | interface EpqRscQuestion extends CommonQuestion {
51 | dimension: EpqRscDimension;
52 | }
53 |
54 | interface EpqRscResultKindDescription {
55 | name: string;
56 | desc: string[];
57 | }
58 |
59 | type EpqRscResultLevel = -2 | -1 | 0 | 1 | 2;
60 |
61 | interface EpqRscResultKind {
62 | level: EpqRscResultLevel;
63 | label: string;
64 | color: string;
65 | }
66 |
67 | type EpqRscResult = {
68 | [K in EpqRscDimension]: {
69 | score: number;
70 | kind: EpqRscResultKind;
71 | };
72 | };
73 |
--------------------------------------------------------------------------------
/types/scale/ept.d.ts:
--------------------------------------------------------------------------------
1 | type EptTypes =
2 | | "PEACEMAKER"
3 | | "REFORMER"
4 | | "INVESTIGATOR"
5 | | "ENTHUSIAST"
6 | | "CHALLENGER"
7 | | "HELPER"
8 | | "INDIVIDUALIST"
9 | | "LOYALIST"
10 | | "ACHIEVER";
11 |
12 | interface EptQuestion extends CommonQuestion {
13 | type: EptTypes;
14 | }
15 |
16 | interface EptCharacter {
17 | keyword: string;
18 | description: string;
19 | }
20 |
21 | interface EptInterpretation {
22 | type_interpretations: EptInterpretationItem[];
23 | dialog: string[];
24 | }
25 |
26 | interface EptInterpretationItem {
27 | type: EptTypes;
28 | desire_trait: string;
29 | basic_confusion: string;
30 | main_features: string;
31 | main_traits: string;
32 | lifestyle: string;
33 | relationships: string;
34 | basic_fear: string;
35 | basic_desire: string;
36 | characters: EptCharacter[];
37 | }
38 |
39 | interface EptValue {
40 | type: EptTypes;
41 | point: number;
42 | }
43 |
44 | interface EptResultItem {
45 | type: EptTypes;
46 | label: string;
47 | total: {
48 | yes: number;
49 | no: number;
50 | };
51 | }
52 |
53 | type EptResult = EptResultItem[];
54 |
--------------------------------------------------------------------------------
/types/scale/h-sds.d.ts:
--------------------------------------------------------------------------------
1 | type HSDSQuestionType =
2 | | "INTERESTED_EVENT"
3 | | "GOOD_AT"
4 | | "LOVED_JOB"
5 | | "CAPACITY_CATEGORY";
6 |
7 | type HSDSCapacityCategoryType = "R" | "A" | "I" | "S" | "E" | "C";
8 |
9 | interface HSDSQuestion extends CommonQuestion {
10 | question_type: HSDSQuestionType;
11 | capacity_category: HSDSCapacityCategoryType;
12 | }
13 |
14 | type HSDSValue =
15 | | {
16 | question_type: "INTERESTED_EVENT";
17 | capacity_category: HSDSCapacityCategoryType;
18 | selected: number[];
19 | }
20 | | {
21 | question_type: "GOOD_AT";
22 | capacity_category: HSDSCapacityCategoryType;
23 | selected: number[];
24 | }
25 | | {
26 | question_type: "LOVED_JOB";
27 | capacity_category: HSDSCapacityCategoryType;
28 | selected: number[];
29 | }
30 | | {
31 | question_type: "CAPACITY_CATEGORY";
32 | capacity_category: HSDSCapacityCategoryType;
33 | selected: number;
34 | };
35 |
36 | interface HSDSCapacityCategoryInterpretation {
37 | capacity_category: HSDSCapacityCategoryType;
38 | name: string;
39 | personality_trait: string;
40 | occupational_stigma: string;
41 | }
42 |
43 | interface HSDSCareerItem {
44 | code: string;
45 | information: string;
46 | }
47 |
48 | interface HSDSInterpretation {
49 | capacity_category_interpretations: HSDSCapacityCategoryInterpretation[];
50 | career_information: HSDSCareerItem[];
51 | }
52 |
53 | interface HSDSResultItem {
54 | capacity_category: HSDSCapacityCategoryType;
55 | total: number;
56 | }
57 |
58 | type HSDSResult = HSDSResultItem[];
59 |
--------------------------------------------------------------------------------
/types/scale/index.d.ts:
--------------------------------------------------------------------------------
1 | interface Option {
2 | text: string;
3 | point: number;
4 | }
5 |
6 | interface CommonQuestion {
7 | title: string;
8 | options: Option[];
9 | }
10 |
11 | type Path =
12 | | "sas"
13 | | "sds"
14 | | "scl90"
15 | | "hamd"
16 | | "epq_rsc"
17 | | "y_bocs"
18 | | "ept"
19 | | "16pf"
20 | | "neo_pi_r"
21 | | "h_sds";
22 |
23 | type ValueTypes = {
24 | scl90: Scl90Value;
25 | "16pf": SPFValue;
26 | };
27 |
28 | type InferValue = P extends "scl90"
29 | ? Scl90Value
30 | : P extends "16pf"
31 | ? SPFValue
32 | : P extends "ept"
33 | ? EptValue
34 | : P extends "epq_rsc"
35 | ? EpqRscValue
36 | : P extends "neo_pi_r"
37 | ? NEOPiRValue
38 | : P extends "h_sds"
39 | ? HSDSValue
40 | : number;
41 |
42 | type InferResult
= P extends "scl90"
43 | ? Scl90Result
44 | : P extends "epq_rsc"
45 | ? EpqRscResult
46 | : P extends "y_bocs"
47 | ? YBocsResult
48 | : P extends "ept"
49 | ? EptResult
50 | : P extends "16pf"
51 | ? SPFResult
52 | : P extends "neo_pi_r"
53 | ? NEOPiRResult
54 | : P extends "h_sds"
55 | ? HSDSResult
56 | : number;
57 |
58 | type InferInterpretation
= P extends "scl90"
59 | ? Scl90Interpretation
60 | : P extends "epq_rsc"
61 | ? EpqRscInterpretation
62 | : P extends "ept"
63 | ? EptInterpretation
64 | : P extends "16pf"
65 | ? SPFInterpretation
66 | : P extends "neo_pi_r"
67 | ? NEOPiRInterpretation
68 | : P extends "h_sds"
69 | ? HSDSInterpretation
70 | : CommonInterpretation;
71 |
72 | type InferQuestion
= P extends "scl90"
73 | ? Scl90Question
74 | : P extends "epq_rsc"
75 | ? EpqRscQuestion
76 | : P extends "ept"
77 | ? EptQuestion
78 | : P extends "16pf"
79 | ? SPFQuestion
80 | : P extends "neo_pi_r"
81 | ? NEOPiRQuestion
82 | : P extends "h_sds"
83 | ? HSDSQuestion
84 | : CommonQuestion;
85 |
86 | type CalculateResult
= (
87 | values: InferValue
[],
88 | ) => InferResult
;
89 |
90 | interface Tag {
91 | info: string[] | null;
92 | normal: string[] | null;
93 | warning: string[] | null;
94 | error: string[] | null;
95 | }
96 |
97 | type ResultStatus = "normal" | "mild" | "moderate" | "major";
98 |
99 | type Integer = "ROUND" | "FLOOR" | "CEIL";
100 |
101 | interface FormulaMode {
102 | operational_rule: { multiply: number } | { divide: number };
103 | integer?: Integer;
104 | }
105 |
106 | interface InterpretationItem {
107 | range: [number, number];
108 | description: string;
109 | advice?: string[];
110 | symptom?: string[];
111 | status: ResultStatus;
112 | }
113 |
114 | type CommonInterpretation = InterpretationItem[];
115 |
116 | interface Scale {
117 | name: string;
118 | abbreviation: string;
119 | instruction: Texts;
120 | questions: T[];
121 | interpretation: I;
122 | introduction: Texts;
123 | references?: string[];
124 | warning?: string;
125 | formula_mode?: FormulaMode;
126 | idea: string[] | null;
127 | }
128 |
129 | interface QuestionListItem {
130 | name: string;
131 | path: string;
132 | introduction: Texts;
133 | warning: string | null;
134 | tags: Tag;
135 | disabled: boolean;
136 | }
137 |
138 | interface Characteristic {
139 | low: string[];
140 | high: string[];
141 | }
142 |
143 | type ComparisonOperator = "L" | "LE" | "G" | "GE";
144 |
145 | interface Comparison {
146 | expression: string;
147 | operator: ComparisonOperator;
148 | }
149 |
150 | type Gender = "male" | "female";
151 |
152 | interface ComparisonArg {
153 | value: number;
154 | operator: ComparisonOperator;
155 | }
156 |
157 | interface BaseRichText {
158 | text: string;
159 | }
160 |
161 | interface StrongText extends BaseRichText {
162 | type: "STRONG";
163 | }
164 |
165 | interface MarkText extends BaseRichText {
166 | type: "MARK";
167 | }
168 |
169 | interface AText extends BaseRichText {
170 | type: "A";
171 | href: string;
172 | }
173 |
174 | type RichText = StrongText | MarkText | AText; // server: HTMLElement
175 |
176 | type SentenceItem = string | RichText;
177 | type Sentence = SentenceItem[];
178 | type Texts = Sentence[];
179 |
--------------------------------------------------------------------------------
/types/scale/neo-pi-r.d.ts:
--------------------------------------------------------------------------------
1 | type NEOPiRDimension = "N" | "E" | "O" | "A" | "C";
2 |
3 | type InferNEOPiRSubdimension =
4 | | `${T}1`
5 | | `${T}2`
6 | | `${T}3`
7 | | `${T}4`
8 | | `${T}5`
9 | | `${T}6`;
10 |
11 | type NEOPiRSubdimensionN = InferNEOPiRSubdimension<"N">;
12 | type NEOPiRSubdimensionE = InferNEOPiRSubdimension<"E">;
13 | type NEOPiRSubdimensionO = InferNEOPiRSubdimension<"O">;
14 | type NEOPiRSubdimensionA = InferNEOPiRSubdimension<"A">;
15 | type NEOPiRSubdimensionC = InferNEOPiRSubdimension<"C">;
16 |
17 | type NEOPiRSubdimension =
18 | | NEOPiRSubdimensionN
19 | | NEOPiRSubdimensionE
20 | | NEOPiRSubdimensionO
21 | | NEOPiRSubdimensionA
22 | | NEOPiRSubdimensionC;
23 |
24 | interface NEOPiRValue {
25 | dimension: NEOPiRDimension;
26 | subdimension: NEOPiRSubdimension;
27 | point: number;
28 | }
29 |
30 | interface NEOPiRQuestion extends CommonQuestion {
31 | dimension: NEOPiRDimension;
32 | subdimension: NEOPiRSubdimension;
33 | }
34 |
35 | interface NEOPiRNormData {
36 | M: number;
37 | SD: number;
38 | }
39 |
40 | interface NEOPiRDimensionNorm {
41 | dimension: T;
42 | data: NEOPiRNormData;
43 | }
44 |
45 | interface NEOPiRNormGender {
46 | dimension_norm: NEOPiRDimensionNorm[];
47 | subdimension_norm: NEOPiRDimensionNorm[];
48 | }
49 |
50 | type NEOPiRNorm = { [K in Gender]: NEOPiRNormGender };
51 |
52 | interface ScoringRuleData {
53 | value: number;
54 | comparisons:
55 | | [Comparison | null, Comparison]
56 | | [Comparison, Comparison | null]
57 | | [Comparison, Comparison];
58 | }
59 |
60 | interface ScoringRule {
61 | range: { start: number; end: number };
62 | low: ScoringRuleData[];
63 | middle: ScoringRuleData[];
64 | high: ScoringRuleData[];
65 | }
66 |
67 | interface NEOPiRSubdimensionInterpretation {
68 | dimension: NEOPiRSubdimension;
69 | name: string;
70 | description: string;
71 | low: string;
72 | high: string;
73 | }
74 |
75 | interface NEOPiRDimensionInterpretation {
76 | dimension: NEOPiRDimension;
77 | name: string;
78 | description: string;
79 | low: string;
80 | high: string;
81 | subdimension_interpretations: NEOPiRSubdimensionInterpretation[];
82 | }
83 |
84 | interface NEOPiRInterpretation {
85 | norm: NEOPiRNorm;
86 | scoring_rule: ScoringRule;
87 | dimensions: NEOPiRDimensionInterpretation[];
88 | }
89 |
90 | interface NEOPiRResultItem {
91 | // 原始分
92 | original: number;
93 | // 常模标准
94 | standard: NEOPiRNormData;
95 | transformRule: transformRule;
96 | }
97 |
98 | interface NEOPiRResult {
99 | dimensions: { [K in NEOPiRDimension]: NEOPiRResultItem };
100 | subdimensions: { [K in NEOPiRSubdimension]: NEOPiRResultItem };
101 | }
102 |
--------------------------------------------------------------------------------
/types/scale/scl-90.d.ts:
--------------------------------------------------------------------------------
1 | type Scl90Symptom =
2 | | "SOMATIZATION"
3 | | "OBSESSIVE_COMPULSIIVE"
4 | | "SENSITIVE_OF_INTERPERSONAL_RELATIONSHIP"
5 | | "DESPONDENT"
6 | | "ANXIETY"
7 | | "HOSTILITY"
8 | | "PHOBIA"
9 | | "BIGOTRY"
10 | | "PSYCHOTIC"
11 | | "OTHER";
12 |
13 | interface Scl90Question extends CommonQuestion {
14 | symptom: Scl90Symptom;
15 | }
16 |
17 | interface Scl90Value {
18 | symptom: Scl90Symptom;
19 | point: number;
20 | }
21 |
22 | interface Scl90PositivaRule {
23 | value: number;
24 | comparison_operator: string;
25 | }
26 |
27 | interface Scl90Interpretation {
28 | positive: {
29 | total: Scl90PositivaRule;
30 | positive_amount: Scl90PositivaRule;
31 | any_symptom_average: Scl90PositivaRule;
32 | };
33 | symptoms: Record;
34 | }
35 |
36 | interface Scl90Result {
37 | /** 总分 */
38 | total: number;
39 | /** 总均分 */
40 | average: number;
41 | /** 阳性项目数 */
42 | positiveAmount: number;
43 | /** 阴性项目数 */
44 | negativeAmount: number;
45 | /** 阳性症状均分 */
46 | positiveAverage: number;
47 | /* 各因子的平均分 **/
48 | symptomsAverage: { [K in Scl90Symptom]: number };
49 | }
50 |
--------------------------------------------------------------------------------
/types/scale/y-bocs.d.ts:
--------------------------------------------------------------------------------
1 | interface YBocsResult {
2 | thinking: number;
3 | behavior: number;
4 | total: number;
5 | }
6 |
7 | interface YBocsInterpretationItem {
8 | range: { total: [number, number]; any: [number, number] };
9 | label: string;
10 | description?: string[];
11 | advice?: string[];
12 | status: ResultStatus;
13 | }
14 |
15 | type YBocsInterpretation = YBocsInterpretationItem[];
16 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import path from "node:path";
2 | import react from "@vitejs/plugin-react";
3 | import { defineConfig, loadEnv } from "vite";
4 | import vitePluginImp from "vite-plugin-imp";
5 |
6 | // eslint-disable-next-line no-undef
7 | const pathSrc = path.resolve(__dirname, "src");
8 |
9 | // https://vitejs.dev/config/
10 | export default ({ mode }) => {
11 | const env = loadEnv(mode, process.cwd(), "");
12 |
13 | return defineConfig({
14 | server: {
15 | host: "0.0.0.0",
16 | proxy: {
17 | "^/api/.*": {
18 | target: env.VITE_API,
19 | // target: 'http://localhost:9999',
20 | changeOrigin: true,
21 | rewrite: (path) => path.replace(/^\/api/, ""),
22 | },
23 | },
24 | },
25 | plugins: [
26 | react(),
27 | vitePluginImp({
28 | libList: [
29 | {
30 | libName: "antd-mobile",
31 | style: () => false,
32 | libDirectory: "es/components",
33 | replaceOldImport: true,
34 | },
35 | ],
36 | }),
37 | ],
38 |
39 | resolve: {
40 | alias: {
41 | "~/": `${pathSrc}/`,
42 | },
43 | },
44 | });
45 | };
46 |
--------------------------------------------------------------------------------