Skip to main content

br_db/
fields.rs

1use json::{object, JsonValue};
2#[derive(Clone, Debug)]
3pub enum Fields {
4    String,
5    StringPass,
6    StringKey,
7    StringTel,
8    StringIdent,
9    StringEmail,
10    StringColor,
11    StringCode,
12    StringBarcode,
13    StringQrcode,
14    Radio,
15    Select,
16    TableList,
17    TableTree,
18    Int,
19    Switch,
20    Dict,
21    Text,
22    TextEditor,
23    TextUrl,
24    Json,
25    Array,
26    Object,
27    Float,
28    DateTime,
29    Year,
30}
31impl Fields {
32    pub fn name(&mut self, name: &str) -> Field {
33        Field::new(self.clone(), name)
34    }
35    pub fn str(self) -> &'static str {
36        match self {
37            Fields::String
38            | Fields::StringPass
39            | Fields::StringKey
40            | Fields::StringTel
41            | Fields::StringIdent
42            | Fields::StringEmail
43            | Fields::StringColor
44            | Fields::StringCode
45            | Fields::StringBarcode
46            | Fields::StringQrcode => "string",
47            Fields::Radio => "radio",
48            Fields::Select => "select",
49            Fields::TableList => "table",
50            Fields::TableTree => "tree",
51            Fields::Int => "int",
52            Fields::Switch => "bool",
53            Fields::Dict => "string",
54            Fields::Text | Fields::TextEditor | Fields::TextUrl => "text",
55            Fields::Json => "json",
56            Fields::Array => "array",
57            Fields::Object => "object",
58            Fields::Float => "float",
59            Fields::DateTime => "datetime",
60            Fields::Year => "year",
61        }
62    }
63}
64#[derive(Debug)]
65pub struct Field {
66    mode: Fields,
67    /// 必填
68    require: bool,
69    field: String,
70    title: String,
71    /// 默认值
72    def: JsonValue,
73    /// 长度
74    length: usize,
75    /// 小数点位数
76    dec: usize,
77    /// 选择项目
78    option: Vec<&'static str>,
79    /// 是否显示
80    show: bool,
81    describe: String,
82    /// 示例
83    example: JsonValue,
84    /// 接口
85    api: String,
86    /// 表名称
87    table_name: String,
88    /// 是否多选
89    multiple: bool,
90}
91
92impl Field {
93    pub fn new(mode: Fields, name: &str) -> Field {
94        Self {
95            mode,
96            require: true,
97            field: name.to_string(),
98            title: "".to_string(),
99            def: JsonValue::Null,
100            length: 0,
101            dec: 0,
102            option: vec![],
103            show: true,
104            describe: "".to_string(),
105            example: JsonValue::Null,
106            api: "".to_string(),
107            table_name: "".to_string(),
108            multiple: false,
109        }
110    }
111    pub fn title(mut self, name: &str) -> Field {
112        self.title = name.to_string();
113        self
114    }
115    /// 默认值
116    pub fn def(mut self, name: JsonValue) -> Field {
117        self.def = name;
118        self
119    }
120    pub fn require(mut self, require: bool) -> Field {
121        self.require = require;
122        self
123    }
124    pub fn show(mut self, show: bool) -> Field {
125        self.show = show;
126        self
127    }
128    pub fn example(mut self, example: JsonValue) -> Field {
129        self.example = example;
130        self
131    }
132    pub fn length(mut self, length: usize) -> Field {
133        self.length = length;
134        self
135    }
136    pub fn describe(mut self, describe: &str) -> Field {
137        self.describe = describe.to_string();
138        self
139    }
140    pub fn option(mut self, option: Vec<&'static str>) -> Field {
141        self.option = option;
142        self
143    }
144    /// 关联数据表配置
145    pub fn table(mut self, table: &str, api: &str, fields: Vec<&'static str>) -> Field {
146        self.api = api.to_string();
147        self.table_name = table.to_string();
148        self.option = fields;
149        self
150    }
151    pub fn multiple(mut self, multiple: bool, count: usize) -> Field {
152        self.multiple = multiple;
153        if count == 0 {
154            self.length = 1
155        } else {
156            self.length = count;
157        }
158        self
159    }
160    pub fn dec(mut self, dec: usize) -> Field {
161        self.dec = dec;
162        self
163    }
164    pub fn sql(self) -> JsonValue {
165        object! {}
166    }
167    pub fn swagger(self) -> JsonValue {
168        object! {
169            "type": self.mode.str(),
170            "example": self.example,
171        }
172    }
173    pub fn field(self) -> JsonValue {
174        let example = if self.example.is_empty() {
175            self.def.clone()
176        } else {
177            self.example
178        };
179        let mut field = object! {
180            "require"=> self.require,
181            "field"=> self.field,
182            "title"=> self.title,
183            "show"=> self.show,
184            "describe"=> self.describe,
185            "example"=> example
186        };
187        match self.mode {
188            Fields::String
189            | Fields::StringPass
190            | Fields::StringKey
191            | Fields::StringTel
192            | Fields::StringIdent
193            | Fields::StringEmail
194            | Fields::StringColor
195            | Fields::StringCode
196            | Fields::StringBarcode
197            | Fields::StringQrcode => {
198                field["length"] = self.length.into();
199                field["def"] = self.def;
200            }
201            Fields::Radio => {
202                field["option"] = self.option.into();
203                field["def"] = self.def;
204            }
205            Fields::Select => {
206                field["option"] = self.option.into();
207                field["def"] = self.def;
208            }
209            Fields::TableList | Fields::TableTree | Fields::Dict => {
210                field["option"] = self.option.into();
211                field["def"] = self.def;
212                field["api"] = self.api.into();
213                field["table"] = self.table_name.into();
214                field["multiple"] = self.multiple.into();
215                field["length"] = self.length.into();
216            }
217            Fields::Int => {
218                field["length"] = self.length.into();
219                field["def"] = self.def;
220            }
221            Fields::Switch => {
222                field["def"] = self.def;
223            }
224            Fields::Text
225            | Fields::TextEditor
226            | Fields::TextUrl
227            | Fields::Json
228            | Fields::Array
229            | Fields::Object => {
230                field["length"] = self.length.into();
231                field["def"] = self.def;
232            }
233            Fields::Float => {
234                field["length"] = self.length.into();
235                field["dec"] = self.dec.into();
236                field["def"] = self.def;
237            }
238            Fields::DateTime => {
239                field["def"] = self.def;
240            }
241            Fields::Year => {
242                field["def"] = self.def;
243            }
244        };
245        field
246    }
247}
248#[cfg(test)]
249mod tests {
250    use super::*;
251    use json::JsonValue;
252
253    #[test]
254    fn fields_str_string_variants() {
255        assert_eq!(Fields::String.str(), "string");
256        assert_eq!(Fields::StringPass.str(), "string");
257        assert_eq!(Fields::StringKey.str(), "string");
258        assert_eq!(Fields::StringTel.str(), "string");
259        assert_eq!(Fields::StringIdent.str(), "string");
260        assert_eq!(Fields::StringEmail.str(), "string");
261        assert_eq!(Fields::StringColor.str(), "string");
262        assert_eq!(Fields::StringCode.str(), "string");
263        assert_eq!(Fields::StringBarcode.str(), "string");
264        assert_eq!(Fields::StringQrcode.str(), "string");
265    }
266
267    #[test]
268    fn fields_str_other_variants() {
269        assert_eq!(Fields::Radio.str(), "radio");
270        assert_eq!(Fields::Select.str(), "select");
271        assert_eq!(Fields::TableList.str(), "table");
272        assert_eq!(Fields::TableTree.str(), "tree");
273        assert_eq!(Fields::Int.str(), "int");
274        assert_eq!(Fields::Switch.str(), "bool");
275        assert_eq!(Fields::Dict.str(), "string");
276        assert_eq!(Fields::Text.str(), "text");
277        assert_eq!(Fields::TextEditor.str(), "text");
278        assert_eq!(Fields::TextUrl.str(), "text");
279        assert_eq!(Fields::Json.str(), "json");
280        assert_eq!(Fields::Array.str(), "array");
281        assert_eq!(Fields::Object.str(), "object");
282        assert_eq!(Fields::Float.str(), "float");
283        assert_eq!(Fields::DateTime.str(), "datetime");
284        assert_eq!(Fields::Year.str(), "year");
285    }
286
287    #[test]
288    fn fields_name_creates_field() {
289        let f = Fields::Int.name("age");
290        assert_eq!(f.field, "age");
291        assert!(matches!(f.mode, Fields::Int));
292    }
293
294    #[test]
295    fn field_new_defaults() {
296        let f = Field::new(Fields::String, "name");
297        assert!(matches!(f.mode, Fields::String));
298        assert!(f.require);
299        assert!(f.show);
300        assert_eq!(f.field, "name");
301        assert_eq!(f.title, "");
302        assert!(f.def.is_null());
303        assert_eq!(f.length, 0);
304        assert_eq!(f.dec, 0);
305        assert!(f.option.is_empty());
306        assert_eq!(f.describe, "");
307        assert!(f.example.is_null());
308        assert_eq!(f.api, "");
309        assert_eq!(f.table_name, "");
310        assert!(!f.multiple);
311    }
312
313    #[test]
314    fn field_title() {
315        let res = Fields::String.name("x").title("My Title").field();
316        assert_eq!(res["title"], "My Title");
317    }
318
319    #[test]
320    fn field_def() {
321        let res = Fields::String.name("x").def("default_val".into()).field();
322        assert_eq!(res["def"], "default_val");
323    }
324
325    #[test]
326    fn field_require_false() {
327        let res = Fields::String.name("x").require(false).field();
328        assert_eq!(res["require"], false);
329    }
330
331    #[test]
332    fn field_show_false() {
333        let res = Fields::String.name("x").show(false).field();
334        assert_eq!(res["show"], false);
335    }
336
337    #[test]
338    fn field_example_set() {
339        let res = Fields::String.name("x").example("ex".into()).field();
340        assert_eq!(res["example"], "ex");
341    }
342
343    #[test]
344    fn field_length() {
345        let res = Fields::String.name("x").length(50).field();
346        assert_eq!(res["length"], 50);
347    }
348
349    #[test]
350    fn field_describe() {
351        let res = Fields::String.name("x").describe("desc text").field();
352        assert_eq!(res["describe"], "desc text");
353    }
354
355    #[test]
356    fn field_option() {
357        let res = Fields::Radio.name("x").option(vec!["a", "b"]).field();
358        assert_eq!(res["option"][0], "a");
359        assert_eq!(res["option"][1], "b");
360    }
361
362    #[test]
363    fn field_table() {
364        let res = Fields::TableList
365            .name("x")
366            .table("my_table", "/api/list", vec!["col1", "col2"])
367            .field();
368        assert_eq!(res["table"], "my_table");
369        assert_eq!(res["api"], "/api/list");
370        assert_eq!(res["option"][0], "col1");
371        assert_eq!(res["option"][1], "col2");
372    }
373
374    #[test]
375    fn field_multiple_count_zero() {
376        let f = Field::new(Fields::TableList, "x").multiple(true, 0);
377        assert!(f.multiple);
378        assert_eq!(f.length, 1);
379    }
380
381    #[test]
382    fn field_multiple_count_nonzero() {
383        let f = Field::new(Fields::TableList, "x").multiple(true, 5);
384        assert!(f.multiple);
385        assert_eq!(f.length, 5);
386    }
387
388    #[test]
389    fn field_dec() {
390        let res = Fields::Float.name("x").dec(4).field();
391        assert_eq!(res["dec"], 4);
392    }
393
394    #[test]
395    fn field_sql_returns_empty_object() {
396        let res = Fields::String.name("x").sql();
397        assert!(res.is_object());
398        assert_eq!(res.len(), 0);
399    }
400
401    #[test]
402    fn field_swagger_returns_type_and_example() {
403        let res = Fields::Int.name("x").example(42.into()).swagger();
404        assert_eq!(res["type"], "int");
405        assert_eq!(res["example"], 42);
406    }
407
408    #[test]
409    fn field_output_string_variants() {
410        let variants = [
411            Fields::String,
412            Fields::StringPass,
413            Fields::StringKey,
414            Fields::StringTel,
415            Fields::StringIdent,
416            Fields::StringEmail,
417            Fields::StringColor,
418            Fields::StringCode,
419            Fields::StringBarcode,
420            Fields::StringQrcode,
421        ];
422        for mut v in variants {
423            let res = v.name("s").length(100).def("d".into()).field();
424            assert_eq!(res["length"], 100);
425            assert_eq!(res["def"], "d");
426        }
427    }
428
429    #[test]
430    fn field_output_radio() {
431        let res = Fields::Radio
432            .name("r")
433            .option(vec!["yes", "no"])
434            .def("yes".into())
435            .field();
436        assert_eq!(res["option"][0], "yes");
437        assert_eq!(res["option"][1], "no");
438        assert_eq!(res["def"], "yes");
439        assert!(res["length"].is_null());
440    }
441
442    #[test]
443    fn field_output_select() {
444        let res = Fields::Select
445            .name("s")
446            .option(vec!["a", "b", "c"])
447            .def("a".into())
448            .field();
449        assert_eq!(res["option"].len(), 3);
450        assert_eq!(res["def"], "a");
451        assert!(res["length"].is_null());
452    }
453
454    #[test]
455    fn field_output_table_list() {
456        let res = Fields::TableList
457            .name("t")
458            .table("tbl", "/api", vec!["f1"])
459            .multiple(true, 3)
460            .def("x".into())
461            .field();
462        assert_eq!(res["option"][0], "f1");
463        assert_eq!(res["def"], "x");
464        assert_eq!(res["api"], "/api");
465        assert_eq!(res["table"], "tbl");
466        assert_eq!(res["multiple"], true);
467        assert_eq!(res["length"], 3);
468    }
469
470    #[test]
471    fn field_output_table_tree() {
472        let res = Fields::TableTree
473            .name("t")
474            .table("tree_tbl", "/tree", vec!["c1", "c2"])
475            .multiple(false, 0)
476            .def(JsonValue::Null)
477            .field();
478        assert_eq!(res["table"], "tree_tbl");
479        assert_eq!(res["api"], "/tree");
480        assert_eq!(res["multiple"], false);
481        assert_eq!(res["length"], 1);
482    }
483
484    #[test]
485    fn field_output_dict() {
486        let res = Fields::Dict
487            .name("d")
488            .table("dict_tbl", "/dict", vec!["k"])
489            .def("v".into())
490            .field();
491        assert_eq!(res["table"], "dict_tbl");
492        assert_eq!(res["api"], "/dict");
493        assert_eq!(res["def"], "v");
494        assert!(!res["multiple"].is_null());
495    }
496
497    #[test]
498    fn field_output_int() {
499        let res = Fields::Int.name("i").length(11).def(0.into()).field();
500        assert_eq!(res["length"], 11);
501        assert_eq!(res["def"], 0);
502    }
503
504    #[test]
505    fn field_output_switch() {
506        let res = Fields::Switch.name("sw").def(true.into()).field();
507        assert_eq!(res["def"], true);
508        assert!(res["length"].is_null());
509    }
510
511    #[test]
512    fn field_output_text_variants() {
513        let variants = [
514            Fields::Text,
515            Fields::TextEditor,
516            Fields::TextUrl,
517            Fields::Json,
518            Fields::Array,
519            Fields::Object,
520        ];
521        for mut v in variants {
522            let res = v.name("t").length(5000).def("body".into()).field();
523            assert_eq!(res["length"], 5000);
524            assert_eq!(res["def"], "body");
525        }
526    }
527
528    #[test]
529    fn field_output_float() {
530        let res = Fields::Float
531            .name("f")
532            .length(10)
533            .dec(2)
534            .def(1.5.into())
535            .field();
536        assert_eq!(res["length"], 10);
537        assert_eq!(res["dec"], 2);
538        assert_eq!(res["def"], 1.5);
539    }
540
541    #[test]
542    fn field_output_datetime() {
543        let res = Fields::DateTime.name("dt").def("2026-01-01".into()).field();
544        assert_eq!(res["def"], "2026-01-01");
545        assert!(res["length"].is_null());
546    }
547
548    #[test]
549    fn field_output_year() {
550        let res = Fields::Year.name("y").def(2026.into()).field();
551        assert_eq!(res["def"], 2026);
552        assert!(res["length"].is_null());
553    }
554
555    #[test]
556    fn field_example_fallback_to_def() {
557        let res = Fields::String.name("x").def("fallback".into()).field();
558        assert_eq!(res["example"], "fallback");
559    }
560
561    #[test]
562    fn field_example_explicit_overrides_def() {
563        let res = Fields::String
564            .name("x")
565            .def("default".into())
566            .example("explicit".into())
567            .field();
568        assert_eq!(res["example"], "explicit");
569    }
570}