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.

304 lines
13 KiB

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. <template>
  2. <div class="customer-css">
  3. <!-- 查询条件 -->
  4. <el-form :inline="true" label-position="top" class="rs-search-form">
  5. <el-form-item label="模板编码">
  6. <el-input v-model="searchData.templateCode" style="width:150px" clearable @keyup.enter.native="getList" />
  7. </el-form-item>
  8. <el-form-item label="模板名称">
  9. <el-input v-model="searchData.templateName" style="width:200px" clearable @keyup.enter.native="getList" />
  10. </el-form-item>
  11. <el-form-item label=" ">
  12. <el-button type="primary" class="customer-bun-min" icon="el-icon-search" @click="getList">查询</el-button>
  13. <el-button v-if="canEdit" type="success" class="customer-bun-min" icon="el-icon-plus" @click="openDialog()">新增</el-button>
  14. </el-form-item>
  15. </el-form>
  16. <!-- 模板列表 -->
  17. <el-table :data="dataList" border highlight-current-row v-loading="loading" style="width:100%;margin-bottom:8px">
  18. <el-table-column v-if="canEdit" label="操作" header-align="center" align="center" width="120">
  19. <template slot-scope="scope">
  20. <a class="customer-a" @click.stop="openDialog(scope.row)">编辑 |</a>
  21. <a class="customer-a" @click.stop="removeRow(scope.row)">删除</a>
  22. </template>
  23. </el-table-column>
  24. <el-table-column type="index" label="#" width="50" align="center" />
  25. <el-table-column prop="templateCode" label="模板编码" min-width="120" header-align="center" align="left" show-overflow-tooltip />
  26. <el-table-column prop="templateName" label="模板名称" min-width="180" header-align="center" align="left" show-overflow-tooltip />
  27. <el-table-column prop="remarks" label="备注" min-width="200" header-align="center" align="left" show-overflow-tooltip />
  28. <el-table-column prop="status" label="状态" width="80" class-name="status-col" header-align="center" align="center">
  29. <template slot-scope="scope">
  30. <el-tag :type="scope.row.status === 'Y' ? 'success' : 'info'" size="mini">{{ scope.row.status === 'Y' ? '启用' : '停用' }}</el-tag>
  31. </template>
  32. </el-table-column>
  33. <el-table-column prop="createBy" label="创建者" width="110" header-align="center" align="left" />
  34. <el-table-column prop="createDate" label="创建时间" width="150" header-align="center" align="center" />
  35. </el-table>
  36. <!-- 分页 -->
  37. <el-pagination style="margin-top:0" @size-change="sizeChangeHandle" @current-change="currentChangeHandle"
  38. :current-page="pageIndex" :page-sizes="[20,50,100,200]" :page-size="pageSize" :total="totalPage"
  39. layout="total, sizes, prev, pager, next, jumper" />
  40. <!-- 新增/编辑 模板(含明细配置) -->
  41. <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="900px" top="6vh" :close-on-click-modal="false" v-drag>
  42. <el-form :model="form" label-position="top" class="rs-form">
  43. <el-row :gutter="20">
  44. <el-col :span="8">
  45. <el-form-item label="模板编码" :required="true">
  46. <el-input v-model="form.templateCode" :disabled="editMode" maxlength="50" />
  47. </el-form-item>
  48. </el-col>
  49. <el-col :span="8">
  50. <el-form-item label="模板名称" :required="true">
  51. <el-input v-model="form.templateName" maxlength="120" />
  52. </el-form-item>
  53. </el-col>
  54. <el-col :span="8">
  55. <el-form-item label="状态">
  56. <el-select v-model="form.status" style="width:100%">
  57. <el-option label="启用" value="Y" />
  58. <el-option label="停用" value="N" />
  59. </el-select>
  60. </el-form-item>
  61. </el-col>
  62. </el-row>
  63. <el-row :gutter="20">
  64. <el-col :span="24">
  65. <el-form-item label="备注">
  66. <el-input v-model="form.remarks" type="textarea" :rows="2" maxlength="500" show-word-limit />
  67. </el-form-item>
  68. </el-col>
  69. </el-row>
  70. </el-form>
  71. <div class="criteria-header">
  72. <span>维修明细(模板包含的明细项)</span>
  73. <el-button size="mini" type="primary" icon="el-icon-plus" @click="openPicker">添加明细</el-button>
  74. </div>
  75. <el-table :data="form.detailList" class="detail-table" size="mini" border max-height="300">
  76. <el-table-column type="index" label="#" width="45" align="center" />
  77. <el-table-column prop="skillCode" label="明细编码" width="130" header-align="center" align="left" show-overflow-tooltip />
  78. <el-table-column prop="skillName" label="明细名称" min-width="180" header-align="center" align="left" show-overflow-tooltip />
  79. <el-table-column prop="maxScore" label="满分" width="80" header-align="center" align="right" />
  80. <el-table-column label="操作" width="80" align="center">
  81. <template slot-scope="scope">
  82. <el-button type="text" size="mini" @click="removeDetail(scope.$index)">移除</el-button>
  83. </template>
  84. </el-table-column>
  85. </el-table>
  86. <span slot="footer" class="dialog-footer">
  87. <el-button type="primary" :loading="submitLoading" @click="submitForm">保存</el-button>
  88. <el-button @click="dialogVisible=false">取消</el-button>
  89. </span>
  90. </el-dialog>
  91. <!-- 从维修明细库选择 -->
  92. <el-dialog title="选择维修明细" :visible.sync="pickerVisible" width="900px" top="8vh" :close-on-click-modal="false" append-to-body v-drag>
  93. <el-form :inline="true" label-position="top">
  94. <el-form-item label="明细名称">
  95. <el-input v-model="pickerQuery.skillName" clearable style="width:180px" @keyup.enter.native="loadCandidates" />
  96. </el-form-item>
  97. <el-form-item label=" ">
  98. <el-button type="primary" icon="el-icon-search" @click="loadCandidates">查询</el-button>
  99. </el-form-item>
  100. </el-form>
  101. <el-table ref="pickerTable" :data="candidateList" height="420" size="mini" border v-loading="pickerLoading" @selection-change="onPick">
  102. <el-table-column type="selection" width="50" />
  103. <el-table-column prop="skillCode" label="明细编码" width="130" header-align="center" align="left" />
  104. <el-table-column prop="skillName" label="明细名称" min-width="180" header-align="center" align="left" show-overflow-tooltip />
  105. <el-table-column prop="maxScore" label="满分" width="80" header-align="center" align="right" />
  106. </el-table>
  107. <span slot="footer" class="dialog-footer">
  108. <el-button type="primary" @click="confirmPick">确定添加</el-button>
  109. <el-button @click="pickerVisible=false">取消</el-button>
  110. </span>
  111. </el-dialog>
  112. </div>
  113. </template>
  114. <script>
  115. import {
  116. searchTemplateList,
  117. createTemplate,
  118. updateTemplate,
  119. deleteTemplate,
  120. getTemplateDetails
  121. } from '@/api/repairSkill/repairSkillTemplate.js'
  122. import { searchContentList } from '@/api/repairSkill/repairSkillContent.js'
  123. export default {
  124. name: 'RepairSkillTemplate',
  125. data () {
  126. return {
  127. loading: false,
  128. submitLoading: false,
  129. dataList: [],
  130. pageIndex: 1,
  131. pageSize: 20,
  132. totalPage: 0,
  133. searchData: {
  134. site: this.$store.state.user.site,
  135. templateCode: '',
  136. templateName: ''
  137. },
  138. dialogVisible: false,
  139. dialogTitle: '新增维修技能模板',
  140. editMode: false,
  141. form: this.emptyForm(),
  142. // 明细选择
  143. pickerVisible: false,
  144. pickerLoading: false,
  145. candidateList: [],
  146. picked: [],
  147. pickerQuery: { skillName: '' }
  148. }
  149. },
  150. computed: {
  151. canEdit () {
  152. // TODO 特殊权限:暂时放开,联调后恢复为 this.isAuth('repairSkill:template:edit')
  153. return true
  154. }
  155. },
  156. mounted () {
  157. this.getList()
  158. },
  159. methods: {
  160. emptyForm () {
  161. return {
  162. site: this.$store.state.user.site,
  163. templateCode: '',
  164. templateName: '',
  165. remarks: '',
  166. status: 'Y',
  167. createBy: this.$store.state.user.name,
  168. updateBy: '',
  169. detailList: []
  170. }
  171. },
  172. getList () {
  173. this.loading = true
  174. const params = { ...this.searchData, page: this.pageIndex, limit: this.pageSize }
  175. searchTemplateList(params).then(({ data }) => {
  176. if (data && (data.code === 0 || data.code === '0') && data.page) {
  177. this.dataList = data.page.list || []
  178. this.totalPage = data.page.totalCount || 0
  179. } else {
  180. this.dataList = []
  181. this.totalPage = 0
  182. }
  183. }).catch(() => { this.dataList = []; this.totalPage = 0 })
  184. .finally(() => { this.loading = false })
  185. },
  186. sizeChangeHandle (v) { this.pageSize = v; this.pageIndex = 1; this.getList() },
  187. currentChangeHandle (v) { this.pageIndex = v; this.getList() },
  188. openDialog (row) {
  189. if (row) {
  190. this.dialogTitle = '编辑维修技能模板'
  191. this.editMode = true
  192. this.form = { ...row, updateBy: this.$store.state.user.name, detailList: [] }
  193. this.loadDetails(row.templateCode)
  194. } else {
  195. this.dialogTitle = '新增维修技能模板'
  196. this.editMode = false
  197. this.form = this.emptyForm()
  198. }
  199. this.dialogVisible = true
  200. },
  201. loadDetails (templateCode) {
  202. getTemplateDetails({ templateCode, site: this.$store.state.user.site }).then(({ data }) => {
  203. if (data && (data.code === 0 || data.code === '0')) {
  204. this.form.detailList = data.obj || []
  205. } else {
  206. this.form.detailList = []
  207. }
  208. }).catch(() => { this.form.detailList = [] })
  209. },
  210. removeDetail (i) { this.form.detailList.splice(i, 1) },
  211. // ===== 明细选择 =====
  212. openPicker () {
  213. this.pickerVisible = true
  214. this.pickerQuery = { skillName: '' }
  215. this.picked = []
  216. this.loadCandidates()
  217. },
  218. loadCandidates () {
  219. this.pickerLoading = true
  220. const params = { site: this.$store.state.user.site, skillName: this.pickerQuery.skillName, status: 'Y', page: 1, limit: 1000 }
  221. searchContentList(params).then(({ data }) => {
  222. if (data && (data.code === 0 || data.code === '0') && data.page) {
  223. const existing = new Set(this.form.detailList.map(d => d.skillContentId))
  224. this.candidateList = (data.page.list || []).filter(s => !existing.has(s.skillCode))
  225. } else {
  226. this.candidateList = []
  227. }
  228. }).catch(() => { this.candidateList = [] })
  229. .finally(() => { this.pickerLoading = false })
  230. },
  231. onPick (val) { this.picked = val },
  232. confirmPick () {
  233. if (!this.picked.length) { this.$message.warning('请选择明细'); return }
  234. this.picked.forEach(p => {
  235. this.form.detailList.push({
  236. skillContentId: p.skillCode,
  237. skillCode: p.skillCode,
  238. skillName: p.skillName,
  239. maxScore: p.maxScore
  240. })
  241. })
  242. this.pickerVisible = false
  243. },
  244. validate () {
  245. if (!this.form.templateCode) { this.$message.warning('模板编码不能为空'); return false }
  246. if (!this.form.templateName) { this.$message.warning('模板名称不能为空'); return false }
  247. if (!this.form.detailList.length) { this.$message.warning('请至少添加一条维修明细'); return false }
  248. return true
  249. },
  250. submitForm () {
  251. if (!this.validate()) return
  252. this.submitLoading = true
  253. const payload = { ...this.form, site: this.$store.state.user.site }
  254. payload.detailList = (this.form.detailList || []).map((d, idx) => ({
  255. skillContentId: d.skillContentId,
  256. seq: d.seq != null ? d.seq : idx
  257. }))
  258. const api = this.editMode ? updateTemplate : createTemplate
  259. api(payload).then(({ data }) => {
  260. if (data && (data.code === 0 || data.code === '0')) {
  261. this.$message.success('保存成功')
  262. this.dialogVisible = false
  263. this.getList()
  264. } else {
  265. this.$message.error((data && data.msg) || '保存失败')
  266. }
  267. }).catch(e => this.$message.error('保存失败: ' + e.message))
  268. .finally(() => { this.submitLoading = false })
  269. },
  270. removeRow (row) {
  271. this.$confirm('确认删除模板: ' + row.templateName + ' ?', '提示', { type: 'warning' }).then(() => {
  272. deleteTemplate({ templateCode: row.templateCode, site: this.$store.state.user.site }).then(({ data }) => {
  273. if (data && (data.code === 0 || data.code === '0')) {
  274. this.$message.success('删除成功')
  275. this.getList()
  276. } else {
  277. this.$message.error((data && data.msg) || '删除失败')
  278. }
  279. }).catch(e => this.$message.error('删除失败: ' + e.message))
  280. }).catch(() => {})
  281. }
  282. }
  283. }
  284. </script>
  285. <style scoped>
  286. .rs-search-form { margin-top: 0; }
  287. .rs-form { margin-top: -5px; }
  288. .criteria-header { display: flex; align-items: center; justify-content: space-between; font-weight: 600; padding: 6px; margin-top: 50px; background: #f5f7fa; border: 1px solid #ebeef5; border-bottom: none; }
  289. .criteria-header button { margin-left: 8px; }
  290. .detail-table /deep/ .cell { height: auto; line-height: 1.5; overflow: visible; }
  291. /* 列表状态列:覆盖全局固定高度,避免 el-tag 被裁切 */
  292. .el-table /deep/ .status-col .cell { height: auto; line-height: 1.5; overflow: visible; }
  293. </style>