综合办公系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  1. <template>
  2. <view class="form-container">
  3. <!-- 表单标题 -->
  4. <view class="form-title">
  5. <text class="title-text">设备申请表</text>
  6. <view class="title-line"></view>
  7. </view>
  8. <!-- 表单内容 -->
  9. <uni-forms ref="form" :modelValue="form" :rules="rules" label-position="top" label-width="150" class="custom-form">
  10. <flow-note :taskForm="taskForm"></flow-note>
  11. <!-- 当前节点 -->
  12. <uni-forms-item label="当前节点" class="form-item" v-if="taskName">
  13. <uni-tag :inverted="true" type="primary" :text="taskName"></uni-tag>
  14. </uni-forms-item>
  15. <!-- 流程发起人 -->
  16. <uni-forms-item label="填报人" class="form-item">
  17. <b style="font-size:30rpx;">{{ applierUserName }}</b>
  18. </uni-forms-item>
  19. <!-- 填报日期 -->
  20. <uni-forms-item label="填报日期" class="form-item">
  21. <text>{{ form.applyDate }}</text>
  22. </uni-forms-item>
  23. <!-- 选择项目 -->
  24. <uni-forms-item label="选择项目" required class="form-item" name="projectId">
  25. <uv-button type="primary" @click="openProject = true" v-if="taskName == '设备申请'">+ 选择项目</uv-button>
  26. <ProjectPicker :visible.sync="openProject" :selected.sync="selectedProject" @confirm="handleConfirm" />
  27. <ProjectInfo :project="projectObj"></ProjectInfo>
  28. </uni-forms-item>
  29. <!-- 设备选择 -->
  30. <uni-forms-item label="申请设备" required class="form-item" name="devices"
  31. v-if="taskName != '安排设备' && taskName != '归还确认'">
  32. <uv-button type="primary" @click="openDevice = true" v-if="taskName == '设备申请'">+ 选择设备</uv-button>
  33. <device-picker :visible.sync="openDevice" :selected.sync="selectDevice" :multiple="!isReplaceMode"
  34. @confirm="handleDeviceConfirm"></device-picker>
  35. <view class="device-cards" v-if="deviceList.length > 0">
  36. <view class="device-card" v-for="(item, index) in deviceList" :key="index">
  37. <view class="card-header">
  38. <text class="card-title">{{ index + 1 }}. 出厂编号:{{ item.code }}</text>
  39. </view>
  40. <view class="card-content">
  41. <view class="card-row">
  42. <view class="card-item">
  43. <text class="label">设备名称:</text>
  44. <text class="value">{{ item.name }}</text>
  45. </view>
  46. </view>
  47. <view class="card-row">
  48. <view class="card-item">
  49. <text class="label">设备品牌:</text>
  50. <text class="value">{{ item.brand }}</text>
  51. </view>
  52. <view class="card-item">
  53. <text class="label">存放地址:</text>
  54. <text class="value">{{ item.place }}</text>
  55. </view>
  56. </view>
  57. <view class="card-row">
  58. <view class="card-item">
  59. <text class="label">规格型号:</text>
  60. <text class="value">{{ item.series }}</text>
  61. </view>
  62. </view>
  63. </view>
  64. </view>
  65. </view>
  66. </uni-forms-item>
  67. <!-- 申领事由 -->
  68. <uni-forms-item label="申领事由" required class="form-item" name="applyReason">
  69. <uv-textarea v-model="form.applyReason" placeholder="请输入申领事由" :disabled="taskName != '设备申请'"></uv-textarea>
  70. </uni-forms-item>
  71. <!-- 日期选择 -->
  72. <view class="date-range">
  73. <uni-forms-item label="使用日期" required class="form-item" name="dateRange">
  74. <uni-datetime-picker v-model="form.dateRange" type="daterange" rangeSeparator="至" :clearIcon="false"
  75. v-if="taskName == '设备申请'" @change="handleDateRangeChange" />
  76. <view class="date-display" v-else>
  77. <uni-icons type="calendar" size="16"></uni-icons>
  78. <text class="date-text">{{ form.beginDate }}</text>
  79. <text class="date-separator">至</text>
  80. <text class="date-text">{{ form.endDate }}</text>
  81. </view>
  82. </uni-forms-item>
  83. <uni-forms-item label="共计" class="form-item">
  84. <text>{{ form.days + '天' }}</text>
  85. </uni-forms-item>
  86. </view>
  87. <!-- 安排设备意见 -->
  88. <uni-forms-item label="拟发放设备" required class="form-item" v-if="taskName != '设备申请' && taskName != '归还确认'">
  89. <view class="device-cards" v-if="modifyDeviceList.length > 0">
  90. <view class="device-card" v-for="(item, index) in modifyDeviceList" :key="index">
  91. <view class="card-header">
  92. <text class="card-title">{{ index + 1 }}. 出厂编号:{{ item.code }}</text>
  93. </view>
  94. <view class="card-content">
  95. <view class="card-row">
  96. <view class="card-item">
  97. <text class="label">设备名称:</text>
  98. <text class="value">{{ item.name }}</text>
  99. </view>
  100. </view>
  101. <view class="card-row">
  102. <view class="card-item">
  103. <text class="label">设备品牌:</text>
  104. <text class="value">{{ item.brand }}</text>
  105. </view>
  106. <view class="card-item">
  107. <text class="label">存放地址:</text>
  108. <text class="value">{{ item.place }}</text>
  109. </view>
  110. </view>
  111. <view class="card-row">
  112. <view class="card-item">
  113. <text class="label">规格型号:</text>
  114. <text class="value">{{ item.series }}</text>
  115. </view>
  116. </view>
  117. </view>
  118. <view class="card-actions" v-if="taskName == '安排设备'">
  119. <uv-button type="primary" size="mini" @click="replaceRowData(item, index)">重新选择</uv-button>
  120. <uv-button type="error" size="mini" @click="deleteRowData(item, index)">删除</uv-button>
  121. </view>
  122. </view>
  123. </view>
  124. <uv-button type="primary" @click="addRowdata()" v-if="taskName == '安排设备'">新增设备</uv-button>
  125. </uni-forms-item>
  126. <!-- 安排设备意见 -->
  127. <uni-forms-item label="安排设备意见" required class="form-item" name="dispatchComment" v-if="taskName != '设备申请'">
  128. <uv-textarea v-model="form.dispatchComment" placeholder="请输入安排设备意见"
  129. :disabled="taskName != '安排设备'"></uv-textarea>
  130. <auditor :name="form.dispatcher ? form.dispatchUser.nickName : ''" :time="form.dispatchTime"></auditor>
  131. </uni-forms-item>
  132. <!-- 分管审核意见 -->
  133. <uni-forms-item label="分管审核意见" required name="managerComment" class="form-item"
  134. v-if="taskName != '设备申请' && taskName != '安排设备'">
  135. <uv-textarea v-model="form.managerComment" placeholder="请输入分管审核意见" :disabled="taskName != '分管审核'"></uv-textarea>
  136. <auditor :name="form.managerUser ? form.managerUser.nickName : ''" :time="form.managerTime"></auditor>
  137. </uni-forms-item>
  138. <!-- 归还确认 -->
  139. <uni-forms-item label="已归还设备" required class="form-item" v-if="taskName == '' || taskName == '归还确认'">
  140. <text style="color: #a69494;" v-if="taskName == '归还确认'">Tips:请点击卡片,切换归还状态</text>
  141. <view class="device-cards" v-if="returnDevicesList.length > 0">
  142. <view class="device-card" v-for="(item, index) in returnDevicesList" :key="index"
  143. :class="{ 'selected': isDeviceSelected(item.deviceId) }" @click="toggleDeviceSelection(item)">
  144. <view class="card-header">
  145. <text class="card-title">{{ index + 1 }}. 出厂编号:{{ item.code }}</text>
  146. <view class="return-tag" v-if="isDeviceSelected(item.deviceId)">
  147. <uni-tag type="success" text="已归还" size="small"></uni-tag>
  148. </view>
  149. </view>
  150. <view class="card-content">
  151. <view class="card-row">
  152. <view class="card-item">
  153. <text class="label">设备名称:</text>
  154. <text class="value">{{ item.name }}</text>
  155. </view>
  156. </view>
  157. <view class="card-row">
  158. <view class="card-item">
  159. <text class="label">设备品牌:</text>
  160. <text class="value">{{ item.brand }}</text>
  161. </view>
  162. <view class="card-item">
  163. <text class="label">存放地址:</text>
  164. <text class="value">{{ item.place }}</text>
  165. </view>
  166. </view>
  167. <view class="card-row">
  168. <view class="card-item">
  169. <text class="label">规格型号:</text>
  170. <text class="value">{{ item.series }}</text>
  171. </view>
  172. </view>
  173. </view>
  174. </view>
  175. </view>
  176. </uni-forms-item>
  177. <!-- 需维修设备 -->
  178. <uni-forms-item label="需维修设备" class="form-item" v-if="taskName == '' || taskName == '归还确认'">
  179. <uv-button type="primary" @click="openRepairDevice = true" v-if="taskName == '归还确认'">+ 选择需维修设备</uv-button>
  180. <repair-device-picker :visible.sync="openRepairDevice" :deviceList="modifyDeviceList"
  181. :selectedDevices.sync="form.repairDevices"></repair-device-picker>
  182. <view class="device-cards" v-if="repairDevicesList.length > 0">
  183. <view class="device-card repair-card" v-for="(item, index) in repairDevicesList" :key="index">
  184. <view class="card-header">
  185. <text class="card-title">{{ index + 1 }}. 出厂编号:{{ item.code }}</text>
  186. <view class="repair-tag">
  187. <uni-tag type="error" text="需维修" size="small"></uni-tag>
  188. </view>
  189. </view>
  190. <view class="card-content">
  191. <view class="card-row">
  192. <view class="card-item">
  193. <text class="label">设备名称:</text>
  194. <text class="value">{{ item.name }}</text>
  195. </view>
  196. </view>
  197. <view class="card-row">
  198. <view class="card-item">
  199. <text class="label">设备品牌:</text>
  200. <text class="value">{{ item.brand }}</text>
  201. </view>
  202. <view class="card-item">
  203. <text class="label">存放地址:</text>
  204. <text class="value">{{ item.place }}</text>
  205. </view>
  206. </view>
  207. <view class="card-row">
  208. <view class="card-item">
  209. <text class="label">规格型号:</text>
  210. <text class="value">{{ item.series }}</text>
  211. </view>
  212. </view>
  213. </view>
  214. </view>
  215. </view>
  216. <view v-else>
  217. <uni-tag type="success" text="没有需维修的设备" size="small"></uni-tag>
  218. </view>
  219. </uni-forms-item>
  220. <!-- 备注 -->
  221. <uni-forms-item label="备注" class="form-item" v-if="taskName == '' || taskName == '归还确认'">
  222. <uv-textarea v-model="form.remark" placeholder="请输入备注" :disabled="taskName != '归还确认'"></uv-textarea>
  223. </uni-forms-item>
  224. <!-- 归还日期 -->
  225. <uni-forms-item label="归还日期" required name="returnDate" class="form-item"
  226. v-if="taskName == '' || taskName == '归还确认'">
  227. <uni-datetime-picker v-model="form.returnDate" type="date" :disabled="taskName != '归还确认'" />
  228. </uni-forms-item>
  229. <!-- 操作按钮 -->
  230. <view class="form-actions" v-if="taskName">
  231. <uv-button type="primary" @click="submit" v-if="taskName == '设备申请'">提交申请</uv-button>
  232. <template v-else>
  233. <uv-button style="margin-bottom: 5px;" type="warning" @click="saves">保存</uv-button>
  234. <uv-button type="primary" @click="completeApply">完成审批</uv-button>
  235. </template>
  236. </view>
  237. </uni-forms>
  238. </view>
  239. </template>
  240. <script>
  241. import { parseTime } from "@/utils/common.js"
  242. import { getDeviceApproval, submitDeviceApproval, modifyDeviceApproval } from '@/api/oa/device/deviceApproval'
  243. import { complete, getNextFlowNode } from "@/api/flowable/todo";
  244. import { getProject } from "@/api/oa/project/project";
  245. import { getDevice } from "@/api/oa/device/device";
  246. import { getUserByRole } from "@/api/system/role";
  247. import { getUsersManageLeader } from '@/api/system/post.js'
  248. import FlowNote from '@/pages/components/flowNote.vue';
  249. import ProjectPicker from '@/pages/components/ProjectPicker.vue';
  250. import ProjectInfo from '@/pages/components/ProjectInfo.vue';
  251. import DevicePicker from "@/pages/components/DevicePicker.vue";
  252. import Auditor from "@/pages/components/auditor.vue";
  253. import RepairDevicePicker from "@/pages/components/RepairDevicePicker.vue";
  254. export default {
  255. components: {
  256. FlowNote,
  257. ProjectPicker,
  258. ProjectInfo,
  259. DevicePicker,
  260. Auditor,
  261. RepairDevicePicker
  262. },
  263. props: {
  264. taskForm: Object,
  265. taskName: String,
  266. startUserName: String,
  267. },
  268. created() {
  269. this.applierUserName = this.startUserName;
  270. this.initForm();
  271. },
  272. data() {
  273. return {
  274. form: {
  275. user: {
  276. nickName: ''
  277. },
  278. dept: {
  279. deptName: ''
  280. },
  281. projectId: '',
  282. applyDate: '',
  283. applyReason: '',
  284. beginDate: '',
  285. endDate: '',
  286. dateRange: [],
  287. days: 0,
  288. dispatchComment: '',
  289. managerComment: '',
  290. devices: [],
  291. modifyDevices: [],
  292. returnDevices: [],
  293. repairDevices: [],
  294. remark: '',
  295. returnDate: ''
  296. },
  297. rules: {
  298. projectId: {
  299. rules: [{ required: true, errorMessage: '请选择项目' }]
  300. },
  301. devices: {
  302. rules: [{ required: true, errorMessage: '请选择设备' }]
  303. },
  304. applyReason: {
  305. rules: [{ required: true, errorMessage: '请输入申领事由' }]
  306. },
  307. dateRange: {
  308. rules: [{
  309. required: this.taskName === '设备申请',
  310. errorMessage: '请选择使用日期',
  311. validateFunction: (rule, value, data, callback) => {
  312. if (!value || value.length !== 2 || !value[0] || !value[1]) {
  313. callback('请选择使用日期');
  314. } else {
  315. callback();
  316. }
  317. }
  318. }]
  319. },
  320. dispatchComment: {
  321. rules: [{
  322. required: true,
  323. errorMessage: '请输入安排设备意见',
  324. validateFunction: (rule, value, data, callback) => {
  325. if (this.taskName === '安排设备' && !value) {
  326. callback('请输入安排设备意见');
  327. } else {
  328. callback();
  329. }
  330. }
  331. }]
  332. },
  333. managerComment: {
  334. rules: [{
  335. required: true,
  336. errorMessage: '请输入分管审核意见',
  337. validateFunction: (rule, value, data, callback) => {
  338. if (this.taskName === '分管审核' && !value) {
  339. callback('请输入分管审核意见');
  340. } else {
  341. callback();
  342. }
  343. }
  344. }]
  345. },
  346. returnDate: {
  347. rules: [{
  348. required: true,
  349. errorMessage: '请选择归还日期',
  350. validateFunction: (rule, value, data, callback) => {
  351. if (this.taskName === '归还确认' && !value) {
  352. callback('请选择归还日期');
  353. } else {
  354. callback();
  355. }
  356. }
  357. }]
  358. }
  359. },
  360. applierUserName: '',
  361. openProject: false,
  362. selectedProject: null,
  363. projectObj: {},
  364. openDevice: false,
  365. selectDevice: [],
  366. deviceList: [],
  367. modifyDeviceList: [],
  368. returnDevicesList: [],
  369. formTotal: 0,
  370. currentIndex: -1,
  371. isReplaceMode: false,
  372. openRepairDevice: false,
  373. repairDevicesList: []
  374. };
  375. },
  376. watch: {
  377. 'form.repairDevices': {
  378. handler(newVal) {
  379. this.updateRepairDevicesList();
  380. },
  381. immediate: true
  382. }
  383. },
  384. methods: {
  385. async initForm() {
  386. try {
  387. const res = await getDeviceApproval(this.taskForm.formId);
  388. if (res.data) {
  389. this.formTotal = 1;
  390. this.form = res.data;
  391. this.applierUserName = res.data.applierUser.nickName;
  392. const project = await getProject(res.data.projectId);
  393. this.projectObj = project.data;
  394. // 初始化申请设备
  395. if (res.data.devices) {
  396. const deviceIds = res.data.devices.split(',').map(id => parseInt(id));
  397. this.form.devices = res.data.devices.split(',');
  398. this.deviceList = [];
  399. this.selectDevice = [];
  400. for (const id of deviceIds) {
  401. const response = await getDevice(id);
  402. if (response.data) {
  403. this.deviceList.push(response.data);
  404. this.selectDevice.push(response.data);
  405. }
  406. }
  407. } else {
  408. this.deviceList = [];
  409. }
  410. // 初始化拟发放设备列表
  411. if (res.data.modifyDevices) {
  412. const modifyDeviceIds = typeof res.data.modifyDevices === 'string'
  413. ? res.data.modifyDevices.split(',').map(id => parseInt(id))
  414. : Array.isArray(res.data.modifyDevices)
  415. ? res.data.modifyDevices.map(id => parseInt(id))
  416. : [];
  417. this.form.modifyDevices = res.data.modifyDevices.split(',');
  418. this.modifyDeviceList = [];
  419. for (const id of modifyDeviceIds) {
  420. const response = await getDevice(id);
  421. if (response.data) {
  422. this.modifyDeviceList.push(response.data);
  423. }
  424. }
  425. } else if (this.taskName === '安排设备') {
  426. this.modifyDeviceList = [...this.deviceList];
  427. } else {
  428. this.modifyDeviceList = [];
  429. }
  430. // 初始化归还设备列表
  431. if (res.data.returnDevices) {
  432. const returnDeviceIds = typeof res.data.returnDevices === 'string'
  433. ? res.data.returnDevices.split(',').map(id => parseInt(id))
  434. : Array.isArray(res.data.returnDevices)
  435. ? res.data.returnDevices.map(id => parseInt(id))
  436. : [];
  437. this.form.returnDevices = returnDeviceIds;
  438. // 获取所有拟发放的设备
  439. const modifyDeviceIds = typeof res.data.modifyDevices === 'string'
  440. ? res.data.modifyDevices.split(',').map(id => parseInt(id))
  441. : Array.isArray(res.data.modifyDevices)
  442. ? res.data.modifyDevices.map(id => parseInt(id))
  443. : [];
  444. this.returnDevicesList = [];
  445. for (const id of modifyDeviceIds) {
  446. const response = await getDevice(id);
  447. if (response.data) {
  448. this.returnDevicesList.push(response.data);
  449. }
  450. }
  451. } else if (this.taskName === '归还确认') {
  452. // 在归还确认节点,使用拟发放的设备列表
  453. this.returnDevicesList = [...this.modifyDeviceList];
  454. this.form.returnDevices = []; // 初始化空数组
  455. } else {
  456. this.returnDevicesList = [];
  457. this.form.returnDevices = []; // 初始化空数组
  458. }
  459. // 初始化维修设备列表
  460. if (res.data.repairDevices) {
  461. const repairDeviceIds = typeof res.data.repairDevices === 'string'
  462. ? res.data.repairDevices.split(',').map(id => parseInt(id))
  463. : Array.isArray(res.data.repairDevices)
  464. ? res.data.repairDevices.map(id => parseInt(id))
  465. : [];
  466. this.form.repairDevices = repairDeviceIds;
  467. this.updateRepairDevicesList();
  468. } else if (this.taskName === '归还确认') {
  469. this.form.repairDevices = [];
  470. this.repairDevicesList = [];
  471. }
  472. if (this.form.beginDate && this.form.endDate) {
  473. this.form.dateRange = [this.form.beginDate, this.form.endDate];
  474. }
  475. } else {
  476. this.form.applier = this.$store.getters.userId;
  477. this.form.applyDate = parseTime(new Date(), "{y}-{m}-{d}");
  478. let name = this.applierUserName.split('-');
  479. this.form.user.nickName = name[0];
  480. this.form.dept.deptName = name[1];
  481. this.formTotal = 0;
  482. this.form.returnDevices = []; // 初始化空数组
  483. this.form.repairDevices = []; // 初始化空数组
  484. }
  485. } catch (error) {
  486. console.error('初始化表单失败:', error);
  487. uni.showToast({
  488. title: '初始化表单失败',
  489. icon: 'error'
  490. });
  491. }
  492. },
  493. handleConfirm(project) {
  494. this.selectedProject = project;
  495. this.projectObj = project;
  496. this.form.projectId = project.projectId;
  497. },
  498. handleDeviceConfirm(devices) {
  499. if (this.taskName === '安排设备') {
  500. if (this.currentIndex >= 0) {
  501. // 替换指定位置的设备,确保只使用第一个选中的设备
  502. const selectedDevice = Array.isArray(devices) ? devices[0] : devices;
  503. this.modifyDeviceList.splice(this.currentIndex, 1, selectedDevice);
  504. } else {
  505. // 新增设备
  506. this.modifyDeviceList.push(...devices);
  507. }
  508. this.isReplaceMode = false;
  509. } else {
  510. this.deviceList = Array.isArray(devices) ? devices : [devices];
  511. this.form.devices = this.deviceList.map(item => item.deviceId);
  512. }
  513. },
  514. handleDateRangeChange(e) {
  515. if (Array.isArray(e) && e.length === 2) {
  516. const [start, end] = e;
  517. this.form.beginDate = start;
  518. this.form.endDate = end;
  519. this.form.dateRange = [start, end];
  520. this.calculateDay();
  521. }
  522. },
  523. calculateDay() {
  524. if (this.form.beginDate && this.form.endDate) {
  525. const begin = new Date(this.form.beginDate);
  526. const end = new Date(this.form.endDate);
  527. if (!isNaN(begin.getTime()) && !isNaN(end.getTime())) {
  528. this.form.days = Math.ceil((end - begin) / (1000 * 60 * 60 * 24)) + 1;
  529. }
  530. }
  531. },
  532. replaceRowData(row, index) {
  533. this.openDevice = true;
  534. this.currentIndex = index;
  535. this.isReplaceMode = true;
  536. // 在安排设备节点时,设置当前选中的设备
  537. if (this.taskName === '安排设备') {
  538. this.selectDevice = [row];
  539. }
  540. },
  541. deleteRowData(row, index) {
  542. uni.showModal({
  543. title: '确认删除',
  544. content: '确定要删除该设备吗?',
  545. success: (res) => {
  546. if (res.confirm) {
  547. this.modifyDeviceList.splice(index, 1);
  548. }
  549. }
  550. });
  551. },
  552. addRowdata() {
  553. this.openDevice = true;
  554. this.currentIndex = -1;
  555. this.isReplaceMode = false;
  556. // 在安排设备节点时,清空已选设备
  557. if (this.taskName === '安排设备') {
  558. this.selectDevice = [];
  559. }
  560. },
  561. submit() {
  562. this.$refs.form.validate().then(() => {
  563. let submitData = {
  564. ...this.form,
  565. ...(this.form.formId ? {} : { formId: this.taskForm.formId }),
  566. ...(this.form.deviceApplyId ? {} : { deviceApplyId: this.taskForm.formId })
  567. };
  568. let jsonForm = JSON.stringify(submitData);
  569. submitDeviceApproval(jsonForm).then(res => {
  570. // 获取下一个流程节点
  571. this.getNextFlowNodeApproval().then(() => {
  572. uni.showToast({
  573. title: '提交成功',
  574. icon: 'success'
  575. });
  576. setTimeout(() => {
  577. uni.switchTab({
  578. url: '/pages/message/index'
  579. })
  580. }, 500);
  581. })
  582. });
  583. });
  584. },
  585. saves() {
  586. try {
  587. this.$refs.form.validate().then(() => {
  588. let submitData = {
  589. ...this.form,
  590. ...(this.form.formId ? {} : { formId: this.taskForm.formId }),
  591. ...(this.form.deviceApplyId ? {} : { deviceApplyId: this.taskForm.formId })
  592. };
  593. // 在安排设备节点时,添加拟发放设备列表
  594. if (this.taskName === '安排设备') {
  595. submitData.modifyDevices = this.modifyDeviceList.map(item => item.deviceId);
  596. }
  597. let jsonForm = JSON.stringify(submitData);
  598. modifyDeviceApproval(jsonForm).then(res => {
  599. if (res.code === 200) {
  600. uni.showToast({
  601. title: '保存成功',
  602. icon: 'success'
  603. });
  604. } else {
  605. uni.showToast({
  606. title: res.msg || '保存失败',
  607. icon: 'error'
  608. });
  609. }
  610. })
  611. })
  612. } catch (error) {
  613. console.error('保存方法错误:', error);
  614. uni.showToast({
  615. title: error.message || '保存失败',
  616. icon: 'error'
  617. });
  618. }
  619. },
  620. completeApply() {
  621. this.$refs.form.validate().then(() => {
  622. // 在归还确认节点时,检查所有设备是否都已归还
  623. if (this.taskName === '归还确认') {
  624. const allDevices = this.modifyDeviceList.map(item => item.deviceId);
  625. const returnedDevices = this.form.returnDevices || [];
  626. const unreturnedDevices = allDevices.filter(id => !returnedDevices.includes(id));
  627. if (unreturnedDevices.length > 0) {
  628. uni.showToast({
  629. title: '请确认所有设备都已归还',
  630. icon: 'none'
  631. });
  632. return;
  633. }
  634. }
  635. uni.showModal({
  636. title: '提示',
  637. content: '确定提交审批吗?',
  638. success: (res) => {
  639. if (res.confirm) {
  640. let submitData = {
  641. ...this.form,
  642. ...(this.form.formId ? {} : { formId: this.taskForm.formId }),
  643. ...(this.form.deviceApplyId ? {} : { deviceApplyId: this.taskForm.formId })
  644. };
  645. // 在安排设备节点时,添加拟发放设备列表
  646. if (this.taskName === '安排设备') {
  647. submitData.modifyDevices = this.modifyDeviceList.map(item => item.deviceId);
  648. }
  649. let jsonForm = JSON.stringify(submitData);
  650. modifyDeviceApproval(jsonForm).then(res => {
  651. // 获取下一个流程节点
  652. getNextFlowNode({ taskId: this.taskForm.taskId }).then(res => {
  653. this.getNextFlowNodeApproval().then(() => {
  654. uni.showToast({
  655. title: '提交成功',
  656. icon: 'success'
  657. });
  658. setTimeout(() => {
  659. uni.switchTab({
  660. url: '/pages/message/index'
  661. });
  662. }, 500);
  663. });
  664. });
  665. });
  666. }
  667. }
  668. });
  669. });
  670. },
  671. // 获取下一个审批人
  672. getNextFlowNodeApproval() {
  673. return new Promise((resolve, reject) => {
  674. const handleComplete = (response) => {
  675. this.$modal.msgSuccess(response.msg);
  676. resolve();
  677. };
  678. const setApprovalAndComplete = (result) => {
  679. this.$set(this.taskForm.variables, "approval", result.data[0]);
  680. complete(this.taskForm).then(handleComplete).catch(reject);
  681. };
  682. switch (this.taskName) {
  683. case '设备申请':
  684. case '分管审核':
  685. getUserByRole({ roleId: 4 }).then(setApprovalAndComplete).catch(reject);
  686. break;
  687. case '安排设备':
  688. getUsersManageLeader({ userId: this.form.applier }).then(res => {
  689. const userIds = res.data.map(user => user.userId);
  690. this.$set(this.taskForm.variables, "approvalList", userIds);
  691. complete(this.taskForm).then(handleComplete).catch(reject);
  692. }).catch(reject);
  693. break;
  694. case '归还确认':
  695. this.$modal.confirm('最后一个节点,提交将结束流程,是否提交?')
  696. .then(() => complete(this.taskForm).then(handleComplete).catch(reject))
  697. .catch(reject);
  698. break;
  699. }
  700. });
  701. },
  702. isDeviceSelected(deviceId) {
  703. return this.form.returnDevices && this.form.returnDevices.includes(deviceId);
  704. },
  705. toggleDeviceSelection(device) {
  706. if (this.taskName !== '归还确认') return;
  707. // 确保 returnDevices 是数组
  708. if (!Array.isArray(this.form.returnDevices)) {
  709. this.form.returnDevices = [];
  710. }
  711. const index = this.form.returnDevices.indexOf(device.deviceId);
  712. if (index === -1) {
  713. // 添加设备到已归还列表
  714. this.form.returnDevices.push(device.deviceId);
  715. } else {
  716. // 从已归还列表中移除设备
  717. this.form.returnDevices.splice(index, 1);
  718. }
  719. },
  720. updateRepairDevicesList() {
  721. // 如果 repairDevices 是字符串,转换为数组
  722. if (typeof this.form.repairDevices === 'string') {
  723. this.form.repairDevices = this.form.repairDevices.split(',').map(id => parseInt(id));
  724. } else if (!Array.isArray(this.form.repairDevices)) {
  725. this.form.repairDevices = [];
  726. }
  727. this.repairDevicesList = this.modifyDeviceList.filter(device =>
  728. this.form.repairDevices.includes(device.deviceId)
  729. );
  730. }
  731. }
  732. }
  733. </script>
  734. <style lang="scss" scoped>
  735. .form-container {
  736. padding: 32rpx;
  737. }
  738. .form-title {
  739. text-align: center;
  740. margin-bottom: 32rpx;
  741. .title-text {
  742. font-size: 36rpx;
  743. font-weight: bold;
  744. }
  745. .title-line {
  746. height: 2rpx;
  747. background: #eee;
  748. margin-top: 16rpx;
  749. }
  750. }
  751. .date-range {
  752. // display: flex;
  753. flex-wrap: wrap;
  754. gap: 32rpx;
  755. }
  756. .date-text {
  757. margin: 0 10px;
  758. font-weight: bold;
  759. }
  760. .form-actions {
  761. justify-content: center;
  762. gap: 32rpx;
  763. margin-top: 32rpx;
  764. }
  765. ::v-deep .uni-forms-item__label {
  766. font-weight: bold;
  767. }
  768. .device-cards {
  769. margin-top: 20rpx;
  770. }
  771. .device-card {
  772. background: #fff;
  773. border-radius: 12rpx;
  774. margin-bottom: 20rpx;
  775. box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
  776. overflow: hidden;
  777. transition: all 0.3s ease;
  778. cursor: pointer;
  779. &.selected {
  780. border: 2rpx solid #67c23a;
  781. background-color: rgba(103, 194, 58, 0.05);
  782. }
  783. }
  784. .card-header {
  785. padding: 16rpx 20rpx;
  786. background: #f5f7fa;
  787. border-bottom: 1rpx solid #eee;
  788. display: flex;
  789. justify-content: space-between;
  790. align-items: center;
  791. }
  792. .return-tag {
  793. margin-left: 10rpx;
  794. }
  795. .card-title {
  796. font-size: 28rpx;
  797. font-weight: bold;
  798. color: #333;
  799. display: block;
  800. overflow: hidden;
  801. text-overflow: ellipsis;
  802. white-space: nowrap;
  803. }
  804. .card-content {
  805. padding: 16rpx 20rpx;
  806. }
  807. .card-row {
  808. display: flex;
  809. margin-bottom: 12rpx;
  810. &:last-child {
  811. margin-bottom: 0;
  812. }
  813. }
  814. .card-item {
  815. flex: 1;
  816. display: flex;
  817. align-items: center;
  818. font-size: 26rpx;
  819. line-height: 1.4;
  820. padding: 0 10rpx;
  821. min-width: 0; // 防止内容溢出
  822. .label {
  823. color: #666;
  824. flex-shrink: 0;
  825. margin-right: 8rpx;
  826. }
  827. .value {
  828. color: #333;
  829. flex: 1;
  830. overflow: hidden;
  831. text-overflow: ellipsis;
  832. white-space: nowrap;
  833. }
  834. }
  835. .card-actions {
  836. padding: 16rpx 20rpx;
  837. display: flex;
  838. justify-content: flex-end;
  839. gap: 20rpx;
  840. border-top: 1rpx solid #eee;
  841. }
  842. .device-card {
  843. background: #fff;
  844. border-radius: 12rpx;
  845. margin-bottom: 20rpx;
  846. box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
  847. overflow: hidden;
  848. transition: all 0.3s ease;
  849. cursor: pointer;
  850. &.repair-card {
  851. border: 2rpx solid #f56c6c;
  852. background-color: rgba(245, 108, 108, 0.05);
  853. }
  854. }
  855. .card-header {
  856. padding: 16rpx 20rpx;
  857. background: #f5f7fa;
  858. border-bottom: 1rpx solid #eee;
  859. display: flex;
  860. justify-content: space-between;
  861. align-items: center;
  862. }
  863. .repair-tag {
  864. margin-left: 10rpx;
  865. }
  866. </style>