crud.tsx 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  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: any, index: any) {
  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.inventory.borrowed_quantity > 0;
  339. const isMaintenance = row.inventory.maintenance_quantity > 0 && row.inventory.maintenance_quantity === row.inventory.total_quantity;
  340. const isDamaged = row.inventory.damaged_quantity > 0 && row.inventory.total_quantity==0;
  341. let label, color;
  342. console.log(isDamaged);
  343. if (isDamaged) {
  344. label = '报废';
  345. color = '#F56C6C';
  346. } else if (isMaintenance) {
  347. label = '维修';
  348. color = '#E6A23C';
  349. } else if (isBorrowed) {
  350. label = row.total_quantity - row.borrowed_quantity === 0 ? '在借' : '在借';
  351. color = '#FFA500';
  352. } else {
  353. label = row.total_quantity === 0 ? '在借' : '空闲';
  354. color = '#4CAF50';
  355. }
  356. return h(
  357. 'span',
  358. {
  359. style: {
  360. display: 'inline-block',
  361. padding: '2px 8px',
  362. border: `1px solid ${color}`,
  363. borderRadius: '4px',
  364. backgroundColor: color,
  365. color: 'white',
  366. fontWeight: 'bold',
  367. }
  368. },
  369. label
  370. );
  371. }
  372. },
  373. form: {
  374. show:false,
  375. component: { placeholder: '请选择设备状态' },
  376. rules: [{ required: true, message: '请选择设备状态' }],
  377. },
  378. },
  379. borrowed_quantity:{
  380. title:"已借出",
  381. type:'input',
  382. search:{show:false},
  383. column: { minWidth: 100 },
  384. form: {
  385. show:false,
  386. component: { placeholder: '请输入已借出' },
  387. rules: [{ required: true, message: '请输入已借出' }],
  388. },
  389. viewForm:{
  390. component: { placeholder: '' },
  391. rules: [{ required: true, message: '' }],
  392. }
  393. },
  394. brand:{
  395. title:'品牌',
  396. type:"input",
  397. column: { minWidth: 100 },
  398. form: {
  399. component: { placeholder: '请输入品牌' }
  400. },
  401. viewForm:{
  402. component: { placeholder: '' },
  403. rules: [{ required: true, message: '' }],
  404. },
  405. },
  406. specification: {
  407. title: '规格型号',
  408. search: { show: false },
  409. type: 'input',
  410. column: { minWidth: 100 },
  411. form: {
  412. component: { placeholder: '请输入规格型号' }
  413. },
  414. viewForm:{
  415. component: { placeholder: '' },
  416. rules: [{ required: true, message: '' }],
  417. },
  418. },
  419. serial_number:{
  420. title:'序列号',
  421. type:"input",
  422. column: { minWidth: 100 },
  423. form: {
  424. component: { placeholder: '请输入序列号' }
  425. },
  426. viewForm:{
  427. component: { placeholder: '' },
  428. rules: [{ required: true, message: '' }],
  429. },
  430. },
  431. available_quantity:{
  432. title:'可用库存',
  433. type:"input",
  434. column: { minWidth: 100 },
  435. addForm:{
  436. show:false,
  437. },
  438. viewForm:{
  439. show:false,
  440. },
  441. editForm:{show:false},
  442. from:{
  443. show:false,
  444. component: { placeholder: '请输入库存数量' },
  445. rules: [{ required: false, message: '请输入库存数量' }],
  446. }
  447. },
  448. total_quantity:{
  449. title:'库存数量',
  450. type:"input",
  451. column: { minWidth: 100 },
  452. addForm:{
  453. show:false,
  454. },
  455. viewForm:{
  456. show:false,
  457. },
  458. editForm:{show:false},
  459. from:{
  460. show:false,
  461. component: { placeholder: '请输入库存数量' },
  462. rules: [{ required: false, message: '请输入库存数量' }],
  463. }
  464. },
  465. warehouse:{
  466. title:'存放仓库',
  467. search: { show: true },
  468. type:"dict-select",
  469. column: { minWidth: 150 },
  470. dict: dict({
  471. url: '/api/system/warehouse/',
  472. value: 'id',
  473. label: 'name'
  474. }),
  475. form: {
  476. component: { placeholder: '请选择存放仓库' },
  477. rules: [{ required: true, message: '请选择存放仓库' }],
  478. }
  479. },
  480. status:{
  481. title:'是否可见',
  482. type: 'dict-switch',
  483. column: {
  484. show:true,
  485. minWidth: 90,
  486. component: {
  487. name: 'fs-dict-switch',
  488. activeText: '',
  489. inactiveText: '',
  490. style: '--el-switch-on-color: var(--el-color-primary); --el-switch-off-color: #dcdfe6',
  491. onChange: compute((context) => {
  492. let isInitialized = false;
  493. // 延迟设置初始化完成标志,避免初始化时触发
  494. setTimeout(() => {
  495. isInitialized = true;
  496. }, 100);
  497. return () => {
  498. // 只有在初始化完成后才执行API调用
  499. if (isInitialized) {
  500. api.UpdateObjStatus(context.row).then((res:APIResponseData) => {
  501. successMessage(res.msg as string);
  502. });
  503. }
  504. };
  505. }),
  506. },
  507. },
  508. dict: dict({
  509. data: dictionary('device_button_status_bool'),
  510. }),
  511. form: {
  512. show:false,
  513. rules: [{ required: true, message: '请选择是否可见' }],
  514. },
  515. viewForm:{
  516. component: { placeholder: '' },
  517. rules: [{ required: true, message: '' }],
  518. }
  519. },
  520. /* status_label:{
  521. title: '当前状态',
  522. search: { show: false },
  523. form: {
  524. show:false,
  525. }
  526. }, */
  527. department: {
  528. title: '所属部门',
  529. search: { show: false },
  530. type: 'input',
  531. column: { minWidth: 120 },
  532. form: {
  533. component: { placeholder: '请输入所属部门' }
  534. },
  535. viewForm:{
  536. component: { placeholder: '' },
  537. rules: [{ required: true, message: '' }],
  538. }
  539. },
  540. purchase_date: {
  541. title: '采购时间',
  542. type: 'date',
  543. search: { show: false },
  544. column: {
  545. minWidth: 120,
  546. formatter: ({ value }) => (value ? dayjs(value).format('YYYY-MM-DD') : ''),
  547. },
  548. form: {
  549. component: { placeholder: '请选择采购时间' },
  550. rules: [{ required: false, message: '请选择采购时间' }],
  551. },
  552. viewForm:{
  553. component: { placeholder: '' },
  554. rules: [{ required: true, message: '' }],
  555. },
  556. valueResolve({ form, value }) {
  557. form.purchase_date = value ? dayjs(value).format('YYYY-MM-DD') : null;
  558. },
  559. valueBuilder({ form, value }) {
  560. form.purchase_date = value;
  561. },
  562. },
  563. supplier: {
  564. title: '供应商',
  565. type: 'dict-select',
  566. search: { show: true },
  567. column: {
  568. minWidth: 120,
  569. },
  570. dict: dict({
  571. url: '/api/system/supplier/',
  572. value: 'id',
  573. label: 'name'
  574. }),
  575. form: {
  576. component: { placeholder: '请输入供应商' },
  577. },
  578. viewForm:{
  579. component: { placeholder: '' },
  580. rules: [{ required: true, message: '' }],
  581. }
  582. },
  583. price: {
  584. title: '价格',
  585. type: 'number',
  586. search: { show: false },
  587. column: { minWidth: 100 },
  588. form: {
  589. component: { placeholder: '请输入设备购入价格' },
  590. rules: [{ required: false, message: '请输入设备购入价格' }],
  591. },
  592. viewForm:{
  593. component: { placeholder: '' },
  594. rules: [{ required: true, message: '' }],
  595. }
  596. },
  597. warranty_expiration: {
  598. title: '质保到期',
  599. type: 'date',
  600. search: { show: false },
  601. column: { minWidth: 120 ,
  602. formatter: ({ value }) => (value ? dayjs(value).format('YYYY-MM-DD') : ''),
  603. },
  604. viewForm: {
  605. title: '质保到期',
  606. component: {
  607. render({ value }) {
  608. // eslint-disable-next-line no-console
  609. console.log("valuevaluevalue:::",value);
  610. if (!value) return '';
  611. const formatted = dayjs(value).format('YYYY-MM-DD');
  612. const isExpired = dayjs(value).isBefore(dayjs(), 'day');
  613. return h(
  614. 'span',
  615. {
  616. style: {
  617. color: isExpired ? 'red' : 'inherit',
  618. fontWeight: isExpired ? 'bold' : 'normal'
  619. }
  620. },
  621. isExpired ? `${formatted}(已过期)` : formatted
  622. );
  623. },
  624. showHtml: true,
  625. }
  626. },
  627. form: {
  628. component: { placeholder: '请选择质保到期' },
  629. rules: [{ required: false, message: '请选择质保到期' }],
  630. },
  631. valueResolve({ form, value }) {
  632. form.warranty_expiration = value ? dayjs(value).format('YYYY-MM-DD') : null;
  633. },
  634. valueBuilder({ form, value }) {
  635. form.warranty_expiration = value;
  636. },
  637. },
  638. tenant_id:{
  639. title: '租户id',
  640. type: 'input',
  641. value: 1,
  642. column: {
  643. show:false,
  644. minWidth: 120,
  645. },
  646. // dict: dict({
  647. // url: '/api/system/tenant/list/',
  648. // value: 'id',
  649. // label: 'name'
  650. // }),
  651. form: {
  652. value:1,
  653. show:false,
  654. component: { placeholder: '请填租户id' },
  655. rules: [{ required: false, message: '请填租户id' }],
  656. },
  657. viewForm:{
  658. component: { placeholder: '' },
  659. rules: [{ required: true, message: '' }],
  660. }
  661. },
  662. category:{
  663. show: false,
  664. title: '设备类别',
  665. search: { show: false },
  666. type: 'dict-select',
  667. column: { show: false,minWidth: 120 },
  668. dict: dict({
  669. url: '/api/system/device/category/?page=1&limit=100',
  670. value: 'id',
  671. label: 'name'
  672. }),
  673. form: {
  674. component: {
  675. placeholder: '请输入设备类别',
  676. filterable: true
  677. },
  678. rules: [{ required: true, message: '请输入设备类别' }],
  679. },
  680. viewForm:{
  681. component: { placeholder: '' },
  682. rules: [{ required: true, message: '' }],
  683. }
  684. },
  685. quantity:{
  686. show: false,
  687. title: '库存数量',
  688. search: { show: false },
  689. type: 'input',
  690. column: { show: false,minWidth: 120 },
  691. viewForm:{
  692. component:{placeholder:""}
  693. },
  694. form: {
  695. component: { placeholder: '请输入库存数量' },
  696. rules: [{ required: true, message: '请输入库存数量' }],
  697. valueResolve({ form, value }) {
  698. form.quantity = Number(value ?? 0);
  699. },
  700. valueBuilder({ form, value }) {
  701. // form.tags =Array.from(String(value), Number);
  702. form.quantity = form.total_quantity;
  703. }
  704. }
  705. },
  706. tags:{
  707. show: false,
  708. title: '设备标签',
  709. search: { show: false },
  710. type: 'dict-select',
  711. column: { show: false,minWidth: 120 },
  712. dict: dict({
  713. url: '/api/system/device_tags/?page=1&limit=100',
  714. value: 'id',
  715. label: 'name'
  716. }),
  717. viewForm:{
  718. component:{placeholder:""}
  719. },
  720. form: {
  721. component: { placeholder: '请选择设备标签',
  722. filterable: true
  723. },
  724. rules: [{ required: true, message: '请选择设备标签' }],
  725. valueResolve({ form, value }) {
  726. form.tags = Array.from(String(value), Number);
  727. },
  728. valueBuilder({ form, value }) {
  729. if(value){
  730. form.tags = Array.isArray(value)? value.length > 0 ? Number(value[0]) : '': Number(value);
  731. }
  732. },
  733. }
  734. },
  735. image:{
  736. title: '设备图片',
  737. type: 'image-uploader',
  738. column: {
  739. minWidth: 120,
  740. show:false,
  741. },
  742. form: {
  743. show: auth('image:upload'),
  744. component: {
  745. uploader: {
  746. type: 'form',
  747. limit: 1,
  748. action: '/api/system/device/upload-image/',
  749. accept: ".jpg,.png",
  750. uploadRequest: async ({ action, file, onProgress }) => {
  751. const token = Cookies.get('token');
  752. const data = new FormData();
  753. data.append("image", file);
  754. return await request({
  755. url: action,
  756. method: "post",
  757. timeout: 60000,
  758. headers: {
  759. "Content-Type": "multipart/form-data",
  760. "Authorization": token ? `JWT ${token}` : ''
  761. },
  762. data,
  763. onUploadProgress: (p) => {
  764. onProgress({ percent: Math.round((p.loaded / p.total) * 100) });
  765. }
  766. });
  767. },
  768. successHandle(ret) {
  769. // eslint-disable-next-line no-console
  770. // console.log("ret.data.image_url:::",ret.data.image_url);
  771. return {
  772. url: getBaseURL(ret.data.image_url),
  773. key: ret.data.id,
  774. ...ret.data
  775. };
  776. },
  777. }
  778. },
  779. },
  780. valueBuilder({ row, key }) {
  781. return row[key] ? [row[key]] : [];
  782. },
  783. valueResolve({ form, key }) {
  784. // eslint-disable-next-line no-console
  785. console.log("form[key]:::",form[key]);
  786. form[key] = Array.isArray(form[key]) ? form[key][0] : form[key];
  787. }
  788. },
  789. id: {
  790. title: 'deviceid',
  791. search: { show: false },
  792. type: 'input',
  793. column: { show:false,minWidth: 120 },
  794. form: {
  795. show:false,
  796. component: { placeholder: '请输入维修' }
  797. },
  798. viewForm:{
  799. show:true,
  800. component: { placeholder: '' },
  801. rules: [{ required: true, message: '' }],
  802. }
  803. },
  804. },
  805. viewForm: {
  806. wrapper: {
  807. buttons: {
  808. ok:{
  809. text:'提交',
  810. show:false
  811. }
  812. }
  813. },
  814. row: { gutter: 20 },
  815. group: {
  816. groupType: "tabs",
  817. groups: {
  818. base: {
  819. slots: {
  820. label: (scope) => {
  821. return (
  822. <span style={{ color: scope.hasError ? "red" : "green" }}>
  823. <fs-icon icon={"ion:checkmark-circle"} />
  824. 基础信息
  825. </span>
  826. );
  827. }
  828. },
  829. icon: "el-icon-goods",
  830. 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"]
  831. },
  832. borrow: {
  833. show:true,
  834. label: "借用记录",
  835. icon: "el-icon-price-tag",
  836. columns: ["id"],
  837. slots: {
  838. default: (scope) => {
  839. const currentRow = crudExpose.getFormData();
  840. console.log("currentRow::",currentRow);
  841. return <BorrowRecords form={currentRow || {}}/>;
  842. }
  843. }
  844. },
  845. maintenance: {
  846. show:true,
  847. label: "维修记录",
  848. icon: "el-icon-warning-outline",
  849. columns: ["id"],
  850. slots: {
  851. default: (scope) => {
  852. const currentRowwx = crudExpose.getFormData();
  853. console.log("currentRowwx::",currentRowwx);
  854. return <MaintenanceHistory form={currentRowwx || {}} />
  855. }
  856. }
  857. },
  858. maintain: {
  859. show: true,
  860. label: "保养记录",
  861. icon: "el-icon-warning-outline",
  862. columns: ["id"],
  863. slots: {
  864. default: (scope) => {
  865. const currentRowMaintain = crudExpose.getFormData();
  866. console.log("currentRowMaintain::",currentRowMaintain);
  867. return <MaintenanceRecords form={currentRowMaintain || {}} />
  868. }
  869. }
  870. },
  871. datastatis: {
  872. show: true,
  873. label: "数据统计",
  874. icon: "el-icon-data-analysis",
  875. columns: ["id"],
  876. slots: {
  877. default: (scope) => {
  878. const currentRowStats = crudExpose.getFormData();
  879. console.log("currentRowStats::",currentRowStats);
  880. return <DeviceStatistics form={currentRowStats || {}} />
  881. }
  882. }
  883. },
  884. }
  885. }
  886. },
  887. },
  888. };
  889. };