crud.tsx 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. import { AddReq, compute,useCrud ,useExpose, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, uiContext, UserPageQuery, } from '@fast-crud/fast-crud';
  2. import dayjs from 'dayjs';
  3. import * as api from './api';
  4. import { uploadFile } from './api';
  5. import { auth } from '/@/utils/authFunction';
  6. import {request} from '/@/utils/service';
  7. import {getBaseURL} from '/@/utils/baseUrl';
  8. import Cookies from 'js-cookie';
  9. import { successMessage } from '/@/utils/message';
  10. import { dictionary } from '/@/utils/dictionary';
  11. import { APIResponseData } from '../columns/types';
  12. import { computed, h,defineComponent, ref, onMounted, watch } from 'vue';
  13. import { ElTable, ElTableColumn, ElLoading } from 'element-plus';
  14. const BorrowRecords = defineComponent({
  15. props: { form: Object },
  16. setup(props) {
  17. try {
  18. const records = ref([]);
  19. const loading = ref(false);
  20. const filteredRecords = computed(() =>
  21. (records.value || [])/* .filter((item: any) => item?.record_type === 0) */
  22. );
  23. const loadData = async () => {
  24. if (!props.form?.id) return;
  25. loading.value = true;
  26. try {
  27. const res = await api.getBorrowRecords(props.form.id);
  28. records.value = res.data || [];
  29. } finally {
  30. loading.value = false;
  31. }
  32. };
  33. watch(() => props.form?.id, loadData, { immediate: true });
  34. return () => (
  35. <ElTable data={filteredRecords.value} v-loading={loading.value} style="width: 100%">
  36. <ElTableColumn prop="application_no" label="借用编号" />
  37. <ElTableColumn prop="borrower_name" label="借用人" />
  38. <ElTableColumn prop="borrower_code" label="学号/工号"/>
  39. <ElTableColumn prop="record_type_label" label="状态" />
  40. <ElTableColumn prop="borrow_type_display" label="借用类型" />
  41. </ElTable>
  42. );
  43. } catch (e) {
  44. console.error("BorrowRecords setup error:", e);
  45. return () => <div>组件加载失败</div>;
  46. }
  47. }
  48. });
  49. const MaintenanceHistory = defineComponent({
  50. props: { form: Object },
  51. setup(props) {
  52. try {
  53. const records = ref([]);
  54. const loading = ref(false);
  55. const loadData = async () => {
  56. if (!props.form?.id) return;
  57. loading.value = true;
  58. try {
  59. const res = await api.getMaintenanceHistory(props.form.id);
  60. records.value = res.data || [];
  61. } finally {
  62. loading.value = false;
  63. }
  64. };
  65. watch(() => props.form?.id, loadData, { immediate: true });
  66. return () => (
  67. <ElTable data={records.value} v-loading={loading.value} style="width: 100%">
  68. <ElTableColumn prop="damage_no" label="维修编号" />
  69. <ElTableColumn prop="device_name" label="设备名称" />
  70. <ElTableColumn prop="damage_reason" label="损坏原因" />
  71. <ElTableColumn prop="estimated_loss" label="损失价格" />
  72. </ElTable>
  73. );
  74. } catch (e) {
  75. console.error("MaintenanceHistory setup error:", e);
  76. return () => <div>组件加载失败</div>;
  77. }
  78. }
  79. });
  80. const MaintenanceRecords = defineComponent({
  81. props: { form: Object },
  82. setup(props) {
  83. try {
  84. const records = ref([]);
  85. const loading = ref(false);
  86. const loadData = async () => {
  87. if (!props.form?.id) return;
  88. loading.value = true;
  89. try {
  90. const res = await api.getMaintenanceRecords(props.form.id);
  91. records.value = res.data || [];
  92. } finally {
  93. loading.value = false;
  94. }
  95. };
  96. watch(() => props.form?.id, loadData, { immediate: true });
  97. return () => (
  98. <ElTable data={records.value} v-loading={loading.value} style="width: 100%">
  99. <ElTableColumn prop="record_no" label="保养编号" />
  100. <ElTableColumn prop="plan_name" label="保养计划" />
  101. <ElTableColumn prop="planned_date" label="保养日期" />
  102. <ElTableColumn prop="maintenance_person" label="保养人员" />
  103. <ElTableColumn prop="maintenance_content" label="保养内容" />
  104. </ElTable>
  105. );
  106. } catch (e) {
  107. console.error("MaintenanceRecords setup error:", e);
  108. return () => <div>组件加载失败</div>;
  109. }
  110. }
  111. });
  112. const DeviceStatistics = defineComponent({
  113. props: { form: Object },
  114. setup(props) {
  115. try {
  116. const statistics = ref<any>({});
  117. const loading = ref(false);
  118. const loadData = async () => {
  119. if (!props.form?.id) return;
  120. loading.value = true;
  121. try {
  122. const res = await api.getDeviceStatistics(props.form.id);
  123. statistics.value = res.data || {};
  124. console.log(statistics.value)
  125. } finally {
  126. loading.value = false;
  127. }
  128. };
  129. watch(() => props.form?.id, loadData, { immediate: true });
  130. return () => (
  131. <div v-loading={loading.value} style={{ padding: '20px' }}>
  132. <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '20px' }}>
  133. <div style={{ background: '#f5f7fa', padding: '20px', borderRadius: '8px', textAlign: 'center' }}>
  134. <div style={{ fontSize: '24px', fontWeight: 'bold', color: '#409eff' }}>{statistics.value.borrow_count || 0}</div>
  135. <div style={{ color: '#606266', marginTop: '8px' }}>总借用次数</div>
  136. </div>
  137. <div style={{ background: '#f5f7fa', padding: '20px', borderRadius: '8px', textAlign: 'center' }}>
  138. <div style={{ fontSize: '24px', fontWeight: 'bold', color: '#67c23a' }}>{statistics.value.maintenance_records_count || 0}</div>
  139. <div style={{ color: '#606266', marginTop: '8px' }}>维护次数</div>
  140. </div>
  141. <div style={{ background: '#f5f7fa', padding: '20px', borderRadius: '8px', textAlign: 'center' }}>
  142. <div style={{ fontSize: '24px', fontWeight: 'bold', color: '#e6a23c' }}>{statistics.value.maintenance_history_count || 0}</div>
  143. <div style={{ color: '#606266', marginTop: '8px' }}>维修次数</div>
  144. </div>
  145. <div style={{ background: '#f5f7fa', padding: '20px', borderRadius: '8px', textAlign: 'center' }}>
  146. <div style={{ fontSize: '24px', fontWeight: 'bold', color: '#f56c6c' }}>{statistics.value.total_borrow_hours || 0}</div>
  147. <div style={{ color: '#606266', marginTop: '8px' }}>借用时长</div>
  148. </div>
  149. </div>
  150. {statistics.value.recent_activities && (
  151. <div style={{ marginTop: '30px' }}>
  152. <h3 style={{ marginBottom: '20px', color: '#303133' }}>最近活动</h3>
  153. <ElTable data={statistics.value.recent_activities} style={{ width: '100%' }}>
  154. <ElTableColumn prop="activity_type" label="活动类型" />
  155. <ElTableColumn prop="activity_date" label="活动日期" />
  156. <ElTableColumn prop="description" label="描述" />
  157. </ElTable>
  158. </div>
  159. )}
  160. </div>
  161. );
  162. } catch (e) {
  163. console.error("DeviceStatistics setup error:", e);
  164. return () => <div>组件加载失败</div>;
  165. }
  166. }
  167. });
  168. export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
  169. const pageRequest = async (query: UserPageQuery) => {
  170. return await api.GetList(query);
  171. };
  172. const editRequest = async ({ form, row }: EditReq) => {
  173. form.id = row.id;
  174. return await api.UpdateObj(form);
  175. };
  176. const delRequest = async ({ row }: DelReq) => {
  177. return await api.DelObj(row.id);
  178. };
  179. const addRequest = async ({ form }: AddReq) => {
  180. return await api.AddObj(form);
  181. };
  182. const selectedIds = ref<any[]>([]);
  183. const onSelectionChange = (changed: any[]) => {
  184. console.log("selection", changed);
  185. selectedIds.value = changed.map((item: any) => item.id);
  186. };
  187. (crudExpose as any).selectedIds = selectedIds;
  188. return {
  189. // selectedIds,
  190. crudOptions: {
  191. request: {
  192. pageRequest,
  193. addRequest,
  194. editRequest,
  195. delRequest,
  196. },
  197. table: {
  198. rowKey: "id",
  199. onSelectionChange
  200. },
  201. toolbar:{
  202. show:true,
  203. },
  204. rowHandle: {
  205. fixed: 'right',
  206. width: 220,
  207. view: {
  208. show: true,
  209. },
  210. edit: {
  211. show: true,
  212. },
  213. remove: {
  214. show: true,
  215. },
  216. },
  217. actionbar: {
  218. buttons: {
  219. add: {
  220. show: auth('user:Create')
  221. },
  222. // batchimport:{
  223. // text: "批量导入",
  224. // title: "导入",
  225. // // show: auth('user:batchimport'),
  226. // },
  227. // export: {
  228. // text: "导出",
  229. // title: "导出",
  230. // show: auth('user:Export'),
  231. // },
  232. // downloadtemplate: {
  233. // text: "下载模板",
  234. // title: "下载模板",
  235. // // show: auth('user:Export'),
  236. // },
  237. // batchdelete: {
  238. // text: "批量删除",
  239. // title: "批量删除",
  240. // // show: auth('user:Export'),
  241. // },
  242. }
  243. },
  244. columns: {
  245. $checked: {
  246. title: "选择",
  247. form: { show: false },
  248. column: {
  249. type: "selection",
  250. align: "center",
  251. width: "55px",
  252. columnSetDisabled: true, //禁止在列设置中选择
  253. selectable(row, index) {
  254. // return row.id !== 1; //设置第一行不允许选择
  255. return row.id;
  256. }
  257. }
  258. },
  259. _index: {
  260. title: '序号',
  261. form: { show: false },
  262. column: {
  263. align: 'center',
  264. width: '70px',
  265. columnSetDisabled: true,
  266. formatter: (context) => {
  267. let index = context.index ?? 1;
  268. let pagination = crudExpose!.crudBinding.value.pagination;
  269. return ((pagination!.currentPage ?? 1) - 1) * pagination!.pageSize + index + 1;
  270. },
  271. },
  272. },
  273. search:{
  274. title: '关键字搜索',
  275. search: { show: true,type: 'input', },
  276. type: 'input',
  277. form: {
  278. component: { placeholder: '请输入' },
  279. show:false},
  280. column: {show:false}
  281. },
  282. code: {
  283. title: '设备编号',
  284. search: { show: true },
  285. type: 'input',
  286. column: { minWidth: 120 },
  287. form: {
  288. component: { placeholder: '请输入设备编号' },
  289. rules: [{ required: true, message: '请输入设备编号' }],
  290. },
  291. viewForm:{
  292. component: { placeholder: '' },
  293. rules: [{ required: true, message: '' }],
  294. },
  295. },
  296. category_name: {
  297. title: '设备分类',
  298. search: { show: true },
  299. type: 'dict-select',
  300. dict: dict({
  301. url: '/api/system/device/category/?page=1&limit=100',
  302. value: 'id',
  303. label: 'name',
  304. }),
  305. column: { minWidth: 100 },
  306. form: {
  307. show:false,
  308. component: { placeholder: '请选择设备分类' },
  309. rules: [{ required: true, message: '请选择设备分类' }],
  310. },
  311. viewForm:{
  312. component: { placeholder: '' },
  313. rules: [{ required: true, message: '' }],
  314. }
  315. },
  316. name: {
  317. title: '设备名称',
  318. search: { show: false },
  319. type: 'input',
  320. column: { minWidth: 120 },
  321. form: {
  322. component: { placeholder: '请输入设备名称' },
  323. rules: [{ required: true, message: '请输入设备名称' }]
  324. },
  325. viewForm:{
  326. component: { placeholder: '' },
  327. rules: [{ required: true, message: '' }],
  328. }
  329. },
  330. "inventory.borrowed_quantity":{
  331. title: '设备状态',
  332. type: 'text',
  333. search: { show: false },
  334. column: {
  335. show: true,
  336. minWidth: 100,
  337. formatter: ({ row }) => {
  338. const isBorrowed = row.borrowed_quantity > 0;
  339. const isMaintenance = row.maintenance_quantity > 0 && row.maintenance_quantity === row.total_quantity;
  340. const isDamaged = row.damaged_quantity > 0 && row.damaged_quantity === row.total_quantity;
  341. let label, color;
  342. if (isDamaged) {
  343. label = '报损';
  344. color = '#F56C6C';
  345. } else if (isMaintenance) {
  346. label = '维修';
  347. color = '#E6A23C';
  348. } else if (isBorrowed) {
  349. label = row.total_quantity - row.borrowed_quantity === 0 ? '在借' : '在借';
  350. color = '#FFA500';
  351. } else {
  352. label = row.total_quantity === 0 ? '在借' : '空闲';
  353. color = '#4CAF50';
  354. }
  355. return h(
  356. 'span',
  357. {
  358. style: {
  359. display: 'inline-block',
  360. padding: '2px 8px',
  361. border: `1px solid ${color}`,
  362. borderRadius: '4px',
  363. backgroundColor: color,
  364. color: 'white',
  365. fontWeight: 'bold',
  366. }
  367. },
  368. label
  369. );
  370. }
  371. },
  372. form: {
  373. show:false,
  374. component: { placeholder: '请选择设备状态' },
  375. rules: [{ required: true, message: '请选择设备状态' }],
  376. },
  377. },
  378. borrowed_quantity:{
  379. title:"已借出",
  380. type:'input',
  381. search:{show:false},
  382. column: { minWidth: 100 },
  383. form: {
  384. show:false,
  385. component: { placeholder: '请输入已借出' },
  386. rules: [{ required: true, message: '请输入已借出' }],
  387. },
  388. viewForm:{
  389. component: { placeholder: '' },
  390. rules: [{ required: true, message: '' }],
  391. }
  392. },
  393. brand:{
  394. title:'品牌',
  395. type:"input",
  396. column: { minWidth: 100 },
  397. form: {
  398. component: { placeholder: '请输入品牌' }
  399. },
  400. viewForm:{
  401. component: { placeholder: '' },
  402. rules: [{ required: true, message: '' }],
  403. },
  404. },
  405. specification: {
  406. title: '规格型号',
  407. search: { show: false },
  408. type: 'input',
  409. column: { minWidth: 100 },
  410. form: {
  411. component: { placeholder: '请输入规格型号' }
  412. },
  413. viewForm:{
  414. component: { placeholder: '' },
  415. rules: [{ required: true, message: '' }],
  416. },
  417. },
  418. serial_number:{
  419. title:'序列号',
  420. type:"input",
  421. column: { minWidth: 100 },
  422. form: {
  423. component: { placeholder: '请输入序列号' }
  424. },
  425. viewForm:{
  426. component: { placeholder: '' },
  427. rules: [{ required: true, message: '' }],
  428. },
  429. },
  430. available_quantity:{
  431. title:'可用库存',
  432. type:"input",
  433. column: { minWidth: 100 },
  434. addForm:{
  435. show:false,
  436. },
  437. viewForm:{
  438. show:false,
  439. },
  440. editForm:{show:false},
  441. from:{
  442. show:false,
  443. component: { placeholder: '请输入库存数量' },
  444. rules: [{ required: false, message: '请输入库存数量' }],
  445. }
  446. },
  447. total_quantity:{
  448. title:'库存数量',
  449. type:"input",
  450. column: { minWidth: 100 },
  451. addForm:{
  452. show:false,
  453. },
  454. viewForm:{
  455. show:false,
  456. },
  457. editForm:{show:false},
  458. from:{
  459. show:false,
  460. component: { placeholder: '请输入库存数量' },
  461. rules: [{ required: false, message: '请输入库存数量' }],
  462. }
  463. },
  464. /* warehouse:{
  465. title:'存放仓库',
  466. search: { show: true },
  467. type:"dict-select",
  468. column: { minWidth: 150 },
  469. dict: dict({
  470. url: '/api/system/warehouse/',
  471. value: 'id',
  472. label: 'name'
  473. }),
  474. form: {
  475. component: { placeholder: '请选择存放仓库' },
  476. rules: [{ required: true, message: '请选择存放仓库' }],
  477. }
  478. }, */
  479. status:{
  480. title:'是否可见',
  481. type: 'dict-switch',
  482. column: {
  483. show:false,
  484. minWidth: 90,
  485. component: {
  486. name: 'fs-dict-switch',
  487. activeText: '',
  488. inactiveText: '',
  489. style: '--el-switch-on-color: var(--el-color-primary); --el-switch-off-color: #dcdfe6',
  490. onChange: compute((context) => {
  491. return () => {
  492. api.UpdateObjStatus(context.row).then((res:APIResponseData) => {
  493. successMessage(res.msg as string);
  494. });
  495. };
  496. }),
  497. },
  498. },
  499. dict: dict({
  500. data: dictionary('device_button_status_bool'),
  501. }),
  502. form: {
  503. show:false,
  504. rules: [{ required: true, message: '请选择是否可见' }],
  505. },
  506. viewForm:{
  507. component: { placeholder: '' },
  508. rules: [{ required: true, message: '' }],
  509. }
  510. },
  511. status_label:{
  512. title: '当前状态',
  513. search: { show: false },
  514. form: {
  515. show:false,
  516. }
  517. },
  518. department: {
  519. title: '所属部门',
  520. search: { show: false },
  521. type: 'input',
  522. column: { minWidth: 120 },
  523. form: {
  524. component: { placeholder: '请输入所属部门' }
  525. },
  526. viewForm:{
  527. component: { placeholder: '' },
  528. rules: [{ required: true, message: '' }],
  529. }
  530. },
  531. purchase_date: {
  532. title: '采购时间',
  533. type: 'date',
  534. search: { show: false },
  535. column: {
  536. minWidth: 120,
  537. formatter: ({ value }) => (value ? dayjs(value).format('YYYY-MM-DD') : ''),
  538. },
  539. form: {
  540. component: { placeholder: '请选择采购时间' },
  541. rules: [{ required: false, message: '请选择采购时间' }],
  542. },
  543. viewForm:{
  544. component: { placeholder: '' },
  545. rules: [{ required: true, message: '' }],
  546. },
  547. valueResolve({ form, value }) {
  548. form.purchase_date = value ? dayjs(value).format('YYYY-MM-DD') : null;
  549. },
  550. valueBuilder({ form, value }) {
  551. form.purchase_date = value;
  552. },
  553. },
  554. supplier: {
  555. title: '供应商',
  556. type: 'dict-select',
  557. search: { show: true },
  558. column: {
  559. minWidth: 120,
  560. },
  561. dict: dict({
  562. url: '/api/system/supplier/',
  563. value: 'id',
  564. label: 'name'
  565. }),
  566. form: {
  567. component: { placeholder: '请输入供应商' },
  568. },
  569. viewForm:{
  570. component: { placeholder: '' },
  571. rules: [{ required: true, message: '' }],
  572. }
  573. },
  574. price: {
  575. title: '价格',
  576. type: 'number',
  577. search: { show: false },
  578. column: { minWidth: 100 },
  579. form: {
  580. component: { placeholder: '请输入设备购入价格' },
  581. rules: [{ required: false, message: '请输入设备购入价格' }],
  582. },
  583. viewForm:{
  584. component: { placeholder: '' },
  585. rules: [{ required: true, message: '' }],
  586. }
  587. },
  588. warranty_expiration: {
  589. title: '质保到期',
  590. type: 'date',
  591. search: { show: false },
  592. column: { minWidth: 120 ,
  593. formatter: ({ value }) => (value ? dayjs(value).format('YYYY-MM-DD') : ''),
  594. },
  595. viewForm: {
  596. title: '质保到期',
  597. component: {
  598. render({ value }) {
  599. // eslint-disable-next-line no-console
  600. console.log("valuevaluevalue:::",value);
  601. if (!value) return '';
  602. const formatted = dayjs(value).format('YYYY-MM-DD');
  603. const isExpired = dayjs(value).isBefore(dayjs(), 'day');
  604. return h(
  605. 'span',
  606. {
  607. style: {
  608. color: isExpired ? 'red' : 'inherit',
  609. fontWeight: isExpired ? 'bold' : 'normal'
  610. }
  611. },
  612. isExpired ? `${formatted}(已过期)` : formatted
  613. );
  614. },
  615. showHtml: true,
  616. }
  617. },
  618. form: {
  619. component: { placeholder: '请选择质保到期' },
  620. rules: [{ required: false, message: '请选择质保到期' }],
  621. },
  622. valueResolve({ form, value }) {
  623. form.warranty_expiration = value ? dayjs(value).format('YYYY-MM-DD') : null;
  624. },
  625. valueBuilder({ form, value }) {
  626. form.warranty_expiration = value;
  627. },
  628. },
  629. tenant_id:{
  630. title: '租户id',
  631. type: 'input',
  632. value: 1,
  633. column: {
  634. show:false,
  635. minWidth: 120,
  636. },
  637. // dict: dict({
  638. // url: '/api/system/tenant/list/',
  639. // value: 'id',
  640. // label: 'name'
  641. // }),
  642. form: {
  643. value:1,
  644. show:false,
  645. component: { placeholder: '请填租户id' },
  646. rules: [{ required: false, message: '请填租户id' }],
  647. },
  648. viewForm:{
  649. component: { placeholder: '' },
  650. rules: [{ required: true, message: '' }],
  651. }
  652. },
  653. category:{
  654. show: false,
  655. title: '设备类别',
  656. search: { show: false },
  657. type: 'dict-select',
  658. column: { show: false,minWidth: 120 },
  659. dict: dict({
  660. url: '/api/system/device/category/?page=1&limit=100',
  661. value: 'id',
  662. label: 'name'
  663. }),
  664. form: {
  665. component: {
  666. placeholder: '请输入设备类别',
  667. filterable: true
  668. },
  669. rules: [{ required: true, message: '请输入设备类别' }],
  670. },
  671. viewForm:{
  672. component: { placeholder: '' },
  673. rules: [{ required: true, message: '' }],
  674. }
  675. },
  676. quantity:{
  677. show: false,
  678. title: '库存数量',
  679. search: { show: false },
  680. type: 'input',
  681. column: { show: false,minWidth: 120 },
  682. viewForm:{
  683. component:{placeholder:""}
  684. },
  685. form: {
  686. component: { placeholder: '请输入库存数量' },
  687. rules: [{ required: true, message: '请输入库存数量' }],
  688. valueResolve({ form, value }) {
  689. form.quantity = Number(value ?? 0);
  690. },
  691. valueBuilder({ form, value }) {
  692. // form.tags =Array.from(String(value), Number);
  693. form.quantity = form.total_quantity;
  694. }
  695. }
  696. },
  697. tags:{
  698. show: false,
  699. title: '设备标签',
  700. search: { show: false },
  701. type: 'dict-select',
  702. column: { show: false,minWidth: 120 },
  703. dict: dict({
  704. url: '/api/system/device_tags/?page=1&limit=100',
  705. value: 'id',
  706. label: 'name'
  707. }),
  708. viewForm:{
  709. component:{placeholder:""}
  710. },
  711. form: {
  712. component: { placeholder: '请选择设备标签',
  713. filterable: true
  714. },
  715. rules: [{ required: true, message: '请选择设备标签' }],
  716. valueResolve({ form, value }) {
  717. form.tags = Array.from(String(value), Number);
  718. },
  719. valueBuilder({ form, value }) {
  720. if(value){
  721. form.tags = Array.isArray(value)? value.length > 0 ? Number(value[0]) : '': Number(value);
  722. }
  723. },
  724. }
  725. },
  726. image:{
  727. title: '设备图片',
  728. type: 'image-uploader',
  729. column: {
  730. minWidth: 120,
  731. show:false,
  732. },
  733. form: {
  734. show: auth('image:upload'),
  735. component: {
  736. uploader: {
  737. type: 'form',
  738. limit: 1,
  739. action: '/api/system/device/upload-image/',
  740. accept: ".jpg,.png",
  741. uploadRequest: async ({ action, file, onProgress }) => {
  742. const token = Cookies.get('token');
  743. const data = new FormData();
  744. data.append("image", file);
  745. return await request({
  746. url: action,
  747. method: "post",
  748. timeout: 60000,
  749. headers: {
  750. "Content-Type": "multipart/form-data",
  751. "Authorization": token ? `JWT ${token}` : ''
  752. },
  753. data,
  754. onUploadProgress: (p) => {
  755. onProgress({ percent: Math.round((p.loaded / p.total) * 100) });
  756. }
  757. });
  758. },
  759. successHandle(ret) {
  760. // eslint-disable-next-line no-console
  761. // console.log("ret.data.image_url:::",ret.data.image_url);
  762. return {
  763. url: getBaseURL(ret.data.image_url),
  764. key: ret.data.id,
  765. ...ret.data
  766. };
  767. },
  768. }
  769. },
  770. },
  771. valueBuilder({ row, key }) {
  772. return row[key] ? [row[key]] : [];
  773. },
  774. valueResolve({ form, key }) {
  775. // eslint-disable-next-line no-console
  776. console.log("form[key]:::",form[key]);
  777. form[key] = Array.isArray(form[key]) ? form[key][0] : form[key];
  778. }
  779. },
  780. id: {
  781. title: 'deviceid',
  782. search: { show: false },
  783. type: 'input',
  784. column: { show:false,minWidth: 120 },
  785. form: {
  786. show:false,
  787. component: { placeholder: '请输入维修' }
  788. },
  789. viewForm:{
  790. show:true,
  791. component: { placeholder: '' },
  792. rules: [{ required: true, message: '' }],
  793. }
  794. },
  795. },
  796. viewForm: {
  797. wrapper: {
  798. buttons: {
  799. ok:{
  800. text:'提交',
  801. show:false
  802. }
  803. }
  804. },
  805. row: { gutter: 20 },
  806. group: {
  807. groupType: "tabs",
  808. groups: {
  809. base: {
  810. slots: {
  811. label: (scope) => {
  812. return (
  813. <span style={{ color: scope.hasError ? "red" : "green" }}>
  814. <fs-icon icon={"ion:checkmark-circle"} />
  815. 基础信息
  816. </span>
  817. );
  818. }
  819. },
  820. icon: "el-icon-goods",
  821. columns: ["code","category_name", "name", "status","borrowed_quantity","brand","specification","serial_number","warehouse","is_visible","department","purchase_date","supplier","price","warranty_expiration","tenant_id","category","quantity","tags","image"]
  822. },
  823. borrow: {
  824. show:true,
  825. label: "借用记录",
  826. icon: "el-icon-price-tag",
  827. columns: ["id"],
  828. slots: {
  829. default: (scope) => {
  830. const currentRow = crudExpose.getFormData();
  831. console.log("currentRow::",currentRow);
  832. return <BorrowRecords form={currentRow || {}}/>;
  833. }
  834. }
  835. },
  836. maintenance: {
  837. show:true,
  838. label: "维修记录",
  839. icon: "el-icon-warning-outline",
  840. columns: ["id"],
  841. slots: {
  842. default: (scope) => {
  843. const currentRowwx = crudExpose.getFormData();
  844. console.log("currentRowwx::",currentRowwx);
  845. return <MaintenanceHistory form={currentRowwx || {}} />
  846. }
  847. }
  848. },
  849. maintain: {
  850. show: true,
  851. label: "保养记录",
  852. icon: "el-icon-warning-outline",
  853. columns: ["id"],
  854. slots: {
  855. default: (scope) => {
  856. const currentRowMaintain = crudExpose.getFormData();
  857. console.log("currentRowMaintain::",currentRowMaintain);
  858. return <MaintenanceRecords form={currentRowMaintain || {}} />
  859. }
  860. }
  861. },
  862. datastatis: {
  863. show: true,
  864. label: "数据统计",
  865. icon: "el-icon-data-analysis",
  866. columns: ["id"],
  867. slots: {
  868. default: (scope) => {
  869. const currentRowStats = crudExpose.getFormData();
  870. console.log("currentRowStats::",currentRowStats);
  871. return <DeviceStatistics form={currentRowStats || {}} />
  872. }
  873. }
  874. },
  875. }
  876. }
  877. },
  878. },
  879. };
  880. };