index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. <script setup lang="ts">
  2. import { ref, getCurrentInstance, reactive } from "vue";
  3. import { useRouter } from "vue-router";
  4. import request, { download } from '~/utils/request';
  5. import { pick } from 'lodash-es';
  6. import { ElMessage } from 'element-plus'
  7. import type { FormInstance, FormRules } from 'element-plus'
  8. import type { AxiosRequestConfig } from 'axios'
  9. // #region (constant)
  10. const TABLE_KEY = 'xktj_id'
  11. const URL_CUT = '/xdjx/kcpzgl_bbtj'
  12. const URL_CUT_REF = ref(URL_CUT)
  13. const URL_SUBMIT_KEY = URL_CUT.split('/').join('_').slice(1)
  14. const instance = getCurrentInstance()
  15. const router = useRouter()
  16. // #endregion
  17. // #region (variable)
  18. const loading_table = ref(true)
  19. let whichDialogSubmit:'add'|'edit'
  20. // #endregion
  21. // #region (type)
  22. type TYPE_TABLE_FIELD = {
  23. [TABLE_KEY]: string;
  24. 'xktj_bbmc': string; // 报表名称
  25. 'xktj_cjr': string; // 创建人
  26. 'xktj_cjsj': string; // 创建时间
  27. 'xktj_bbsz_json': string; // 报表设置JSON
  28. }
  29. // #endregion
  30. // #region (props)
  31. // #endregion
  32. // #region (query row)
  33. const queryForm_Data = ref<Partial<TYPE_TABLE_FIELD>>({})
  34. const handleQueryFormBtn_search = () => {
  35. queryApi()
  36. }
  37. const handleQueryFormBtn_clear = () => {
  38. queryForm_Data.value = {}
  39. }
  40. // #endregion
  41. // #region (table selection)
  42. const multipleSelection = ref<TYPE_TABLE_FIELD[]>([])
  43. const handleSelectionChange = (val:TYPE_TABLE_FIELD[]) => {
  44. multipleSelection.value = val
  45. }
  46. // #endregion
  47. // #region (table row)
  48. const handleTableRowBtn_import = async ({ file }: { file: File }) => {
  49. const res = await API_MAP['import']({ file })
  50. if(res.code === '1'){
  51. queryApi()
  52. ElMessage.success(res.msg)
  53. }
  54. }
  55. const handleTableRowBtn_export = () => {
  56. exportApi()
  57. }
  58. const handleTableRowBtn_add = () => {
  59. whichDialogSubmit = 'add'
  60. dialogForm_Data.value = {}
  61. dialogVisible_addOrEdit.value = true
  62. }
  63. const handleTableRowBtn_delete = async () => {
  64. await deleteApi(multipleSelection.value.map((item: TYPE_TABLE_FIELD)=>item[TABLE_KEY]))
  65. queryApi()
  66. }
  67. // #endregion
  68. // #region (table body)
  69. const tableData = ref<TYPE_TABLE_FIELD[]>([])
  70. const DetailName = '-KCPZGL-BBTJ-DETAIL'
  71. const DetailParam = 'aid'
  72. const handleTableColBtn_edit = async (scope:{row:TYPE_TABLE_FIELD}) => {
  73. whichDialogSubmit = 'edit'
  74. const res = await detailApi(scope.row[TABLE_KEY])
  75. dialogForm_Data.value = (res.data.one_info)
  76. dialogVisible_addOrEdit.value = true
  77. }
  78. const handleTableColBtn_audit = (scope:{row:TYPE_TABLE_FIELD}) => {
  79. whichDialogSubmit = 'edit'
  80. dialogForm_Data.value = { ...scope.row }
  81. dialogVisible_audit.value = true
  82. }
  83. const handleTableColBtn_detail = (scope:{row:TYPE_TABLE_FIELD}) => {
  84. router.push({ name:DetailName, params:{ [DetailParam]:scope.row[TABLE_KEY]} })
  85. }
  86. const handleTableColBtn_delete = async (scope:{row:TYPE_TABLE_FIELD}) => {
  87. await deleteApi(scope.row[TABLE_KEY])
  88. queryApi()
  89. }
  90. // #endregion
  91. // #region (pagination)
  92. const total = ref(0)
  93. const limit = ref(10)
  94. const currentPage=ref(1)
  95. function handleCurrentChange(){
  96. queryApi()
  97. }
  98. // #endregion
  99. // #region (dialog base)
  100. const dialogForm_Data = ref<Partial<TYPE_TABLE_FIELD>>({})
  101. const handleDialogFormBtn_submit = async (formRefKey:string) => {
  102. const isValid = await (instance?.refs[formRefKey] as FormInstance).validate((valid:boolean) => valid)
  103. if (isValid) {
  104. await API_MAP[whichDialogSubmit](<TYPE_TABLE_FIELD>(dialogForm_Data.value))
  105. handleDialogFormBtn_cancel()
  106. queryApi()
  107. }
  108. }
  109. const handleDialogFormBtn_cancel = (formRefKey?:string) => {
  110. dialogVisible_addOrEdit.value = false
  111. dialogVisible_audit.value = false
  112. }
  113. // #endregion
  114. // #region (dialog add/edit)
  115. const dialogVisible_addOrEdit = ref<boolean>(false)
  116. const dialogForm_Ref_addOrEdit= ref<FormInstance>()
  117. const dialogForm_Rules_addOrEdit = reactive({
  118. 'xktj_bbmc':{required : true ,message:'报表名称不能为空'},
  119. 'xktj_cjr':{required : true ,message:'创建人不能为空'},
  120. 'xktj_cjsj':{required : true ,message:'创建时间不能为空'},
  121. 'xktj_bbsz_json':{required : true ,message:'报表设置JSON不能为空'},
  122. })
  123. // #endregion
  124. // #region (dialog audit)
  125. const dialogVisible_audit = ref<boolean>(false)
  126. const dialogForm_Field_audit= reactive<{
  127. FLAG:keyof TYPE_TABLE_FIELD,
  128. REASON?:keyof TYPE_TABLE_FIELD
  129. }>({
  130. FLAG:'xktj_id',
  131. REASON:'xktj_id'
  132. })
  133. const dialogForm_Ref_audit= ref<FormInstance>()
  134. const dialogForm_Rules_audit = reactive<FormRules>({
  135. 'xktj_bbmc':{required : true ,message:'报表名称不能为空'},
  136. 'xktj_cjr':{required : true ,message:'创建人不能为空'},
  137. 'xktj_cjsj':{required : true ,message:'创建时间不能为空'},
  138. 'xktj_bbsz_json':{required : true ,message:'报表设置JSON不能为空'},
  139. })
  140. // #endregion
  141. // #region (request api):
  142. function queryApi(){
  143. loading_table.value = true
  144. return request({
  145. url: URL_CUT + '/index',
  146. data: {
  147. ...queryForm_Data.value,
  148. limit: limit.value,
  149. page: currentPage.value
  150. }
  151. }).then((response:{data:{total_rows:string,page_data:TYPE_TABLE_FIELD[]}}) => {
  152. const { data } = response
  153. total.value = parseInt(data.total_rows)
  154. tableData.value = data.page_data
  155. return response
  156. }).then(() => {
  157. loading_table.value = false
  158. })
  159. }
  160. function addApi(data:TYPE_TABLE_FIELD){
  161. return request({
  162. url: URL_CUT + '/add',
  163. data: {
  164. [URL_SUBMIT_KEY]:data,
  165. }
  166. })
  167. }
  168. function editApi(data:TYPE_TABLE_FIELD){
  169. return request({
  170. url: URL_CUT + '/edit',
  171. data: {
  172. [TABLE_KEY]:data[TABLE_KEY],
  173. [URL_SUBMIT_KEY]:pick(data,['xktj_bbmc','xktj_cjr','xktj_cjsj','xktj_bbsz_json',]),
  174. }
  175. })
  176. }
  177. function deleteApi(id:string|string[]){
  178. return request({
  179. url: URL_CUT + '/delete',
  180. data: {
  181. [TABLE_KEY]:id,
  182. }
  183. })
  184. }
  185. function detailApi(id:string){
  186. return request({
  187. url: URL_CUT + '/detail',
  188. data: {
  189. [TABLE_KEY]:id,
  190. }
  191. })
  192. }
  193. function importApi(data:{file:File}){
  194. return request({
  195. $type: 'import',
  196. url: URL_CUT + '/import',
  197. data
  198. } as AxiosRequestConfig)
  199. }
  200. function exportApi(){
  201. return download(URL_CUT + '/index', queryForm_Data.value)
  202. }
  203. const API_MAP = {
  204. query:queryApi,
  205. add:addApi,
  206. edit:editApi,
  207. delete:deleteApi,
  208. detail:detailApi,
  209. import:importApi,
  210. export:exportApi,
  211. }
  212. // #endregion
  213. // #region (page init)
  214. function init(){
  215. queryApi()
  216. }
  217. init()
  218. // #endregion
  219. </script>
  220. <template>
  221. <div class="card flex-grow flex flex-col">
  222. <el-form inline :model="queryForm_Data">
  223. <el-form-item label="报表名称"><el-input v-model="queryForm_Data.xktj_bbmc" clearable /></el-form-item>
  224. <el-form-item label="创建人"><el-input v-model="queryForm_Data.xktj_cjr" clearable /></el-form-item>
  225. <!-- <el-form-item label="创建时间"><el-date-picker type="date" v-model="queryForm_Data.xktj_cjsj" value-format="YYYY-MM-DD HH:mm:ss" clearable /></el-form-item>
  226. <el-form-item label="报表设置JSON"><el-input v-model="queryForm_Data.xktj_bbsz_json" type="textarea" /></el-form-item> -->
  227. <el-form-item>
  228. <el-button @click="handleQueryFormBtn_search" type="primary">搜索</el-button>
  229. <el-button @click="handleQueryFormBtn_clear" type="warning">清空</el-button>
  230. </el-form-item>
  231. </el-form>
  232. <div class="divider"></div>
  233. <div>
  234. <import-button :url="URL_CUT_REF"></import-button>
  235. <el-button @click="handleTableRowBtn_export" type="success">导出</el-button>
  236. <el-button @click="handleTableRowBtn_add" type="primary">新增</el-button>
  237. <el-button @click="handleTableRowBtn_delete" type="danger">删除</el-button>
  238. </div>
  239. <div class="divider"></div>
  240. <div class="flex-auto">
  241. <el-table :data="tableData" @selection-change="handleSelectionChange" v-loading="loading_table"
  242. element-loading-background="#ffffff70">
  243. <el-table-column type="selection"></el-table-column>
  244. <el-table-column prop="xktj_bbmc" label="报表名称" width="auto" show-overflow-tooltip></el-table-column>
  245. <el-table-column prop="xktj_cjr" label="创建人" width="auto" show-overflow-tooltip></el-table-column>
  246. <el-table-column prop="xktj_cjsj" label="创建时间" width="auto" show-overflow-tooltip></el-table-column>
  247. <!-- <el-table-column prop="xktj_bbsz_json" label="报表设置JSON" width="auto" show-overflow-tooltip></el-table-column> -->
  248. <el-table-column label="操作" fixed="right">
  249. <template #default="scope">
  250. <el-link @click="handleTableColBtn_edit(scope)" type="primary" :underline="false" class="mr-2">编辑</el-link>
  251. <!-- <el-link @click="handleTableColBtn_audit(scope)" type="primary" :underline="false" class="mr-2">审核</el-link> -->
  252. <el-link @click="handleTableColBtn_detail(scope)" type="primary" :underline="false" class="mr-2">详情</el-link>
  253. <el-link @click="handleTableColBtn_delete(scope)" type="primary" :underline="false" class="mr-2">删除</el-link>
  254. </template>
  255. </el-table-column>
  256. </el-table>
  257. </div>
  258. <div class="flex justify-end mt-10 py-4">
  259. <el-pagination :page-size="limit" v-model:current-page="currentPage" @current-change="handleCurrentChange"
  260. background layout="total, prev, pager, next" :total="total" />
  261. </div>
  262. </div>
  263. <el-dialog v-model="dialogVisible_addOrEdit" append-to-body destroy-on-close>
  264. <el-form :model="dialogForm_Data" ref="dialogForm_Ref_addOrEdit" :rules="dialogForm_Rules_addOrEdit" label-width="120px">
  265. <el-form-item label="报表名称" prop="xktj_bbmc"><el-input v-model="dialogForm_Data.xktj_bbmc" clearable /></el-form-item>
  266. <el-form-item label="创建人" prop="xktj_cjr"><el-input v-model="dialogForm_Data.xktj_cjr" clearable /></el-form-item>
  267. <el-form-item label="创建时间" prop="xktj_cjsj"><el-date-picker type="date" v-model="dialogForm_Data.xktj_cjsj" value-format="YYYY-MM-DD HH:mm:ss" clearable /></el-form-item>
  268. <el-form-item label="报表设置JSON" prop="xktj_bbsz_json"><el-input v-model="dialogForm_Data.xktj_bbsz_json" type="textarea" /></el-form-item>
  269. <div class="flex justify-center">
  270. <el-button @click="handleDialogFormBtn_submit('dialogForm_Ref_addOrEdit')" type="primary">提交</el-button>
  271. <el-button @click="handleDialogFormBtn_cancel('dialogForm_Ref_addOrEdit')" type="default">取消</el-button>
  272. </div>
  273. </el-form>
  274. </el-dialog>
  275. <el-dialog v-model="dialogVisible_audit" append-to-body destroy-on-close>
  276. <el-form :model="dialogForm_Data" ref="dialogForm_Ref_audit" :rules="dialogForm_Rules_audit" label-width="120px">
  277. <el-form-item label="状态">
  278. <el-radio-group v-model="dialogForm_Data[dialogForm_Field_audit.FLAG]">
  279. <el-radio label="1">通过</el-radio>
  280. <el-radio label="2">未通过</el-radio>
  281. </el-radio-group>
  282. </el-form-item>
  283. <!-- <el-form-item label="原因" v-show="dialogForm_Data[dialogForm_Field_audit.FLAG] === '1'">
  284. <el-input type="textarea" v-model="dialogForm_Data[dialogForm_Field_audit.REASON]" :rows="5" />
  285. </el-form-item> -->
  286. <div class="flex justify-center">
  287. <el-button @click="handleDialogFormBtn_submit('dialogForm_Ref_audit')" type="primary">提交</el-button>
  288. <el-button @click="handleDialogFormBtn_cancel('dialogForm_Ref_audit')" type="default">取消</el-button>
  289. </div>
  290. </el-form>
  291. </el-dialog>
  292. </template>